From f80adfae956a660c6922f81ed66a878f75b48261 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Thu, 25 Jun 2015 14:13:02 -0700 Subject: [PATCH] Add LZMA --- LICENSE.md | 7 ++- lime/utils/LZMA.hx | 48 ++++++++++++++++ project/Build.xml | 5 +- project/include/utils/LZMA.h | 26 +++++++++ project/src/ExternalInterface.cpp | 41 ++++---------- project/src/utils/LZMA.cpp | 94 +++++++++++++++++++++++++++++++ 6 files changed, 187 insertions(+), 34 deletions(-) create mode 100644 lime/utils/LZMA.hx create mode 100644 project/include/utils/LZMA.h create mode 100644 project/src/utils/LZMA.cpp diff --git a/LICENSE.md b/LICENSE.md index 9134afcfe..422b2f51e 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -80,13 +80,14 @@ https://github.com/haxenme/nme legacy/ lime/utils/ByteArray.hx - lime/utils/JNI.hx + lime/utils/JNI.hx project/include/utils/ByteArray.h project/include/utils/QuickVec.h project/src/graphics/format/ project/src/graphics/opengl/ project/src/text/Font.cpp project/src/utils/ByteArray.cpp + project/src/utils/LZMA.cpp tools/utils/JavaExternGenerator.hx The following files were developed in collaboration with Sven Bergström @@ -95,8 +96,8 @@ details, see https://github.com/underscorediscovery/snow project/src/audio/openal/OpenALBindings.cpp -The typed array implementation was also developed in collaboration with Sven -Bergström and the hxtypedarray project, which is available under an "MIT" license. +The typed array implementation was developed in collaboration with Sven Bergström +and the hxtypedarray project, which is available under an "MIT" license. For details, see https://github.com/underscorediscovery/hxtypedarray ------- diff --git a/lime/utils/LZMA.hx b/lime/utils/LZMA.hx new file mode 100644 index 000000000..a3b097369 --- /dev/null +++ b/lime/utils/LZMA.hx @@ -0,0 +1,48 @@ +package lime.utils; + + +import haxe.io.Bytes; +import lime.system.System; + + +class LZMA { + + + public static function decode (bytes:ByteArray):ByteArray { + + #if (cpp || neko || nodejs) + var data = lime_lzma_decode (bytes); + return ByteArray.fromBytes (@:privateAccess new Bytes (data.length, data.b)); + #else + return null; + #end + + } + + + public static function encode (bytes:ByteArray):ByteArray { + + #if (cpp || neko || nodejs) + var data = lime_lzma_encode (bytes); + return ByteArray.fromBytes (@:privateAccess new Bytes (data.length, data.b)); + #else + return null; + #end + + } + + + + + // Native Methods + + + + + #if (cpp || neko || nodejs) + private static var lime_lzma_decode = System.load ("lime", "lime_lzma_decode", 1); + private static var lime_lzma_encode = System.load ("lime", "lime_lzma_encode", 1); + #end + + +} \ No newline at end of file diff --git a/project/Build.xml b/project/Build.xml index d02e4bf28..6c0d4d026 100644 --- a/project/Build.xml +++ b/project/Build.xml @@ -14,7 +14,7 @@ - + @@ -94,8 +94,11 @@
+ + +
diff --git a/project/include/utils/LZMA.h b/project/include/utils/LZMA.h new file mode 100644 index 000000000..301ac2b34 --- /dev/null +++ b/project/include/utils/LZMA.h @@ -0,0 +1,26 @@ +#ifndef LIME_UTILS_LZMA_H +#define LIME_UTILS_LZMA_H + + +#include + + +namespace lime { + + + class LZMA { + + + public: + + static void Decode (Bytes* data, Bytes* result); + static void Encode (Bytes* data, Bytes* result); + + + }; + + +} + + +#endif \ No newline at end of file diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 65ffa3850..d1e3de508 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -34,12 +34,9 @@ #include #include #include +#include #include -#ifdef LIME_LZMA -#include -#endif - namespace lime { @@ -675,42 +672,26 @@ namespace lime { } - value lime_lzma_decode (value input_value) { + value lime_lzma_decode (value buffer) { - #ifdef LIME_LZMA + Bytes data = Bytes (buffer); + Bytes result; - buffer input_buffer = val_to_buffer(input_value); - buffer output_buffer = alloc_buffer_len(0); + LZMA::Decode (&data, &result); - native_toolkit_lzma::Lzma::Decode (input_buffer, output_buffer); - - return buffer_val (output_buffer); - - #else - - return alloc_null (); - - #endif + return result.Value (); } - value lime_lzma_encode (value input_value) { + value lime_lzma_encode (value buffer) { - #ifdef LIME_LZMA + Bytes data = Bytes (buffer); + Bytes result; - buffer input_buffer = val_to_buffer(input_value); - buffer output_buffer = alloc_buffer_len(0); + LZMA::Encode (&data, &result); - native_toolkit_lzma::Lzma::Encode (input_buffer, output_buffer); - - return buffer_val (output_buffer); - - #else - - return alloc_null (); - - #endif + return result.Value (); } diff --git a/project/src/utils/LZMA.cpp b/project/src/utils/LZMA.cpp new file mode 100644 index 000000000..f6e341922 --- /dev/null +++ b/project/src/utils/LZMA.cpp @@ -0,0 +1,94 @@ +#include +#include "LzmaEnc.h" +#include "LzmaDec.h" + + +namespace lime { + + + inline void WRITE_LE8 (unsigned char *ptr, char value) { *ptr = value; } + inline void WRITE_LE16 (unsigned char *ptr, short value) { WRITE_LE8 ((ptr) + 0, ((value) >> 0)); WRITE_LE8 ((ptr) + 1, ((value) >> 8)); } + inline void WRITE_LE32 (unsigned char *ptr, int value) { WRITE_LE16 ((ptr) + 0, ((value) >> 0)); WRITE_LE16 ((ptr) + 2, ((value) >> 16)); } + inline void WRITE_LE64 (unsigned char *ptr, Int64 value) { WRITE_LE32 ((ptr) + 0, ((value) >> 0)); WRITE_LE32 ((ptr) + 4, ((value) >> 32)); } + + inline unsigned char READ_LE8 (unsigned char *ptr) { return *ptr; } + inline unsigned short READ_LE16 (unsigned char *ptr) { return ((unsigned short)READ_LE8 (ptr + 0) << 0) | ((unsigned short)READ_LE8 (ptr + 1) << 8); } + inline unsigned int READ_LE32 (unsigned char *ptr) { return ((unsigned int)READ_LE16 (ptr + 0) << 0) | ((unsigned int)READ_LE16 (ptr + 2) << 16); } + inline UInt64 READ_LE64 (unsigned char *ptr) { return ((UInt64)READ_LE32 (ptr + 0) << 0) | ((UInt64)READ_LE32 (ptr + 4) << 32); } + + + extern "C" { + + SRes LZMA_progress (void *p, UInt64 inSize, UInt64 outSize) { return SZ_OK; } + void *LZMA_alloc (void *p, size_t size) { return malloc (size); } + + void LZMA_free(void *p, void *address) { + + if (address == NULL) return; + free (address); + + } + + } + + + void LZMA::Decode (Bytes* data, Bytes* result) { + + SizeT inputBufferSize = data->Length (); + Byte* inputBufferData = data->Data (); + Int64 uncompressedLength = -1; + + ELzmaStatus status = LZMA_STATUS_NOT_SPECIFIED; + ISzAlloc alloc = { LZMA_alloc, LZMA_free }; + CLzmaProps props = { 0 }; + + LzmaProps_Decode (&props, inputBufferData, LZMA_PROPS_SIZE); + uncompressedLength = READ_LE64 (inputBufferData + LZMA_PROPS_SIZE); + + result->Resize ((int)uncompressedLength); + + SizeT outputBufferSize = result->Length (); + Byte* outputBufferData = result->Data (); + + Byte* _inputBufferData = inputBufferData + LZMA_PROPS_SIZE + sizeof (uncompressedLength); + SizeT _inputBufferSize = inputBufferSize - LZMA_PROPS_SIZE - sizeof (uncompressedLength); + + LzmaDecode (outputBufferData, &outputBufferSize, _inputBufferData, &_inputBufferSize, inputBufferData, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &alloc); + + } + + + void LZMA::Encode (Bytes* data, Bytes* result) { + + SizeT inputBufferSize = data->Length (); + Byte* inputBufferData = data->Data (); + + result->Resize (inputBufferSize + 1024); + + SizeT outputBufferSize = result->Length (); + Byte* outputBufferData = result->Data (); + SizeT propsSize = 100; + Byte* propsData = (Byte *)malloc (propsSize); + Int64 uncompressedLength = inputBufferSize; + + CLzmaEncProps props = { 0 }; + LzmaEncProps_Init (&props); + props.dictSize = (1 << 20); + props.writeEndMark = 0; + props.numThreads = 1; + + ICompressProgress progress = { LZMA_progress }; + ISzAlloc allocSmall = { LZMA_alloc, LZMA_free }; + ISzAlloc allocBig = { LZMA_alloc, LZMA_free }; + + LzmaEncode (outputBufferData + propsSize + 8, &outputBufferSize, inputBufferData, inputBufferSize, &props, propsData, &propsSize, props.writeEndMark, &progress, &allocSmall, &allocBig); + + memcpy (outputBufferData, propsData, propsSize); + WRITE_LE64 (outputBufferData + propsSize, uncompressedLength); + + free(propsData); + + } + + +} \ No newline at end of file