| /* NOLINT(build/header_guard) */ | ||
| /* Copyright 2018 Google Inc. All Rights Reserved. | ||
| Distributed under MIT license. | ||
| See file LICENSE for detail or copy at https://opensource.org/licenses/MIT | ||
| */ | ||
| /* template parameters: FN, HASHER_A, HASHER_B */ | ||
| /* Composite hasher: This hasher allows to combine two other hashers, HASHER_A | ||
| and HASHER_B. */ | ||
| #define HashComposite HASHER() | ||
| #define FN_A(X) EXPAND_CAT(X, HASHER_A) | ||
| #define FN_B(X) EXPAND_CAT(X, HASHER_B) | ||
| static BROTLI_INLINE size_t FN(HashTypeLength)(void) { | ||
| size_t a = FN_A(HashTypeLength)(); | ||
| size_t b = FN_B(HashTypeLength)(); | ||
| return a > b ? a : b; | ||
| } | ||
| static BROTLI_INLINE size_t FN(StoreLookahead)(void) { | ||
| size_t a = FN_A(StoreLookahead)(); | ||
| size_t b = FN_B(StoreLookahead)(); | ||
| return a > b ? a : b; | ||
| } | ||
| typedef struct HashComposite { | ||
| HasherHandle ha; | ||
| HasherHandle hb; | ||
| const BrotliEncoderParams* params; | ||
| } HashComposite; | ||
| static BROTLI_INLINE HashComposite* FN(Self)(HasherHandle handle) { | ||
| return (HashComposite*)&(GetHasherCommon(handle)[1]); | ||
| } | ||
| static void FN(Initialize)( | ||
| HasherHandle handle, const BrotliEncoderParams* params) { | ||
| HashComposite* self = FN(Self)(handle); | ||
| self->ha = 0; | ||
| self->hb = 0; | ||
| self->params = params; | ||
| /* TODO: Initialize of the hashers is defered to Prepare (and params | ||
| remembered here) because we don't get the one_shot and input_size params | ||
| here that are needed to know the memory size of them. Instead provide | ||
| those params to all hashers FN(Initialize) */ | ||
| } | ||
| static void FN(Prepare)(HasherHandle handle, BROTLI_BOOL one_shot, | ||
| size_t input_size, const uint8_t* data) { | ||
| HashComposite* self = FN(Self)(handle); | ||
| if (!self->ha) { | ||
| HasherCommon* common_a; | ||
| HasherCommon* common_b; | ||
| self->ha = handle + sizeof(HasherCommon) + sizeof(HashComposite); | ||
| common_a = (HasherCommon*)self->ha; | ||
| common_a->params = self->params->hasher; | ||
| common_a->is_prepared_ = BROTLI_FALSE; | ||
| common_a->dict_num_lookups = 0; | ||
| common_a->dict_num_matches = 0; | ||
| FN_A(Initialize)(self->ha, self->params); | ||
| self->hb = self->ha + sizeof(HasherCommon) + FN_A(HashMemAllocInBytes)( | ||
| self->params, one_shot, input_size); | ||
| common_b = (HasherCommon*)self->hb; | ||
| common_b->params = self->params->hasher; | ||
| common_b->is_prepared_ = BROTLI_FALSE; | ||
| common_b->dict_num_lookups = 0; | ||
| common_b->dict_num_matches = 0; | ||
| FN_B(Initialize)(self->hb, self->params); | ||
| } | ||
| FN_A(Prepare)(self->ha, one_shot, input_size, data); | ||
| FN_B(Prepare)(self->hb, one_shot, input_size, data); | ||
| } | ||
| static BROTLI_INLINE size_t FN(HashMemAllocInBytes)( | ||
| const BrotliEncoderParams* params, BROTLI_BOOL one_shot, | ||
| size_t input_size) { | ||
| return sizeof(HashComposite) + 2 * sizeof(HasherCommon) + | ||
| FN_A(HashMemAllocInBytes)(params, one_shot, input_size) + | ||
| FN_B(HashMemAllocInBytes)(params, one_shot, input_size); | ||
| } | ||
| static BROTLI_INLINE void FN(Store)(HasherHandle BROTLI_RESTRICT handle, | ||
| const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { | ||
| HashComposite* self = FN(Self)(handle); | ||
| FN_A(Store)(self->ha, data, mask, ix); | ||
| FN_B(Store)(self->hb, data, mask, ix); | ||
| } | ||
| static BROTLI_INLINE void FN(StoreRange)(HasherHandle handle, | ||
| const uint8_t* data, const size_t mask, const size_t ix_start, | ||
| const size_t ix_end) { | ||
| HashComposite* self = FN(Self)(handle); | ||
| FN_A(StoreRange)(self->ha, data, mask, ix_start, ix_end); | ||
| FN_B(StoreRange)(self->hb, data, mask, ix_start, ix_end); | ||
| } | ||
| static BROTLI_INLINE void FN(StitchToPreviousBlock)(HasherHandle handle, | ||
| size_t num_bytes, size_t position, const uint8_t* ringbuffer, | ||
| size_t ring_buffer_mask) { | ||
| HashComposite* self = FN(Self)(handle); | ||
| FN_A(StitchToPreviousBlock)(self->ha, num_bytes, position, ringbuffer, | ||
| ring_buffer_mask); | ||
| FN_B(StitchToPreviousBlock)(self->hb, num_bytes, position, ringbuffer, | ||
| ring_buffer_mask); | ||
| } | ||
| static BROTLI_INLINE void FN(PrepareDistanceCache)( | ||
| HasherHandle handle, int* BROTLI_RESTRICT distance_cache) { | ||
| HashComposite* self = FN(Self)(handle); | ||
| FN_A(PrepareDistanceCache)(self->ha, distance_cache); | ||
| FN_B(PrepareDistanceCache)(self->hb, distance_cache); | ||
| } | ||
| static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle, | ||
| const BrotliEncoderDictionary* dictionary, | ||
| const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, | ||
| const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, | ||
| const size_t max_length, const size_t max_backward, const size_t gap, | ||
| const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) { | ||
| HashComposite* self = FN(Self)(handle); | ||
| FN_A(FindLongestMatch)(self->ha, dictionary, data, ring_buffer_mask, | ||
| distance_cache, cur_ix, max_length, max_backward, gap, max_distance, out); | ||
| FN_B(FindLongestMatch)(self->hb, dictionary, data, ring_buffer_mask, | ||
| distance_cache, cur_ix, max_length, max_backward, gap, max_distance, out); | ||
| } | ||
| #undef HashComposite |
| /* NOLINT(build/header_guard) */ | ||
| /* Copyright 2018 Google Inc. All Rights Reserved. | ||
| Distributed under MIT license. | ||
| See file LICENSE for detail or copy at https://opensource.org/licenses/MIT | ||
| */ | ||
| /* template parameters: FN, JUMP, NUMBUCKETS, MASK, CHUNKLEN */ | ||
| /* NUMBUCKETS / (MASK + 1) = probability of storing and using hash code. */ | ||
| /* JUMP = skip bytes for speedup */ | ||
| /* Rolling hash for long distance long string matches. Stores one position | ||
| per bucket, bucket key is computed over a long region. */ | ||
| #define HashRolling HASHER() | ||
| static const uint32_t FN(kRollingHashMul32) = 69069; | ||
| static const uint32_t FN(kInvalidPos) = 0xffffffff; | ||
| /* This hasher uses a longer forward length, but returning a higher value here | ||
| will hurt compression by the main hasher when combined with a composite | ||
| hasher. The hasher tests for forward itself instead. */ | ||
| static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; } | ||
| static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; } | ||
| /* Computes a code from a single byte. A lookup table of 256 values could be | ||
| used, but simply adding 1 works about as good. */ | ||
| static uint32_t FN(HashByte)(uint8_t byte) { | ||
| return (uint32_t)byte + 1u; | ||
| } | ||
| static uint32_t FN(HashRollingFunctionInitial)(uint32_t state, uint8_t add, | ||
| uint32_t factor) { | ||
| return (uint32_t)(factor * state + FN(HashByte)(add)); | ||
| } | ||
| static uint32_t FN(HashRollingFunction)(uint32_t state, uint8_t add, | ||
| uint8_t rem, uint32_t factor, | ||
| uint32_t factor_remove) { | ||
| return (uint32_t)(factor * state + | ||
| FN(HashByte)(add) - factor_remove * FN(HashByte)(rem)); | ||
| } | ||
| typedef struct HashRolling { | ||
| uint32_t state; | ||
| uint32_t* table; | ||
| size_t next_ix; | ||
| uint32_t chunk_len; | ||
| uint32_t factor; | ||
| uint32_t factor_remove; | ||
| } HashRolling; | ||
| static BROTLI_INLINE HashRolling* FN(Self)(HasherHandle handle) { | ||
| return (HashRolling*)&(GetHasherCommon(handle)[1]); | ||
| } | ||
| static void FN(Initialize)( | ||
| HasherHandle handle, const BrotliEncoderParams* params) { | ||
| HashRolling* self = FN(Self)(handle); | ||
| size_t i; | ||
| self->state = 0; | ||
| self->next_ix = 0; | ||
| self->factor = FN(kRollingHashMul32); | ||
| /* Compute the factor of the oldest byte to remove: factor**steps modulo | ||
| 0xffffffff (the multiplications rely on 32-bit overflow) */ | ||
| self->factor_remove = 1; | ||
| for (i = 0; i < CHUNKLEN; i += JUMP) { | ||
| self->factor_remove *= self->factor; | ||
| } | ||
| self->table = (uint32_t*)((HasherHandle)self + sizeof(HashRolling)); | ||
| for (i = 0; i < NUMBUCKETS; i++) { | ||
| self->table[i] = FN(kInvalidPos); | ||
| } | ||
| BROTLI_UNUSED(params); | ||
| } | ||
| static void FN(Prepare)(HasherHandle handle, BROTLI_BOOL one_shot, | ||
| size_t input_size, const uint8_t* data) { | ||
| HashRolling* self = FN(Self)(handle); | ||
| size_t i; | ||
| /* Too small size, cannot use this hasher. */ | ||
| if (input_size < CHUNKLEN) return; | ||
| self->state = 0; | ||
| for (i = 0; i < CHUNKLEN; i += JUMP) { | ||
| self->state = FN(HashRollingFunctionInitial)( | ||
| self->state, data[i], self->factor); | ||
| } | ||
| BROTLI_UNUSED(one_shot); | ||
| } | ||
| static BROTLI_INLINE size_t FN(HashMemAllocInBytes)( | ||
| const BrotliEncoderParams* params, BROTLI_BOOL one_shot, | ||
| size_t input_size) { | ||
| return sizeof(HashRolling) + NUMBUCKETS * sizeof(uint32_t); | ||
| BROTLI_UNUSED(params); | ||
| BROTLI_UNUSED(one_shot); | ||
| BROTLI_UNUSED(input_size); | ||
| } | ||
| static BROTLI_INLINE void FN(Store)(HasherHandle BROTLI_RESTRICT handle, | ||
| const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) { | ||
| BROTLI_UNUSED(handle); | ||
| BROTLI_UNUSED(data); | ||
| BROTLI_UNUSED(mask); | ||
| BROTLI_UNUSED(ix); | ||
| } | ||
| static BROTLI_INLINE void FN(StoreRange)(HasherHandle handle, | ||
| const uint8_t* data, const size_t mask, const size_t ix_start, | ||
| const size_t ix_end) { | ||
| BROTLI_UNUSED(handle); | ||
| BROTLI_UNUSED(data); | ||
| BROTLI_UNUSED(mask); | ||
| BROTLI_UNUSED(ix_start); | ||
| BROTLI_UNUSED(ix_end); | ||
| } | ||
| static BROTLI_INLINE void FN(StitchToPreviousBlock)(HasherHandle handle, | ||
| size_t num_bytes, size_t position, const uint8_t* ringbuffer, | ||
| size_t ring_buffer_mask) { | ||
| /* In this case we must re-initialize the hasher from scratch from the | ||
| current position. */ | ||
| HashRolling* self = FN(Self)(handle); | ||
| size_t position_masked; | ||
| size_t available = num_bytes; | ||
| if ((position & (JUMP - 1)) != 0) { | ||
| size_t diff = JUMP - (position & (JUMP - 1)); | ||
| available = (diff > available) ? 0 : (available - diff); | ||
| position += diff; | ||
| } | ||
| position_masked = position & ring_buffer_mask; | ||
| /* wrapping around ringbuffer not handled. */ | ||
| if (available > ring_buffer_mask - position_masked) { | ||
| available = ring_buffer_mask - position_masked; | ||
| } | ||
| FN(Prepare)(handle, BROTLI_FALSE, available, | ||
| ringbuffer + (position & ring_buffer_mask)); | ||
| self->next_ix = position; | ||
| BROTLI_UNUSED(num_bytes); | ||
| } | ||
| static BROTLI_INLINE void FN(PrepareDistanceCache)( | ||
| HasherHandle handle, int* BROTLI_RESTRICT distance_cache) { | ||
| BROTLI_UNUSED(handle); | ||
| BROTLI_UNUSED(distance_cache); | ||
| } | ||
| static BROTLI_INLINE void FN(FindLongestMatch)(HasherHandle handle, | ||
| const BrotliEncoderDictionary* dictionary, | ||
| const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask, | ||
| const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix, | ||
| const size_t max_length, const size_t max_backward, const size_t gap, | ||
| const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) { | ||
| HashRolling* self = FN(Self)(handle); | ||
| const size_t cur_ix_masked = cur_ix & ring_buffer_mask; | ||
| size_t pos = self->next_ix; | ||
| if ((cur_ix & (JUMP - 1)) != 0) return; | ||
| /* Not enough lookahead */ | ||
| if (max_length < CHUNKLEN) return; | ||
| for (pos = self->next_ix; pos <= cur_ix; pos += JUMP) { | ||
| uint32_t code = self->state & MASK; | ||
| uint8_t rem = data[pos & ring_buffer_mask]; | ||
| uint8_t add = data[(pos + CHUNKLEN) & ring_buffer_mask]; | ||
| size_t found_ix = FN(kInvalidPos); | ||
| self->state = FN(HashRollingFunction)( | ||
| self->state, add, rem, self->factor, self->factor_remove); | ||
| if (code < NUMBUCKETS) { | ||
| found_ix = self->table[code]; | ||
| self->table[code] = (uint32_t)pos; | ||
| if (pos == cur_ix && found_ix != FN(kInvalidPos)) { | ||
| /* The cast to 32-bit makes backward distances up to 4GB work even | ||
| if cur_ix is above 4GB, despite using 32-bit values in the table. */ | ||
| size_t backward = (uint32_t)(cur_ix - found_ix); | ||
| if (backward <= max_backward) { | ||
| const size_t found_ix_masked = found_ix & ring_buffer_mask; | ||
| const size_t len = FindMatchLengthWithLimit(&data[found_ix_masked], | ||
| &data[cur_ix_masked], | ||
| max_length); | ||
| if (len >= 4 && len > out->len) { | ||
| score_t score = BackwardReferenceScore(len, backward); | ||
| if (score > out->score) { | ||
| out->len = len; | ||
| out->distance = backward; | ||
| out->score = score; | ||
| out->len_code_delta = 0; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| self->next_ix = cur_ix + JUMP; | ||
| /* NOTE: this hasher does not search in the dictionary. It is used as | ||
| backup-hasher, the main hasher already searches in it. */ | ||
| BROTLI_UNUSED(dictionary); | ||
| BROTLI_UNUSED(distance_cache); | ||
| BROTLI_UNUSED(gap); | ||
| BROTLI_UNUSED(max_distance); | ||
| } | ||
| #undef HashRolling |
| #include "stream_decode_tasks.h" | ||
| void StartDecode(napi_env env, StreamDecode* obj) { | ||
| if (obj->isAsync) { | ||
| napi_value resource_name; | ||
| napi_create_string_utf8(env, "DecodeResource", NAPI_AUTO_LENGTH, &resource_name); | ||
| napi_create_async_work(env, | ||
| nullptr, | ||
| resource_name, | ||
| ExecuteDecode, | ||
| CompleteDecode, | ||
| obj, | ||
| &obj->work); | ||
| napi_queue_async_work(env, obj->work); | ||
| } else { | ||
| napi_status status = napi_ok; | ||
| ExecuteDecode(env, obj); | ||
| CompleteDecode(env, status, obj); | ||
| } | ||
| } | ||
| void ExecuteDecode(napi_env env, void* data) { | ||
| StreamDecode* obj = reinterpret_cast<StreamDecode*>(data); | ||
| BrotliDecoderResult res; | ||
| do { | ||
| size_t available_out = 0; | ||
| res = BrotliDecoderDecompressStream(obj->state, | ||
| &obj->available_in, | ||
| &obj->next_in, | ||
| &available_out, | ||
| NULL, | ||
| NULL); | ||
| if (res == BROTLI_DECODER_RESULT_ERROR) { | ||
| obj->hasError = true; | ||
| return; | ||
| } | ||
| while (BrotliDecoderHasMoreOutput(obj->state) == BROTLI_TRUE) { | ||
| size_t size = 0; | ||
| const uint8_t* output = BrotliDecoderTakeOutput(obj->state, &size); | ||
| void* buf = obj->alloc.Alloc(size); | ||
| if (!buf) { | ||
| obj->hasError = true; | ||
| return; | ||
| } | ||
| memcpy(buf, output, size); | ||
| obj->pending_output.push_back(static_cast<uint8_t*>(buf)); | ||
| } | ||
| } while (res == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT); | ||
| } | ||
| void CompleteDecode(napi_env env, napi_status, void* data) { | ||
| StreamDecode* obj = reinterpret_cast<StreamDecode*>(data); | ||
| napi_value null; | ||
| napi_get_null(env, &null); | ||
| napi_value cb; | ||
| napi_get_reference_value(env, obj->cbref, &cb); | ||
| if (obj->work != NULL) { | ||
| napi_delete_async_work(env, obj->work); | ||
| obj->work = NULL; | ||
| } | ||
| if (obj->bufref != NULL) { | ||
| napi_delete_reference(env, obj->bufref); | ||
| obj->bufref = NULL; | ||
| } | ||
| napi_delete_reference(env, obj->cbref); | ||
| if (obj->hasError) { | ||
| napi_value msg; | ||
| napi_create_string_utf8(env, "Brotli failed to decompress.", NAPI_AUTO_LENGTH, &msg); | ||
| napi_value err; | ||
| napi_create_error(env, NULL, msg, &err); | ||
| napi_value argv[] = {err}; | ||
| napi_call_function(env, null, cb, 1, argv, nullptr); | ||
| } else { | ||
| napi_value arr; | ||
| obj->PendingChunksAsArray(env, &arr); | ||
| napi_value argv[] = {null, arr}; | ||
| napi_call_function(env, null, cb, 2, argv, nullptr); | ||
| } | ||
| } |
| #ifndef STREAM_DECODE_WORKER_H | ||
| #define STREAM_DECODE_WORKER_H | ||
| #include <string.h> | ||
| #include <node_api.h> | ||
| #include "brotli/decode.h" | ||
| #include "stream_decode.h" | ||
| void StartDecode(napi_env env, StreamDecode* obj); | ||
| void ExecuteDecode(napi_env env, void* data); | ||
| void CompleteDecode(napi_env env, napi_status, void* data); | ||
| #endif |
| #include "stream_encode_tasks.h" | ||
| void StartEncode(napi_env env, StreamEncode* obj) { | ||
| if (obj->isAsync) { | ||
| napi_value resource_name; | ||
| napi_create_string_utf8(env, "EncodeResource", NAPI_AUTO_LENGTH, &resource_name); | ||
| napi_create_async_work(env, | ||
| nullptr, | ||
| resource_name, | ||
| ExecuteEncode, | ||
| CompleteEncode, | ||
| obj, | ||
| &obj->work); | ||
| napi_queue_async_work(env, obj->work); | ||
| } else { | ||
| napi_status status = napi_ok; | ||
| ExecuteEncode(env, obj); | ||
| CompleteEncode(env, status, obj); | ||
| } | ||
| } | ||
| void ExecuteEncode(napi_env env, void* data) { | ||
| StreamEncode* obj = reinterpret_cast<StreamEncode*>(data); | ||
| do { | ||
| size_t available_out = 0; | ||
| bool res = BrotliEncoderCompressStream(obj->state, | ||
| obj->op, | ||
| &obj->available_in, | ||
| &obj->next_in, | ||
| &available_out, | ||
| NULL, | ||
| NULL); | ||
| if (res == BROTLI_FALSE) { | ||
| obj->hasError = true; | ||
| return; | ||
| } | ||
| while (BrotliEncoderHasMoreOutput(obj->state) == BROTLI_TRUE) { | ||
| size_t size = 0; | ||
| const uint8_t* output = BrotliEncoderTakeOutput(obj->state, &size); | ||
| void* buf = obj->alloc.Alloc(size); | ||
| if (!buf) { | ||
| obj->hasError = true; | ||
| return; | ||
| } | ||
| memcpy(buf, output, size); | ||
| obj->pending_output.push_back(static_cast<uint8_t*>(buf)); | ||
| } | ||
| } while (obj->available_in > 0); | ||
| } | ||
| void CompleteEncode(napi_env env, napi_status, void* data) { | ||
| StreamEncode* obj = reinterpret_cast<StreamEncode*>(data); | ||
| napi_value null; | ||
| napi_get_null(env, &null); | ||
| napi_value cb; | ||
| napi_get_reference_value(env, obj->cbref, &cb); | ||
| if (obj->work != NULL) { | ||
| napi_delete_async_work(env, obj->work); | ||
| obj->work = NULL; | ||
| } | ||
| if (obj->bufref != NULL) { | ||
| napi_delete_reference(env, obj->bufref); | ||
| obj->bufref = NULL; | ||
| } | ||
| napi_delete_reference(env, obj->cbref); | ||
| if (obj->hasError) { | ||
| napi_value msg; | ||
| napi_create_string_utf8(env, "Brotli failed to compress.", NAPI_AUTO_LENGTH, &msg); | ||
| napi_value err; | ||
| napi_create_error(env, NULL, msg, &err); | ||
| napi_value argv[] = {err}; | ||
| napi_call_function(env, null, cb, 1, argv, nullptr); | ||
| } else { | ||
| napi_value arr; | ||
| obj->PendingChunksAsArray(env, &arr); | ||
| napi_value argv[] = {null, arr}; | ||
| napi_call_function(env, null, cb, 2, argv, nullptr); | ||
| } | ||
| } |
| #ifndef STREAM_ENCODE_WORKER_H | ||
| #define STREAM_ENCODE_WORKER_H | ||
| #include <string.h> | ||
| #include <node_api.h> | ||
| #include "brotli/encode.h" | ||
| #include "stream_encode.h" | ||
| void StartEncode(napi_env env, StreamEncode* obj); | ||
| void ExecuteEncode(napi_env env, void* data); | ||
| void CompleteEncode(napi_env env, napi_status, void* data); | ||
| #endif |
+169
-107
@@ -7,4 +7,18 @@ /* Copyright 2016 Google Inc. All Rights Reserved. | ||
| /* Macros for compiler / platform specific features and build options. */ | ||
| /* Macros for compiler / platform specific features and build options. | ||
| Build options are: | ||
| * BROTLI_BUILD_32_BIT disables 64-bit optimizations | ||
| * BROTLI_BUILD_64_BIT forces to use 64-bit optimizations | ||
| * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations | ||
| * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations | ||
| * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations | ||
| * BROTLI_BUILD_PORTABLE disables dangerous optimizations, like unaligned | ||
| read and overlapping memcpy; this reduces decompression speed by 5% | ||
| * BROTLI_BUILD_NO_RBIT disables "rbit" optimization for ARM CPUs | ||
| * BROTLI_DEBUG dumps file name and line number when decoder detects stream | ||
| or memory error | ||
| * BROTLI_ENABLE_LOG enables asserts and dumps various state information | ||
| */ | ||
| #ifndef BROTLI_COMMON_PLATFORM_H_ | ||
@@ -19,7 +33,7 @@ #define BROTLI_COMMON_PLATFORM_H_ | ||
| #if defined OS_LINUX || defined OS_CYGWIN | ||
| #if defined(OS_LINUX) || defined(OS_CYGWIN) | ||
| #include <endian.h> | ||
| #elif defined OS_FREEBSD | ||
| #elif defined(OS_FREEBSD) | ||
| #include <machine/endian.h> | ||
| #elif defined OS_MACOSX | ||
| #elif defined(OS_MACOSX) | ||
| #include <machine/endian.h> | ||
@@ -37,67 +51,134 @@ /* Let's try and follow the Linux convention */ | ||
| /* Macros for compiler / platform specific features and build options. | ||
| /* The following macros were borrowed from https://github.com/nemequ/hedley | ||
| * with permission of original author - Evan Nemerson <evan@nemerson.com> */ | ||
| Build options are: | ||
| * BROTLI_BUILD_32_BIT disables 64-bit optimizations | ||
| * BROTLI_BUILD_64_BIT forces to use 64-bit optimizations | ||
| * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations | ||
| * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations | ||
| * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations | ||
| * BROTLI_BUILD_PORTABLE disables dangerous optimizations, like unaligned | ||
| read and overlapping memcpy; this reduces decompression speed by 5% | ||
| * BROTLI_BUILD_NO_RBIT disables "rbit" optimization for ARM CPUs | ||
| * BROTLI_DEBUG dumps file name and line number when decoder detects stream | ||
| or memory error | ||
| * BROTLI_ENABLE_LOG enables asserts and dumps various state information | ||
| /* >>> >>> >>> hedley macros */ | ||
| /* Define "BROTLI_PREDICT_TRUE" and "BROTLI_PREDICT_FALSE" macros for capable | ||
| compilers. | ||
| To apply compiler hint, enclose the branching condition into macros, like this: | ||
| if (BROTLI_PREDICT_TRUE(zero == 0)) { | ||
| // main execution path | ||
| } else { | ||
| // compiler should place this code outside of main execution path | ||
| } | ||
| OR: | ||
| if (BROTLI_PREDICT_FALSE(something_rare_or_unexpected_happens)) { | ||
| // compiler should place this code outside of main execution path | ||
| } | ||
| */ | ||
| #if BROTLI_MODERN_COMPILER || __has_attribute(always_inline) | ||
| #define BROTLI_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline)) | ||
| #if BROTLI_GNUC_HAS_BUILTIN(__builtin_expect, 3, 0, 0) || \ | ||
| BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ | ||
| BROTLI_SUNPRO_VERSION_CHECK(5, 12, 0) || \ | ||
| BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ | ||
| BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \ | ||
| BROTLI_TI_VERSION_CHECK(7, 3, 0) || \ | ||
| BROTLI_TINYC_VERSION_CHECK(0, 9, 27) | ||
| #define BROTLI_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) | ||
| #define BROTLI_PREDICT_FALSE(x) (__builtin_expect(x, 0)) | ||
| #else | ||
| #define BROTLI_ATTRIBUTE_ALWAYS_INLINE | ||
| #define BROTLI_PREDICT_FALSE(x) (x) | ||
| #define BROTLI_PREDICT_TRUE(x) (x) | ||
| #endif | ||
| #if defined(_WIN32) || defined(__CYGWIN__) | ||
| #define BROTLI_ATTRIBUTE_VISIBILITY_HIDDEN | ||
| #elif BROTLI_MODERN_COMPILER || __has_attribute(visibility) | ||
| #define BROTLI_ATTRIBUTE_VISIBILITY_HIDDEN \ | ||
| __attribute__ ((visibility ("hidden"))) | ||
| #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ | ||
| !defined(__cplusplus) | ||
| #define BROTLI_RESTRICT restrict | ||
| #elif BROTLI_GNUC_VERSION_CHECK(3, 1, 0) || \ | ||
| BROTLI_MSVC_VERSION_CHECK(14, 0, 0) || \ | ||
| BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ | ||
| BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ | ||
| BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \ | ||
| BROTLI_PGI_VERSION_CHECK(17, 10, 0) || \ | ||
| BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ | ||
| BROTLI_IAR_VERSION_CHECK(8, 0, 0) || \ | ||
| (BROTLI_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus)) | ||
| #define BROTLI_RESTRICT __restrict | ||
| #elif BROTLI_SUNPRO_VERSION_CHECK(5, 3, 0) && !defined(__cplusplus) | ||
| #define BROTLI_RESTRICT _Restrict | ||
| #else | ||
| #define BROTLI_ATTRIBUTE_VISIBILITY_HIDDEN | ||
| #define BROTLI_RESTRICT | ||
| #endif | ||
| #ifndef BROTLI_INTERNAL | ||
| #define BROTLI_INTERNAL BROTLI_ATTRIBUTE_VISIBILITY_HIDDEN | ||
| #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ | ||
| (defined(__cplusplus) && (__cplusplus >= 199711L)) | ||
| #define BROTLI_MAYBE_INLINE inline | ||
| #elif defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__) || \ | ||
| BROTLI_ARM_VERSION_CHECK(6, 2, 0) | ||
| #define BROTLI_MAYBE_INLINE __inline__ | ||
| #elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0) || \ | ||
| BROTLI_ARM_VERSION_CHECK(4, 1, 0) || BROTLI_TI_VERSION_CHECK(8, 0, 0) | ||
| #define BROTLI_MAYBE_INLINE __inline | ||
| #else | ||
| #define BROTLI_MAYBE_INLINE | ||
| #endif | ||
| #ifndef _MSC_VER | ||
| #if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ | ||
| (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) | ||
| #define BROTLI_INLINE inline BROTLI_ATTRIBUTE_ALWAYS_INLINE | ||
| #if BROTLI_GNUC_HAS_ATTRIBUTE(always_inline, 4, 0, 0) || \ | ||
| BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ | ||
| BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \ | ||
| BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ | ||
| BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \ | ||
| BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ | ||
| (BROTLI_TI_VERSION_CHECK(7, 3, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) | ||
| #define BROTLI_INLINE BROTLI_MAYBE_INLINE __attribute__((__always_inline__)) | ||
| #elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0) | ||
| #define BROTLI_INLINE BROTLI_MAYBE_INLINE __forceinline | ||
| #elif BROTLI_TI_VERSION_CHECK(7, 0, 0) && defined(__cplusplus) | ||
| #define BROTLI_INLINE BROTLI_MAYBE_INLINE _Pragma("FUNC_ALWAYS_INLINE;") | ||
| #elif BROTLI_IAR_VERSION_CHECK(8, 0, 0) | ||
| #define BROTLI_INLINE BROTLI_MAYBE_INLINE _Pragma("inline=forced") | ||
| #else | ||
| #define BROTLI_INLINE | ||
| #define BROTLI_INLINE BROTLI_MAYBE_INLINE | ||
| #endif | ||
| #else /* _MSC_VER */ | ||
| #define BROTLI_INLINE __forceinline | ||
| #endif /* _MSC_VER */ | ||
| #if BROTLI_MODERN_COMPILER || __has_attribute(unused) | ||
| #define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE __attribute__ ((unused)) | ||
| #if BROTLI_GNUC_HAS_ATTRIBUTE(noinline, 4, 0, 0) || \ | ||
| BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ | ||
| BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \ | ||
| BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ | ||
| BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \ | ||
| BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ | ||
| (BROTLI_TI_VERSION_CHECK(7, 3, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) | ||
| #define BROTLI_NOINLINE __attribute__((__noinline__)) | ||
| #elif BROTLI_MSVC_VERSION_CHECK(13, 10, 0) | ||
| #define BROTLI_NOINLINE __declspec(noinline) | ||
| #elif BROTLI_PGI_VERSION_CHECK(10, 2, 0) | ||
| #define BROTLI_NOINLINE _Pragma("noinline") | ||
| #elif BROTLI_TI_VERSION_CHECK(6, 0, 0) && defined(__cplusplus) | ||
| #define BROTLI_NOINLINE _Pragma("FUNC_CANNOT_INLINE;") | ||
| #elif BROTLI_IAR_VERSION_CHECK(8, 0, 0) | ||
| #define BROTLI_NOINLINE _Pragma("inline=never") | ||
| #else | ||
| #define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE | ||
| #define BROTLI_NOINLINE | ||
| #endif | ||
| #if !defined(__cplusplus) && !defined(c_plusplus) && \ | ||
| (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) | ||
| #define BROTLI_RESTRICT restrict | ||
| #elif BROTLI_GCC_VERSION > 295 || defined(__llvm__) | ||
| #define BROTLI_RESTRICT __restrict | ||
| /* BROTLI_INTERNAL could be defined to override visibility, e.g. for tests. */ | ||
| #if !defined(BROTLI_INTERNAL) | ||
| #if defined(_WIN32) || defined(__CYGWIN__) | ||
| #define BROTLI_INTERNAL | ||
| #elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) || \ | ||
| BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ | ||
| BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ | ||
| BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ | ||
| BROTLI_IBM_VERSION_CHECK(13, 1, 0) || \ | ||
| BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \ | ||
| (BROTLI_TI_VERSION_CHECK(7, 3, 0) && \ | ||
| defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__)) | ||
| #define BROTLI_INTERNAL __attribute__ ((visibility ("hidden"))) | ||
| #else | ||
| #define BROTLI_RESTRICT | ||
| #define BROTLI_INTERNAL | ||
| #endif | ||
| #endif | ||
| #if BROTLI_MODERN_COMPILER || __has_attribute(noinline) | ||
| #define BROTLI_NOINLINE __attribute__((noinline)) | ||
| /* <<< <<< <<< end of hedley macros. */ | ||
| #if BROTLI_GNUC_HAS_ATTRIBUTE(unused, 2, 7, 0) || \ | ||
| BROTLI_INTEL_VERSION_CHECK(16, 0, 0) | ||
| #define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE __attribute__ ((unused)) | ||
| #else | ||
| #define BROTLI_NOINLINE | ||
| #define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE | ||
| #endif | ||
@@ -127,2 +208,6 @@ | ||
| #if defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64 | ||
| #define BROTLI_TARGET_RISCV64 | ||
| #endif | ||
| #if defined(BROTLI_BUILD_64_BIT) | ||
@@ -133,3 +218,3 @@ #define BROTLI_64_BITS 1 | ||
| #elif defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8) || \ | ||
| defined(BROTLI_TARGET_POWERPC64) | ||
| defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64) | ||
| #define BROTLI_64_BITS 1 | ||
@@ -175,3 +260,3 @@ #else | ||
| #ifdef BROTLI_X_BYTE_ORDER | ||
| #if defined(BROTLI_X_BYTE_ORDER) | ||
| #undef BROTLI_X_BYTE_ORDER | ||
@@ -182,6 +267,7 @@ #undef BROTLI_X_LITTLE_ENDIAN | ||
| #ifdef BROTLI_BUILD_PORTABLE | ||
| #if defined(BROTLI_BUILD_PORTABLE) | ||
| #define BROTLI_ALIGNED_READ (!!1) | ||
| #elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \ | ||
| defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8) | ||
| defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8) || \ | ||
| defined(BROTLI_TARGET_RISCV64) | ||
| /* Allow unaligned read only for white-listed CPUs. */ | ||
@@ -316,30 +402,5 @@ #define BROTLI_ALIGNED_READ (!!0) | ||
| /* Define "BROTLI_PREDICT_TRUE" and "BROTLI_PREDICT_FALSE" macros for capable | ||
| compilers. | ||
| To apply compiler hint, enclose the branching condition into macros, like this: | ||
| if (BROTLI_PREDICT_TRUE(zero == 0)) { | ||
| // main execution path | ||
| } else { | ||
| // compiler should place this code outside of main execution path | ||
| } | ||
| OR: | ||
| if (BROTLI_PREDICT_FALSE(something_rare_or_unexpected_happens)) { | ||
| // compiler should place this code outside of main execution path | ||
| } | ||
| */ | ||
| #if BROTLI_MODERN_COMPILER || __has_builtin(__builtin_expect) | ||
| #define BROTLI_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) | ||
| #define BROTLI_PREDICT_FALSE(x) (__builtin_expect(x, 0)) | ||
| #else | ||
| #define BROTLI_PREDICT_FALSE(x) (x) | ||
| #define BROTLI_PREDICT_TRUE(x) (x) | ||
| #endif | ||
| /* BROTLI_IS_CONSTANT macros returns true for compile-time constants. */ | ||
| #if BROTLI_MODERN_COMPILER || __has_builtin(__builtin_constant_p) | ||
| #if BROTLI_GNUC_HAS_BUILTIN(__builtin_constant_p, 3, 0, 1) || \ | ||
| BROTLI_INTEL_VERSION_CHECK(16, 0, 0) | ||
| #define BROTLI_IS_CONSTANT(x) (!!__builtin_constant_p(x)) | ||
@@ -356,3 +417,3 @@ #else | ||
| #ifdef BROTLI_ENABLE_LOG | ||
| #if defined(BROTLI_ENABLE_LOG) | ||
| #define BROTLI_DCHECK(x) assert(x) | ||
@@ -375,3 +436,4 @@ #define BROTLI_LOG(x) printf x | ||
| #if (BROTLI_MODERN_COMPILER || defined(__llvm__)) && \ | ||
| /* TODO: add appropriate icc/sunpro/arm/ibm/ti checks. */ | ||
| #if (BROTLI_GNUC_VERSION_CHECK(3, 0, 0) || defined(__llvm__)) && \ | ||
| !defined(BROTLI_BUILD_NO_RBIT) | ||
@@ -428,28 +490,28 @@ #if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8) | ||
| BROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) { | ||
| BROTLI_UNUSED(BrotliSuppressUnusedFunctions); | ||
| BROTLI_UNUSED(BrotliUnalignedRead16); | ||
| BROTLI_UNUSED(BrotliUnalignedRead32); | ||
| BROTLI_UNUSED(BrotliUnalignedRead64); | ||
| BROTLI_UNUSED(BrotliUnalignedWrite64); | ||
| BROTLI_UNUSED(BROTLI_UNALIGNED_LOAD16LE); | ||
| BROTLI_UNUSED(BROTLI_UNALIGNED_LOAD32LE); | ||
| BROTLI_UNUSED(BROTLI_UNALIGNED_LOAD64LE); | ||
| BROTLI_UNUSED(BROTLI_UNALIGNED_STORE64LE); | ||
| BROTLI_UNUSED(BrotliRBit); | ||
| BROTLI_UNUSED(brotli_min_double); | ||
| BROTLI_UNUSED(brotli_max_double); | ||
| BROTLI_UNUSED(brotli_min_float); | ||
| BROTLI_UNUSED(brotli_max_float); | ||
| BROTLI_UNUSED(brotli_min_int); | ||
| BROTLI_UNUSED(brotli_max_int); | ||
| BROTLI_UNUSED(brotli_min_size_t); | ||
| BROTLI_UNUSED(brotli_max_size_t); | ||
| BROTLI_UNUSED(brotli_min_uint32_t); | ||
| BROTLI_UNUSED(brotli_max_uint32_t); | ||
| BROTLI_UNUSED(brotli_min_uint8_t); | ||
| BROTLI_UNUSED(brotli_max_uint8_t); | ||
| BROTLI_UNUSED(BrotliDefaultAllocFunc); | ||
| BROTLI_UNUSED(BrotliDefaultFreeFunc); | ||
| BROTLI_UNUSED(&BrotliSuppressUnusedFunctions); | ||
| BROTLI_UNUSED(&BrotliUnalignedRead16); | ||
| BROTLI_UNUSED(&BrotliUnalignedRead32); | ||
| BROTLI_UNUSED(&BrotliUnalignedRead64); | ||
| BROTLI_UNUSED(&BrotliUnalignedWrite64); | ||
| BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD16LE); | ||
| BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD32LE); | ||
| BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD64LE); | ||
| BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE64LE); | ||
| BROTLI_UNUSED(&BrotliRBit); | ||
| BROTLI_UNUSED(&brotli_min_double); | ||
| BROTLI_UNUSED(&brotli_max_double); | ||
| BROTLI_UNUSED(&brotli_min_float); | ||
| BROTLI_UNUSED(&brotli_max_float); | ||
| BROTLI_UNUSED(&brotli_min_int); | ||
| BROTLI_UNUSED(&brotli_max_int); | ||
| BROTLI_UNUSED(&brotli_min_size_t); | ||
| BROTLI_UNUSED(&brotli_max_size_t); | ||
| BROTLI_UNUSED(&brotli_min_uint32_t); | ||
| BROTLI_UNUSED(&brotli_max_uint32_t); | ||
| BROTLI_UNUSED(&brotli_min_uint8_t); | ||
| BROTLI_UNUSED(&brotli_max_uint8_t); | ||
| BROTLI_UNUSED(&BrotliDefaultAllocFunc); | ||
| BROTLI_UNUSED(&BrotliDefaultFreeFunc); | ||
| #if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG) | ||
| BROTLI_UNUSED(BrotliDump); | ||
| BROTLI_UNUSED(&BrotliDump); | ||
| #endif | ||
@@ -456,0 +518,0 @@ } |
@@ -7,3 +7,2 @@ /* Copyright 2013 Google Inc. All Rights Reserved. | ||
| #include "./platform.h" | ||
| #include "./transform.h" | ||
@@ -196,3 +195,3 @@ | ||
| int BrotliTransformDictionaryWord(uint8_t* dst, const uint8_t* word, int len, | ||
| const BrotliTransforms* BROTLI_RESTRICT transforms, int transfom_idx) { | ||
| const BrotliTransforms* transforms, int transfom_idx) { | ||
| int idx = 0; | ||
@@ -199,0 +198,0 @@ const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, transfom_idx); |
@@ -17,3 +17,3 @@ /* Copyright 2016 Google Inc. All Rights Reserved. | ||
| /* Semantic version, calculated as (MAJOR << 24) | (MINOR << 12) | PATCH */ | ||
| #define BROTLI_VERSION 0x1000004 | ||
| #define BROTLI_VERSION 0x1000005 | ||
@@ -25,4 +25,4 @@ /* This macro is used by build system to produce Libtool-friendly soname. See | ||
| /* ABI version, calculated as (CURRENT << 24) | (REVISION << 12) | AGE */ | ||
| #define BROTLI_ABI_VERSION 0x1004000 | ||
| #define BROTLI_ABI_VERSION 0x1005000 | ||
| #endif /* BROTLI_COMMON_VERSION_H_ */ |
@@ -241,3 +241,3 @@ /* Copyright 2013 Google Inc. All Rights Reserved. | ||
| BROTLI_LOG(("[BrotliReadBits] %d %d %d val: %6x\n", | ||
| (int)br->avail_in, (int)br->bit_pos_, n_bits, (int)*val)); | ||
| (int)br->avail_in, (int)br->bit_pos_, (int)n_bits, (int)*val)); | ||
| BrotliDropBits(br, n_bits); | ||
@@ -244,0 +244,0 @@ } |
@@ -23,3 +23,3 @@ /* Copyright 2013 Google Inc. All Rights Reserved. | ||
| #ifdef BROTLI_RBIT | ||
| #if defined(BROTLI_RBIT) | ||
| #define BROTLI_REVERSE_BITS_BASE \ | ||
@@ -72,3 +72,3 @@ ((sizeof(brotli_reg_t) << 3) - BROTLI_REVERSE_BITS_MAX) | ||
| static BROTLI_INLINE brotli_reg_t BrotliReverseBits(brotli_reg_t num) { | ||
| #ifdef BROTLI_RBIT | ||
| #if defined(BROTLI_RBIT) | ||
| return BROTLI_RBIT(num); | ||
@@ -75,0 +75,0 @@ #else |
@@ -100,2 +100,17 @@ /* Copyright 2013 Google Inc. All Rights Reserved. | ||
| #define HASHER() H35 | ||
| /* NOLINTNEXTLINE(build/include) */ | ||
| #include "./backward_references_inc.h" | ||
| #undef HASHER | ||
| #define HASHER() H55 | ||
| /* NOLINTNEXTLINE(build/include) */ | ||
| #include "./backward_references_inc.h" | ||
| #undef HASHER | ||
| #define HASHER() H65 | ||
| /* NOLINTNEXTLINE(build/include) */ | ||
| #include "./backward_references_inc.h" | ||
| #undef HASHER | ||
| #undef PREFIX | ||
@@ -102,0 +117,0 @@ |
@@ -76,4 +76,5 @@ /* Copyright 2014 Google Inc. All Rights Reserved. | ||
| BROTLI_INTERNAL void BrotliStoreUncompressedMetaBlock( | ||
| BROTLI_BOOL is_final_block, const uint8_t* input, size_t position, | ||
| size_t mask, size_t len, size_t* storage_ix, uint8_t* storage); | ||
| BROTLI_BOOL is_final_block, const uint8_t* BROTLI_RESTRICT input, | ||
| size_t position, size_t mask, size_t len, | ||
| size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage); | ||
@@ -80,0 +81,0 @@ #if defined(__cplusplus) || defined(c_plusplus) |
@@ -65,9 +65,9 @@ /* Copyright 2013 Google Inc. All Rights Reserved. | ||
| uint16_t bits64 = | ||
| (uint16_t)((copycode & 0x7u) | ((inscode & 0x7u) << 3)); | ||
| if (use_last_distance && inscode < 8 && copycode < 16) { | ||
| return (copycode < 8) ? bits64 : (bits64 | 64); | ||
| (uint16_t)((copycode & 0x7u) | ((inscode & 0x7u) << 3u)); | ||
| if (use_last_distance && inscode < 8u && copycode < 16u) { | ||
| return (copycode < 8u) ? bits64 : (bits64 | 64u); | ||
| } else { | ||
| /* Specification: 5 Encoding of ... (last table) */ | ||
| /* offset = 2 * index, where index is in range [0..8] */ | ||
| int offset = 2 * ((copycode >> 3) + 3 * (inscode >> 3)); | ||
| uint32_t offset = 2u * ((copycode >> 3u) + 3u * (inscode >> 3u)); | ||
| /* All values in specification are K * 64, | ||
@@ -79,4 +79,4 @@ where K = [2, 3, 6, 4, 5, 8, 7, 9, 10], | ||
| Magic constant is shifted 6 bits left, to avoid final multiplication. */ | ||
| offset = (offset << 5) + 0x40 + ((0x520D40 >> offset) & 0xC0); | ||
| return (uint16_t)offset | bits64; | ||
| offset = (offset << 5u) + 0x40u + ((0x520D40u >> offset) & 0xC0u); | ||
| return (uint16_t)(offset | bits64); | ||
| } | ||
@@ -83,0 +83,0 @@ } |
@@ -42,13 +42,14 @@ /* Copyright 2015 Google Inc. All Rights Reserved. | ||
| static BROTLI_INLINE uint32_t Hash(const uint8_t* p, size_t shift) { | ||
| const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(p) << 16) * kHashMul32; | ||
| static BROTLI_INLINE uint32_t Hash(const uint8_t* p, | ||
| size_t shift, size_t length) { | ||
| const uint64_t h = | ||
| (BROTLI_UNALIGNED_LOAD64LE(p) << ((8 - length) * 8)) * kHashMul32; | ||
| return (uint32_t)(h >> shift); | ||
| } | ||
| static BROTLI_INLINE uint32_t HashBytesAtOffset( | ||
| uint64_t v, int offset, size_t shift) { | ||
| BROTLI_DCHECK(offset >= 0); | ||
| BROTLI_DCHECK(offset <= 2); | ||
| static BROTLI_INLINE uint32_t HashBytesAtOffset(uint64_t v, size_t offset, | ||
| size_t shift, size_t length) { | ||
| BROTLI_DCHECK(offset <= 8 - length); | ||
| { | ||
| const uint64_t h = ((v >> (8 * offset)) << 16) * kHashMul32; | ||
| const uint64_t h = ((v >> (8 * offset)) << ((8 - length) * 8)) * kHashMul32; | ||
| return (uint32_t)(h >> shift); | ||
@@ -58,7 +59,9 @@ } | ||
| static BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2) { | ||
| return TO_BROTLI_BOOL( | ||
| BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2) && | ||
| p1[4] == p2[4] && | ||
| p1[5] == p2[5]); | ||
| static BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2, | ||
| size_t length) { | ||
| if (BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2)) { | ||
| if (length == 4) return BROTLI_TRUE; | ||
| return TO_BROTLI_BOOL(p1[4] == p2[4] && p1[5] == p2[5]); | ||
| } | ||
| return BROTLI_FALSE; | ||
| } | ||
@@ -240,3 +243,4 @@ | ||
| size_t block_size, size_t input_size, const uint8_t* base_ip, int* table, | ||
| size_t table_bits, uint8_t** literals, uint32_t** commands) { | ||
| size_t table_bits, size_t min_match, | ||
| uint8_t** literals, uint32_t** commands) { | ||
| /* "ip" is the input pointer. */ | ||
@@ -253,3 +257,2 @@ const uint8_t* ip = input; | ||
| const size_t kInputMarginBytes = BROTLI_WINDOW_GAP; | ||
| const size_t kMinMatchLen = 6; | ||
@@ -261,3 +264,3 @@ if (BROTLI_PREDICT_TRUE(block_size >= kInputMarginBytes)) { | ||
| we don't go over the block size with a copy. */ | ||
| const size_t len_limit = BROTLI_MIN(size_t, block_size - kMinMatchLen, | ||
| const size_t len_limit = BROTLI_MIN(size_t, block_size - min_match, | ||
| input_size - kInputMarginBytes); | ||
@@ -267,3 +270,3 @@ const uint8_t* ip_limit = input + len_limit; | ||
| uint32_t next_hash; | ||
| for (next_hash = Hash(++ip, shift); ; ) { | ||
| for (next_hash = Hash(++ip, shift, min_match); ; ) { | ||
| /* Step 1: Scan forward in the input looking for a 6-byte-long match. | ||
@@ -295,3 +298,3 @@ If we get close to exhausting the input then goto emit_remainder. | ||
| ip = next_ip; | ||
| BROTLI_DCHECK(hash == Hash(ip, shift)); | ||
| BROTLI_DCHECK(hash == Hash(ip, shift, min_match)); | ||
| next_ip = ip + bytes_between_hash_lookups; | ||
@@ -301,5 +304,5 @@ if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) { | ||
| } | ||
| next_hash = Hash(next_ip, shift); | ||
| next_hash = Hash(next_ip, shift, min_match); | ||
| candidate = ip - last_distance; | ||
| if (IsMatch(ip, candidate)) { | ||
| if (IsMatch(ip, candidate, min_match)) { | ||
| if (BROTLI_PREDICT_TRUE(candidate < ip)) { | ||
@@ -315,3 +318,3 @@ table[hash] = (int)(ip - base_ip); | ||
| table[hash] = (int)(ip - base_ip); | ||
| } while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate))); | ||
| } while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate, min_match))); | ||
@@ -331,4 +334,5 @@ /* Check copy distance. If candidate is not feasible, continue search. | ||
| const uint8_t* base = ip; | ||
| size_t matched = 6 + FindMatchLengthWithLimit( | ||
| candidate + 6, ip + 6, (size_t)(ip_end - ip) - 6); | ||
| size_t matched = min_match + FindMatchLengthWithLimit( | ||
| candidate + min_match, ip + min_match, | ||
| (size_t)(ip_end - ip) - min_match); | ||
| int distance = (int)(base - candidate); /* > 0 */ | ||
@@ -358,16 +362,29 @@ int insert = (int)(base - next_emit); | ||
| positions within the last copy. */ | ||
| uint64_t input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5); | ||
| uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift); | ||
| uint64_t input_bytes; | ||
| uint32_t cur_hash; | ||
| table[prev_hash] = (int)(ip - base_ip - 5); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 1, shift); | ||
| table[prev_hash] = (int)(ip - base_ip - 4); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 2, shift); | ||
| table[prev_hash] = (int)(ip - base_ip - 3); | ||
| input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2); | ||
| cur_hash = HashBytesAtOffset(input_bytes, 2, shift); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 0, shift); | ||
| table[prev_hash] = (int)(ip - base_ip - 2); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 1, shift); | ||
| table[prev_hash] = (int)(ip - base_ip - 1); | ||
| uint32_t prev_hash; | ||
| if (min_match == 4) { | ||
| input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3); | ||
| cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 3); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 2); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 1); | ||
| } else { | ||
| input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 5); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 4); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 3); | ||
| input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2); | ||
| cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 2); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 1); | ||
| } | ||
@@ -379,8 +396,10 @@ candidate = base_ip + table[cur_hash]; | ||
| while (ip - candidate <= MAX_DISTANCE && IsMatch(ip, candidate)) { | ||
| while (ip - candidate <= MAX_DISTANCE && | ||
| IsMatch(ip, candidate, min_match)) { | ||
| /* We have a 6-byte match at ip, and no need to emit any | ||
| literal bytes prior to ip. */ | ||
| const uint8_t* base = ip; | ||
| size_t matched = 6 + FindMatchLengthWithLimit( | ||
| candidate + 6, ip + 6, (size_t)(ip_end - ip) - 6); | ||
| size_t matched = min_match + FindMatchLengthWithLimit( | ||
| candidate + min_match, ip + min_match, | ||
| (size_t)(ip_end - ip) - min_match); | ||
| ip += matched; | ||
@@ -400,16 +419,29 @@ last_distance = (int)(base - candidate); /* > 0 */ | ||
| positions within the last copy. */ | ||
| uint64_t input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5); | ||
| uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift); | ||
| uint64_t input_bytes; | ||
| uint32_t cur_hash; | ||
| table[prev_hash] = (int)(ip - base_ip - 5); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 1, shift); | ||
| table[prev_hash] = (int)(ip - base_ip - 4); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 2, shift); | ||
| table[prev_hash] = (int)(ip - base_ip - 3); | ||
| input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2); | ||
| cur_hash = HashBytesAtOffset(input_bytes, 2, shift); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 0, shift); | ||
| table[prev_hash] = (int)(ip - base_ip - 2); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 1, shift); | ||
| table[prev_hash] = (int)(ip - base_ip - 1); | ||
| uint32_t prev_hash; | ||
| if (min_match == 4) { | ||
| input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3); | ||
| cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 3); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 2); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 1); | ||
| } else { | ||
| input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 5); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 4); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 3); | ||
| input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2); | ||
| cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 2); | ||
| prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match); | ||
| table[prev_hash] = (int)(ip - base_ip - 1); | ||
| } | ||
@@ -421,3 +453,3 @@ candidate = base_ip + table[cur_hash]; | ||
| next_hash = Hash(++ip, shift); | ||
| next_hash = Hash(++ip, shift, min_match); | ||
| } | ||
@@ -542,3 +574,4 @@ } | ||
| BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf, | ||
| int* table, size_t table_bits, size_t* storage_ix, uint8_t* storage) { | ||
| int* table, size_t table_bits, size_t min_match, | ||
| size_t* storage_ix, uint8_t* storage) { | ||
| /* Save the start of the first block for position and distance computations. | ||
@@ -555,4 +588,4 @@ */ | ||
| size_t num_literals; | ||
| CreateCommands(input, block_size, input_size, base_ip, table, table_bits, | ||
| &literals, &commands); | ||
| CreateCommands(input, block_size, input_size, base_ip, table, | ||
| table_bits, min_match, &literals, &commands); | ||
| num_literals = (size_t)(literals - literal_buf); | ||
@@ -586,4 +619,5 @@ if (ShouldCompress(input, block_size, num_literals)) { | ||
| int* table, size_t* storage_ix, uint8_t* storage) { \ | ||
| size_t min_match = (B <= 15) ? 4 : 6; \ | ||
| BrotliCompressFragmentTwoPassImpl(m, input, input_size, is_last, command_buf,\ | ||
| literal_buf, table, B, storage_ix, storage); \ | ||
| literal_buf, table, B, min_match, storage_ix, storage); \ | ||
| } | ||
@@ -590,0 +624,0 @@ FOR_TABLE_BITS_(BAKE_METHOD_PARAM_) |
@@ -205,3 +205,3 @@ /* Copyright 2015 Google Inc. All Rights Reserved. | ||
| BrotliWriteBits(12, insertlen - 2114, storage_ix, storage); | ||
| ++histo[21]; | ||
| ++histo[61]; | ||
| } | ||
@@ -219,7 +219,7 @@ } | ||
| BrotliWriteBits(14, insertlen - 6210, storage_ix, storage); | ||
| ++histo[22]; | ||
| ++histo[62]; | ||
| } else { | ||
| BrotliWriteBits(depth[63], bits[63], storage_ix, storage); | ||
| BrotliWriteBits(24, insertlen - 22594, storage_ix, storage); | ||
| ++histo[23]; | ||
| ++histo[63]; | ||
| } | ||
@@ -256,3 +256,3 @@ } | ||
| BrotliWriteBits(24, copylen - 2118, storage_ix, storage); | ||
| ++histo[47]; | ||
| ++histo[39]; | ||
| } | ||
@@ -299,3 +299,3 @@ } | ||
| BrotliWriteBits(depth[64], bits[64], storage_ix, storage); | ||
| ++histo[47]; | ||
| ++histo[39]; | ||
| ++histo[64]; | ||
@@ -302,0 +302,0 @@ } |
@@ -37,3 +37,2 @@ /* Copyright 2017 Google Inc. All Rights Reserved. | ||
| #if defined(__cplusplus) || defined(c_plusplus) | ||
@@ -40,0 +39,0 @@ } /* extern "C" */ |
@@ -22,3 +22,5 @@ /* Copyright 2013 Google Inc. All Rights Reserved. | ||
| static BROTLI_INLINE uint32_t Log2FloorNonZero(size_t n) { | ||
| #if BROTLI_MODERN_COMPILER || __has_builtin(__builtin_clz) | ||
| /* TODO: generalize and move to platform.h */ | ||
| #if BROTLI_GNUC_HAS_BUILTIN(__builtin_clz, 3, 4, 0) || \ | ||
| BROTLI_INTEL_VERSION_CHECK(16, 0, 0) | ||
| return 31u ^ (uint32_t)__builtin_clz((uint32_t)n); | ||
@@ -25,0 +27,0 @@ #else |
+55
-7
@@ -39,4 +39,6 @@ /* Copyright 2010 Google Inc. All Rights Reserved. | ||
| * * private dynamic hasher data, depending on hasher type and parameters | ||
| */ | ||
| typedef uint8_t* HasherHandle; | ||
| * | ||
| * Using "define" instead of "typedef", because on MSVC __restrict does not work | ||
| * on typedef pointer types. */ | ||
| #define HasherHandle uint8_t* | ||
@@ -155,3 +157,3 @@ typedef struct { | ||
| size_t len; | ||
| size_t dist; | ||
| size_t word_idx; | ||
| size_t offset; | ||
@@ -162,4 +164,4 @@ size_t matchlen; | ||
| len = item & 0x1F; | ||
| dist = item >> 5; | ||
| offset = dictionary->words->offsets_by_length[len] + len * dist; | ||
| word_idx = item >> 5; | ||
| offset = dictionary->words->offsets_by_length[len] + len * word_idx; | ||
| if (len > max_length) { | ||
@@ -178,3 +180,3 @@ return BROTLI_FALSE; | ||
| (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F); | ||
| backward = max_backward + dist + 1 + | ||
| backward = max_backward + 1 + word_idx + | ||
| (transform_id << dictionary->words->size_bits_by_length[len]); | ||
@@ -348,2 +350,47 @@ } | ||
| /* fast large window hashers */ | ||
| #define HASHER() HROLLING_FAST | ||
| #define CHUNKLEN 32 | ||
| #define JUMP 4 | ||
| #define NUMBUCKETS 16777216 | ||
| #define MASK ((NUMBUCKETS * 64) - 1) | ||
| #include "./hash_rolling_inc.h" /* NOLINT(build/include) */ | ||
| #undef JUMP | ||
| #undef HASHER | ||
| #define HASHER() HROLLING | ||
| #define JUMP 1 | ||
| #include "./hash_rolling_inc.h" /* NOLINT(build/include) */ | ||
| #undef MASK | ||
| #undef NUMBUCKETS | ||
| #undef JUMP | ||
| #undef CHUNKLEN | ||
| #undef HASHER | ||
| #define HASHER() H35 | ||
| #define HASHER_A H3 | ||
| #define HASHER_B HROLLING_FAST | ||
| #include "./hash_composite_inc.h" /* NOLINT(build/include) */ | ||
| #undef HASHER_A | ||
| #undef HASHER_B | ||
| #undef HASHER | ||
| #define HASHER() H55 | ||
| #define HASHER_A H54 | ||
| #define HASHER_B HROLLING_FAST | ||
| #include "./hash_composite_inc.h" /* NOLINT(build/include) */ | ||
| #undef HASHER_A | ||
| #undef HASHER_B | ||
| #undef HASHER | ||
| #define HASHER() H65 | ||
| #define HASHER_A H6 | ||
| #define HASHER_B HROLLING | ||
| #include "./hash_composite_inc.h" /* NOLINT(build/include) */ | ||
| #undef HASHER_A | ||
| #undef HASHER_B | ||
| #undef HASHER | ||
| #undef FN | ||
@@ -353,3 +400,4 @@ #undef CAT | ||
| #define FOR_GENERIC_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54) | ||
| #define FOR_GENERIC_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)\ | ||
| H(35) H(55) H(65) | ||
| #define FOR_ALL_HASHERS(H) FOR_GENERIC_HASHERS(H) H(10) | ||
@@ -356,0 +404,0 @@ |
@@ -145,4 +145,22 @@ /* Copyright 2016 Google Inc. All Rights Reserved. | ||
| } | ||
| if (params->lgwin > 24) { | ||
| /* Different hashers for large window brotli: not for qualities <= 2, | ||
| these are too fast for large window. Not for qualities >= 10: their | ||
| hasher already works well with large window. So the changes are: | ||
| H3 --> H35: for quality 3. | ||
| H54 --> H55: for quality 4 with size hint > 1MB | ||
| H6 --> H65: for qualities 5, 6, 7, 8, 9. */ | ||
| if (hparams->type == 3) { | ||
| hparams->type = 35; | ||
| } | ||
| if (hparams->type == 54) { | ||
| hparams->type = 55; | ||
| } | ||
| if (hparams->type == 6) { | ||
| hparams->type = 65; | ||
| } | ||
| } | ||
| } | ||
| #endif /* BROTLI_ENC_QUALITY_H_ */ |
@@ -19,7 +19,2 @@ /* Copyright 2013 Google Inc. All Rights Reserved. | ||
| /* TODO: use BrotliTransforms.cutOffTransforms instead. */ | ||
| static const uint8_t kOmitLastNTransforms[10] = { | ||
| 0, 12, 27, 23, 42, 63, 56, 48, 59, 64, | ||
| }; | ||
| static BROTLI_INLINE uint32_t Hash(const uint8_t* data) { | ||
@@ -125,3 +120,6 @@ uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kDictHashMul32; | ||
| for (len = minlen; len <= maxlen; ++len) { | ||
| AddMatch(id + kOmitLastNTransforms[l - len] * n, len, l, matches); | ||
| size_t cut = l - len; | ||
| size_t transform_id = (cut << 2) + | ||
| (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F); | ||
| AddMatch(id + transform_id * n, len, l, matches); | ||
| has_found_match = BROTLI_TRUE; | ||
@@ -128,0 +126,0 @@ } |
@@ -40,3 +40,3 @@ /* Copyright 2010 Google Inc. All Rights Reserved. | ||
| uint8_t* BROTLI_RESTRICT array) { | ||
| #ifdef BROTLI_LITTLE_ENDIAN | ||
| #if defined(BROTLI_LITTLE_ENDIAN) | ||
| /* This branch of the code can write up to 56 bits at a time, | ||
@@ -43,0 +43,0 @@ 7 bits are lost by being perhaps already in *p and at least |
@@ -7,46 +7,243 @@ /* Copyright 2016 Google Inc. All Rights Reserved. | ||
| /* Macros for compiler / platform specific features and build options. | ||
| /* Macros for compiler / platform specific API declarations. */ | ||
| Build options are: | ||
| * BROTLI_BUILD_MODERN_COMPILER forces to use modern compilers built-ins, | ||
| features and attributes | ||
| */ | ||
| #ifndef BROTLI_COMMON_PORT_H_ | ||
| #define BROTLI_COMMON_PORT_H_ | ||
| /* Compatibility with non-clang compilers. */ | ||
| #ifndef __has_builtin | ||
| #define __has_builtin(x) 0 | ||
| /* The following macros were borrowed from https://github.com/nemequ/hedley | ||
| * with permission of original author - Evan Nemerson <evan@nemerson.com> */ | ||
| /* >>> >>> >>> hedley macros */ | ||
| #define BROTLI_MAKE_VERSION(major, minor, revision) \ | ||
| (((major) * 1000000) + ((minor) * 1000) + (revision)) | ||
| #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) | ||
| #define BROTLI_GNUC_VERSION \ | ||
| BROTLI_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) | ||
| #elif defined(__GNUC__) | ||
| #define BROTLI_GNUC_VERSION BROTLI_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, 0) | ||
| #endif | ||
| #ifndef __has_attribute | ||
| #define __has_attribute(x) 0 | ||
| #if defined(BROTLI_GNUC_VERSION) | ||
| #define BROTLI_GNUC_VERSION_CHECK(major, minor, patch) \ | ||
| (BROTLI_GNUC_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) | ||
| #else | ||
| #define BROTLI_GNUC_VERSION_CHECK(major, minor, patch) (0) | ||
| #endif | ||
| #ifndef __has_feature | ||
| #define __has_feature(x) 0 | ||
| #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) | ||
| #define BROTLI_MSVC_VERSION \ | ||
| BROTLI_MAKE_VERSION((_MSC_FULL_VER / 10000000), \ | ||
| (_MSC_FULL_VER % 10000000) / 100000, \ | ||
| (_MSC_FULL_VER % 100000) / 100) | ||
| #elif defined(_MSC_FULL_VER) | ||
| #define BROTLI_MSVC_VERSION \ | ||
| BROTLI_MAKE_VERSION((_MSC_FULL_VER / 1000000), \ | ||
| (_MSC_FULL_VER % 1000000) / 10000, \ | ||
| (_MSC_FULL_VER % 10000) / 10) | ||
| #elif defined(_MSC_VER) | ||
| #define BROTLI_MSVC_VERSION \ | ||
| BROTLI_MAKE_VERSION(_MSC_VER / 100, _MSC_VER % 100, 0) | ||
| #endif | ||
| #if defined(__GNUC__) && defined(__GNUC_MINOR__) | ||
| #define BROTLI_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) | ||
| #if !defined(_MSC_VER) | ||
| #define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) (0) | ||
| #elif defined(_MSC_VER) && (_MSC_VER >= 1400) | ||
| #define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \ | ||
| (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) | ||
| #elif defined(_MSC_VER) && (_MSC_VER >= 1200) | ||
| #define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \ | ||
| (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) | ||
| #else | ||
| #define BROTLI_GCC_VERSION 0 | ||
| #define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \ | ||
| (_MSC_VER >= ((major * 100) + (minor))) | ||
| #endif | ||
| #if defined(__ICC) | ||
| #define BROTLI_ICC_VERSION __ICC | ||
| #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) | ||
| #define BROTLI_INTEL_VERSION \ | ||
| BROTLI_MAKE_VERSION(__INTEL_COMPILER / 100, \ | ||
| __INTEL_COMPILER % 100, \ | ||
| __INTEL_COMPILER_UPDATE) | ||
| #elif defined(__INTEL_COMPILER) | ||
| #define BROTLI_INTEL_VERSION \ | ||
| BROTLI_MAKE_VERSION(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) | ||
| #endif | ||
| #if defined(BROTLI_INTEL_VERSION) | ||
| #define BROTLI_INTEL_VERSION_CHECK(major, minor, patch) \ | ||
| (BROTLI_INTEL_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) | ||
| #else | ||
| #define BROTLI_ICC_VERSION 0 | ||
| #define BROTLI_INTEL_VERSION_CHECK(major, minor, patch) (0) | ||
| #endif | ||
| #if defined(BROTLI_BUILD_MODERN_COMPILER) | ||
| #define BROTLI_MODERN_COMPILER 1 | ||
| #elif BROTLI_GCC_VERSION >= 304 || BROTLI_ICC_VERSION >= 1600 | ||
| #define BROTLI_MODERN_COMPILER 1 | ||
| #if defined(__PGI) && \ | ||
| defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) | ||
| #define BROTLI_PGI_VERSION \ | ||
| BROTLI_MAKE_VERSION(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) | ||
| #endif | ||
| #if defined(BROTLI_PGI_VERSION) | ||
| #define BROTLI_PGI_VERSION_CHECK(major, minor, patch) \ | ||
| (BROTLI_PGI_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) | ||
| #else | ||
| #define BROTLI_MODERN_COMPILER 0 | ||
| #define BROTLI_PGI_VERSION_CHECK(major, minor, patch) (0) | ||
| #endif | ||
| #if defined(BROTLI_SHARED_COMPILATION) && defined(_WIN32) | ||
| #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) | ||
| #define BROTLI_SUNPRO_VERSION \ | ||
| BROTLI_MAKE_VERSION( \ | ||
| (((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), \ | ||
| (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), \ | ||
| (__SUNPRO_C & 0xf) * 10) | ||
| #elif defined(__SUNPRO_C) | ||
| #define BROTLI_SUNPRO_VERSION \ | ||
| BROTLI_MAKE_VERSION((__SUNPRO_C >> 8) & 0xf, \ | ||
| (__SUNPRO_C >> 4) & 0xf, \ | ||
| (__SUNPRO_C) & 0xf) | ||
| #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) | ||
| #define BROTLI_SUNPRO_VERSION \ | ||
| BROTLI_MAKE_VERSION( \ | ||
| (((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), \ | ||
| (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), \ | ||
| (__SUNPRO_CC & 0xf) * 10) | ||
| #elif defined(__SUNPRO_CC) | ||
| #define BROTLI_SUNPRO_VERSION \ | ||
| BROTLI_MAKE_VERSION((__SUNPRO_CC >> 8) & 0xf, \ | ||
| (__SUNPRO_CC >> 4) & 0xf, \ | ||
| (__SUNPRO_CC) & 0xf) | ||
| #endif | ||
| #if defined(BROTLI_SUNPRO_VERSION) | ||
| #define BROTLI_SUNPRO_VERSION_CHECK(major, minor, patch) \ | ||
| (BROTLI_SUNPRO_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) | ||
| #else | ||
| #define BROTLI_SUNPRO_VERSION_CHECK(major, minor, patch) (0) | ||
| #endif | ||
| #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) | ||
| #define BROTLI_ARM_VERSION \ | ||
| BROTLI_MAKE_VERSION((__ARMCOMPILER_VERSION / 1000000), \ | ||
| (__ARMCOMPILER_VERSION % 1000000) / 10000, \ | ||
| (__ARMCOMPILER_VERSION % 10000) / 100) | ||
| #elif defined(__CC_ARM) && defined(__ARMCC_VERSION) | ||
| #define BROTLI_ARM_VERSION \ | ||
| BROTLI_MAKE_VERSION((__ARMCC_VERSION / 1000000), \ | ||
| (__ARMCC_VERSION % 1000000) / 10000, \ | ||
| (__ARMCC_VERSION % 10000) / 100) | ||
| #endif | ||
| #if defined(BROTLI_ARM_VERSION) | ||
| #define BROTLI_ARM_VERSION_CHECK(major, minor, patch) \ | ||
| (BROTLI_ARM_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) | ||
| #else | ||
| #define BROTLI_ARM_VERSION_CHECK(major, minor, patch) (0) | ||
| #endif | ||
| #if defined(__ibmxl__) | ||
| #define BROTLI_IBM_VERSION \ | ||
| BROTLI_MAKE_VERSION(__ibmxl_version__, \ | ||
| __ibmxl_release__, \ | ||
| __ibmxl_modification__) | ||
| #elif defined(__xlC__) && defined(__xlC_ver__) | ||
| #define BROTLI_IBM_VERSION \ | ||
| BROTLI_MAKE_VERSION(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) | ||
| #elif defined(__xlC__) | ||
| #define BROTLI_IBM_VERSION BROTLI_MAKE_VERSION(__xlC__ >> 8, __xlC__ & 0xff, 0) | ||
| #endif | ||
| #if defined(BROTLI_IBM_VERSION) | ||
| #define BROTLI_IBM_VERSION_CHECK(major, minor, patch) \ | ||
| (BROTLI_IBM_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) | ||
| #else | ||
| #define BROTLI_IBM_VERSION_CHECK(major, minor, patch) (0) | ||
| #endif | ||
| #if defined(__TI_COMPILER_VERSION__) | ||
| #define BROTLI_TI_VERSION \ | ||
| BROTLI_MAKE_VERSION((__TI_COMPILER_VERSION__ / 1000000), \ | ||
| (__TI_COMPILER_VERSION__ % 1000000) / 1000, \ | ||
| (__TI_COMPILER_VERSION__ % 1000)) | ||
| #endif | ||
| #if defined(BROTLI_TI_VERSION) | ||
| #define BROTLI_TI_VERSION_CHECK(major, minor, patch) \ | ||
| (BROTLI_TI_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) | ||
| #else | ||
| #define BROTLI_TI_VERSION_CHECK(major, minor, patch) (0) | ||
| #endif | ||
| #if defined(__IAR_SYSTEMS_ICC__) | ||
| #if __VER__ > 1000 | ||
| #define BROTLI_IAR_VERSION \ | ||
| BROTLI_MAKE_VERSION((__VER__ / 1000000), \ | ||
| (__VER__ / 1000) % 1000, \ | ||
| (__VER__ % 1000)) | ||
| #else | ||
| #define BROTLI_IAR_VERSION BROTLI_MAKE_VERSION(VER / 100, __VER__ % 100, 0) | ||
| #endif | ||
| #endif | ||
| #if defined(BROTLI_IAR_VERSION) | ||
| #define BROTLI_IAR_VERSION_CHECK(major, minor, patch) \ | ||
| (BROTLI_IAR_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) | ||
| #else | ||
| #define BROTLI_IAR_VERSION_CHECK(major, minor, patch) (0) | ||
| #endif | ||
| #if defined(__TINYC__) | ||
| #define BROTLI_TINYC_VERSION \ | ||
| BROTLI_MAKE_VERSION(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) | ||
| #endif | ||
| #if defined(BROTLI_TINYC_VERSION) | ||
| #define BROTLI_TINYC_VERSION_CHECK(major, minor, patch) \ | ||
| (BROTLI_TINYC_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch)) | ||
| #else | ||
| #define BROTLI_TINYC_VERSION_CHECK(major, minor, patch) (0) | ||
| #endif | ||
| #if defined(__has_attribute) | ||
| #define BROTLI_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \ | ||
| __has_attribute(attribute) | ||
| #else | ||
| #define BROTLI_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \ | ||
| BROTLI_GNUC_VERSION_CHECK(major, minor, patch) | ||
| #endif | ||
| #if defined(__has_builtin) | ||
| #define BROTLI_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \ | ||
| __has_builtin(builtin) | ||
| #else | ||
| #define BROTLI_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \ | ||
| BROTLI_GNUC_VERSION_CHECK(major, minor, patch) | ||
| #endif | ||
| #if defined(_WIN32) || defined(__CYGWIN__) | ||
| #define BROTLI_PUBLIC | ||
| #elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) || \ | ||
| BROTLI_TI_VERSION_CHECK(8, 0, 0) || \ | ||
| BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \ | ||
| BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \ | ||
| BROTLI_IBM_VERSION_CHECK(13, 1, 0) || \ | ||
| BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \ | ||
| (BROTLI_TI_VERSION_CHECK(7, 3, 0) && \ | ||
| defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__)) | ||
| #define BROTLI_PUBLIC __attribute__ ((visibility ("default"))) | ||
| #else | ||
| #define BROTLI_PUBLIC | ||
| #endif | ||
| #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ | ||
| !defined(__STDC_NO_VLA__) && !defined(__cplusplus) && \ | ||
| !defined(__PGI) && !defined(__PGIC__) && !defined(__TINYC__) | ||
| #define BROTLI_ARRAY_PARAM(name) (name) | ||
| #else | ||
| #define BROTLI_ARRAY_PARAM(name) | ||
| #endif | ||
| /* <<< <<< <<< end of hedley macros. */ | ||
| #if defined(BROTLI_SHARED_COMPILATION) | ||
| #if defined(_WIN32) | ||
| #if defined(BROTLICOMMON_SHARED_COMPILATION) | ||
@@ -67,3 +264,8 @@ #define BROTLI_COMMON_API __declspec(dllexport) | ||
| #endif /* BROTLIENC_SHARED_COMPILATION */ | ||
| #else /* BROTLI_SHARED_COMPILATION && _WIN32 */ | ||
| #else /* _WIN32 */ | ||
| #define BROTLI_COMMON_API BROTLI_PUBLIC | ||
| #define BROTLI_DEC_API BROTLI_PUBLIC | ||
| #define BROTLI_ENC_API BROTLI_PUBLIC | ||
| #endif /* _WIN32 */ | ||
| #else /* BROTLI_SHARED_COMPILATION */ | ||
| #define BROTLI_COMMON_API | ||
@@ -74,8 +276,2 @@ #define BROTLI_DEC_API | ||
| #if BROTLI_MODERN_COMPILER || __has_attribute(deprecated) | ||
| #define BROTLI_DEPRECATED __attribute__((deprecated)) | ||
| #else | ||
| #define BROTLI_DEPRECATED | ||
| #endif | ||
| #endif /* BROTLI_COMMON_PORT_H_ */ |
@@ -83,9 +83,2 @@ /* Copyright 2013 Google Inc. All Rights Reserved. | ||
| #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ | ||
| !defined(__cplusplus) && !defined(__PGI) | ||
| #define BROTLI_ARRAY_PARAM(L) L | ||
| #else | ||
| #define BROTLI_ARRAY_PARAM(L) | ||
| #endif | ||
| #endif /* BROTLI_COMMON_TYPES_H_ */ |
+10
-0
@@ -5,2 +5,10 @@ # Change Log | ||
| ## [2.4.0] - 2018-07-31 | ||
| ### Changed | ||
| - Updated brotli from [v1.0.4] to [v1.0.5] | ||
| - Replaced NAN with N-API | ||
| ### Removed | ||
| - Dropped support for Node 9 | ||
| ## [2.3.2] - 2018-05-01 | ||
@@ -274,2 +282,3 @@ ### Fixed | ||
| [2.4.0]: https://github.com/MayhemYDG/iltorb/compare/v2.3.2...v2.4.0 | ||
| [2.3.2]: https://github.com/MayhemYDG/iltorb/compare/v2.3.1...v2.3.2 | ||
@@ -319,2 +328,3 @@ [2.3.1]: https://github.com/MayhemYDG/iltorb/compare/v2.3.0...v2.3.1 | ||
| [v1.0.5]: https://github.com/google/brotli/releases/tag/v1.0.5 | ||
| [v1.0.4]: https://github.com/google/brotli/releases/tag/v1.0.4 | ||
@@ -321,0 +331,0 @@ [v1.0.3]: https://github.com/google/brotli/releases/tag/v1.0.3 |
+13
-15
@@ -10,13 +10,12 @@ 'use strict'; | ||
| const iltorb = require('./build/bindings/iltorb.node'); | ||
| const { StreamEncode, StreamDecode } = require('./build/bindings/iltorb.node'); | ||
| const { Transform } = require('stream'); | ||
| class TransformStreamEncode extends Transform { | ||
| constructor(params={}, sync=false) { | ||
| constructor(params={}, async=true) { | ||
| super(); | ||
| this.sync = sync; | ||
| this.encoding = false; | ||
| this.corked = false; | ||
| this.flushing = false; | ||
| this.encoder = new iltorb.StreamEncode(params); | ||
| this.encoder = new StreamEncode(async, params); | ||
| } | ||
@@ -36,3 +35,3 @@ | ||
| } | ||
| }, !this.sync); | ||
| }); | ||
| } | ||
@@ -47,3 +46,3 @@ | ||
| done(); | ||
| }, !this.sync); | ||
| }); | ||
| } | ||
@@ -83,3 +82,3 @@ | ||
| this.uncork(); | ||
| }, true); | ||
| }); | ||
| } | ||
@@ -89,6 +88,5 @@ } | ||
| class TransformStreamDecode extends Transform { | ||
| constructor(sync=false) { | ||
| constructor(async=true) { | ||
| super(); | ||
| this.sync = sync; | ||
| this.decoder = new iltorb.StreamDecode(); | ||
| this.decoder = new StreamDecode(async); | ||
| } | ||
@@ -103,3 +101,3 @@ | ||
| next(); | ||
| }, !this.sync); | ||
| }); | ||
| } | ||
@@ -114,3 +112,3 @@ | ||
| done(); | ||
| }, !this.sync); | ||
| }); | ||
| } | ||
@@ -223,4 +221,4 @@ | ||
| } | ||
| params.size_hint = input.length; | ||
| const stream = new TransformStreamEncode(params, true); | ||
| params = Object.assign({}, params, {size_hint: input.length}); | ||
| const stream = new TransformStreamEncode(params, false); | ||
| const chunks = []; | ||
@@ -243,3 +241,3 @@ let length = 0; | ||
| } | ||
| const stream = new TransformStreamDecode(true); | ||
| const stream = new TransformStreamDecode(false); | ||
| const chunks = []; | ||
@@ -246,0 +244,0 @@ let length = 0; |
+8
-10
| { | ||
| "name": "iltorb", | ||
| "version": "2.3.2", | ||
| "version": "2.4.0", | ||
| "description": "Brotli compression/decompression with native bindings", | ||
@@ -39,16 +39,14 @@ "homepage": "https://github.com/MayhemYDG/iltorb", | ||
| "detect-libc": "^1.0.3", | ||
| "nan": "^2.10.0", | ||
| "npmlog": "^4.1.2", | ||
| "prebuild-install": "^3.0.0", | ||
| "prebuild-install": "^5.0.0", | ||
| "which-pm-runs": "^1.0.0" | ||
| }, | ||
| "devDependencies": { | ||
| "chai": "^4.1.2", | ||
| "cross-env": "^5.1.4", | ||
| "ava": "^0.25.0", | ||
| "cross-env": "^5.2.0", | ||
| "cross-spawn": "^6.0.5", | ||
| "mocha": "^5.0.5", | ||
| "node-abi": "^2.4.0", | ||
| "node-gyp": "^3.6.2", | ||
| "node-abi": "^2.4.3", | ||
| "node-gyp": "^3.7.0", | ||
| "npm-run-path-compat": "^2.0.3", | ||
| "prebuild": "^7.5.0" | ||
| "prebuild": "^7.6.1" | ||
| }, | ||
@@ -61,3 +59,3 @@ "scripts": { | ||
| "prebuild-upload": "cross-env PUBLISH_BINARY=1 npm run prebuild-ci", | ||
| "test": "mocha" | ||
| "test": "ava" | ||
| }, | ||
@@ -64,0 +62,0 @@ "binary": { |
+4
-19
@@ -11,5 +11,5 @@ const libc = require('detect-libc'); | ||
| function build(runtime, target) { | ||
| function build({target, runtime, abi}) { | ||
| try { | ||
| getTarget(target, runtime); | ||
| abi && getTarget(target, runtime); | ||
| } catch (err) { | ||
@@ -45,18 +45,3 @@ return Promise.resolve(); | ||
| const builds = [ | ||
| { runtime: 'node', target: process.versions.modules } | ||
| ]; | ||
| if (PUBLISH_BINARY) { | ||
| builds.push( | ||
| { runtime: 'electron', target: '50' }, | ||
| { runtime: 'electron', target: '53' }, | ||
| { runtime: 'electron', target: process.versions.modules } | ||
| ); | ||
| } | ||
| builds | ||
| .reduce((promise, item) => { | ||
| return promise.then(() => build(item.runtime, item.target)).catch((code) => process.exit(code)); | ||
| }, Promise.resolve()); | ||
| build({ runtime: 'node', target: process.versions.node, abi: false }) | ||
| .catch(code => process.exit(code)); |
| #include "allocator.h" | ||
| #include <nan.h> | ||
@@ -24,3 +23,3 @@ void* Allocator::Alloc(void* opaque, size_t size) { | ||
| void Allocator::Free(void* opaque, void* address) { | ||
| void Allocator::Free(void* opaque, void* address, napi_env env) { | ||
| if (!address) { | ||
@@ -31,8 +30,10 @@ return; | ||
| AllocatedBuffer* buf = GetBufferInfo(address); | ||
| int64_t size = buf->size + sizeof(*buf); | ||
| if (opaque) { | ||
| Allocator* alloc = static_cast<Allocator*>(opaque); | ||
| alloc->allocated_unreported_memory -= buf->size + sizeof(*buf); | ||
| alloc->allocated_unreported_memory -= size; | ||
| } else { | ||
| Nan::AdjustExternalMemory(-(buf->size + sizeof(*buf))); | ||
| int64_t result; | ||
| napi_adjust_external_memory(env, -size, &result); | ||
| } | ||
@@ -44,8 +45,9 @@ | ||
| void Allocator::Free(void* address) { | ||
| Free(this, address); | ||
| Free(this, address, NULL); | ||
| } | ||
| void Allocator::ReportMemoryToV8() { | ||
| Nan::AdjustExternalMemory(allocated_unreported_memory); | ||
| void Allocator::ReportMemoryToV8(napi_env env) { | ||
| int64_t result; | ||
| napi_adjust_external_memory(env, allocated_unreported_memory, &result); | ||
| allocated_unreported_memory = 0; | ||
| } |
| #ifndef ILTORB_ALLOCATOR_H | ||
| #define ILTORB_ALLOCATOR_H | ||
| #include <stddef.h> | ||
| #include <stdint.h> | ||
| #include <stdlib.h> | ||
| #include <node_api.h> | ||
@@ -21,11 +21,14 @@ struct Allocator { | ||
| static AllocatedBuffer* GetBufferInfo(void* address); | ||
| void ReportMemoryToV8(); | ||
| void ReportMemoryToV8(napi_env env); | ||
| // Brotli-style parameter order. | ||
| static void* Alloc(void* opaque, size_t size); | ||
| static void Free(void* opaque, void* address); | ||
| static void Free(void* opaque, void* address) { | ||
| Free(opaque, address, NULL); | ||
| } | ||
| static void Free(void* opaque, void* address, napi_env env); | ||
| // Like Free, but in node::Buffer::FreeCallback style. | ||
| static void NodeFree(char* address, void* opaque) { | ||
| return Free(opaque, address); | ||
| static void NodeFree(napi_env env, void* address, void* opaque) { | ||
| Free(opaque, address, env); | ||
| } | ||
@@ -32,0 +35,0 @@ }; |
| #include "stream_coder.h" | ||
| StreamCoder::StreamCoder() { | ||
| } | ||
| StreamCoder::~StreamCoder() { | ||
| void StreamCoder::ClearPendingOutput(napi_env env) { | ||
| size_t n_chunks = pending_output.size(); | ||
@@ -12,20 +9,20 @@ for (size_t i = 0; i < n_chunks; i++) { | ||
| alloc.ReportMemoryToV8(); | ||
| alloc.ReportMemoryToV8(env); | ||
| } | ||
| Local<Array> StreamCoder::PendingChunksAsArray() { | ||
| void StreamCoder::PendingChunksAsArray(napi_env env, napi_value* arr) { | ||
| size_t n_chunks = pending_output.size(); | ||
| Local<Array> chunks = Nan::New<Array>(n_chunks); | ||
| napi_create_array_with_length(env, n_chunks, arr); | ||
| for (size_t i = 0; i < n_chunks; i++) { | ||
| uint8_t* current = pending_output[i]; | ||
| Allocator::AllocatedBuffer* buf_info = Allocator::GetBufferInfo(current); | ||
| Nan::Set(chunks, i, Nan::NewBuffer(reinterpret_cast<char*>(current), | ||
| buf_info->size, | ||
| Allocator::NodeFree, | ||
| NULL).ToLocalChecked()); | ||
| uint8_t* chunk = pending_output[i]; | ||
| Allocator::AllocatedBuffer* buf_info = Allocator::GetBufferInfo(chunk); | ||
| napi_value buf; | ||
| napi_create_external_buffer(env, buf_info->size, chunk, Allocator::NodeFree, NULL, &buf); | ||
| napi_set_element(env, *arr, i, buf); | ||
| } | ||
| pending_output.clear(); | ||
| return chunks; | ||
| alloc.ReportMemoryToV8(env); | ||
| } |
| #ifndef STREAM_CODER_H | ||
| #define STREAM_CODER_H | ||
| #include <vector> | ||
| #include <node_api.h> | ||
| #include "allocator.h" | ||
| #include <nan.h> | ||
| using namespace v8; | ||
| class StreamCoder : public Nan::ObjectWrap { | ||
| class StreamCoder { | ||
| public: | ||
@@ -14,8 +13,6 @@ Allocator alloc; | ||
| Local<Array> PendingChunksAsArray(); | ||
| protected: | ||
| explicit StreamCoder(); | ||
| ~StreamCoder(); | ||
| void ClearPendingOutput(napi_env env); | ||
| void PendingChunksAsArray(napi_env env, napi_value* arr); | ||
| }; | ||
| #endif |
+65
-46
| #include "stream_decode.h" | ||
| #include "stream_decode_worker.h" | ||
| #include "stream_decode_tasks.h" | ||
| using namespace v8; | ||
| napi_ref StreamDecode::constructor; | ||
| StreamDecode::StreamDecode() : next_in(NULL), available_in(0) { | ||
| StreamDecode::StreamDecode(napi_env env, napi_value async) { | ||
| napi_get_value_bool(env, async, &isAsync); | ||
| state = BrotliDecoderCreateInstance(Allocator::Alloc, Allocator::Free, &alloc); | ||
| alloc.ReportMemoryToV8(); | ||
| alloc.ReportMemoryToV8(env); | ||
| } | ||
| StreamDecode::~StreamDecode() { | ||
| BrotliDecoderDestroyInstance(state); | ||
| void StreamDecode::Destructor(napi_env env, void* nativeObject, void* /*finalize_hint*/) { | ||
| StreamDecode* obj = reinterpret_cast<StreamDecode*>(nativeObject); | ||
| BrotliDecoderDestroyInstance(obj->state); | ||
| obj->ClearPendingOutput(env); | ||
| delete obj; | ||
| } | ||
| void StreamDecode::Init(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { | ||
| Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New); | ||
| tpl->SetClassName(Nan::New("StreamDecode").ToLocalChecked()); | ||
| tpl->InstanceTemplate()->SetInternalFieldCount(1); | ||
| napi_value StreamDecode::Init(napi_env env, napi_value exports) { | ||
| napi_value cons; | ||
| napi_property_descriptor properties[] = { | ||
| { "transform", NULL, Transform, NULL, NULL, NULL, napi_default, NULL }, | ||
| { "flush", NULL, Flush, NULL, NULL, NULL, napi_default, NULL } | ||
| }; | ||
| Nan::SetPrototypeMethod(tpl, "transform", Transform); | ||
| Nan::SetPrototypeMethod(tpl, "flush", Flush); | ||
| napi_define_class(env, "StreamDecode", NAPI_AUTO_LENGTH, New, nullptr, 2, properties, &cons); | ||
| napi_create_reference(env, cons, 1, &constructor); | ||
| napi_set_named_property(env, exports, "StreamDecode", cons); | ||
| constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked()); | ||
| Nan::Set(target, Nan::New("StreamDecode").ToLocalChecked(), | ||
| Nan::GetFunction(tpl).ToLocalChecked()); | ||
| return exports; | ||
| } | ||
| NAN_METHOD(StreamDecode::New) { | ||
| StreamDecode* obj = new StreamDecode(); | ||
| obj->Wrap(info.This()); | ||
| info.GetReturnValue().Set(info.This()); | ||
| napi_value StreamDecode::New(napi_env env, napi_callback_info info) { | ||
| size_t argc = 1; | ||
| napi_value argv[1]; | ||
| napi_value jsthis; | ||
| napi_get_cb_info(env, info, &argc, argv, &jsthis, nullptr); | ||
| StreamDecode* obj = new StreamDecode(env, argv[0]); | ||
| napi_wrap(env, | ||
| jsthis, | ||
| reinterpret_cast<void*>(obj), | ||
| StreamDecode::Destructor, | ||
| nullptr, | ||
| nullptr); | ||
| return jsthis; | ||
| } | ||
| NAN_METHOD(StreamDecode::Transform) { | ||
| StreamDecode* obj = ObjectWrap::Unwrap<StreamDecode>(info.Holder()); | ||
| napi_value StreamDecode::Transform(napi_env env, napi_callback_info info) { | ||
| size_t argc = 2; | ||
| napi_value argv[2]; | ||
| napi_value jsthis; | ||
| napi_get_cb_info(env, info, &argc, argv, &jsthis, nullptr); | ||
| Local<Object> buffer = info[0]->ToObject(); | ||
| obj->next_in = (const uint8_t*) node::Buffer::Data(buffer); | ||
| obj->available_in = node::Buffer::Length(buffer); | ||
| StreamDecode* obj; | ||
| napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj)); | ||
| Nan::Callback *callback = new Nan::Callback(info[1].As<Function>()); | ||
| StreamDecodeWorker *worker = new StreamDecodeWorker(callback, obj); | ||
| if (info[2]->BooleanValue()) { | ||
| Nan::AsyncQueueWorker(worker); | ||
| } else { | ||
| worker->Execute(); | ||
| worker->WorkComplete(); | ||
| worker->Destroy(); | ||
| } | ||
| napi_get_buffer_info(env, argv[0], (void**)&obj->next_in, &obj->available_in); | ||
| napi_create_reference(env, argv[0], 1, &obj->bufref); | ||
| napi_create_reference(env, argv[1], 1, &obj->cbref); | ||
| StartDecode(env, obj); | ||
| return nullptr; | ||
| } | ||
| NAN_METHOD(StreamDecode::Flush) { | ||
| StreamDecode* obj = ObjectWrap::Unwrap<StreamDecode>(info.Holder()); | ||
| napi_value StreamDecode::Flush(napi_env env, napi_callback_info info) { | ||
| size_t argc = 1; | ||
| napi_value argv[1]; | ||
| napi_value jsthis; | ||
| napi_get_cb_info(env, info, &argc, argv, &jsthis, nullptr); | ||
| Nan::Callback *callback = new Nan::Callback(info[0].As<Function>()); | ||
| StreamDecode* obj; | ||
| napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj)); | ||
| napi_create_reference(env, argv[0], 1, &obj->cbref); | ||
| obj->next_in = nullptr; | ||
| obj->available_in = 0; | ||
| StreamDecodeWorker *worker = new StreamDecodeWorker(callback, obj); | ||
| if (info[1]->BooleanValue()) { | ||
| Nan::AsyncQueueWorker(worker); | ||
| } else { | ||
| worker->Execute(); | ||
| worker->WorkComplete(); | ||
| worker->Destroy(); | ||
| } | ||
| StartDecode(env, obj); | ||
| return nullptr; | ||
| } | ||
| Nan::Persistent<Function> StreamDecode::constructor; |
+15
-10
| #ifndef STREAM_DECODE_H | ||
| #define STREAM_DECODE_H | ||
| #include <nan.h> | ||
| #include <node_api.h> | ||
| #include "brotli/decode.h" | ||
| #include "../common/stream_coder.h" | ||
| #include "brotli/decode.h" | ||
| class StreamDecode : public StreamCoder { | ||
| public: | ||
| static void Init(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target); | ||
| static napi_value Init(napi_env env, napi_value exports); | ||
| static void Destructor(napi_env env, void* nativeObject, void* finalize_hint); | ||
| bool isAsync = true; | ||
| bool hasError = false; | ||
| BrotliDecoderState* state; | ||
| const uint8_t* next_in; | ||
| size_t available_in; | ||
| napi_ref bufref = NULL; | ||
| napi_ref cbref = NULL; | ||
| napi_async_work work = NULL; | ||
| BrotliDecoderState* state; | ||
| private: | ||
| explicit StreamDecode(); | ||
| ~StreamDecode(); | ||
| explicit StreamDecode(napi_env env, napi_value async); | ||
| static NAN_METHOD(New); | ||
| static NAN_METHOD(Transform); | ||
| static NAN_METHOD(Flush); | ||
| static Nan::Persistent<v8::Function> constructor; | ||
| static napi_value New(napi_env env, napi_callback_info info); | ||
| static napi_value Transform(napi_env env, napi_callback_info info); | ||
| static napi_value Flush(napi_env env, napi_callback_info info); | ||
| static napi_ref constructor; | ||
| }; | ||
| #endif |
+98
-92
| #include "stream_encode.h" | ||
| #include "stream_encode_worker.h" | ||
| #include "stream_encode_tasks.h" | ||
| using namespace v8; | ||
| napi_ref StreamEncode::constructor; | ||
| StreamEncode::StreamEncode(Local<Object> params) { | ||
| StreamEncode::StreamEncode(napi_env env, napi_value async, napi_value params) { | ||
| napi_get_value_bool(env, async, &isAsync); | ||
| state = BrotliEncoderCreateInstance(Allocator::Alloc, Allocator::Free, &alloc); | ||
| Local<String> key; | ||
| uint32_t val; | ||
| SetParameter(env, params, "mode", BROTLI_PARAM_MODE); | ||
| SetParameter(env, params, "quality", BROTLI_PARAM_QUALITY); | ||
| SetParameter(env, params, "lgwin", BROTLI_PARAM_LGWIN); | ||
| SetParameter(env, params, "lgblock", BROTLI_PARAM_LGBLOCK); | ||
| SetParameter(env, params, "disable_literal_context_modeling", BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING); | ||
| SetParameter(env, params, "size_hint", BROTLI_PARAM_SIZE_HINT); | ||
| SetParameter(env, params, "large_window", BROTLI_PARAM_LARGE_WINDOW); | ||
| SetParameter(env, params, "npostfix", BROTLI_PARAM_NPOSTFIX); | ||
| SetParameter(env, params, "ndirect", BROTLI_PARAM_NDIRECT); | ||
| key = Nan::New<String>("mode").ToLocalChecked(); | ||
| if (Nan::Has(params, key).FromJust()) { | ||
| val = Nan::Get(params, key).ToLocalChecked()->Int32Value(); | ||
| BrotliEncoderSetParameter(state, BROTLI_PARAM_MODE, val); | ||
| } | ||
| alloc.ReportMemoryToV8(env); | ||
| } | ||
| key = Nan::New<String>("quality").ToLocalChecked(); | ||
| if (Nan::Has(params, key).FromJust()) { | ||
| val = Nan::Get(params, key).ToLocalChecked()->Int32Value(); | ||
| BrotliEncoderSetParameter(state, BROTLI_PARAM_QUALITY, val); | ||
| } | ||
| void StreamEncode::Destructor(napi_env env, void* nativeObject, void* /*finalize_hint*/) { | ||
| StreamEncode* obj = reinterpret_cast<StreamEncode*>(nativeObject); | ||
| BrotliEncoderDestroyInstance(obj->state); | ||
| obj->ClearPendingOutput(env); | ||
| delete obj; | ||
| } | ||
| key = Nan::New<String>("lgwin").ToLocalChecked(); | ||
| if (Nan::Has(params, key).FromJust()) { | ||
| val = Nan::Get(params, key).ToLocalChecked()->Int32Value(); | ||
| BrotliEncoderSetParameter(state, BROTLI_PARAM_LGWIN, val); | ||
| } | ||
| void StreamEncode::SetParameter(napi_env env, napi_value params, const char* key, BrotliEncoderParameter p) { | ||
| bool hasProp; | ||
| napi_has_named_property(env, params, key, &hasProp); | ||
| key = Nan::New<String>("lgblock").ToLocalChecked(); | ||
| if (Nan::Has(params, key).FromJust()) { | ||
| val = Nan::Get(params, key).ToLocalChecked()->Int32Value(); | ||
| BrotliEncoderSetParameter(state, BROTLI_PARAM_LGBLOCK, val); | ||
| if (!hasProp) { | ||
| return; | ||
| } | ||
| key = Nan::New<String>("disable_literal_context_modeling").ToLocalChecked(); | ||
| if (Nan::Has(params, key).FromJust()) { | ||
| val = Nan::Get(params, key).ToLocalChecked()->BooleanValue(); | ||
| BrotliEncoderSetParameter(state, BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING, val); | ||
| } | ||
| napi_value prop; | ||
| napi_get_named_property(env, params, key, &prop); | ||
| key = Nan::New<String>("size_hint").ToLocalChecked(); | ||
| if (Nan::Has(params, key).FromJust()) { | ||
| val = Nan::Get(params, key).ToLocalChecked()->Int32Value(); | ||
| BrotliEncoderSetParameter(state, BROTLI_PARAM_SIZE_HINT, val); | ||
| } | ||
| napi_valuetype valuetype; | ||
| napi_typeof(env, prop, &valuetype); | ||
| key = Nan::New<String>("large_window").ToLocalChecked(); | ||
| if (Nan::Has(params, key).FromJust()) { | ||
| val = Nan::Get(params, key).ToLocalChecked()->BooleanValue(); | ||
| BrotliEncoderSetParameter(state, BROTLI_PARAM_LARGE_WINDOW, val); | ||
| if (valuetype == napi_boolean) { | ||
| napi_coerce_to_number(env, prop, &prop); | ||
| } else if (valuetype != napi_number) { | ||
| return; | ||
| } | ||
| key = Nan::New<String>("npostfix").ToLocalChecked(); | ||
| if (Nan::Has(params, key).FromJust()) { | ||
| val = Nan::Get(params, key).ToLocalChecked()->Int32Value(); | ||
| BrotliEncoderSetParameter(state, BROTLI_PARAM_NPOSTFIX, val); | ||
| } | ||
| uint32_t value; | ||
| napi_get_value_uint32(env, prop, &value); | ||
| key = Nan::New<String>("ndirect").ToLocalChecked(); | ||
| if (Nan::Has(params, key).FromJust()) { | ||
| val = Nan::Get(params, key).ToLocalChecked()->Int32Value(); | ||
| BrotliEncoderSetParameter(state, BROTLI_PARAM_NDIRECT, val); | ||
| } | ||
| BrotliEncoderSetParameter(state, p, value); | ||
| } | ||
| StreamEncode::~StreamEncode() { | ||
| BrotliEncoderDestroyInstance(state); | ||
| napi_value StreamEncode::Init(napi_env env, napi_value exports) { | ||
| napi_value cons; | ||
| napi_property_descriptor properties[] = { | ||
| { "transform", NULL, Transform, NULL, NULL, NULL, napi_default, NULL }, | ||
| { "flush", NULL, Flush, NULL, NULL, NULL, napi_default, NULL } | ||
| }; | ||
| napi_define_class(env, "StreamEncode", NAPI_AUTO_LENGTH, New, nullptr, 2, properties, &cons); | ||
| napi_create_reference(env, cons, 1, &constructor); | ||
| napi_set_named_property(env, exports, "StreamEncode", cons); | ||
| return exports; | ||
| } | ||
| void StreamEncode::Init(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) { | ||
| Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New); | ||
| tpl->SetClassName(Nan::New("StreamEncode").ToLocalChecked()); | ||
| tpl->InstanceTemplate()->SetInternalFieldCount(1); | ||
| napi_value StreamEncode::New(napi_env env, napi_callback_info info) { | ||
| size_t argc = 2; | ||
| napi_value argv[2]; | ||
| napi_value jsthis; | ||
| napi_get_cb_info(env, info, &argc, argv, &jsthis, nullptr); | ||
| Nan::SetPrototypeMethod(tpl, "transform", Transform); | ||
| Nan::SetPrototypeMethod(tpl, "flush", Flush); | ||
| StreamEncode* obj = new StreamEncode(env, argv[0], argv[1]); | ||
| constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked()); | ||
| Nan::Set(target, Nan::New("StreamEncode").ToLocalChecked(), | ||
| Nan::GetFunction(tpl).ToLocalChecked()); | ||
| } | ||
| napi_wrap(env, | ||
| jsthis, | ||
| reinterpret_cast<void*>(obj), | ||
| StreamEncode::Destructor, | ||
| nullptr, | ||
| nullptr); | ||
| NAN_METHOD(StreamEncode::New) { | ||
| StreamEncode* obj = new StreamEncode(info[0]->ToObject()); | ||
| obj->Wrap(info.This()); | ||
| info.GetReturnValue().Set(info.This()); | ||
| return jsthis; | ||
| } | ||
| NAN_METHOD(StreamEncode::Transform) { | ||
| StreamEncode* obj = ObjectWrap::Unwrap<StreamEncode>(info.Holder()); | ||
| napi_value StreamEncode::Transform(napi_env env, napi_callback_info info) { | ||
| size_t argc = 2; | ||
| napi_value argv[2]; | ||
| napi_value jsthis; | ||
| napi_get_cb_info(env, info, &argc, argv, &jsthis, nullptr); | ||
| Local<Object> buffer = info[0]->ToObject(); | ||
| obj->next_in = (const uint8_t*) node::Buffer::Data(buffer); | ||
| obj->available_in = node::Buffer::Length(buffer); | ||
| StreamEncode* obj; | ||
| napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj)); | ||
| Nan::Callback *callback = new Nan::Callback(info[1].As<Function>()); | ||
| StreamEncodeWorker *worker = new StreamEncodeWorker(callback, obj, BROTLI_OPERATION_PROCESS); | ||
| if (info[2]->BooleanValue()) { | ||
| Nan::AsyncQueueWorker(worker); | ||
| } else { | ||
| worker->Execute(); | ||
| worker->WorkComplete(); | ||
| worker->Destroy(); | ||
| } | ||
| napi_get_buffer_info(env, argv[0], (void**)&obj->next_in, &obj->available_in); | ||
| napi_create_reference(env, argv[0], 1, &obj->bufref); | ||
| napi_create_reference(env, argv[1], 1, &obj->cbref); | ||
| obj->op = BROTLI_OPERATION_PROCESS; | ||
| StartEncode(env, obj); | ||
| return nullptr; | ||
| } | ||
| NAN_METHOD(StreamEncode::Flush) { | ||
| StreamEncode* obj = ObjectWrap::Unwrap<StreamEncode>(info.Holder()); | ||
| napi_value StreamEncode::Flush(napi_env env, napi_callback_info info) { | ||
| size_t argc = 2; | ||
| napi_value argv[2]; | ||
| napi_value jsthis; | ||
| napi_get_cb_info(env, info, &argc, argv, &jsthis, nullptr); | ||
| Nan::Callback *callback = new Nan::Callback(info[1].As<Function>()); | ||
| BrotliEncoderOperation op = info[0]->BooleanValue() | ||
| StreamEncode* obj; | ||
| napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj)); | ||
| bool isFinish; | ||
| napi_get_value_bool(env, argv[0], &isFinish); | ||
| napi_create_reference(env, argv[1], 1, &obj->cbref); | ||
| obj->op = isFinish | ||
| ? BROTLI_OPERATION_FINISH | ||
| : BROTLI_OPERATION_FLUSH; | ||
| obj->next_in = nullptr; | ||
| obj->available_in = 0; | ||
| StreamEncodeWorker *worker = new StreamEncodeWorker(callback, obj, op); | ||
| if (info[2]->BooleanValue()) { | ||
| Nan::AsyncQueueWorker(worker); | ||
| } else { | ||
| worker->Execute(); | ||
| worker->WorkComplete(); | ||
| worker->Destroy(); | ||
| } | ||
| StartEncode(env, obj); | ||
| return nullptr; | ||
| } | ||
| Nan::Persistent<Function> StreamEncode::constructor; |
+17
-10
| #ifndef STREAM_ENCODE_H | ||
| #define STREAM_ENCODE_H | ||
| #include <nan.h> | ||
| #include <node_api.h> | ||
| #include "brotli/encode.h" | ||
| #include "../common/stream_coder.h" | ||
| #include "brotli/encode.h" | ||
| class StreamEncode : public StreamCoder { | ||
| public: | ||
| static void Init(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target); | ||
| static napi_value Init(napi_env env, napi_value exports); | ||
| static void Destructor(napi_env env, void* nativeObject, void* finalize_hint); | ||
| bool isAsync = true; | ||
| bool hasError = false; | ||
| BrotliEncoderState* state; | ||
| BrotliEncoderOperation op; | ||
| const uint8_t* next_in; | ||
| size_t available_in; | ||
| napi_ref bufref = NULL; | ||
| napi_ref cbref = NULL; | ||
| napi_async_work work = NULL; | ||
| BrotliEncoderState* state; | ||
| private: | ||
| explicit StreamEncode(Local<Object> params); | ||
| ~StreamEncode(); | ||
| explicit StreamEncode(napi_env env, napi_value async, napi_value params); | ||
| void SetParameter(napi_env env, napi_value params, const char* key, BrotliEncoderParameter p); | ||
| static NAN_METHOD(New); | ||
| static NAN_METHOD(Transform); | ||
| static NAN_METHOD(Flush); | ||
| static Nan::Persistent<v8::Function> constructor; | ||
| static napi_value New(napi_env env, napi_callback_info info); | ||
| static napi_value Transform(napi_env env, napi_callback_info info); | ||
| static napi_value Flush(napi_env env, napi_callback_info info); | ||
| static napi_ref constructor; | ||
| }; | ||
| #endif |
+6
-7
@@ -1,12 +0,11 @@ | ||
| #include <nan.h> | ||
| #include <node_api.h> | ||
| #include "dec/stream_decode.h" | ||
| #include "enc/stream_encode.h" | ||
| using namespace v8; | ||
| NAN_MODULE_INIT(Init) { | ||
| StreamDecode::Init(target); | ||
| StreamEncode::Init(target); | ||
| napi_value Init(napi_env env, napi_value exports) { | ||
| StreamDecode::Init(env, exports); | ||
| StreamEncode::Init(env, exports); | ||
| return exports; | ||
| } | ||
| NODE_MODULE(iltorb, Init) | ||
| NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) |
| #include <nan.h> | ||
| #include "stream_decode.h" | ||
| using namespace v8; | ||
| NAN_MODULE_INIT(Init) { | ||
| StreamDecode::Init(target); | ||
| } | ||
| NODE_MODULE(decode, Init) |
| #include "stream_decode_worker.h" | ||
| using namespace v8; | ||
| StreamDecodeWorker::StreamDecodeWorker(Nan::Callback *callback, StreamDecode* obj) | ||
| : Nan::AsyncWorker(callback), obj(obj) {} | ||
| StreamDecodeWorker::~StreamDecodeWorker() { | ||
| } | ||
| void StreamDecodeWorker::Execute() { | ||
| do { | ||
| size_t available_out = 0; | ||
| res = BrotliDecoderDecompressStream(obj->state, | ||
| &obj->available_in, | ||
| &obj->next_in, | ||
| &available_out, | ||
| NULL, | ||
| NULL); | ||
| if (res == BROTLI_DECODER_RESULT_ERROR) { | ||
| return; | ||
| } | ||
| while (BrotliDecoderHasMoreOutput(obj->state) == BROTLI_TRUE) { | ||
| size_t size = 0; | ||
| const uint8_t* output = BrotliDecoderTakeOutput(obj->state, &size); | ||
| void* buf = obj->alloc.Alloc(size); | ||
| if (!buf) { | ||
| res = BROTLI_DECODER_RESULT_ERROR; | ||
| return; | ||
| } | ||
| memcpy(buf, output, size); | ||
| obj->pending_output.push_back(static_cast<uint8_t*>(buf)); | ||
| } | ||
| } while(res == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT); | ||
| } | ||
| void StreamDecodeWorker::HandleOKCallback() { | ||
| if (res == BROTLI_DECODER_RESULT_ERROR || res == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { | ||
| Local<Value> argv[] = { | ||
| Nan::Error("Brotli failed to decompress.") | ||
| }; | ||
| callback->Call(1, argv, async_resource); | ||
| } else { | ||
| Local<Value> argv[] = { | ||
| Nan::Null(), | ||
| obj->PendingChunksAsArray() | ||
| }; | ||
| callback->Call(2, argv, async_resource); | ||
| } | ||
| obj->alloc.ReportMemoryToV8(); | ||
| } |
| #ifndef STREAM_DECODE_WORKER_H | ||
| #define STREAM_DECODE_WORKER_H | ||
| #include <nan.h> | ||
| #include "stream_decode.h" | ||
| #include "brotli/decode.h" | ||
| class StreamDecodeWorker : public Nan::AsyncWorker { | ||
| public: | ||
| StreamDecodeWorker(Nan::Callback *callback, StreamDecode* obj); | ||
| void Execute(); | ||
| void HandleOKCallback(); | ||
| private: | ||
| ~StreamDecodeWorker(); | ||
| StreamDecode* obj; | ||
| BrotliDecoderResult res; | ||
| }; | ||
| #endif |
| #include <nan.h> | ||
| #include "stream_encode.h" | ||
| using namespace v8; | ||
| NAN_MODULE_INIT(Init) { | ||
| StreamEncode::Init(target); | ||
| } | ||
| NODE_MODULE(encode, Init) |
| #include "stream_encode_worker.h" | ||
| using namespace v8; | ||
| StreamEncodeWorker::StreamEncodeWorker(Nan::Callback *callback, StreamEncode* obj, BrotliEncoderOperation op) | ||
| : Nan::AsyncWorker(callback), obj(obj), op(op) {} | ||
| StreamEncodeWorker::~StreamEncodeWorker() { | ||
| } | ||
| void StreamEncodeWorker::Execute() { | ||
| do { | ||
| size_t available_out = 0; | ||
| res = BrotliEncoderCompressStream(obj->state, | ||
| op, | ||
| &obj->available_in, | ||
| &obj->next_in, | ||
| &available_out, | ||
| NULL, | ||
| NULL); | ||
| if (res == BROTLI_FALSE) { | ||
| return; | ||
| } | ||
| if (BrotliEncoderHasMoreOutput(obj->state) == BROTLI_TRUE) { | ||
| size_t size = 0; | ||
| const uint8_t* output = BrotliEncoderTakeOutput(obj->state, &size); | ||
| void* buf = obj->alloc.Alloc(size); | ||
| if (!buf) { | ||
| res = BROTLI_FALSE; | ||
| return; | ||
| } | ||
| memcpy(buf, output, size); | ||
| obj->pending_output.push_back(static_cast<uint8_t*>(buf)); | ||
| } | ||
| } while (obj->available_in > 0); | ||
| } | ||
| void StreamEncodeWorker::HandleOKCallback() { | ||
| if (res == BROTLI_FALSE) { | ||
| Local<Value> argv[] = { | ||
| Nan::Error("Brotli failed to compress.") | ||
| }; | ||
| callback->Call(1, argv, async_resource); | ||
| } else { | ||
| Local<Value> argv[] = { | ||
| Nan::Null(), | ||
| obj->PendingChunksAsArray() | ||
| }; | ||
| callback->Call(2, argv, async_resource); | ||
| } | ||
| obj->alloc.ReportMemoryToV8(); | ||
| } |
| #ifndef STREAM_ENCODE_WORKER_H | ||
| #define STREAM_ENCODE_WORKER_H | ||
| #include <nan.h> | ||
| #include "stream_encode.h" | ||
| #include "brotli/encode.h" | ||
| class StreamEncodeWorker : public Nan::AsyncWorker { | ||
| public: | ||
| StreamEncodeWorker(Nan::Callback *callback, StreamEncode* obj, BrotliEncoderOperation op); | ||
| void Execute(); | ||
| void HandleOKCallback(); | ||
| private: | ||
| ~StreamEncodeWorker(); | ||
| StreamEncode* obj; | ||
| BrotliEncoderOperation op; | ||
| bool res; | ||
| }; | ||
| #endif |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
1985323
1.56%4
-20%7
-12.5%304
-4.4%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated