/** * Copyright (c) 2006-2017 LOVE Development Team * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. **/ // LOVE #include "wrap_DataModule.h" #include "wrap_Data.h" #include "wrap_ByteData.h" #include "wrap_DataView.h" #include "wrap_CompressedData.h" #include "DataModule.h" #include "common/b64.h" // Lua 5.3 #include "libraries/lua53/lstrlib.h" // C #include #include #include #include namespace love { namespace data { int w_newDataView(lua_State *L) { Data *data = luax_checkdata(L, 1); lua_Integer offset = luaL_checkinteger(L, 2); lua_Integer size = luaL_checkinteger(L, 3); if (offset < 0 || size < 0) return luaL_error(L, "DataView offset and size must not be negative."); DataView *d = DataModule::instance.newDataView(data, (size_t) offset, (size_t) size); luax_pushtype(L, d); d->release(); return 1; } int w_newByteData(lua_State *L) { ByteData *d = nullptr; if (luax_istype(L, 1, Data::type)) { Data *data = luax_checkdata(L, 1); if (data->getSize() > std::numeric_limits::max()) return luaL_error(L, "Data's size is too large!"); lua_Integer offset = luaL_optinteger(L, 2, 0); if (offset < 0) return luaL_error(L, "Offset argument must not be negative."); lua_Integer size = luaL_optinteger(L, 3, data->getSize() - offset); if (size <= 0) return luaL_error(L, "Size argument must be greater than zero."); else if ((size_t)(offset + size) > data->getSize()) return luaL_error(L, "Offset and size arguments must fit within the given Data's size."); const char *bytes = (const char *) data->getData() + offset; luax_catchexcept(L, [&]() { d = DataModule::instance.newByteData(bytes, (size_t) size); }); } else if (lua_type(L, 1) == LUA_TSTRING) { size_t size = 0; const char *data = luaL_checklstring(L, 1, &size); luax_catchexcept(L, [&]() { d = DataModule::instance.newByteData(data, size); }); } else { lua_Integer size = luaL_checkinteger(L, 1); if (size <= 0) return luaL_error(L, "Data size must be a positive number."); luax_catchexcept(L, [&]() { d = DataModule::instance.newByteData((size_t) size); }); } luax_pushtype(L, d); d->release(); return 1; } int w_compress(lua_State *L) { const char *fstr = luaL_checkstring(L, 1); Compressor::Format format = Compressor::FORMAT_LZ4; if (!Compressor::getConstant(fstr, format)) return luax_enumerror(L, "compressed data format", Compressor::getConstants(format), fstr); int level = (int) luaL_optinteger(L, 3, -1); CompressedData *cdata = nullptr; if (lua_isstring(L, 2)) { size_t rawsize = 0; const char *rawbytes = luaL_checklstring(L, 2, &rawsize); luax_catchexcept(L, [&](){ cdata = compress(format, rawbytes, rawsize, level); }); } else { Data *rawdata = luax_checktype(L, 2); luax_catchexcept(L, [&](){ cdata = compress(format, rawdata, level); }); } luax_pushtype(L, cdata); cdata->release(); return 1; } int w_decompress(lua_State *L) { char *rawbytes = nullptr; size_t rawsize = 0; if (luax_istype(L, 1, CompressedData::type)) { CompressedData *data = luax_checkcompresseddata(L, 1); rawsize = data->getDecompressedSize(); luax_catchexcept(L, [&](){ rawbytes = decompress(data, rawsize); }); } else { Compressor::Format format = Compressor::FORMAT_LZ4; const char *fstr = luaL_checkstring(L, 1); if (!Compressor::getConstant(fstr, format)) return luax_enumerror(L, "compressed data format", Compressor::getConstants(format), fstr); size_t compressedsize = 0; const char *cbytes = nullptr; if (luax_istype(L, 2, Data::type)) { Data *data = luax_checktype(L, 2); cbytes = (const char *) data->getData(); compressedsize = data->getSize(); } else cbytes = luaL_checklstring(L, 2, &compressedsize); luax_catchexcept(L, [&](){ rawbytes = decompress(format, cbytes, compressedsize, rawsize); }); } lua_pushlstring(L, rawbytes, rawsize); delete[] rawbytes; return 1; } int w_encode(lua_State *L) { const char *formatstr = luaL_checkstring(L, 1); EncodeFormat format; if (!getConstant(formatstr, format)) return luax_enumerror(L, "encode format", getConstants(format), formatstr); size_t srclen = 0; const char *src = nullptr; if (luax_istype(L, 2, Data::type)) { Data *data = luax_totype(L, 2); src = (const char *) data->getData(); srclen = data->getSize(); } else src = luaL_checklstring(L, 2, &srclen); size_t linelen = (size_t) luaL_optinteger(L, 3, 0); size_t dstlen = 0; char *dst = nullptr; luax_catchexcept(L, [&](){ dst = encode(format, src, srclen, dstlen, linelen); }); if (dst != nullptr) lua_pushlstring(L, dst, dstlen); else lua_pushstring(L, ""); delete[] dst; return 1; } int w_decode(lua_State *L) { const char *formatstr = luaL_checkstring(L, 1); EncodeFormat format; if (!getConstant(formatstr, format)) return luax_enumerror(L, "decode format", getConstants(format), formatstr); size_t srclen = 0; const char *src = nullptr; if (luax_istype(L, 2, Data::type)) { Data *data = luax_totype(L, 2); src = (const char *) data->getData(); srclen = data->getSize(); } else src = luaL_checklstring(L, 2, &srclen); size_t dstlen = 0; char *dst = nullptr; luax_catchexcept(L, [&](){ dst = decode(format, src, srclen, dstlen); }); if (dst != nullptr) lua_pushlstring(L, dst, dstlen); else lua_pushstring(L, ""); delete[] dst; return 1; } int w_hash(lua_State *L) { const char *fstr = luaL_checkstring(L, 1); HashFunction::Function function; if (!HashFunction::getConstant(fstr, function)) return luax_enumerror(L, "hash function", HashFunction::getConstants(function), fstr); HashFunction::Value hashvalue; if (lua_isstring(L, 2)) { size_t rawsize = 0; const char *rawbytes = luaL_checklstring(L, 2, &rawsize); luax_catchexcept(L, [&](){ love::data::hash(function, rawbytes, rawsize, hashvalue); }); } else { Data *rawdata = luax_checktype(L, 2); luax_catchexcept(L, [&](){ love::data::hash(function, rawdata, hashvalue); }); } lua_pushlstring(L, hashvalue.data, hashvalue.size); return 1; } static int w_pack(lua_State *L, bool data) { const char *fmt = luaL_checkstring(L, 1); luaL_Buffer_53 b; lua53_str_pack(L, fmt, 2, &b); if (data) { Data *d = nullptr; luax_catchexcept(L, [&]() { d = DataModule::instance.newByteData(b.nelems); }); memcpy(d->getData(), b.ptr, d->getSize()); lua53_cleanupbuffer(&b); luax_pushtype(L, Data::type, d); d->release(); } else lua53_pushresult(&b); return 1; } int w_packString(lua_State *L) { return w_pack(L, false); } int w_packData(lua_State *L) { return w_pack(L, true); } int w_unpack(lua_State *L) { const char *fmt = luaL_checkstring(L, 1); const char *data = nullptr; size_t datasize = 0; if (luax_istype(L, 2, Data::type)) { Data *d = luax_checkdata(L, 2); data = (const char *) d->getData(); datasize = d->getSize(); } else data = luaL_checklstring(L, 2, &datasize); return lua53_str_unpack(L, fmt, data, datasize, 2, 3); } // List of functions to wrap. static const luaL_Reg functions[] = { { "newDataView", w_newDataView }, { "newByteData", w_newByteData }, { "compress", w_compress }, { "decompress", w_decompress }, { "encode", w_encode }, { "decode", w_decode }, { "hash", w_hash }, { "packString", w_packString }, { "packData", w_packData }, { "unpack", w_unpack }, { "getPackedSize", lua53_str_packsize }, { 0, 0 } }; static const lua_CFunction types[] = { luaopen_data, luaopen_bytedata, luaopen_dataview, luaopen_compresseddata, nullptr }; extern "C" int luaopen_love_data(lua_State *L) { DataModule::instance.retain(); WrappedModule w; w.module = &DataModule::instance; w.name = "data"; w.type = &Module::type; w.functions = functions; w.types = types; int n = luax_register_module(L, w); return n; } } // data } // love