incrementaltp: respect physics overrides
[waspsaliva.git] / src / util / serialize.cpp
blobd770101f20b19c585fc1ea98a5ad77dceb24fbea
1 /*
2 Minetest
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"
21 #include "pointer.h"
22 #include "porting.h"
23 #include "util/string.h"
24 #include "exceptions.h"
25 #include "irrlichttypes.h"
27 #include <sstream>
28 #include <iomanip>
29 #include <vector>
31 FloatType g_serialize_f32_type = FLOATTYPE_UNKNOWN;
34 ////
35 //// String
36 ////
38 std::string serializeString16(const std::string &plain)
40 std::string s;
41 char buf[2];
43 if (plain.size() > STRING_MAX_LEN)
44 throw SerializationError("String too long for serializeString16");
45 s.reserve(2 + plain.size());
47 writeU16((u8 *)&buf[0], plain.size());
48 s.append(buf, 2);
50 s.append(plain);
51 return s;
54 std::string deSerializeString16(std::istream &is)
56 std::string s;
57 char buf[2];
59 is.read(buf, 2);
60 if (is.gcount() != 2)
61 throw SerializationError("deSerializeString16: size not read");
63 u16 s_size = readU16((u8 *)buf);
64 if (s_size == 0)
65 return s;
67 s.resize(s_size);
68 is.read(&s[0], s_size);
69 if (is.gcount() != s_size)
70 throw SerializationError("deSerializeString16: couldn't read all chars");
72 return s;
76 ////
77 //// Long String
78 ////
80 std::string serializeString32(const std::string &plain)
82 std::string s;
83 char buf[4];
85 if (plain.size() > LONG_STRING_MAX_LEN)
86 throw SerializationError("String too long for serializeLongString");
87 s.reserve(4 + plain.size());
89 writeU32((u8*)&buf[0], plain.size());
90 s.append(buf, 4);
91 s.append(plain);
92 return s;
95 std::string deSerializeString32(std::istream &is)
97 std::string s;
98 char buf[4];
100 is.read(buf, 4);
101 if (is.gcount() != 4)
102 throw SerializationError("deSerializeLongString: size not read");
104 u32 s_size = readU32((u8 *)buf);
105 if (s_size == 0)
106 return s;
108 // We don't really want a remote attacker to force us to allocate 4GB...
109 if (s_size > LONG_STRING_MAX_LEN) {
110 throw SerializationError("deSerializeLongString: "
111 "string too long: " + itos(s_size) + " bytes");
114 s.resize(s_size);
115 is.read(&s[0], s_size);
116 if ((u32)is.gcount() != s_size)
117 throw SerializationError("deSerializeLongString: couldn't read all chars");
119 return s;
122 ////
123 //// JSON
124 ////
126 std::string serializeJsonString(const std::string &plain)
128 std::ostringstream os(std::ios::binary);
129 os << "\"";
131 for (char c : plain) {
132 switch (c) {
133 case '"':
134 os << "\\\"";
135 break;
136 case '\\':
137 os << "\\\\";
138 break;
139 case '/':
140 os << "\\/";
141 break;
142 case '\b':
143 os << "\\b";
144 break;
145 case '\f':
146 os << "\\f";
147 break;
148 case '\n':
149 os << "\\n";
150 break;
151 case '\r':
152 os << "\\r";
153 break;
154 case '\t':
155 os << "\\t";
156 break;
157 default: {
158 if (c >= 32 && c <= 126) {
159 os << c;
160 } else {
161 u32 cnum = (u8)c;
162 os << "\\u" << std::hex << std::setw(4)
163 << std::setfill('0') << cnum;
165 break;
170 os << "\"";
171 return os.str();
174 std::string deSerializeJsonString(std::istream &is)
176 std::ostringstream os(std::ios::binary);
177 char c, c2;
179 // Parse initial doublequote
180 is >> c;
181 if (c != '"')
182 throw SerializationError("JSON string must start with doublequote");
184 // Parse characters
185 for (;;) {
186 c = is.get();
187 if (is.eof())
188 throw SerializationError("JSON string ended prematurely");
190 if (c == '"') {
191 return os.str();
194 if (c == '\\') {
195 c2 = is.get();
196 if (is.eof())
197 throw SerializationError("JSON string ended prematurely");
198 switch (c2) {
199 case 'b':
200 os << '\b';
201 break;
202 case 'f':
203 os << '\f';
204 break;
205 case 'n':
206 os << '\n';
207 break;
208 case 'r':
209 os << '\r';
210 break;
211 case 't':
212 os << '\t';
213 break;
214 case 'u': {
215 int hexnumber;
216 char hexdigits[4 + 1];
218 is.read(hexdigits, 4);
219 if (is.eof())
220 throw SerializationError("JSON string ended prematurely");
221 hexdigits[4] = 0;
223 std::istringstream tmp_is(hexdigits, std::ios::binary);
224 tmp_is >> std::hex >> hexnumber;
225 os << (char)hexnumber;
226 break;
228 default:
229 os << c2;
230 break;
232 } else {
233 os << c;
237 return os.str();
240 std::string serializeJsonStringIfNeeded(const std::string &s)
242 for (size_t i = 0; i < s.size(); ++i) {
243 if (s[i] <= 0x1f || s[i] >= 0x7f || s[i] == ' ' || s[i] == '\"')
244 return serializeJsonString(s);
246 return s;
249 std::string deSerializeJsonStringIfNeeded(std::istream &is)
251 std::ostringstream tmp_os;
252 bool expect_initial_quote = true;
253 bool is_json = false;
254 bool was_backslash = false;
255 for (;;) {
256 char c = is.get();
257 if (is.eof())
258 break;
260 if (expect_initial_quote && c == '"') {
261 tmp_os << c;
262 is_json = true;
263 } else if(is_json) {
264 tmp_os << c;
265 if (was_backslash)
266 was_backslash = false;
267 else if (c == '\\')
268 was_backslash = true;
269 else if (c == '"')
270 break; // Found end of string
271 } else {
272 if (c == ' ') {
273 // Found end of word
274 is.unget();
275 break;
278 tmp_os << c;
280 expect_initial_quote = false;
282 if (is_json) {
283 std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
284 return deSerializeJsonString(tmp_is);
287 return tmp_os.str();