Encoder fixes.

* Remove default constructors.
* Initialize bit_cost in histogram.Clear().
* Check fseek result in FileSize.
* Replace malloc in BrotliFileIn constructor with "new".
* Catch bad_alloc in bro tool.
This commit is contained in:
Zoltan Szabadka 2015-10-06 11:23:44 +02:00
parent 47835c6089
commit 2726b8a4f6
8 changed files with 39 additions and 30 deletions

View File

@ -339,6 +339,7 @@ std::vector<int> MoveToFrontTransform(const std::vector<int>& v) {
std::vector<int> result(v.size());
for (int i = 0; i < v.size(); ++i) {
int index = IndexOf(mtf, v[i]);
assert(index >= 0);
result[i] = index;
MoveToFront(&mtf, index);
}

View File

@ -90,8 +90,6 @@ static inline void GetLengthCode(int insertlen, int copylen, int distancecode,
}
struct Command {
Command() {}
// distance_code is e.g. 0 for same-as-last short code, or 16 for offset 1.
Command(int insertlen, int copylen, int copylen_code, int distance_code)
: insert_len_(insertlen), copy_len_(copylen) {

View File

@ -39,15 +39,15 @@ namespace brotli {
namespace {
void RecomputeDistancePrefixes(std::vector<Command>* cmds,
void RecomputeDistancePrefixes(Command* cmds, int num_commands,
int num_direct_distance_codes,
int distance_postfix_bits) {
if (num_direct_distance_codes == 0 &&
distance_postfix_bits == 0) {
return;
}
for (int i = 0; i < cmds->size(); ++i) {
Command* cmd = &(*cmds)[i];
for (int i = 0; i < num_commands; ++i) {
Command* cmd = &cmds[i];
if (cmd->copy_len_ > 0 && cmd->cmd_prefix_ >= 128) {
PrefixEncodeCopyDistance(cmd->DistanceCode(),
num_direct_distance_codes,
@ -104,7 +104,12 @@ bool WriteMetaBlockParallel(const BrotliParams& params,
int num_literals = 0;
int max_backward_distance = (1 << params.lgwin) - 16;
int dist_cache[4] = { -4, -4, -4, -4 };
std::vector<Command> commands((input_size + 1) >> 1);
Command* commands = static_cast<Command*>(
malloc(sizeof(Command) * ((input_size + 1) >> 1)));
if (commands == 0) {
delete hashers;
return false;
}
CreateBackwardReferences(
input_size, input_pos,
&input[0], mask,
@ -114,16 +119,15 @@ bool WriteMetaBlockParallel(const BrotliParams& params,
hash_type,
dist_cache,
&last_insert_len,
&commands[0],
commands,
&num_commands,
&num_literals);
delete hashers;
commands.resize(num_commands);
if (last_insert_len > 0) {
commands.push_back(Command(last_insert_len));
commands[num_commands++] = Command(last_insert_len);
num_literals += last_insert_len;
}
assert(!commands.empty());
assert(num_commands != 0);
// Build the meta-block.
MetaBlockSplit mb;
@ -131,17 +135,17 @@ bool WriteMetaBlockParallel(const BrotliParams& params,
params.mode == BrotliParams::MODE_FONT ? 12 : 0;
int distance_postfix_bits = params.mode == BrotliParams::MODE_FONT ? 1 : 0;
int literal_context_mode = utf8_mode ? CONTEXT_UTF8 : CONTEXT_SIGNED;
RecomputeDistancePrefixes(&commands,
RecomputeDistancePrefixes(commands, num_commands,
num_direct_distance_codes,
distance_postfix_bits);
if (params.quality <= 9) {
BuildMetaBlockGreedy(&input[0], input_pos, mask,
&commands[0], commands.size(),
commands, num_commands,
&mb);
} else {
BuildMetaBlock(&input[0], input_pos, mask,
prev_byte, prev_byte2,
&commands[0], commands.size(),
commands, num_commands,
literal_context_mode,
&mb);
}
@ -173,11 +177,13 @@ bool WriteMetaBlockParallel(const BrotliParams& params,
num_direct_distance_codes,
distance_postfix_bits,
literal_context_mode,
&commands[0], commands.size(),
commands, num_commands,
mb,
&storage_ix, &storage[0])) {
free(commands);
return false;
}
free(commands);
// If this is not the last meta-block, store an empty metadata
// meta-block so that the meta-block will end at a byte boundary.

View File

@ -29,7 +29,6 @@ namespace brotli {
namespace {
struct HuffmanTree {
HuffmanTree();
HuffmanTree(int count, int16_t left, int16_t right)
: total_count_(count),
index_left_(left),
@ -40,8 +39,6 @@ struct HuffmanTree {
int16_t index_right_or_value_;
};
HuffmanTree::HuffmanTree() {}
// Sort the root nodes, least popular first.
bool SortHuffmanTree(const HuffmanTree &v0, const HuffmanTree &v1) {
return v0.total_count_ < v1.total_count_;

View File

@ -18,6 +18,7 @@
#define BROTLI_ENC_HISTOGRAM_H_
#include <string.h>
#include <limits>
#include <vector>
#include <utility>
#include "./command.h"
@ -38,6 +39,7 @@ struct Histogram {
void Clear() {
memset(data_, 0, sizeof(data_));
total_count_ = 0;
bit_cost_ = std::numeric_limits<double>::infinity();
}
void Add(int val) {
++data_[val];

View File

@ -89,18 +89,14 @@ const void* BrotliMemIn::Read(size_t n, size_t* output) {
BrotliFileIn::BrotliFileIn(FILE* f, size_t max_read_size)
: f_(f),
buf_(malloc(max_read_size)),
buf_size_(max_read_size) {}
buf_(new char[max_read_size]),
buf_size_(max_read_size) { }
BrotliFileIn::~BrotliFileIn() {
if (buf_) free(buf_);
delete[] buf_;
}
const void* BrotliFileIn::Read(size_t n, size_t* bytes_read) {
if (buf_ == NULL) {
*bytes_read = 0;
return NULL;
}
if (n > buf_size_) {
n = buf_size_;
} else if (n == 0) {

View File

@ -110,7 +110,7 @@ class BrotliFileIn : public BrotliIn {
private:
FILE* f_;
void* buf_;
char* buf_;
size_t buf_size_;
};

View File

@ -177,7 +177,10 @@ int64_t FileSize(char *path) {
if (f == NULL) {
return -1;
}
fseek(f, 0L, SEEK_END);
if (fseek(f, 0L, SEEK_END) != 0) {
fclose(f);
return -1;
}
int64_t retval = ftell(f);
fclose(f);
return retval;
@ -209,10 +212,16 @@ int main(int argc, char** argv) {
brotli::BrotliParams params;
params.lgwin = lgwin;
params.quality = quality;
brotli::BrotliFileIn in(fin, 1 << 16);
brotli::BrotliFileOut out(fout);
if (!BrotliCompress(params, &in, &out)) {
fprintf(stderr, "compression failed\n");
try {
brotli::BrotliFileIn in(fin, 1 << 16);
brotli::BrotliFileOut out(fout);
if (!BrotliCompress(params, &in, &out)) {
fprintf(stderr, "compression failed\n");
unlink(output_path);
exit(1);
}
} catch (std::bad_alloc&) {
fprintf(stderr, "not enough memory\n");
unlink(output_path);
exit(1);
}