3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "serialize.h"
22 #include "util/string.h"
24 #include "exceptions.h"
25 #include "irrlichttypes.h"
30 FloatType g_serialize_f32_type = FLOATTYPE_UNKNOWN;
37 std::string serializeString16(const std::string &plain)
42 if (plain.size() > STRING_MAX_LEN)
43 throw SerializationError("String too long for serializeString16");
44 s.reserve(2 + plain.size());
46 writeU16((u8 *)&buf[0], plain.size());
53 std::string deSerializeString16(std::istream &is)
60 throw SerializationError("deSerializeString16: size not read");
62 u16 s_size = readU16((u8 *)buf);
67 is.read(&s[0], s_size);
68 if (is.gcount() != s_size)
69 throw SerializationError("deSerializeString16: couldn't read all chars");
79 std::string serializeString32(const std::string &plain)
84 if (plain.size() > LONG_STRING_MAX_LEN)
85 throw SerializationError("String too long for serializeLongString");
86 s.reserve(4 + plain.size());
88 writeU32((u8*)&buf[0], plain.size());
94 std::string deSerializeString32(std::istream &is)
100 if (is.gcount() != 4)
101 throw SerializationError("deSerializeLongString: size not read");
103 u32 s_size = readU32((u8 *)buf);
107 // We don't really want a remote attacker to force us to allocate 4GB...
108 if (s_size > LONG_STRING_MAX_LEN) {
109 throw SerializationError("deSerializeLongString: "
110 "string too long: " + itos(s_size) + " bytes");
114 is.read(&s[0], s_size);
115 if ((u32)is.gcount() != s_size)
116 throw SerializationError("deSerializeLongString: couldn't read all chars");
122 //// JSON-like strings
125 std::string serializeJsonString(const std::string &plain)
129 tmp.reserve(plain.size() + 2);
132 for (char c : plain) {
156 if (c >= 32 && c <= 126) {
159 // We pretend that Unicode codepoints map to bytes (they don't)
160 u8 cnum = static_cast<u8>(c);
162 tmp.push_back(hex_chars[cnum >> 4]);
163 tmp.push_back(hex_chars[cnum & 0xf]);
174 static void deSerializeJsonString(std::string &s)
176 assert(s.size() >= 2);
177 assert(s.front() == '"' && s.back() == '"');
179 size_t w = 0; // write index
180 size_t i = 1; // read index
181 const size_t len = s.size() - 1; // string length with trailing quote removed
193 throw SerializationError("JSON string ended prematurely");
213 throw SerializationError("JSON string ended prematurely");
214 unsigned char v[4] = {};
215 for (int j = 0; j < 4; j++)
216 hex_digit_decode(s[i+j], v[j]);
218 u32 hexnumber = (v[0] << 12) | (v[1] << 8) | (v[2] << 4) | v[3];
219 // Note that this does not work for anything other than ASCII
220 // but these functions do not actually interact with real JSON input.
221 s[w++] = (int) hexnumber;
230 assert(w <= i && i <= len);
231 // Truncate string to current write index
235 std::string deSerializeJsonString(std::istream &is)
239 bool was_backslash = false;
241 // Parse initial doublequote
244 throw SerializationError("JSON string must start with doublequote");
247 // Grab the entire json string
251 throw SerializationError("JSON string ended prematurely");
255 was_backslash = false;
257 was_backslash = true;
259 break; // found end of string
262 deSerializeJsonString(tmp);
266 std::string serializeJsonStringIfNeeded(const std::string &s)
268 for (size_t i = 0; i < s.size(); ++i) {
269 if (s[i] <= 0x1f || s[i] >= 0x7f || s[i] == ' ' || s[i] == '\"')
270 return serializeJsonString(s);
275 std::string deSerializeJsonStringIfNeeded(std::istream &is)
277 // Check for initial quote
283 // json string: defer to the right implementation
284 return deSerializeJsonString(is);
287 // not a json string:
289 std::getline(is, tmp, ' ');
291 is.unget(); // we hit a space, put it back