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()); std::vector<int> result(v.size());
for (int i = 0; i < v.size(); ++i) { for (int i = 0; i < v.size(); ++i) {
int index = IndexOf(mtf, v[i]); int index = IndexOf(mtf, v[i]);
assert(index >= 0);
result[i] = index; result[i] = index;
MoveToFront(&mtf, index); MoveToFront(&mtf, index);
} }

View File

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

View File

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

View File

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

View File

@ -18,6 +18,7 @@
#define BROTLI_ENC_HISTOGRAM_H_ #define BROTLI_ENC_HISTOGRAM_H_
#include <string.h> #include <string.h>
#include <limits>
#include <vector> #include <vector>
#include <utility> #include <utility>
#include "./command.h" #include "./command.h"
@ -38,6 +39,7 @@ struct Histogram {
void Clear() { void Clear() {
memset(data_, 0, sizeof(data_)); memset(data_, 0, sizeof(data_));
total_count_ = 0; total_count_ = 0;
bit_cost_ = std::numeric_limits<double>::infinity();
} }
void Add(int val) { void Add(int val) {
++data_[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) BrotliFileIn::BrotliFileIn(FILE* f, size_t max_read_size)
: f_(f), : f_(f),
buf_(malloc(max_read_size)), buf_(new char[max_read_size]),
buf_size_(max_read_size) {} buf_size_(max_read_size) { }
BrotliFileIn::~BrotliFileIn() { BrotliFileIn::~BrotliFileIn() {
if (buf_) free(buf_); delete[] buf_;
} }
const void* BrotliFileIn::Read(size_t n, size_t* bytes_read) { const void* BrotliFileIn::Read(size_t n, size_t* bytes_read) {
if (buf_ == NULL) {
*bytes_read = 0;
return NULL;
}
if (n > buf_size_) { if (n > buf_size_) {
n = buf_size_; n = buf_size_;
} else if (n == 0) { } else if (n == 0) {

View File

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

View File

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