1 /*
2 * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2015
3 * Martin Lambers <marlam@marlam.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
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 General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "config.h"
20
21 #include <cstring>
22
23 #include "base/str.h"
24
25 #include "base/ser.h"
26
27
28 static const char* low_char_encodings[] = {
29 "\\(NUL)", // 0
30 "\\(SOH)", // 1
31 "\\(STX)", // 2
32 "\\(ETX)", // 3
33 "\\(EOT)", // 4
34 "\\(ENQ)", // 5
35 "\\(ACK)", // 6
36 "\\(BEL)", // 7
37 "\\(_BS)", // 8
38 "\\(_HT)", // 9
39 "\\(_LF)", // 10
40 "\\(_VT)", // 11
41 "\\(_FF)", // 12
42 "\\(_CR)", // 13
43 "\\(_SO)", // 14
44 "\\(_SI)", // 15
45 "\\(DLE)", // 16
46 "\\(DC1)", // 17
47 "\\(DC2)", // 18
48 "\\(DC3)", // 19
49 "\\(DC4)", // 20
50 "\\(NAK)", // 21
51 "\\(SYN)", // 22
52 "\\(ETB)", // 23
53 "\\(CAN)", // 24
54 "\\(_EM)", // 25
55 "\\(SUB)", // 26
56 "\\(ESC)", // 27
57 "\\(_FS)", // 28
58 "\\(_GS)", // 29
59 "\\(_RS)", // 30
60 "\\(_US)", // 31
61 };
62
63
startgroup(std::ostream & os,const char * name)64 void s11n::startgroup(std::ostream& os, const char* name)
65 {
66 os << ' ' << name << "={";
67 }
68
endgroup(std::ostream & os)69 void s11n::endgroup(std::ostream& os)
70 {
71 os << " }";
72 }
73
load(std::istream & is,std::string & name,std::string & value)74 void s11n::load(std::istream& is, std::string& name, std::string& value)
75 {
76 char c;
77 // skip leading spaces
78 while (is.good() && (c = is.get()) == ' ');
79 // read name
80 name.clear();
81 while (is.good() && c != '=') {
82 name.push_back(c);
83 c = is.get();
84 }
85 c = is.get();
86 // read value
87 value.clear();
88 bool value_is_valid = false;
89 int group_depth = 0;
90 char enc_char[] = "\\(...)";
91 for (;;) {
92 bool c_is_valid = false;
93 if (c == '\\') {
94 c = is.get();
95 if (c == '\\' || c == ' ' || c == '{' || c == '}') {
96 c_is_valid = true;
97 } else {
98 enc_char[1] = c;
99 enc_char[2] = is.get();
100 enc_char[3] = is.get();
101 enc_char[4] = is.get();
102 enc_char[5] = is.get();
103 if (std::memcmp(enc_char, "\\(DEL)", 6) == 0) {
104 c = 127;
105 c_is_valid = true;
106 } else {
107 for (int j = 0; j <= 31; j++) {
108 if (std::memcmp(enc_char, low_char_encodings[j], 6) == 0) {
109 c = j;
110 c_is_valid = true;
111 break;
112 }
113 }
114 }
115 }
116 } else {
117 if (c == '{') {
118 group_depth++;
119 } else if (c == '}') {
120 group_depth--;
121 if (group_depth < 0)
122 break;
123 }
124 c_is_valid = true;
125 }
126 if (!c_is_valid || !is.good())
127 break;
128 value.append(1, c);
129 if (group_depth == 0 && (is.peek() == ' ' || is.eof())) {
130 value_is_valid = true;
131 break;
132 }
133 c = is.get();
134 }
135 if (!value_is_valid)
136 value = "";
137 else if (value.length() >= 2 && value[0] == '{' && value[value.length() - 1] == '}')
138 value = value.substr(1, value.length() - 2);
139 }
140
save(std::ostream & os,const char * name) const141 void serializable::save(std::ostream& os, const char* name) const
142 {
143 // Default implementation: use binary save and store binary blob
144 std::ostringstream oss;
145 this->save(oss);
146 s11n::startgroup(os, name);
147 s11n::save(os, "size", oss.str().length());
148 s11n::save(os, "", oss.str().data(), oss.str().length());
149 s11n::endgroup(os);
150 }
151
load(const std::string & s)152 void serializable::load(const std::string& s)
153 {
154 // Default implementation: read and restore binary blob
155 std::istringstream iss(s);
156 std::string name, value;
157 s11n::load(iss, name, value);
158 size_t size = 0;
159 if (name == "size")
160 s11n::load(value, size);
161 s11n::load(iss, name, value);
162 std::string str;
163 char* buf = new char[size];
164 s11n::load(value, buf, size);
165 str.assign(buf, size);
166 delete[] buf;
167 std::istringstream iss2(str);
168 this->load(iss2);
169 }
170
171 // Return value NULL means the character can be written as is.
enc_char(char x)172 static const char* enc_char(char x)
173 {
174 return (x >= 0 && x <= 31 ? low_char_encodings[static_cast<int>(x)]
175 : x == 127 ? "\\(DEL)"
176 : x == '{' ? "\\{"
177 : x == '}' ? "\\}"
178 : x == ' ' ? "\\ "
179 : x == '\\' ? "\\\\"
180 : NULL);
181 }
182
183 // Decode a character. The index i is incremented according to the characters consumed from s.
dec_char(const char * s,size_t & i)184 static char dec_char(const char* s, size_t& i)
185 {
186 if (s[i] == '\\') {
187 if (s[i + 1] == '\\' || s[i + 1] == ' ' || s[i + 1] == '{' || s[i + 1] == '}') {
188 i++;
189 return s[i++];
190 } else if (s[i + 1] != '\0' && s[i + 2] != '\0' && s[i + 3] != '\0' && s[i + 4] != '\0' && s[i + 5] != '\0') {
191 if (std::memcmp(s, "\\(DEL)", 6) == 0) {
192 i += 6;
193 return 127;
194 } else {
195 for (int j = 0; j <= 31; j++) {
196 if (std::memcmp(s, low_char_encodings[j], 6) == 0) {
197 i += 6;
198 return j;
199 }
200 }
201 // invalid string!
202 return '\0';
203 }
204 } else {
205 // invalid string!
206 return '\0';
207 }
208 } else {
209 return s[i++];
210 }
211 }
212
213 /*
214 * Save a value to a stream
215 */
216
217 // Fundamental arithmetic data types
218
save(std::ostream & os,bool x)219 void s11n::save(std::ostream& os, bool x)
220 {
221 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
222 }
223
save(std::ostream & os,const char * name,bool x)224 void s11n::save(std::ostream& os, const char* name, bool x)
225 {
226 os << ' ' << name << '=' << (x ? '1' : '0');
227 }
228
save(std::ostream & os,char x)229 void s11n::save(std::ostream& os, char x)
230 {
231 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
232 }
233
save(std::ostream & os,const char * name,char x)234 void s11n::save(std::ostream& os, const char* name, char x)
235 {
236 const char* e = enc_char(x);
237 os << ' ' << name << '=';
238 if (e)
239 os << e;
240 else
241 os << x;
242 }
243
save(std::ostream & os,signed char x)244 void s11n::save(std::ostream& os, signed char x)
245 {
246 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
247 }
248
save(std::ostream & os,const char * name,signed char x)249 void s11n::save(std::ostream& os, const char* name, signed char x)
250 {
251 os << ' ' << name << '=' << static_cast<int>(x);
252 }
253
save(std::ostream & os,unsigned char x)254 void s11n::save(std::ostream& os, unsigned char x)
255 {
256 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
257 }
258
save(std::ostream & os,const char * name,unsigned char x)259 void s11n::save(std::ostream& os, const char* name, unsigned char x)
260 {
261 os << ' ' << name << '=' << static_cast<int>(x);
262 }
263
save(std::ostream & os,short x)264 void s11n::save(std::ostream& os, short x)
265 {
266 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
267 }
268
save(std::ostream & os,const char * name,short x)269 void s11n::save(std::ostream& os, const char* name, short x)
270 {
271 os << ' ' << name << '=' << x;
272 }
273
save(std::ostream & os,unsigned short x)274 void s11n::save(std::ostream& os, unsigned short x)
275 {
276 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
277 }
278
save(std::ostream & os,const char * name,unsigned short x)279 void s11n::save(std::ostream& os, const char* name, unsigned short x)
280 {
281 os << ' ' << name << '=' << x;
282 }
283
save(std::ostream & os,int x)284 void s11n::save(std::ostream& os, int x)
285 {
286 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
287 }
288
save(std::ostream & os,const char * name,int x)289 void s11n::save(std::ostream& os, const char* name, int x)
290 {
291 os << ' ' << name << '=' << x;
292 }
293
save(std::ostream & os,unsigned int x)294 void s11n::save(std::ostream& os, unsigned int x)
295 {
296 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
297 }
298
save(std::ostream & os,const char * name,unsigned int x)299 void s11n::save(std::ostream& os, const char* name, unsigned int x)
300 {
301 os << ' ' << name << '=' << x;
302 }
303
save(std::ostream & os,long x)304 void s11n::save(std::ostream& os, long x)
305 {
306 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
307 }
308
save(std::ostream & os,const char * name,long x)309 void s11n::save(std::ostream& os, const char* name, long x)
310 {
311 os << ' ' << name << '=' << x;
312 }
313
save(std::ostream & os,unsigned long x)314 void s11n::save(std::ostream& os, unsigned long x)
315 {
316 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
317 }
318
save(std::ostream & os,const char * name,unsigned long x)319 void s11n::save(std::ostream& os, const char* name, unsigned long x)
320 {
321 os << ' ' << name << '=' << x;
322 }
323
save(std::ostream & os,long long x)324 void s11n::save(std::ostream& os, long long x)
325 {
326 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
327 }
328
save(std::ostream & os,const char * name,long long x)329 void s11n::save(std::ostream& os, const char* name, long long x)
330 {
331 os << ' ' << name << '=' << x;
332 }
333
save(std::ostream & os,unsigned long long x)334 void s11n::save(std::ostream& os, unsigned long long x)
335 {
336 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
337 }
338
save(std::ostream & os,const char * name,unsigned long long x)339 void s11n::save(std::ostream& os, const char* name, unsigned long long x)
340 {
341 os << ' ' << name << '=' << x;
342 }
343
save(std::ostream & os,float x)344 void s11n::save(std::ostream& os, float x)
345 {
346 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
347 }
348
save(std::ostream & os,const char * name,float x)349 void s11n::save(std::ostream& os, const char* name, float x)
350 {
351 os << ' ' << name << '=' << str::from(x).c_str();
352 }
353
save(std::ostream & os,double x)354 void s11n::save(std::ostream& os, double x)
355 {
356 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
357 }
358
save(std::ostream & os,const char * name,double x)359 void s11n::save(std::ostream& os, const char* name, double x)
360 {
361 os << ' ' << name << '=' << str::from(x).c_str();
362 }
363
save(std::ostream & os,long double x)364 void s11n::save(std::ostream& os, long double x)
365 {
366 os.write(reinterpret_cast<const char*>(&x), sizeof(x));
367 }
368
save(std::ostream & os,const char * name,long double x)369 void s11n::save(std::ostream& os, const char* name, long double x)
370 {
371 os << ' ' << name << '=' << str::from(x).c_str();
372 }
373
374 // Binary blobs
375
save(std::ostream & os,const void * x,const size_t n)376 void s11n::save(std::ostream& os, const void* x, const size_t n)
377 {
378 os.write(reinterpret_cast<const char*>(x), n);
379 }
380
save(std::ostream & os,const char * name,const void * x,const size_t n)381 void s11n::save(std::ostream& os, const char* name, const void* x, const size_t n)
382 {
383 static const char hex[] = "0123456789abcdef";
384 startgroup(os, name);
385 for (size_t i = 0; i < n; i++) {
386 unsigned char val = static_cast<const unsigned char*>(x)[i];
387 os << hex[(val >> 4) & 0xf] << hex[val & 0xf];
388 if (i < n - 1)
389 os << ' ';
390 }
391 endgroup(os);
392 }
393
394 // Serializable classes
395
save(std::ostream & os,const serializable & x)396 void s11n::save(std::ostream& os, const serializable& x)
397 {
398 x.save(os);
399 }
400
save(std::ostream & os,const char * name,const serializable & x)401 void s11n::save(std::ostream& os, const char* name, const serializable& x)
402 {
403 x.save(os, name);
404 }
405
406 // Basic STL types
407
save(std::ostream & os,const std::string & x)408 void s11n::save(std::ostream& os, const std::string& x)
409 {
410 size_t s = x.length();
411 os.write(reinterpret_cast<const char*>(&s), sizeof(s));
412 os.write(reinterpret_cast<const char*>(x.data()), s);
413 }
414
save(std::ostream & os,const char * name,const std::string & x)415 void s11n::save(std::ostream& os, const char* name, const std::string& x)
416 {
417 os << ' ' << name << '=';
418 for (size_t i = 0; i < x.length(); i++) {
419 char c = x[i];
420 const char* e = enc_char(c);
421 if (e)
422 os << e;
423 else
424 os << c;
425 }
426 }
427
428
429 /*
430 * Load a value from a stream
431 */
432
433 // Fundamental arithmetic data types
434
load(std::istream & is,bool & x)435 void s11n::load(std::istream& is, bool& x)
436 {
437 is.read(reinterpret_cast<char*>(&x), sizeof(x));
438 }
439
load(const std::string & s,bool & x)440 void s11n::load(const std::string& s, bool& x)
441 {
442 x = str::to<bool>(s);
443 }
444
load(std::istream & is,char & x)445 void s11n::load(std::istream& is, char& x)
446 {
447 is.read(reinterpret_cast<char*>(&x), sizeof(x));
448 }
449
load(const std::string & s,char & x)450 void s11n::load(const std::string& s, char& x)
451 {
452 size_t i = 0;
453 x = dec_char(s.c_str(), i);
454 }
455
load(std::istream & is,signed char & x)456 void s11n::load(std::istream& is, signed char& x)
457 {
458 is.read(reinterpret_cast<char*>(&x), sizeof(x));
459 }
460
load(const std::string & s,signed char & x)461 void s11n::load(const std::string& s, signed char& x)
462 {
463 x = str::to<int>(s);
464 }
465
load(std::istream & is,unsigned char & x)466 void s11n::load(std::istream& is, unsigned char& x)
467 {
468 is.read(reinterpret_cast<char*>(&x), sizeof(x));
469 }
470
load(const std::string & s,unsigned char & x)471 void s11n::load(const std::string& s, unsigned char& x)
472 {
473 x = str::to<unsigned int>(s);
474 }
475
load(std::istream & is,short & x)476 void s11n::load(std::istream& is, short& x)
477 {
478 is.read(reinterpret_cast<char*>(&x), sizeof(x));
479 }
480
load(const std::string & s,short & x)481 void s11n::load(const std::string& s, short& x)
482 {
483 x = str::to<short>(s);
484 }
485
load(std::istream & is,unsigned short & x)486 void s11n::load(std::istream& is, unsigned short& x)
487 {
488 is.read(reinterpret_cast<char*>(&x), sizeof(x));
489 }
490
load(const std::string & s,unsigned short & x)491 void s11n::load(const std::string& s, unsigned short& x)
492 {
493 x = str::to<unsigned short>(s);
494 }
495
load(std::istream & is,int & x)496 void s11n::load(std::istream& is, int& x)
497 {
498 is.read(reinterpret_cast<char*>(&x), sizeof(x));
499 }
500
load(const std::string & s,int & x)501 void s11n::load(const std::string& s, int& x)
502 {
503 x = str::to<int>(s);
504 }
505
load(std::istream & is,unsigned int & x)506 void s11n::load(std::istream& is, unsigned int& x)
507 {
508 is.read(reinterpret_cast<char*>(&x), sizeof(x));
509 }
510
load(const std::string & s,unsigned int & x)511 void s11n::load(const std::string& s, unsigned int& x)
512 {
513 x = str::to<unsigned int>(s);
514 }
515
load(std::istream & is,long & x)516 void s11n::load(std::istream& is, long& x)
517 {
518 is.read(reinterpret_cast<char*>(&x), sizeof(x));
519 }
520
load(const std::string & s,long & x)521 void s11n::load(const std::string& s, long& x)
522 {
523 x = str::to<long>(s);
524 }
525
load(std::istream & is,unsigned long & x)526 void s11n::load(std::istream& is, unsigned long& x)
527 {
528 is.read(reinterpret_cast<char*>(&x), sizeof(x));
529 }
530
load(const std::string & s,unsigned long & x)531 void s11n::load(const std::string& s, unsigned long& x)
532 {
533 x = str::to<unsigned long>(s);
534 }
535
load(std::istream & is,long long & x)536 void s11n::load(std::istream& is, long long& x)
537 {
538 is.read(reinterpret_cast<char*>(&x), sizeof(x));
539 }
540
load(const std::string & s,long long & x)541 void s11n::load(const std::string& s, long long& x)
542 {
543 x = str::to<long long>(s);
544 }
545
load(std::istream & is,unsigned long long & x)546 void s11n::load(std::istream& is, unsigned long long& x)
547 {
548 is.read(reinterpret_cast<char*>(&x), sizeof(x));
549 }
550
load(const std::string & s,unsigned long long & x)551 void s11n::load(const std::string& s, unsigned long long& x)
552 {
553 x = str::to<unsigned long long>(s);
554 }
555
load(std::istream & is,float & x)556 void s11n::load(std::istream& is, float& x)
557 {
558 is.read(reinterpret_cast<char*>(&x), sizeof(x));
559 }
560
load(const std::string & s,float & x)561 void s11n::load(const std::string& s, float& x)
562 {
563 x = str::to<float>(s);
564 }
565
load(std::istream & is,double & x)566 void s11n::load(std::istream& is, double& x)
567 {
568 is.read(reinterpret_cast<char*>(&x), sizeof(x));
569 }
570
load(const std::string & s,double & x)571 void s11n::load(const std::string& s, double& x)
572 {
573 x = str::to<double>(s);
574 }
575
load(std::istream & is,long double & x)576 void s11n::load(std::istream& is, long double& x)
577 {
578 is.read(reinterpret_cast<char*>(&x), sizeof(x));
579 }
580
load(const std::string & s,long double & x)581 void s11n::load(const std::string& s, long double& x)
582 {
583 x = str::to<long double>(s);
584 }
585
586 // Binary blobs
587
load(std::istream & is,void * x,const size_t n)588 void s11n::load(std::istream& is, void* x, const size_t n)
589 {
590 is.read(reinterpret_cast<char*>(x), n);
591 }
592
load(const std::string & s,void * x,const size_t n)593 void s11n::load(const std::string& s, void* x, const size_t n)
594 {
595 std::memset(x, 0, n);
596 size_t i = 0;
597 while (i < n && i + 3 < s.length()) {
598 unsigned char val = 0;
599 if (s[i] == ' ') {
600 i++;
601 if (s[i] >= '0' && s[i] <= '9')
602 val |= (s[i] - '0') << 4;
603 else if (s[i] >= 'a' && s[i] <= 'z')
604 val |= (s[i] - 'a' + 10) << 4;
605 i++;
606 if (s[i] >= '0' && s[i] <= '9')
607 val |= (s[i] - '0');
608 else if (s[i] >= 'a' && s[i] <= 'z')
609 val |= (s[i] - 'a' + 10);
610 }
611 static_cast<unsigned char*>(x)[i] = val;
612 }
613 }
614
615 // Serializable classes
616
load(std::istream & is,serializable & x)617 void s11n::load(std::istream& is, serializable& x)
618 {
619 x.load(is);
620 }
621
load(const std::string & s,serializable & x)622 void s11n::load(const std::string& s, serializable& x)
623 {
624 x.load(s);
625 }
626
627 // Basic STL types
628
load(std::istream & is,std::string & x)629 void s11n::load(std::istream& is, std::string& x)
630 {
631 size_t s;
632 is.read(reinterpret_cast<char*>(&s), sizeof(s));
633 char* buf = new char[s];
634 is.read(buf, s);
635 x.assign(buf, s);
636 delete[] buf;
637 }
638
load(const std::string & s,std::string & x)639 void s11n::load(const std::string& s, std::string& x)
640 {
641 x.clear();
642 if (s.length() == 0)
643 return;
644 const char *sc = s.c_str();
645 size_t i = 0;
646 while (i < s.length()) {
647 x.append(1, dec_char(sc, i));
648 }
649 }
650