From 1b90e88d4197ccdbeafc8934fecf979cefe67ae6 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Sun, 2 Sep 2018 18:43:07 -0400 Subject: [PATCH] Add love.data.encode() (#278) * Add cppcodec * Add love.data.encode(base64) * Add love.data.encode(hex) --- .gitmodules | 5 +++++ Makefile.common | 3 +++ src/libretro.cpp | 6 ++++-- src/love/data.cpp | 35 +++++++++++++++++++++++++++++++++++ src/love/data.h | 26 ++++++++++++++++++++++++++ src/love/script.cpp | 2 ++ test/unittests/data.chai | 20 ++++++++++++++++++++ vendor/cppcodec | 1 + 8 files changed, 96 insertions(+), 2 deletions(-) create mode 160000 vendor/cppcodec diff --git a/.gitmodules b/.gitmodules index 2d0594e..55c17f6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -73,3 +73,8 @@ url = https://github.com/Didstopia/physfs.git ignore = dirty branch = master +[submodule "vendor/cppcodec"] + path = vendor/cppcodec + url = https://github.com/tplgy/cppcodec.git + ignore = dirty + branch = master diff --git a/Makefile.common b/Makefile.common index e7abb33..26d3054 100644 --- a/Makefile.common +++ b/Makefile.common @@ -147,6 +147,9 @@ SOURCES_C += $(CORE_DIR)/vendor/libretro-common/utils/md5.c # TinySHA1 FLAGS += -I$(CORE_DIR)/vendor/TinySHA1 +# cppcodec +FLAGS += -I$(CORE_DIR)/vendor/cppcodec + # ChaiScript ifeq ($(HAVE_CHAISCRIPT),) FLAGS += -I$(CORE_DIR)/vendor/chaiscript/include diff --git a/src/libretro.cpp b/src/libretro.cpp index 89a80d5..e7adb0a 100644 --- a/src/libretro.cpp +++ b/src/libretro.cpp @@ -257,7 +257,8 @@ bool retro_serialize(void *data, size_t size) { return false; } - // Compress the JSON state data. + // Encode the JSON state data. + // state = app->data.encode("string", "base64", state); state = app->data.compress(state); // Save the information to the state data. @@ -269,7 +270,7 @@ bool retro_serialize(void *data, size_t size) { * libretro callback; Unserialize the given data and load the state. */ bool retro_unserialize(const void *data, size_t size) { - if (!ChaiLove::hasInstance()) { + if (!ChaiLove::hasInstance() || size <= 0) { return false; } std::cout << "[ChaiLove] retro_unserialize" << std::endl; @@ -286,6 +287,7 @@ bool retro_unserialize(const void *data, size_t size) { ChaiLove* app = ChaiLove::getInstance(); // Decompress the state data. + // loadData = app->data.decode("string", "base64", loadData); loadData = app->data.decompress(loadData); // Finally, load the string. diff --git a/src/love/data.cpp b/src/love/data.cpp index 4aff891..5754557 100644 --- a/src/love/data.cpp +++ b/src/love/data.cpp @@ -5,9 +5,12 @@ #include #include #include +#include #include "compat/zlib.h" #include "utils/md5.h" #include "TinySHA1.hpp" +#include +#include namespace love { @@ -93,6 +96,38 @@ std::string data::decompress(const std::string& str) { return outstring; } +std::string data::encode(const std::string& containerType, const std::string& format, const std::string& sourceString) { + if (format == "base64") { + std::string encoded = base64::encode(sourceString); + return encoded; + } + + if (format == "hex") { + std::string encoded = hex::encode(sourceString); + return encoded; + } + + std::cout << "[ChaiLove] Warning: love.data.encode format not found: " << format << "." << std::endl; + return sourceString; +} + +std::string data::decode(const std::string& containerType, const std::string& format, const std::string& sourceString) { + if (format == "base64") { + std::vector decodedVector = base64::decode(sourceString); + std::string decoded(decodedVector.begin(), decodedVector.end()); + return decoded; + } + + if (format == "hex") { + std::vector decodedVector = hex::decode(sourceString); + std::string decoded(decodedVector.begin(), decodedVector.end()); + return decoded; + } + + std::cout << "[ChaiLove] Warning: love.data.decode format not found: " << format << "." << std::endl; + return sourceString; +} + std::string data::hash(const std::string& hashFunction, const std::string& data) { if (hashFunction == "md5") { return hash_md5(data); diff --git a/src/love/data.h b/src/love/data.h index 2b1d271..d369cc8 100644 --- a/src/love/data.h +++ b/src/love/data.h @@ -41,6 +41,32 @@ class data { */ std::string decompress(const std::string& str); + /** + * Encode Data or a string to a Data or string in one of the EncodeFormats. + * + * @param containerType What type to return the encoded data as. Only supports "string" currently. + * @param format The format of the output data. Can be "base64" or "hex". + * @param sourceString The raw data to encode. + * + * @return String which contains the encoded version of source. + * + * @see love.data.decode + */ + std::string encode(const std::string& containerType, const std::string& format, const std::string& sourceString); + + /** + * Decode Data or a string to a Data or string in one of the EncodeFormats. + * + * @param containerType What type to return the decoded data as. Only supports "string" currently. + * @param format The format of the input data. Can be "base64" or "hex". + * @param sourceString The raw (encoded) data to decode. + * + * @return String which contains the decoded version of source. + * + * @see love.data.encode + */ + std::string decode(const std::string& containerType, const std::string& format, const std::string& sourceString); + /** * Compute the message digest of specified string with specified algorithm. * diff --git a/src/love/script.cpp b/src/love/script.cpp index f71c5e6..c06fe1d 100644 --- a/src/love/script.cpp +++ b/src/love/script.cpp @@ -344,6 +344,8 @@ script::script(const std::string& file) { chai.add(fun(&data::compress), "compress"); chai.add(fun(&data::decompress), "decompress"); chai.add(fun(&data::hash), "hash"); + chai.add(fun(&data::encode), "encode"); + chai.add(fun(&data::decode), "decode"); // Ensure the love namespace is imported and ready. chai.import("love"); diff --git a/test/unittests/data.chai b/test/unittests/data.chai index 078b1fb..84746e2 100644 --- a/test/unittests/data.chai +++ b/test/unittests/data.chai @@ -14,3 +14,23 @@ assert_equal(md5Hash, "b10a8db164e0754105b7a99be72e3fe5", "love.data.hash('md5') // hash(sha1) var sha1Hash = love.data.hash("sha1", "Hello World") assert_equal(sha1Hash, "0a4d55a8d778e5022fab701977c5d840bbc486d0", "love.data.hash('sha1')") + +// encode(base64) +var decodedString = "any carnal pleasure" +var encodedString = "YW55IGNhcm5hbCBwbGVhc3VyZQ==" +var encodeResult = love.data.encode("string", "base64", decodedString) +assert_equal(encodeResult, encodedString, "love.data.encode('base64')") + +// decode(base64) +var decodeResult = love.data.decode("string", "base64", encodedString) +assert_equal(decodeResult, decodedString, "love.data.decode('base64')") + +// encode(hex) +var dehexedString = "Hello World" +var hexedString = "48656c6c6f20576f726c64" +var hexResult = love.data.encode("string", "hex", dehexedString) +assert_equal(hexResult, hexedString, "love.data.encode('hex')") + +// decode(hex) +var dedexResult = love.data.decode("string", "hex", hexedString) +assert_equal(dedexResult, dehexedString, "love.data.decode('hex')") diff --git a/vendor/cppcodec b/vendor/cppcodec new file mode 160000 index 0000000..302dc28 --- /dev/null +++ b/vendor/cppcodec @@ -0,0 +1 @@ +Subproject commit 302dc28f8fd5c8bf2ea8d7212aed3be884d5d166