载入中...
搜索中...
未找到
DataModule.cpp
浏览该文件的文档.
1
2
3#include "DataModule.h"
4#include "common/b64.h"
5#include "common/Exception.h"
6#include "HashFunction.h"
7
8#include <simplesquirrel/simplesquirrel.hpp>
9
10#include <Poco/Exception.h>
11#include <Poco/DOM/DOMParser.h>
12#include <Poco/DOM/DOMWriter.h>
13#include <Poco/JSON/Parser.h>
14#include <Poco/JSON/Stringifier.h>
15#include <Poco/XML/XMLWriter.h>
16
17// STL
18#include <cmath>
19#include <functional>
20#include <iostream>
21#include <list>
22#include <sstream>
23
24namespace eve
25{
26namespace data
27{
28
30
31void DataModule::expose(ssq::Table& table)
32{
33 auto cls = table.addClass(name, DataModule::create, false);
34 expose(cls);
35
36 auto json = table.addClass<JsonDocument>(
37 "JsonDocument",
38 std::function<JsonDocument*()>([]() { return new JsonDocument(); }),
39 true);
40 json.addFunc("empty", &JsonDocument::empty);
41 json.addFunc("isObject", &JsonDocument::isObject);
42 json.addFunc("isArray", &JsonDocument::isArray);
43
44 auto xml = table.addClass<XmlDocument>(
45 "XmlDocument",
46 std::function<XmlDocument*()>([]() { return new XmlDocument(); }),
47 true);
48 xml.addFunc("empty", &XmlDocument::empty);
49}
50
51void DataModule::expose(ssq::Class& cls)
52{
53 cls.addFunc("getName", &DataModule::getName);
54 cls.addFunc("newByteData",
55 static_cast<ByteData* (DataModule::*)(size_t)>(&DataModule::newByteData));
56 cls.addFunc("newDataView", &DataModule::newDataView);
57 cls.addFunc("newJsonDocument", &DataModule::newJsonDocument);
58 cls.addFunc("newXmlDocument", &DataModule::newXmlDocument);
59 cls.addFunc("decodeJson",
60 static_cast<JsonDocument* (DataModule::*)(const std::string&)>(&DataModule::decodeJson));
61 cls.addFunc("decodeXml",
62 static_cast<XmlDocument* (DataModule::*)(const std::string&)>(&DataModule::decodeXml));
63 cls.addFunc("encodeJson", &DataModule::encodeJson);
64 cls.addFunc("encodeXml", &DataModule::encodeXml);
65}
66
67} // data
68} // eve
69
70namespace
71{
72
73static const char hexchars[] = "0123456789abcdef";
74
75char *bytesToHex(const uint8_t *src, size_t srclen, size_t &dstlen)
76{
77 dstlen = srclen * 2;
78
79 if (dstlen == 0)
80 return nullptr;
81
82 char *dst = nullptr;
83 try
84 {
85 dst = new char[dstlen + 1];
86 }
87 catch (std::exception &)
88 {
89 throw eve::Exception("Out of memory.");
90 }
91
92 for (size_t i = 0; i < srclen; i++)
93 {
94 uint8_t b = src[i];
95 dst[i * 2 + 0] = hexchars[b >> 4];
96 dst[i * 2 + 1] = hexchars[b & 0xF];
97 }
98
99 dst[dstlen] = '\0';
100 return dst;
101}
102
103uint8_t nibble(char c)
104{
105 if (c >= '0' && c <= '9')
106 return (uint8_t) (c - '0');
107
108 if (c >= 'A' && c <= 'F')
109 return (uint8_t) (c - 'A' + 0x0a);
110
111 if (c >= 'a' && c <= 'f')
112 return (uint8_t) (c - 'a' + 0x0a);
113
114 return 0;
115}
116
117uint8_t *hexToBytes(const char *src, size_t srclen, size_t &dstlen)
118{
119 if (srclen >= 2 && src[0] == '0' && (src[1] == 'x' || src[1] == 'X'))
120 {
121 src += 2;
122 srclen -= 2;
123 }
124
125 dstlen = (srclen + 1) / 2;
126
127 if (dstlen == 0)
128 return nullptr;
129
130 uint8_t *dst = nullptr;
131 try
132 {
133 dst = new uint8_t[dstlen];
134 }
135 catch (std::exception &)
136 {
137 throw eve::Exception("Out of memory.");
138 }
139
140 for (size_t i = 0; i < dstlen; i++)
141 {
142 dst[i] = nibble(src[i * 2]) << 4;
143
144 if (i * 2 + 1 < srclen)
145 dst[i] |= nibble(src[i * 2 + 1]);
146 }
147
148 return dst;
149}
150
151} // anonymous namespace
152
153namespace eve
154{
155namespace data
156{
157
158CompressedData *compress(std::string format, const char *rawbytes, size_t rawsize, int level)
159{
160 Compressor *compressor = Compressor::getCompressor(format);
161
162 if (compressor == nullptr)
163 throw eve::Exception("Invalid compression format.");
164
165 size_t compressedsize = 0;
166 char *cbytes = compressor->compress(format, rawbytes, rawsize, level, compressedsize);
167
168 CompressedData *data = nullptr;
169
170 try
171 {
172 data = new CompressedData(format, cbytes, compressedsize, rawsize, true);
173 }
174 catch (eve::Exception &)
175 {
176 delete[] cbytes;
177 throw;
178 }
179
180 return data;
181}
182
183char *decompress(CompressedData *data, size_t &decompressedsize)
184{
185 size_t rawsize = data->getDecompressedSize();
186
187 char *rawbytes = decompress(data->getFormat(), (const char *) data->getData(),
188 data->getSize(), rawsize);
189
190 decompressedsize = rawsize;
191 return rawbytes;
192}
193
194char *decompress(std::string format, const char *cbytes, size_t compressedsize, size_t &rawsize)
195{
196 Compressor *compressor = Compressor::getCompressor(format);
197
198 if (compressor == nullptr)
199 throw eve::Exception("Invalid compression format.");
200
201 return compressor->decompress(format, cbytes, compressedsize, rawsize);
202}
203
204char *encode(std::string format, const char *src, size_t srclen, size_t &dstlen, size_t linelen)
205{
206 if (format == "hex")
207 return bytesToHex((const uint8_t *) src, srclen, dstlen);
208 else
209 return b64_encode(src, srclen, linelen, dstlen);
210}
211
212char *decode(std::string format, const char *src, size_t srclen, size_t &dstlen)
213{
214 if (format == "hex")
215 return (char *) hexToBytes(src, srclen, dstlen);
216 else
217 return b64_decode(src, srclen, dstlen);
218}
219
220std::string hash(std::string function, Data *input)
221{
222 return hash(function, (const char*) input->getData(), input->getSize());
223}
224
225std::string hash(std::string function, const char *input, uint64_t size)
226{
227 HashFunction::Value output;
228 hash(function, input, size, output);
229 return std::string(output.data, output.size);
230}
231
232void hash(std::string function, Data *input, HashFunction::Value &output)
233{
234 hash(function, (const char*) input->getData(), input->getSize(), output);
235}
236
237void hash(std::string function, const char *input, uint64_t size, HashFunction::Value &output)
238{
239 HashFunction *hashfunction = HashFunction::getHashFunction(function);
240 if (hashfunction == nullptr)
241 throw eve::Exception("Invalid hash function.");
242
243 hashfunction->hash(function, input, size, output);
244}
245
249
253
254DataView *DataModule::newDataView(Data *data, size_t offset, size_t size)
255{
256 return new DataView(data, offset, size);
257}
258
260{
261 return new ByteData(size);
262}
263
264ByteData *DataModule::newByteData(const void *d, size_t size)
265{
266 return new ByteData(d, size);
267}
268
269ByteData *DataModule::newByteData(void *d, size_t size, bool own)
270{
271 return new ByteData(d, size, own);
272}
273
278
279JsonDocument *DataModule::decodeJson(const std::string &text, std::string *error)
280{
281 try
282 {
283 Poco::JSON::Parser parser;
284 Poco::Dynamic::Var result = parser.parse(text);
285 return new JsonDocument(result);
286 }
287 catch (const Poco::Exception &ex)
288 {
289 if (error)
290 *error = ex.displayText();
291 return nullptr;
292 }
293}
294
295JsonDocument *DataModule::decodeJson(const std::string &text)
296{
297 return decodeJson(text, nullptr);
298}
299
301{
302 if (!data || !data->getData())
303 {
304 if (error)
305 *error = "null data";
306 return nullptr;
307 }
308 std::string text(static_cast<const char *>(data->getData()), data->getSize());
309 return decodeJson(text, error);
310}
311
312std::string DataModule::encodeJson(JsonDocument *doc, bool pretty)
313{
314 if (!doc)
315 return {};
316 try
317 {
318 std::ostringstream oss;
319 int indent = pretty ? 2 : 0;
320 Poco::JSON::Stringifier::stringify(doc->root(), oss, indent);
321 return oss.str();
322 }
323 catch (const Poco::Exception &)
324 {
325 return {};
326 }
327}
328
330{
331 if (!doc)
332 return nullptr;
333 std::string out = encodeJson(doc, pretty);
334 if (out.empty())
335 return nullptr;
336 return new ByteData(out.data(), out.size());
337}
338
343
344XmlDocument *DataModule::decodeXml(const std::string &text, std::string *error)
345{
346 try
347 {
348 Poco::XML::DOMParser parser;
349 Poco::AutoPtr<Poco::XML::Document> pdoc = parser.parseString(text);
350 return new XmlDocument(pdoc);
351 }
352 catch (const Poco::Exception &ex)
353 {
354 if (error)
355 *error = ex.displayText();
356 return nullptr;
357 }
358}
359
360XmlDocument *DataModule::decodeXml(const std::string &text)
361{
362 return decodeXml(text, nullptr);
363}
364
366{
367 if (!data || !data->getData())
368 {
369 if (error)
370 *error = "null data";
371 return nullptr;
372 }
373 std::string text(static_cast<const char *>(data->getData()), data->getSize());
374 return decodeXml(text, error);
375}
376
377std::string DataModule::encodeXml(XmlDocument *doc, bool pretty)
378{
379 if (!doc || !doc->get())
380 return {};
381 try
382 {
383 Poco::XML::DOMWriter writer;
384 if (pretty)
385 writer.setOptions(Poco::XML::XMLWriter::PRETTY_PRINT);
386 std::ostringstream oss;
387 writer.writeNode(oss, doc->get());
388 return oss.str();
389 }
390 catch (const Poco::Exception &)
391 {
392 return {};
393 }
394}
395
397{
398 if (!doc)
399 return nullptr;
400 std::string out = encodeXml(doc, pretty);
401 if (out.empty())
402 return nullptr;
403 return new ByteData(out.data(), out.size());
404}
405
406
407} // data
408} // eve
HSQOBJECT cls
Definition ECS.cpp:21
std::string error
uint32_t b
uint32_t c
#define Module_IMPL(ModuleName, newExpr)
Definition Module.h:24
Light2D::Data * data
const char * name
Definition RockMesh.cpp:21
int d
virtual size_t getSize() const =0
Gets the size of the Data in bytes.
virtual void * getData() const =0
Gets a pointer to the data. This pointer will obviously not be valid if the Data object is destroyed.
virtual std::string getName() const =0
In-memory byte buffer implementing eve::Data (ref-counted).
Definition ByteData.h:11
Stores byte data compressed via DataModule::compress.
Base class for backends for different compression formats.
Definition Compressor.h:14
static Compressor * getCompressor(std::string format)
Gets a Compressor that can compress and decompress a specific format. Returns null if there are no su...
virtual char * compress(std::string format, const char *data, size_t dataSize, int level, size_t &compressedSize)=0
Compresses input data, and returns the compressed result.
virtual char * decompress(std::string format, const char *data, size_t dataSize, size_t &decompressedSize)=0
Decompresses compressed data, and returns the decompressed result.
ByteData * encodeXmlData(XmlDocument *doc, bool pretty=false)
ByteData * encodeJsonData(JsonDocument *doc, bool pretty=false)
DataView * newDataView(Data *data, size_t offset, size_t size)
ByteData * newByteData(size_t size)
std::string encodeXml(XmlDocument *doc, bool pretty=false)
JsonDocument * decodeJson(const std::string &text)
XmlDocument * decodeXml(const std::string &text)
XmlDocument * newXmlDocument()
JsonDocument * newJsonDocument()
std::string encodeJson(JsonDocument *doc, bool pretty=false)
Contains a reference to a subsection of an existing Data object.
Definition DataView.h:16
static HashFunction * getHashFunction(std::string function)
Get a HashFunction instance for the given function.
virtual void hash(std::string function, const char *input, uint64_t length, Value &output) const =0
Hash the input, producing an set of bytes as output.
Thin RAII wrapper over a Poco JSON value (object/array/scalar).
bool empty() const
True when the root value is empty.
bool isObject() const
Root type predicates.
Poco::Dynamic::Var & root()
Underlying Poco dynamic value.
Thin RAII wrapper over a Poco XML DOM document.
Definition XmlDocument.h:10
Poco::XML::Document * get()
Underlying Poco document access.
bool empty() const
True when no underlying document is held.
CompressedData * compress(std::string format, const char *rawbytes, size_t rawsize, int level)
Compresses a block of memory using the given compression format.
char * decompress(CompressedData *data, size_t &decompressedsize)
Decompresses existing compressed data into raw bytes.
char * decode(std::string format, const char *src, size_t srclen, size_t &dstlen)
char * encode(std::string format, const char *src, size_t srclen, size_t &dstlen, size_t linelen)
std::string hash(std::string function, Data *input)
Hash the input, producing an set of bytes as output.
Definition Build.cpp:11
char * b64_encode(const char *src, size_t srclen, size_t linelen, size_t &dstlen)
Base64-encode data.
Definition b64.cpp:28
char * b64_decode(const char *src, size_t srclen, size_t &size)
Decode base64 encoded data.
Definition b64.cpp:102