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