Browse Source

Add LZ4 compression functions to public API. Expose the VectorBuffer compression/decompression functions also to script. Closes #438.

Lasse Öörni 11 years ago
parent
commit
3a93866936

+ 124 - 0
Source/Engine/IO/Compression.cpp

@@ -0,0 +1,124 @@
+//
+// Copyright (c) 2008-2014 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "Precompiled.h"
+#include "ArrayPtr.h"
+#include "Compression.h"
+#include "Deserializer.h"
+#include "Serializer.h"
+#include "VectorBuffer.h"
+
+#include <lz4.h>
+#include <lz4hc.h>
+
+namespace Urho3D
+{
+
+unsigned EstimateCompressBound(unsigned srcSize)
+{
+    return LZ4_compressBound(srcSize);
+}
+
+unsigned CompressData(void* dest, const void* src, unsigned srcSize)
+{
+    if (!dest || !src || !srcSize)
+        return 0;
+    else
+        return LZ4_compressHC((const char*)src, (char*)dest, srcSize);
+}
+
+unsigned DecompressData(void* dest, const void* src, unsigned destSize)
+{
+    if (!dest || !src || !destSize)
+        return 0;
+    else
+        return LZ4_decompress_fast((const char*)src, (char*)dest, destSize);
+}
+
+bool CompressStream(Serializer& dest, Deserializer& src)
+{
+    unsigned srcSize = src.GetSize() - src.GetPosition();
+    // Prepend the source and dest. data size in the stream so that we know to buffer & uncompress the right amount
+    if (!srcSize)
+    {
+        dest.WriteUInt(0);
+        dest.WriteUInt(0);
+        return true;
+    }
+    
+    unsigned maxDestSize = LZ4_compressBound(srcSize);
+    SharedArrayPtr<unsigned char> srcBuffer(new unsigned char[srcSize]);
+    SharedArrayPtr<unsigned char> destBuffer(new unsigned char[maxDestSize]);
+    
+    if (src.Read(srcBuffer, srcSize) != srcSize)
+        return false;
+    
+    unsigned destSize = LZ4_compressHC((const char*)srcBuffer.Get(), (char*)destBuffer.Get(), srcSize);
+    bool success = true;
+    success &= dest.WriteUInt(srcSize);
+    success &= dest.WriteUInt(destSize);
+    success &= dest.Write(destBuffer, destSize) == destSize;
+    return success;
+}
+
+bool DecompressStream(Serializer& dest, Deserializer& src)
+{
+    if (src.IsEof())
+        return false;
+    
+    unsigned destSize = src.ReadUInt();
+    unsigned srcSize = src.ReadUInt();
+    if (!srcSize || !destSize)
+        return true; // No data
+    
+    if (srcSize > src.GetSize())
+        return false; // Illegal source (packed data) size reported, possibly not valid data
+    
+    SharedArrayPtr<unsigned char> srcBuffer(new unsigned char[srcSize]);
+    SharedArrayPtr<unsigned char> destBuffer(new unsigned char[destSize]);
+    
+    if (src.Read(srcBuffer, srcSize) != srcSize)
+        return false;
+    
+    LZ4_decompress_fast((const char*)srcBuffer.Get(), (char*)destBuffer.Get(), destSize);
+    return dest.Write(destBuffer, destSize) == destSize;
+}
+
+VectorBuffer CompressVectorBuffer(VectorBuffer& src)
+{
+    VectorBuffer ret;
+    src.Seek(0);
+    CompressStream(ret, src);
+    ret.Seek(0);
+    return ret;
+}
+
+VectorBuffer DecompressVectorBuffer(VectorBuffer& src)
+{
+    VectorBuffer ret;
+    src.Seek(0);
+    DecompressStream(ret, src);
+    ret.Seek(0);
+    return ret;
+}
+
+}

+ 49 - 0
Source/Engine/IO/Compression.h

@@ -0,0 +1,49 @@
+//
+// Copyright (c) 2008-2014 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "Urho3D.h"
+
+namespace Urho3D
+{
+
+class Deserializer;
+class Serializer;
+class VectorBuffer;
+
+/// Estimate and return worst case LZ4 compressed output size for given input size.
+URHO3D_API unsigned EstimateCompressBound(unsigned srcSize);
+/// Compress data using the LZ4 algorithm and return the compressed data size. The needed destination buffer worst-case size is given by EstimateCompressBound().
+URHO3D_API unsigned CompressData(void* dest, const void* src, unsigned srcSize);
+/// Uncompress data using the LZ4 algorithm. Return the number of compressed data consumed.
+URHO3D_API unsigned DecompressData(void* dest, const void* src, unsigned destSize);
+/// Compress a source stream from current position to the destination stream using the LZ4 algorithm. Return true on success.
+URHO3D_API bool CompressStream(Serializer& dest, Deserializer& src);
+/// Decompress a compressed source stream produced using CompressStream() to the destination stream. Return true on success.
+URHO3D_API bool DecompressStream(Serializer& dest, Deserializer& src);
+/// Compress a VectorBuffer using the LZ4 algorithm and return the compressed result buffer.
+URHO3D_API VectorBuffer CompressVectorBuffer(VectorBuffer& src);
+/// Decompress a VectorBuffer produced using CompressVectorBuffer().
+URHO3D_API VectorBuffer DecompressVectorBuffer(VectorBuffer& src);
+
+}

+ 4 - 0
Source/Engine/LuaScript/pkgs/IO/Compression.pkg

@@ -0,0 +1,4 @@
+$#include "Compression.h"
+
+VectorBuffer CompressVectorBuffer(VectorBuffer& src);
+VectorBuffer DecompressVectorBuffer(VectorBuffer& src);

+ 1 - 0
Source/Engine/LuaScript/pkgs/IOLuaAPI.pkg

@@ -1,3 +1,4 @@
+$pfile "IO/Compression.pkg"
 $pfile "IO/Deserializer.pkg"
 $pfile "IO/File.pkg"
 $pfile "IO/FileSystem.pkg"

+ 5 - 0
Source/Engine/Script/IOAPI.cpp

@@ -22,6 +22,7 @@
 
 #include "Precompiled.h"
 #include "APITemplates.h"
+#include "Compression.h"
 #include "FileSystem.h"
 #include "Log.h"
 #include "PackageFile.h"
@@ -321,6 +322,10 @@ static void RegisterSerialization(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Variant", "Variant& opAssign(const VectorBuffer&in)", asFUNCTION(VariantAssignBuffer), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Variant", "VectorBuffer GetBuffer() const", asFUNCTION(VariantGetBuffer), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Variant", "bool opEquals(const VectorBuffer&in) const", asFUNCTION(VariantEqualsBuffer), asCALL_CDECL_OBJLAST);
+    
+    // Register VectorBuffer compression functions
+    engine->RegisterGlobalFunction("VectorBuffer CompressVectorBuffer(VectorBuffer&in)", asFUNCTION(CompressVectorBuffer), asCALL_CDECL);
+    engine->RegisterGlobalFunction("VectorBuffer DecompressVectorBuffer(VectorBuffer&in)", asFUNCTION(DecompressVectorBuffer), asCALL_CDECL);
 }
 
 void RegisterFileSystem(asIScriptEngine* engine)