wrap_DataModule.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /**
  2. * Copyright (c) 2006-2017 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. // LOVE
  21. #include "wrap_DataModule.h"
  22. #include "wrap_Data.h"
  23. #include "wrap_ByteData.h"
  24. #include "wrap_DataView.h"
  25. #include "wrap_CompressedData.h"
  26. #include "DataModule.h"
  27. #include "common/b64.h"
  28. // Lua 5.3
  29. #include "libraries/lua53/lstrlib.h"
  30. // C
  31. #include <cmath>
  32. #include <iostream>
  33. #include <algorithm>
  34. #include <limits>
  35. namespace love
  36. {
  37. namespace data
  38. {
  39. int w_newDataView(lua_State *L)
  40. {
  41. Data *data = luax_checkdata(L, 1);
  42. lua_Integer offset = luaL_checkinteger(L, 2);
  43. lua_Integer size = luaL_checkinteger(L, 3);
  44. if (offset < 0 || size < 0)
  45. return luaL_error(L, "DataView offset and size must not be negative.");
  46. DataView *d = DataModule::instance.newDataView(data, (size_t) offset, (size_t) size);
  47. luax_pushtype(L, d);
  48. d->release();
  49. return 1;
  50. }
  51. int w_newByteData(lua_State *L)
  52. {
  53. ByteData *d = nullptr;
  54. if (luax_istype(L, 1, Data::type))
  55. {
  56. Data *data = luax_checkdata(L, 1);
  57. if (data->getSize() > std::numeric_limits<lua_Integer>::max())
  58. return luaL_error(L, "Data's size is too large!");
  59. lua_Integer offset = luaL_optinteger(L, 2, 0);
  60. if (offset < 0)
  61. return luaL_error(L, "Offset argument must not be negative.");
  62. lua_Integer size = luaL_optinteger(L, 3, data->getSize() - offset);
  63. if (size <= 0)
  64. return luaL_error(L, "Size argument must be greater than zero.");
  65. else if ((size_t)(offset + size) > data->getSize())
  66. return luaL_error(L, "Offset and size arguments must fit within the given Data's size.");
  67. const char *bytes = (const char *) data->getData() + offset;
  68. luax_catchexcept(L, [&]() { d = DataModule::instance.newByteData(bytes, (size_t) size); });
  69. }
  70. else if (lua_type(L, 1) == LUA_TSTRING)
  71. {
  72. size_t size = 0;
  73. const char *data = luaL_checklstring(L, 1, &size);
  74. luax_catchexcept(L, [&]() { d = DataModule::instance.newByteData(data, size); });
  75. }
  76. else
  77. {
  78. lua_Integer size = luaL_checkinteger(L, 1);
  79. if (size <= 0)
  80. return luaL_error(L, "Data size must be a positive number.");
  81. luax_catchexcept(L, [&]() { d = DataModule::instance.newByteData((size_t) size); });
  82. }
  83. luax_pushtype(L, d);
  84. d->release();
  85. return 1;
  86. }
  87. int w_compress(lua_State *L)
  88. {
  89. const char *fstr = luaL_checkstring(L, 1);
  90. Compressor::Format format = Compressor::FORMAT_LZ4;
  91. if (!Compressor::getConstant(fstr, format))
  92. return luax_enumerror(L, "compressed data format", Compressor::getConstants(format), fstr);
  93. int level = (int) luaL_optinteger(L, 3, -1);
  94. CompressedData *cdata = nullptr;
  95. if (lua_isstring(L, 2))
  96. {
  97. size_t rawsize = 0;
  98. const char *rawbytes = luaL_checklstring(L, 2, &rawsize);
  99. luax_catchexcept(L, [&](){ cdata = compress(format, rawbytes, rawsize, level); });
  100. }
  101. else
  102. {
  103. Data *rawdata = luax_checktype<Data>(L, 2);
  104. luax_catchexcept(L, [&](){ cdata = compress(format, rawdata, level); });
  105. }
  106. luax_pushtype(L, cdata);
  107. cdata->release();
  108. return 1;
  109. }
  110. int w_decompress(lua_State *L)
  111. {
  112. char *rawbytes = nullptr;
  113. size_t rawsize = 0;
  114. if (luax_istype(L, 1, CompressedData::type))
  115. {
  116. CompressedData *data = luax_checkcompresseddata(L, 1);
  117. rawsize = data->getDecompressedSize();
  118. luax_catchexcept(L, [&](){ rawbytes = decompress(data, rawsize); });
  119. }
  120. else
  121. {
  122. Compressor::Format format = Compressor::FORMAT_LZ4;
  123. const char *fstr = luaL_checkstring(L, 1);
  124. if (!Compressor::getConstant(fstr, format))
  125. return luax_enumerror(L, "compressed data format", Compressor::getConstants(format), fstr);
  126. size_t compressedsize = 0;
  127. const char *cbytes = nullptr;
  128. if (luax_istype(L, 2, Data::type))
  129. {
  130. Data *data = luax_checktype<Data>(L, 2);
  131. cbytes = (const char *) data->getData();
  132. compressedsize = data->getSize();
  133. }
  134. else
  135. cbytes = luaL_checklstring(L, 2, &compressedsize);
  136. luax_catchexcept(L, [&](){ rawbytes = decompress(format, cbytes, compressedsize, rawsize); });
  137. }
  138. lua_pushlstring(L, rawbytes, rawsize);
  139. delete[] rawbytes;
  140. return 1;
  141. }
  142. int w_encode(lua_State *L)
  143. {
  144. const char *formatstr = luaL_checkstring(L, 1);
  145. EncodeFormat format;
  146. if (!getConstant(formatstr, format))
  147. return luax_enumerror(L, "encode format", getConstants(format), formatstr);
  148. size_t srclen = 0;
  149. const char *src = nullptr;
  150. if (luax_istype(L, 2, Data::type))
  151. {
  152. Data *data = luax_totype<Data>(L, 2);
  153. src = (const char *) data->getData();
  154. srclen = data->getSize();
  155. }
  156. else
  157. src = luaL_checklstring(L, 2, &srclen);
  158. size_t linelen = (size_t) luaL_optinteger(L, 3, 0);
  159. size_t dstlen = 0;
  160. char *dst = nullptr;
  161. luax_catchexcept(L, [&](){ dst = encode(format, src, srclen, dstlen, linelen); });
  162. if (dst != nullptr)
  163. lua_pushlstring(L, dst, dstlen);
  164. else
  165. lua_pushstring(L, "");
  166. delete[] dst;
  167. return 1;
  168. }
  169. int w_decode(lua_State *L)
  170. {
  171. const char *formatstr = luaL_checkstring(L, 1);
  172. EncodeFormat format;
  173. if (!getConstant(formatstr, format))
  174. return luax_enumerror(L, "decode format", getConstants(format), formatstr);
  175. size_t srclen = 0;
  176. const char *src = nullptr;
  177. if (luax_istype(L, 2, Data::type))
  178. {
  179. Data *data = luax_totype<Data>(L, 2);
  180. src = (const char *) data->getData();
  181. srclen = data->getSize();
  182. }
  183. else
  184. src = luaL_checklstring(L, 2, &srclen);
  185. size_t dstlen = 0;
  186. char *dst = nullptr;
  187. luax_catchexcept(L, [&](){ dst = decode(format, src, srclen, dstlen); });
  188. if (dst != nullptr)
  189. lua_pushlstring(L, dst, dstlen);
  190. else
  191. lua_pushstring(L, "");
  192. delete[] dst;
  193. return 1;
  194. }
  195. int w_hash(lua_State *L)
  196. {
  197. const char *fstr = luaL_checkstring(L, 1);
  198. HashFunction::Function function;
  199. if (!HashFunction::getConstant(fstr, function))
  200. return luax_enumerror(L, "hash function", HashFunction::getConstants(function), fstr);
  201. HashFunction::Value hashvalue;
  202. if (lua_isstring(L, 2))
  203. {
  204. size_t rawsize = 0;
  205. const char *rawbytes = luaL_checklstring(L, 2, &rawsize);
  206. luax_catchexcept(L, [&](){ love::data::hash(function, rawbytes, rawsize, hashvalue); });
  207. }
  208. else
  209. {
  210. Data *rawdata = luax_checktype<Data>(L, 2);
  211. luax_catchexcept(L, [&](){ love::data::hash(function, rawdata, hashvalue); });
  212. }
  213. lua_pushlstring(L, hashvalue.data, hashvalue.size);
  214. return 1;
  215. }
  216. static int w_pack(lua_State *L, bool data)
  217. {
  218. const char *fmt = luaL_checkstring(L, 1);
  219. luaL_Buffer_53 b;
  220. lua53_str_pack(L, fmt, 2, &b);
  221. if (data)
  222. {
  223. Data *d = nullptr;
  224. luax_catchexcept(L, [&]() { d = DataModule::instance.newByteData(b.nelems); });
  225. memcpy(d->getData(), b.ptr, d->getSize());
  226. lua53_cleanupbuffer(&b);
  227. luax_pushtype(L, Data::type, d);
  228. d->release();
  229. }
  230. else
  231. lua53_pushresult(&b);
  232. return 1;
  233. }
  234. int w_packString(lua_State *L)
  235. {
  236. return w_pack(L, false);
  237. }
  238. int w_packData(lua_State *L)
  239. {
  240. return w_pack(L, true);
  241. }
  242. int w_unpack(lua_State *L)
  243. {
  244. const char *fmt = luaL_checkstring(L, 1);
  245. const char *data = nullptr;
  246. size_t datasize = 0;
  247. if (luax_istype(L, 2, Data::type))
  248. {
  249. Data *d = luax_checkdata(L, 2);
  250. data = (const char *) d->getData();
  251. datasize = d->getSize();
  252. }
  253. else
  254. data = luaL_checklstring(L, 2, &datasize);
  255. return lua53_str_unpack(L, fmt, data, datasize, 2, 3);
  256. }
  257. // List of functions to wrap.
  258. static const luaL_Reg functions[] =
  259. {
  260. { "newDataView", w_newDataView },
  261. { "newByteData", w_newByteData },
  262. { "compress", w_compress },
  263. { "decompress", w_decompress },
  264. { "encode", w_encode },
  265. { "decode", w_decode },
  266. { "hash", w_hash },
  267. { "packString", w_packString },
  268. { "packData", w_packData },
  269. { "unpack", w_unpack },
  270. { "getPackedSize", lua53_str_packsize },
  271. { 0, 0 }
  272. };
  273. static const lua_CFunction types[] =
  274. {
  275. luaopen_data,
  276. luaopen_bytedata,
  277. luaopen_dataview,
  278. luaopen_compresseddata,
  279. nullptr
  280. };
  281. extern "C" int luaopen_love_data(lua_State *L)
  282. {
  283. DataModule::instance.retain();
  284. WrappedModule w;
  285. w.module = &DataModule::instance;
  286. w.name = "data";
  287. w.type = &Module::type;
  288. w.functions = functions;
  289. w.types = types;
  290. int n = luax_register_module(L, w);
  291. return n;
  292. }
  293. } // data
  294. } // love