From b8756d89cbd29bb509469367acd397d81a57747d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Tue, 28 Nov 2023 10:16:40 +0300 Subject: [PATCH 01/16] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 54aa999..5011b9b 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "url": "git://github.com/Topface/node-lzf.git" }, "dependencies": { - "nan": "^2.0.9" + "nan": "^2.5.0" }, "directories": { "lib": "./lib" From cbb5e01e4c4a90778f35cb4b61a4a9b76214a759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Tue, 28 Nov 2023 10:23:21 +0300 Subject: [PATCH 02/16] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5011b9b..fa9ec91 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "url": "git://github.com/Topface/node-lzf.git" }, "dependencies": { - "nan": "^2.5.0" + "nan": "^2.18.0" }, "directories": { "lib": "./lib" From b97b882c93b6936c3586233b90e36b7ff2675f16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Tue, 28 Nov 2023 10:44:28 +0300 Subject: [PATCH 03/16] Nan upgraded to latest version --- src/lzf.cc | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/lzf.cc b/src/lzf.cc index d8b769d..155bbb2 100644 --- a/src/lzf.cc +++ b/src/lzf.cc @@ -58,7 +58,7 @@ NAN_METHOD(decompress) { size_t bytesUncompressed = 999 * 1024 * 1024; // it's about max size that V8 supports if (info.Length() > 1 && info[1]->IsNumber()) { // accept dest buffer size - bytesUncompressed = info[1]->Uint32Value(); + bytesUncompressed = Nan::To(info[1]).FromJust(); } @@ -79,10 +79,16 @@ NAN_METHOD(decompress) { info.GetReturnValue().Set(BufferOut.ToLocalChecked()); } -extern "C" void -init (Handle target) { - Nan::SetMethod(target, "compress", compress); - Nan::SetMethod(target, "decompress", decompress); +extern "C" void init(Local exports, Local module, Local context) { + Nan::HandleScope scope; + + if (!exports->IsObject() || exports->IsNull()) { + Nan::ThrowTypeError("Target object is not valid"); + return; + } + + Nan::SetMethod(exports.As(), "compress", compress); + Nan::SetMethod(exports.As(), "decompress", decompress); } NODE_MODULE(lzf, init) From 0657226c2f0c285c51029a4150a69cf1f957e482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Tue, 29 Oct 2024 01:08:53 +0300 Subject: [PATCH 04/16] Update lzf.cc --- src/lzf.cc | 51 +++++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/src/lzf.cc b/src/lzf.cc index 155bbb2..c9e2ed0 100644 --- a/src/lzf.cc +++ b/src/lzf.cc @@ -1,7 +1,7 @@ /* node-lzf (C) 2011 Ian Babrou */ #include -#include +#include #ifdef __APPLE__ #include @@ -11,43 +11,35 @@ #include "lzf/lzf.h" - using namespace v8; using namespace node; - -// Handle ThrowNodeError(const char* what = NULL) { -// return Nan::ThrowError(Exception::Error(Nan::New(what))); -// } NAN_METHOD(compress) { if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { return Nan::ThrowError("First argument must be a Buffer"); } - Local bufferIn = info[0]; - size_t bytesIn = Buffer::Length(bufferIn); - char * dataPointer = Buffer::Data(bufferIn); - size_t bytesCompressed = bytesIn + 100; - char * bufferOut = (char*) malloc(bytesCompressed); + Local bufferIn = info[0]; + size_t bytesIn = Buffer::Length(bufferIn); + char *dataPointer = Buffer::Data(bufferIn); - if (!bufferOut) { - return Nan::ThrowError("LZF malloc failed!"); - } + // Use vector instead of malloc + std::vector bufferOut(bytesIn + 100); - unsigned result = lzf_compress(dataPointer, bytesIn, bufferOut, bytesCompressed); + unsigned result = lzf_compress(dataPointer, bytesIn, bufferOut.data(), bufferOut.size()); if (!result) { - free(bufferOut); return Nan::ThrowError("Compression failed, probably too small buffer"); } - bufferOut = (char*) realloc (bufferOut, result); - Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut, result); + // Resize vector to the actual size of compressed data + bufferOut.resize(result); + + Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut.data(), bufferOut.size()); info.GetReturnValue().Set(BufferOut.ToLocalChecked()); } - NAN_METHOD(decompress) { if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { return Nan::ThrowError("First argument must be a Buffer"); @@ -55,26 +47,25 @@ NAN_METHOD(decompress) { Local bufferIn = info[0]; - size_t bytesUncompressed = 999 * 1024 * 1024; // it's about max size that V8 supports + size_t bytesUncompressed = 999 * 1024 * 1024; // Max size V8 supports - if (info.Length() > 1 && info[1]->IsNumber()) { // accept dest buffer size + if (info.Length() > 1 && info[1]->IsNumber()) { // Accept dest buffer size bytesUncompressed = Nan::To(info[1]).FromJust(); } + // Use vector instead of malloc + std::vector bufferOut(bytesUncompressed); - char * bufferOut = (char*) malloc(bytesUncompressed); - if (!bufferOut) { - return Nan::ThrowError("LZF malloc failed!"); - } - - unsigned result = lzf_decompress(Buffer::Data(bufferIn), Buffer::Length(bufferIn), bufferOut, bytesUncompressed); + unsigned result = lzf_decompress(Buffer::Data(bufferIn), Buffer::Length(bufferIn), bufferOut.data(), bufferOut.size()); if (!result) { - return Nan::ThrowError("Unrompression failed, probably too small buffer"); + return Nan::ThrowError("Decompression failed, probably too small buffer"); } - bufferOut = (char*) realloc (bufferOut, result); - Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut, result); + // Resize vector to the actual size of decompressed data + bufferOut.resize(result); + + Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut.data(), bufferOut.size()); info.GetReturnValue().Set(BufferOut.ToLocalChecked()); } From 7ca6befb8187d79539f1401b7408139cc0f3c1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Tue, 29 Oct 2024 21:28:31 +0300 Subject: [PATCH 05/16] Revert "Update lzf.cc" This reverts commit 0657226c2f0c285c51029a4150a69cf1f957e482. --- src/lzf.cc | 51 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/lzf.cc b/src/lzf.cc index c9e2ed0..155bbb2 100644 --- a/src/lzf.cc +++ b/src/lzf.cc @@ -1,7 +1,7 @@ /* node-lzf (C) 2011 Ian Babrou */ #include -#include +#include #ifdef __APPLE__ #include @@ -11,35 +11,43 @@ #include "lzf/lzf.h" + using namespace v8; using namespace node; + +// Handle ThrowNodeError(const char* what = NULL) { +// return Nan::ThrowError(Exception::Error(Nan::New(what))); +// } NAN_METHOD(compress) { if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { return Nan::ThrowError("First argument must be a Buffer"); } - Local bufferIn = info[0]; - size_t bytesIn = Buffer::Length(bufferIn); - char *dataPointer = Buffer::Data(bufferIn); + Local bufferIn = info[0]; + size_t bytesIn = Buffer::Length(bufferIn); + char * dataPointer = Buffer::Data(bufferIn); + size_t bytesCompressed = bytesIn + 100; + char * bufferOut = (char*) malloc(bytesCompressed); - // Use vector instead of malloc - std::vector bufferOut(bytesIn + 100); + if (!bufferOut) { + return Nan::ThrowError("LZF malloc failed!"); + } - unsigned result = lzf_compress(dataPointer, bytesIn, bufferOut.data(), bufferOut.size()); + unsigned result = lzf_compress(dataPointer, bytesIn, bufferOut, bytesCompressed); if (!result) { + free(bufferOut); return Nan::ThrowError("Compression failed, probably too small buffer"); } - // Resize vector to the actual size of compressed data - bufferOut.resize(result); - - Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut.data(), bufferOut.size()); + bufferOut = (char*) realloc (bufferOut, result); + Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut, result); info.GetReturnValue().Set(BufferOut.ToLocalChecked()); } + NAN_METHOD(decompress) { if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { return Nan::ThrowError("First argument must be a Buffer"); @@ -47,25 +55,26 @@ NAN_METHOD(decompress) { Local bufferIn = info[0]; - size_t bytesUncompressed = 999 * 1024 * 1024; // Max size V8 supports + size_t bytesUncompressed = 999 * 1024 * 1024; // it's about max size that V8 supports - if (info.Length() > 1 && info[1]->IsNumber()) { // Accept dest buffer size + if (info.Length() > 1 && info[1]->IsNumber()) { // accept dest buffer size bytesUncompressed = Nan::To(info[1]).FromJust(); } - // Use vector instead of malloc - std::vector bufferOut(bytesUncompressed); - unsigned result = lzf_decompress(Buffer::Data(bufferIn), Buffer::Length(bufferIn), bufferOut.data(), bufferOut.size()); + char * bufferOut = (char*) malloc(bytesUncompressed); + if (!bufferOut) { + return Nan::ThrowError("LZF malloc failed!"); + } + + unsigned result = lzf_decompress(Buffer::Data(bufferIn), Buffer::Length(bufferIn), bufferOut, bytesUncompressed); if (!result) { - return Nan::ThrowError("Decompression failed, probably too small buffer"); + return Nan::ThrowError("Unrompression failed, probably too small buffer"); } - // Resize vector to the actual size of decompressed data - bufferOut.resize(result); - - Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut.data(), bufferOut.size()); + bufferOut = (char*) realloc (bufferOut, result); + Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut, result); info.GetReturnValue().Set(BufferOut.ToLocalChecked()); } From 9150af408ff657bf27ed4cca23d751d384ba33c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Tue, 29 Oct 2024 21:40:18 +0300 Subject: [PATCH 06/16] Update lzf.cc --- src/lzf.cc | 60 ++++++++++++++++++++++-------------------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/src/lzf.cc b/src/lzf.cc index 155bbb2..d1b2f6b 100644 --- a/src/lzf.cc +++ b/src/lzf.cc @@ -1,82 +1,70 @@ /* node-lzf (C) 2011 Ian Babrou */ #include -#include - -#ifdef __APPLE__ -#include -#endif - -#include "nan.h" - +#include #include "lzf/lzf.h" - using namespace v8; using namespace node; +inline void ThrowNodeError(const char* what) { + Nan::ThrowError(Nan::New(std::string(what) + "- Error: " + std::to_string(errno)).ToLocalChecked()); +} -// Handle ThrowNodeError(const char* what = NULL) { -// return Nan::ThrowError(Exception::Error(Nan::New(what))); -// } NAN_METHOD(compress) { if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { return Nan::ThrowError("First argument must be a Buffer"); } - Local bufferIn = info[0]; - size_t bytesIn = Buffer::Length(bufferIn); - char * dataPointer = Buffer::Data(bufferIn); + Local bufferIn = info[0]; + size_t bytesIn = Buffer::Length(bufferIn); + char* dataPointer = Buffer::Data(bufferIn); + size_t bytesCompressed = bytesIn + 100; - char * bufferOut = (char*) malloc(bytesCompressed); + Nan::MaybeLocal BufferOut = Nan::NewBuffer(bytesCompressed); - if (!bufferOut) { - return Nan::ThrowError("LZF malloc failed!"); + if (BufferOut.IsEmpty()) { + return Nan::ThrowError("Buffer allocation failed!"); } + char* bufferOut = node::Buffer::Data(BufferOut.ToLocalChecked()); + unsigned result = lzf_compress(dataPointer, bytesIn, bufferOut, bytesCompressed); if (!result) { - free(bufferOut); - return Nan::ThrowError("Compression failed, probably too small buffer"); + return ThrowNodeError("Compression failed, probably too small buffer"); } - bufferOut = (char*) realloc (bufferOut, result); - Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut, result); - - info.GetReturnValue().Set(BufferOut.ToLocalChecked()); + info.GetReturnValue().Set(Nan::NewBuffer(bufferOut, result).ToLocalChecked()); } - NAN_METHOD(decompress) { if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { return Nan::ThrowError("First argument must be a Buffer"); } Local bufferIn = info[0]; + size_t bytesUncompressed = 999 * 1024 * 1024; - size_t bytesUncompressed = 999 * 1024 * 1024; // it's about max size that V8 supports - - if (info.Length() > 1 && info[1]->IsNumber()) { // accept dest buffer size + if (info.Length() > 1 && info[1]->IsNumber()) { bytesUncompressed = Nan::To(info[1]).FromJust(); } + Nan::MaybeLocal BufferOut = Nan::NewBuffer(bytesUncompressed); - char * bufferOut = (char*) malloc(bytesUncompressed); - if (!bufferOut) { - return Nan::ThrowError("LZF malloc failed!"); + if (BufferOut.IsEmpty()) { + return Nan::ThrowError("Buffer allocation failed!"); } + char* bufferOut = node::Buffer::Data(BufferOut.ToLocalChecked()); + unsigned result = lzf_decompress(Buffer::Data(bufferIn), Buffer::Length(bufferIn), bufferOut, bytesUncompressed); if (!result) { - return Nan::ThrowError("Unrompression failed, probably too small buffer"); + return ThrowNodeError("Decompression failed, probably too small buffer"); } - bufferOut = (char*) realloc (bufferOut, result); - Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut, result); - - info.GetReturnValue().Set(BufferOut.ToLocalChecked()); + info.GetReturnValue().Set(Nan::NewBuffer(bufferOut, result).ToLocalChecked()); } extern "C" void init(Local exports, Local module, Local context) { From 1ff141e17ce58034c4d6b9e2bebacd4de5bc7426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Tue, 29 Oct 2024 22:06:45 +0300 Subject: [PATCH 07/16] Revert "Update lzf.cc" This reverts commit 9150af408ff657bf27ed4cca23d751d384ba33c4. --- src/lzf.cc | 60 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/src/lzf.cc b/src/lzf.cc index d1b2f6b..155bbb2 100644 --- a/src/lzf.cc +++ b/src/lzf.cc @@ -1,70 +1,82 @@ /* node-lzf (C) 2011 Ian Babrou */ #include -#include +#include + +#ifdef __APPLE__ +#include +#endif + +#include "nan.h" + #include "lzf/lzf.h" + using namespace v8; using namespace node; -inline void ThrowNodeError(const char* what) { - Nan::ThrowError(Nan::New(std::string(what) + "- Error: " + std::to_string(errno)).ToLocalChecked()); -} +// Handle ThrowNodeError(const char* what = NULL) { +// return Nan::ThrowError(Exception::Error(Nan::New(what))); +// } NAN_METHOD(compress) { if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { return Nan::ThrowError("First argument must be a Buffer"); } - Local bufferIn = info[0]; - size_t bytesIn = Buffer::Length(bufferIn); - char* dataPointer = Buffer::Data(bufferIn); - + Local bufferIn = info[0]; + size_t bytesIn = Buffer::Length(bufferIn); + char * dataPointer = Buffer::Data(bufferIn); size_t bytesCompressed = bytesIn + 100; - Nan::MaybeLocal BufferOut = Nan::NewBuffer(bytesCompressed); + char * bufferOut = (char*) malloc(bytesCompressed); - if (BufferOut.IsEmpty()) { - return Nan::ThrowError("Buffer allocation failed!"); + if (!bufferOut) { + return Nan::ThrowError("LZF malloc failed!"); } - char* bufferOut = node::Buffer::Data(BufferOut.ToLocalChecked()); - unsigned result = lzf_compress(dataPointer, bytesIn, bufferOut, bytesCompressed); if (!result) { - return ThrowNodeError("Compression failed, probably too small buffer"); + free(bufferOut); + return Nan::ThrowError("Compression failed, probably too small buffer"); } - info.GetReturnValue().Set(Nan::NewBuffer(bufferOut, result).ToLocalChecked()); + bufferOut = (char*) realloc (bufferOut, result); + Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut, result); + + info.GetReturnValue().Set(BufferOut.ToLocalChecked()); } + NAN_METHOD(decompress) { if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { return Nan::ThrowError("First argument must be a Buffer"); } Local bufferIn = info[0]; - size_t bytesUncompressed = 999 * 1024 * 1024; - if (info.Length() > 1 && info[1]->IsNumber()) { + size_t bytesUncompressed = 999 * 1024 * 1024; // it's about max size that V8 supports + + if (info.Length() > 1 && info[1]->IsNumber()) { // accept dest buffer size bytesUncompressed = Nan::To(info[1]).FromJust(); } - Nan::MaybeLocal BufferOut = Nan::NewBuffer(bytesUncompressed); - if (BufferOut.IsEmpty()) { - return Nan::ThrowError("Buffer allocation failed!"); + char * bufferOut = (char*) malloc(bytesUncompressed); + if (!bufferOut) { + return Nan::ThrowError("LZF malloc failed!"); } - char* bufferOut = node::Buffer::Data(BufferOut.ToLocalChecked()); - unsigned result = lzf_decompress(Buffer::Data(bufferIn), Buffer::Length(bufferIn), bufferOut, bytesUncompressed); if (!result) { - return ThrowNodeError("Decompression failed, probably too small buffer"); + return Nan::ThrowError("Unrompression failed, probably too small buffer"); } - info.GetReturnValue().Set(Nan::NewBuffer(bufferOut, result).ToLocalChecked()); + bufferOut = (char*) realloc (bufferOut, result); + Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut, result); + + info.GetReturnValue().Set(BufferOut.ToLocalChecked()); } extern "C" void init(Local exports, Local module, Local context) { From 32c38e5c0fd13b694ad8fa527c234271c37708a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Wed, 30 Oct 2024 21:11:27 +0300 Subject: [PATCH 08/16] Update lfz.cc --- src/lzf.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lzf.cc b/src/lzf.cc index 155bbb2..0bfa413 100644 --- a/src/lzf.cc +++ b/src/lzf.cc @@ -27,7 +27,7 @@ NAN_METHOD(compress) { Local bufferIn = info[0]; size_t bytesIn = Buffer::Length(bufferIn); char * dataPointer = Buffer::Data(bufferIn); - size_t bytesCompressed = bytesIn + 100; + size_t bytesCompressed = bytesIn + (bytesIn / 16) + 64 + 3; char * bufferOut = (char*) malloc(bytesCompressed); if (!bufferOut) { From f00cfe5176f2aa3868c48c358b050e26de0a5e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Wed, 30 Oct 2024 21:21:54 +0300 Subject: [PATCH 09/16] Improve Buffer Size Calculation for LZF Compression Enhance the buffer size calculation for LZF compression to handle worst-case scenarios more effectively. In cases where compression is minimal or none, the buffer size needs to be slightly larger than the original data size. To ensure a safer buffer allocation, the buffer size is increased by 6.25% of the input size, plus an additional 64 bytes, and 3 bytes for termination or minor overhead. Updated calculation: `size_t bytesCompressed = bytesIn + (bytesIn / 16) + 64 + 3;` `bytesIn / 16`: Adds 6.25% of the input size to the buffer. `+ 64`: Accommodates any additional bytes needed by the LZF algorithm. `+ 3`: Handles termination and other small additions. This change ensures more reliable compression performance, even in edge cases. --- src/lzf.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lzf.cc b/src/lzf.cc index 0bfa413..ccb113f 100644 --- a/src/lzf.cc +++ b/src/lzf.cc @@ -1,4 +1,5 @@ /* node-lzf (C) 2011 Ian Babrou */ +/* node-lzf (C) 2024 Maintained Türkay Tanrikulu */ #include #include @@ -11,11 +12,9 @@ #include "lzf/lzf.h" - using namespace v8; using namespace node; - // Handle ThrowNodeError(const char* what = NULL) { // return Nan::ThrowError(Exception::Error(Nan::New(what))); // } From dea7e8b3951690ecf1b771146e5b08371998fd9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Thu, 5 Jun 2025 05:14:58 +0300 Subject: [PATCH 10/16] Update lzf.cc --- src/lzf.cc | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/lzf.cc b/src/lzf.cc index d8b769d..d58f330 100644 --- a/src/lzf.cc +++ b/src/lzf.cc @@ -27,7 +27,7 @@ NAN_METHOD(compress) { Local bufferIn = info[0]; size_t bytesIn = Buffer::Length(bufferIn); char * dataPointer = Buffer::Data(bufferIn); - size_t bytesCompressed = bytesIn + 100; + size_t bytesCompressed = bytesIn + (bytesIn / 16) + 64 + 3; char * bufferOut = (char*) malloc(bytesCompressed); if (!bufferOut) { @@ -38,30 +38,33 @@ NAN_METHOD(compress) { if (!result) { free(bufferOut); - return Nan::ThrowError("Compression failed, probably too small buffer"); + return Nan::ThrowError("Compression failed"); } - bufferOut = (char*) realloc (bufferOut, result); - Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut, result); + // Optional: shrink allocation + char* finalBuffer = (char*) malloc(result); + memcpy(finalBuffer, bufferOut, result); + free(bufferOut); - info.GetReturnValue().Set(BufferOut.ToLocalChecked()); + info.GetReturnValue().Set( + Nan::NewBuffer(finalBuffer, result, [](char* data, void*) { + free(data); + }, nullptr).ToLocalChecked() + ); } - NAN_METHOD(decompress) { if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { return Nan::ThrowError("First argument must be a Buffer"); } Local bufferIn = info[0]; + size_t bytesUncompressed = 999 * 1024 * 1024; - size_t bytesUncompressed = 999 * 1024 * 1024; // it's about max size that V8 supports - - if (info.Length() > 1 && info[1]->IsNumber()) { // accept dest buffer size - bytesUncompressed = info[1]->Uint32Value(); + if (info.Length() > 1 && info[1]->IsNumber()) { + bytesUncompressed = Nan::To(info[1]).FromJust(); } - char * bufferOut = (char*) malloc(bytesUncompressed); if (!bufferOut) { return Nan::ThrowError("LZF malloc failed!"); @@ -70,13 +73,19 @@ NAN_METHOD(decompress) { unsigned result = lzf_decompress(Buffer::Data(bufferIn), Buffer::Length(bufferIn), bufferOut, bytesUncompressed); if (!result) { - return Nan::ThrowError("Unrompression failed, probably too small buffer"); + free(bufferOut); + return Nan::ThrowError("Decompression failed"); } - bufferOut = (char*) realloc (bufferOut, result); - Nan::MaybeLocal BufferOut = Nan::NewBuffer(bufferOut, result); + char* finalBuffer = (char*) malloc(result); + memcpy(finalBuffer, bufferOut, result); + free(bufferOut); - info.GetReturnValue().Set(BufferOut.ToLocalChecked()); + info.GetReturnValue().Set( + Nan::NewBuffer(finalBuffer, result, [](char* data, void*) { + free(data); + }, nullptr).ToLocalChecked() + ); } extern "C" void From 4e7d067810dc6ca800fccf7741289790245831de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Thu, 5 Jun 2025 05:22:37 +0300 Subject: [PATCH 11/16] Update lzf.cc --- src/lzf.cc | 90 ++++++++++++++++++++++++------------------------------ 1 file changed, 40 insertions(+), 50 deletions(-) diff --git a/src/lzf.cc b/src/lzf.cc index d58f330..7a0dcd8 100644 --- a/src/lzf.cc +++ b/src/lzf.cc @@ -1,5 +1,3 @@ -/* node-lzf (C) 2011 Ian Babrou */ - #include #include @@ -8,49 +6,42 @@ #endif #include "nan.h" - #include "lzf/lzf.h" - using namespace v8; using namespace node; - -// Handle ThrowNodeError(const char* what = NULL) { -// return Nan::ThrowError(Exception::Error(Nan::New(what))); -// } NAN_METHOD(compress) { if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { return Nan::ThrowError("First argument must be a Buffer"); } - Local bufferIn = info[0]; - size_t bytesIn = Buffer::Length(bufferIn); - char * dataPointer = Buffer::Data(bufferIn); - size_t bytesCompressed = bytesIn + (bytesIn / 16) + 64 + 3; - char * bufferOut = (char*) malloc(bytesCompressed); + char* dataIn = Buffer::Data(info[0]); + uint32_t lenIn = Buffer::Length(info[0]); - if (!bufferOut) { - return Nan::ThrowError("LZF malloc failed!"); + uint32_t maxCompressedLen = lenIn + (lenIn / 16) + 64 + 3; + + // Allocate Node.js-managed buffer + auto maybeBuf = Nan::NewBuffer(maxCompressedLen); + if (maybeBuf.IsEmpty()) { + return Nan::ThrowError("Failed to allocate output buffer"); } - unsigned result = lzf_compress(dataPointer, bytesIn, bufferOut, bytesCompressed); + Local outBuf = maybeBuf.ToLocalChecked(); + char* outData = Buffer::Data(outBuf); - if (!result) { - free(bufferOut); + unsigned int compressedLen = lzf_compress(dataIn, lenIn, outData, maxCompressedLen); + if (compressedLen == 0) { return Nan::ThrowError("Compression failed"); } - // Optional: shrink allocation - char* finalBuffer = (char*) malloc(result); - memcpy(finalBuffer, bufferOut, result); - free(bufferOut); - - info.GetReturnValue().Set( - Nan::NewBuffer(finalBuffer, result, [](char* data, void*) { - free(data); - }, nullptr).ToLocalChecked() - ); + // Slice buffer to actual compressed length (no copy) + info.GetReturnValue().Set(outBuf->Get(Nan::GetCurrentContext(), Nan::New("slice").ToLocalChecked()) + .ToLocalChecked().As()->Call(Nan::GetCurrentContext(), outBuf, 2, + new Local[2]{ + Nan::New(0), + Nan::New((uint32_t)compressedLen) + }).ToLocalChecked()); } NAN_METHOD(decompress) { @@ -58,40 +49,39 @@ NAN_METHOD(decompress) { return Nan::ThrowError("First argument must be a Buffer"); } - Local bufferIn = info[0]; - size_t bytesUncompressed = 999 * 1024 * 1024; + char* dataIn = Buffer::Data(info[0]); + uint32_t lenIn = Buffer::Length(info[0]); + uint32_t expectedOutLen = 999 * 1024 * 1024; if (info.Length() > 1 && info[1]->IsNumber()) { - bytesUncompressed = Nan::To(info[1]).FromJust(); + expectedOutLen = Nan::To(info[1]).FromJust(); } - char * bufferOut = (char*) malloc(bytesUncompressed); - if (!bufferOut) { - return Nan::ThrowError("LZF malloc failed!"); + auto maybeBuf = Nan::NewBuffer(expectedOutLen); + if (maybeBuf.IsEmpty()) { + return Nan::ThrowError("Failed to allocate output buffer"); } - unsigned result = lzf_decompress(Buffer::Data(bufferIn), Buffer::Length(bufferIn), bufferOut, bytesUncompressed); + Local outBuf = maybeBuf.ToLocalChecked(); + char* outData = Buffer::Data(outBuf); - if (!result) { - free(bufferOut); + unsigned int decompressedLen = lzf_decompress(dataIn, lenIn, outData, expectedOutLen); + if (decompressedLen == 0) { return Nan::ThrowError("Decompression failed"); } - char* finalBuffer = (char*) malloc(result); - memcpy(finalBuffer, bufferOut, result); - free(bufferOut); - - info.GetReturnValue().Set( - Nan::NewBuffer(finalBuffer, result, [](char* data, void*) { - free(data); - }, nullptr).ToLocalChecked() - ); + // Slice to decompressed size (no copy) + info.GetReturnValue().Set(outBuf->Get(Nan::GetCurrentContext(), Nan::New("slice").ToLocalChecked()) + .ToLocalChecked().As()->Call(Nan::GetCurrentContext(), outBuf, 2, + new Local[2]{ + Nan::New(0), + Nan::New((uint32_t)decompressedLen) + }).ToLocalChecked()); } -extern "C" void -init (Handle target) { - Nan::SetMethod(target, "compress", compress); - Nan::SetMethod(target, "decompress", decompress); +extern "C" void init(Local exports) { + Nan::SetMethod(exports, "compress", compress); + Nan::SetMethod(exports, "decompress", decompress); } NODE_MODULE(lzf, init) From 4e90de04edba58afb2851d4f7c904fce90a26ac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Thu, 5 Jun 2025 05:25:35 +0300 Subject: [PATCH 12/16] Update binding.gyp and lzf.cc --- binding.gyp | 49 ++++++++++++++++++++++++++++----------- src/lzf.cc | 67 ++++++++++++++++++++++++++++------------------------- 2 files changed, 71 insertions(+), 45 deletions(-) diff --git a/binding.gyp b/binding.gyp index 6690863..3eb584d 100644 --- a/binding.gyp +++ b/binding.gyp @@ -4,22 +4,43 @@ "target_name": "lzf", "sources": [ "src/lzf.cc", - "src/lzf/lzf_c.cc", - "src/lzf/lzf_d.cc", - "src/lzf/lzf.h", - "src/lzf/lzfP.h" + "src/lzf/lzf_c.c", + "src/lzf/lzf_d.c" ], - 'conditions': [ - [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', { - 'cflags': ['-O2'] - }], - ['OS=="mac"', { - 'xcode_settings': { - 'OTHER_CFLAGS': ['-O2'] - } - }] + "include_dirs": [ + "IsObject() || !node::Buffer::HasInstance(info[0])) { + return Nan::ThrowTypeError("First argument must be a Buffer"); } - char* dataIn = Buffer::Data(info[0]); - uint32_t lenIn = Buffer::Length(info[0]); + Local inBuf = Nan::To(info[0]).ToLocalChecked(); + char* dataIn = node::Buffer::Data(inBuf); + size_t lenIn = node::Buffer::Length(inBuf); - uint32_t maxCompressedLen = lenIn + (lenIn / 16) + 64 + 3; - - // Allocate Node.js-managed buffer + size_t maxCompressedLen = lenIn + (lenIn / 16) + 64 + 3; auto maybeBuf = Nan::NewBuffer(maxCompressedLen); if (maybeBuf.IsEmpty()) { return Nan::ThrowError("Failed to allocate output buffer"); } Local outBuf = maybeBuf.ToLocalChecked(); - char* outData = Buffer::Data(outBuf); + char* outData = node::Buffer::Data(outBuf); unsigned int compressedLen = lzf_compress(dataIn, lenIn, outData, maxCompressedLen); if (compressedLen == 0) { return Nan::ThrowError("Compression failed"); } - // Slice buffer to actual compressed length (no copy) - info.GetReturnValue().Set(outBuf->Get(Nan::GetCurrentContext(), Nan::New("slice").ToLocalChecked()) - .ToLocalChecked().As()->Call(Nan::GetCurrentContext(), outBuf, 2, - new Local[2]{ - Nan::New(0), - Nan::New((uint32_t)compressedLen) - }).ToLocalChecked()); + // Avoid .Get + .Call + new[] + Local sliceFn = outBuf->Get(Nan::GetCurrentContext(), Nan::New("slice").ToLocalChecked()) + .ToLocalChecked().As(); + Local args[] = { + Nan::New(0), + Nan::New((uint32_t)compressedLen) + }; + Local sliced = sliceFn->Call(Nan::GetCurrentContext(), outBuf, 2, args).ToLocalChecked(); + + info.GetReturnValue().Set(sliced); } NAN_METHOD(decompress) { - if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { - return Nan::ThrowError("First argument must be a Buffer"); + if (info.Length() < 1 || !info[0]->IsObject() || !node::Buffer::HasInstance(info[0])) { + return Nan::ThrowTypeError("First argument must be a Buffer"); } - char* dataIn = Buffer::Data(info[0]); - uint32_t lenIn = Buffer::Length(info[0]); + Local inBuf = Nan::To(info[0]).ToLocalChecked(); + char* dataIn = node::Buffer::Data(inBuf); + size_t lenIn = node::Buffer::Length(inBuf); - uint32_t expectedOutLen = 999 * 1024 * 1024; + size_t expectedOutLen = 999 * 1024 * 1024; if (info.Length() > 1 && info[1]->IsNumber()) { expectedOutLen = Nan::To(info[1]).FromJust(); } @@ -63,25 +66,27 @@ NAN_METHOD(decompress) { } Local outBuf = maybeBuf.ToLocalChecked(); - char* outData = Buffer::Data(outBuf); + char* outData = node::Buffer::Data(outBuf); unsigned int decompressedLen = lzf_decompress(dataIn, lenIn, outData, expectedOutLen); if (decompressedLen == 0) { return Nan::ThrowError("Decompression failed"); } - // Slice to decompressed size (no copy) - info.GetReturnValue().Set(outBuf->Get(Nan::GetCurrentContext(), Nan::New("slice").ToLocalChecked()) - .ToLocalChecked().As()->Call(Nan::GetCurrentContext(), outBuf, 2, - new Local[2]{ - Nan::New(0), - Nan::New((uint32_t)decompressedLen) - }).ToLocalChecked()); + Local sliceFn = outBuf->Get(Nan::GetCurrentContext(), Nan::New("slice").ToLocalChecked()) + .ToLocalChecked().As(); + Local args[] = { + Nan::New(0), + Nan::New((uint32_t)decompressedLen) + }; + Local sliced = sliceFn->Call(Nan::GetCurrentContext(), outBuf, 2, args).ToLocalChecked(); + + info.GetReturnValue().Set(sliced); } -extern "C" void init(Local exports) { - Nan::SetMethod(exports, "compress", compress); - Nan::SetMethod(exports, "decompress", decompress); +NAN_MODULE_INIT(init) { + Nan::SetMethod(target, "compress", compress); + Nan::SetMethod(target, "decompress", decompress); } NODE_MODULE(lzf, init) From 318423933ee2d7f1cd7a313db750c5aa0066a564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Thu, 5 Jun 2025 05:26:24 +0300 Subject: [PATCH 13/16] Update binding.gyp --- binding.gyp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/binding.gyp b/binding.gyp index 3eb584d..d0dc725 100644 --- a/binding.gyp +++ b/binding.gyp @@ -4,8 +4,8 @@ "target_name": "lzf", "sources": [ "src/lzf.cc", - "src/lzf/lzf_c.c", - "src/lzf/lzf_d.c" + "src/lzf/lzf_c.cc", + "src/lzf/lzf_d.cc" ], "include_dirs": [ " Date: Thu, 5 Jun 2025 06:02:28 +0300 Subject: [PATCH 14/16] Update lzf.cc --- src/lzf.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lzf.cc b/src/lzf.cc index cabab1b..a8db6d2 100644 --- a/src/lzf.cc +++ b/src/lzf.cc @@ -1,3 +1,6 @@ +/* node-lzf (C) 2011 Ian Babrou */ +/* node-lzf (C) 2025 Maintained Türkay Tanrikulu */ + #include #include From 283a29d02ed0ba11e0f43332617d7a0ecb23b5ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Thu, 5 Jun 2025 09:31:05 +0300 Subject: [PATCH 15/16] Update lzf.cc --- src/lzf.cc | 69 ++++++++++++++---------------------------------------- 1 file changed, 17 insertions(+), 52 deletions(-) diff --git a/src/lzf.cc b/src/lzf.cc index a8db6d2..59c66b2 100644 --- a/src/lzf.cc +++ b/src/lzf.cc @@ -2,12 +2,6 @@ /* node-lzf (C) 2025 Maintained Türkay Tanrikulu */ #include -#include - -#ifdef __APPLE__ -#include -#endif - #include "nan.h" #include "lzf/lzf.h" @@ -15,76 +9,47 @@ using namespace v8; using namespace node; NAN_METHOD(compress) { - if (info.Length() < 1 || !info[0]->IsObject() || !node::Buffer::HasInstance(info[0])) { + if (info.Length() < 1 || !info[0]->IsObject() || !Buffer::HasInstance(info[0])) { return Nan::ThrowTypeError("First argument must be a Buffer"); } - Local inBuf = Nan::To(info[0]).ToLocalChecked(); - char* dataIn = node::Buffer::Data(inBuf); - size_t lenIn = node::Buffer::Length(inBuf); - - size_t maxCompressedLen = lenIn + (lenIn / 16) + 64 + 3; - auto maybeBuf = Nan::NewBuffer(maxCompressedLen); - if (maybeBuf.IsEmpty()) { - return Nan::ThrowError("Failed to allocate output buffer"); - } + Local inputBuf = Nan::To(info[0]).ToLocalChecked(); + char* inputData = Buffer::Data(inputBuf); + size_t inputLen = Buffer::Length(inputBuf); - Local outBuf = maybeBuf.ToLocalChecked(); - char* outData = node::Buffer::Data(outBuf); + size_t maxOutputLen = inputLen + (inputLen / 16) + 64 + 3; + std::unique_ptr output(new char[maxOutputLen]); - unsigned int compressedLen = lzf_compress(dataIn, lenIn, outData, maxCompressedLen); + unsigned int compressedLen = lzf_compress(inputData, inputLen, output.get(), maxOutputLen); if (compressedLen == 0) { return Nan::ThrowError("Compression failed"); } - // Avoid .Get + .Call + new[] - Local sliceFn = outBuf->Get(Nan::GetCurrentContext(), Nan::New("slice").ToLocalChecked()) - .ToLocalChecked().As(); - Local args[] = { - Nan::New(0), - Nan::New((uint32_t)compressedLen) - }; - Local sliced = sliceFn->Call(Nan::GetCurrentContext(), outBuf, 2, args).ToLocalChecked(); - - info.GetReturnValue().Set(sliced); + info.GetReturnValue().Set(Nan::CopyBuffer(output.get(), compressedLen).ToLocalChecked()); } NAN_METHOD(decompress) { - if (info.Length() < 1 || !info[0]->IsObject() || !node::Buffer::HasInstance(info[0])) { + if (info.Length() < 1 || !info[0]->IsObject() || !Buffer::HasInstance(info[0])) { return Nan::ThrowTypeError("First argument must be a Buffer"); } - Local inBuf = Nan::To(info[0]).ToLocalChecked(); - char* dataIn = node::Buffer::Data(inBuf); - size_t lenIn = node::Buffer::Length(inBuf); + Local inputBuf = Nan::To(info[0]).ToLocalChecked(); + char* inputData = Buffer::Data(inputBuf); + size_t inputLen = Buffer::Length(inputBuf); - size_t expectedOutLen = 999 * 1024 * 1024; + size_t expectedOutLen = 1024 * 1024 * 100; if (info.Length() > 1 && info[1]->IsNumber()) { expectedOutLen = Nan::To(info[1]).FromJust(); } - auto maybeBuf = Nan::NewBuffer(expectedOutLen); - if (maybeBuf.IsEmpty()) { - return Nan::ThrowError("Failed to allocate output buffer"); - } - - Local outBuf = maybeBuf.ToLocalChecked(); - char* outData = node::Buffer::Data(outBuf); + std::unique_ptr output(new char[expectedOutLen]); - unsigned int decompressedLen = lzf_decompress(dataIn, lenIn, outData, expectedOutLen); + unsigned int decompressedLen = lzf_decompress(inputData, inputLen, output.get(), expectedOutLen); if (decompressedLen == 0) { return Nan::ThrowError("Decompression failed"); } - Local sliceFn = outBuf->Get(Nan::GetCurrentContext(), Nan::New("slice").ToLocalChecked()) - .ToLocalChecked().As(); - Local args[] = { - Nan::New(0), - Nan::New((uint32_t)decompressedLen) - }; - Local sliced = sliceFn->Call(Nan::GetCurrentContext(), outBuf, 2, args).ToLocalChecked(); - - info.GetReturnValue().Set(sliced); + info.GetReturnValue().Set(Nan::CopyBuffer(output.get(), decompressedLen).ToLocalChecked()); } NAN_MODULE_INIT(init) { @@ -92,4 +57,4 @@ NAN_MODULE_INIT(init) { Nan::SetMethod(target, "decompress", decompress); } -NODE_MODULE(lzf, init) +NODE_MODULE(lzf, init) \ No newline at end of file From c398005d427f55713649ee90a0311fd9149fd123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=BCrkay=20Tanrikulu?= Date: Thu, 5 Jun 2025 09:41:49 +0300 Subject: [PATCH 16/16] Update lzf.cc --- src/lzf.cc | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/lzf.cc b/src/lzf.cc index 59c66b2..f502376 100644 --- a/src/lzf.cc +++ b/src/lzf.cc @@ -9,49 +9,56 @@ using namespace v8; using namespace node; NAN_METHOD(compress) { - if (info.Length() < 1 || !info[0]->IsObject() || !Buffer::HasInstance(info[0])) { + if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { return Nan::ThrowTypeError("First argument must be a Buffer"); } - Local inputBuf = Nan::To(info[0]).ToLocalChecked(); - char* inputData = Buffer::Data(inputBuf); - size_t inputLen = Buffer::Length(inputBuf); + Local input = info[0].As(); + char* inputData = Buffer::Data(input); + size_t inputLen = Buffer::Length(input); - size_t maxOutputLen = inputLen + (inputLen / 16) + 64 + 3; - std::unique_ptr output(new char[maxOutputLen]); + size_t maxOut = inputLen + (inputLen / 16) + 64 + 3; + char* outBuf = new char[maxOut]; - unsigned int compressedLen = lzf_compress(inputData, inputLen, output.get(), maxOutputLen); - if (compressedLen == 0) { + unsigned int outLen = lzf_compress(inputData, inputLen, outBuf, maxOut); + if (outLen == 0) { + delete[] outBuf; return Nan::ThrowError("Compression failed"); } - info.GetReturnValue().Set(Nan::CopyBuffer(output.get(), compressedLen).ToLocalChecked()); + info.GetReturnValue().Set(Nan::NewBuffer(outBuf, outLen, [](char* data, void*) { + delete[] data; + }, nullptr).ToLocalChecked()); } NAN_METHOD(decompress) { - if (info.Length() < 1 || !info[0]->IsObject() || !Buffer::HasInstance(info[0])) { + if (info.Length() < 1 || !Buffer::HasInstance(info[0])) { return Nan::ThrowTypeError("First argument must be a Buffer"); } - Local inputBuf = Nan::To(info[0]).ToLocalChecked(); - char* inputData = Buffer::Data(inputBuf); - size_t inputLen = Buffer::Length(inputBuf); + Local input = info[0].As(); + char* inputData = Buffer::Data(input); + size_t inputLen = Buffer::Length(input); - size_t expectedOutLen = 1024 * 1024 * 100; + size_t expectedLen = 1024 * 1024 * 10; if (info.Length() > 1 && info[1]->IsNumber()) { - expectedOutLen = Nan::To(info[1]).FromJust(); + expectedLen = Nan::To(info[1]).FromJust(); } - std::unique_ptr output(new char[expectedOutLen]); + char* outBuf = new char[expectedLen]; + unsigned int outLen = lzf_decompress(inputData, inputLen, outBuf, expectedLen); - unsigned int decompressedLen = lzf_decompress(inputData, inputLen, output.get(), expectedOutLen); - if (decompressedLen == 0) { + if (outLen == 0) { + delete[] outBuf; return Nan::ThrowError("Decompression failed"); } - info.GetReturnValue().Set(Nan::CopyBuffer(output.get(), decompressedLen).ToLocalChecked()); + info.GetReturnValue().Set(Nan::NewBuffer(outBuf, outLen, [](char* data, void*) { + delete[] data; + }, nullptr).ToLocalChecked()); } + NAN_MODULE_INIT(init) { Nan::SetMethod(target, "compress", compress); Nan::SetMethod(target, "decompress", decompress);