f3281355133e957dfa9b054f1f7ca5fd3937b8da
[oweals/minetest.git] / src / util / serialize.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
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 Lesser General Public License for more details.
14
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.
18 */
19
20 #include "serialize.h"
21
22 #include <sstream>
23 #include <iomanip>
24
25 // Creates a string encoded in JSON format (almost equivalent to a C string literal)
26 std::string serializeJsonString(const std::string &plain)
27 {
28         std::ostringstream os(std::ios::binary);
29         os<<"\"";
30         for(size_t i = 0; i < plain.size(); i++)
31         {
32                 char c = plain[i];
33                 switch(c)
34                 {
35                         case '"': os<<"\\\""; break;
36                         case '\\': os<<"\\\\"; break;
37                         case '/': os<<"\\/"; break;
38                         case '\b': os<<"\\b"; break;
39                         case '\f': os<<"\\f"; break;
40                         case '\n': os<<"\\n"; break;
41                         case '\r': os<<"\\r"; break;
42                         case '\t': os<<"\\t"; break;
43                         default:
44                         {
45                                 if(c >= 32 && c <= 126)
46                                 {
47                                         os<<c;
48                                 }
49                                 else
50                                 {
51                                         u32 cnum = (u32) (u8) c;
52                                         os<<"\\u"<<std::hex<<std::setw(4)<<std::setfill('0')<<cnum;
53                                 }
54                                 break;
55                         }
56                 }
57         }
58         os<<"\"";
59         return os.str();
60 }
61
62 // Reads a string encoded in JSON format
63 std::string deSerializeJsonString(std::istream &is)
64 {
65         std::ostringstream os(std::ios::binary);
66         char c, c2;
67
68         // Parse initial doublequote
69         is >> c;
70         if(c != '"')
71                 throw SerializationError("JSON string must start with doublequote");
72
73         // Parse characters
74         for(;;)
75         {
76                 c = is.get();
77                 if(is.eof())
78                         throw SerializationError("JSON string ended prematurely");
79                 if(c == '"')
80                 {
81                         return os.str();
82                 }
83                 else if(c == '\\')
84                 {
85                         c2 = is.get();
86                         if(is.eof())
87                                 throw SerializationError("JSON string ended prematurely");
88                         switch(c2)
89                         {
90                                 default:  os<<c2; break;
91                                 case 'b': os<<'\b'; break;
92                                 case 'f': os<<'\f'; break;
93                                 case 'n': os<<'\n'; break;
94                                 case 'r': os<<'\r'; break;
95                                 case 't': os<<'\t'; break;
96                                 case 'u':
97                                 {
98                                         char hexdigits[4+1];
99                                         is.read(hexdigits, 4);
100                                         if(is.eof())
101                                                 throw SerializationError("JSON string ended prematurely");
102                                         hexdigits[4] = 0;
103                                         std::istringstream tmp_is(hexdigits, std::ios::binary);
104                                         int hexnumber;
105                                         tmp_is >> std::hex >> hexnumber;
106                                         os<<((char)hexnumber);
107                                         break;
108                                 }
109                         }
110                 }
111                 else
112                 {
113                         os<<c;
114                 }
115         }
116         return os.str();
117 }
118
119