Atlas  0.7.0
Networking protocol for the Worldforge system.
Packed.h
1 // This file may be redistributed and modified only under the terms of
2 // the GNU Lesser General Public License (See COPYING for details).
3 // Copyright (C) 2000-2001 Stefanus Du Toit, Michael Day
4 
5 // $Id$
6 
7 #ifndef ATLAS_CODECS_PACKED_H
8 #define ATLAS_CODECS_PACKED_H
9 
10 #include <Atlas/Codecs/Utility.h>
11 #include <Atlas/Codec.h>
12 
13 #include <iosfwd>
14 #include <stack>
15 
16 namespace Atlas {
17  namespace Codecs {
18 
19 /*
20 
21 The form for each element of this codec is as follows:
22 
23 [type][name=][data][|endtype]
24 
25 ( ) for lists
26 [ ] for maps
27 $ for string
28 @ for int
29 # for float
30 
31 Sample output for this codec: (whitespace added for clarity)
32 
33 [@id=17$name=Fred +28the +2b great+29#weight=1.5(args=@1@2@3)]
34 
35 The complete specification is located in cvs at:
36  forge/protocols/atlas/spec/packed_syntax.html
37 
38 */
39 
40  class Packed : public Codec {
41  public:
42 
43  Packed(std::istream &in, std::ostream &out, Atlas::Bridge &b);
44 
45  void poll() override;
46 
47  void streamBegin() override;
48 
49  void streamMessage() override;
50 
51  void streamEnd() override;
52 
53  void mapMapItem(std::string name) override;
54 
55  void mapListItem(std::string name) override;
56 
57  void mapIntItem(std::string name, std::int64_t) override;
58 
59  void mapFloatItem(std::string name, double) override;
60 
61  void mapStringItem(std::string name, std::string) override;
62 
63  void mapNoneItem(std::string name) override;
64 
65  void mapEnd() override;
66 
67  void listMapItem() override;
68 
69  void listListItem() override;
70 
71  void listIntItem(std::int64_t) override;
72 
73  void listFloatItem(double) override;
74 
75  void listStringItem(std::string) override;
76 
77  void listNoneItem() override;
78 
79  void listEnd() override;
80 
81  protected:
82 
83  std::istream &m_istream;
84  std::ostream &m_ostream;
85  Bridge &m_bridge;
86 
87  enum State {
88  PARSE_NOTHING,
89  PARSE_STREAM,
90  PARSE_MAP,
91  PARSE_LIST,
92  PARSE_MAP_BEGIN,
93  PARSE_LIST_BEGIN,
94  PARSE_INT,
95  PARSE_FLOAT,
96  PARSE_STRING,
97  PARSE_NAME
98  };
99 
100  std::stack<State> m_state;
101 
102  std::string m_name;
103  std::string m_data;
104 
108  std::string m_encoded;
112  std::string m_decoded;
113 
114  void parsingBegins(char);
115 
116  void parseStream(char);
117 
118  void parseMap(char);
119 
120  void parseList(char);
121 
122  void parseMapBegin(char);
123 
124  void parseListBegin(char);
125 
126  void parseInt(char);
127 
128  void parseFloat(char);
129 
130  void parseString(char);
131 
132  void parseName(char);
133 
134  inline std::string hexEncode(std::string data) {
135 
136  for (size_t i = 0; i < data.size(); i++) {
137  char currentChar = data[i];
138 
139  switch (currentChar) {
140  case '+':
141  case '[':
142  case ']':
143  case '(':
144  case ')':
145  case '@':
146  case '#':
147  case '$':
148  case '=':
149  //First special character, use an encoded string instead
150  m_encoded.clear();
151  m_encoded.reserve(data.size() + (data.size() / 4));
152  m_encoded.assign(data, 0, i);
153  for (; i < data.size(); i++) {
154  currentChar = data[i];
155 
156  switch (currentChar) {
157  case '+':
158  case '[':
159  case ']':
160  case '(':
161  case ')':
162  case '@':
163  case '#':
164  case '$':
165  case '=':
166  //First special character, use an encoded string instead
167  m_encoded += '+';
168  m_encoded += charToHex(currentChar);
169  break;
170  default:
171  m_encoded += currentChar;
172  break;
173  }
174  }
175 
176  return std::move(m_encoded);
177  default:
178  break;
179  }
180  }
181 
182  //If no special character, just return the original string, avoiding any allocations.
183  return data;
184  }
185 
186  inline std::string hexDecode(std::string data) {
187  char hex[3];
188 
189  for (size_t i = 0; i < data.size(); i++) {
190  char currentChar = data[i];
191  if (currentChar == '+') {
192  //First special character, use a decoded string instead
193  m_decoded.clear();
194  m_decoded.reserve(data.size());
195  m_decoded.assign(data, 0, i);
196 
197  for (; i < data.size(); i++) {
198  currentChar = data[i];
199  if (currentChar == '+') {
200  hex[0] = data[++i];
201  hex[1] = data[++i];
202  hex[2] = 0;
203  m_decoded += hexToChar(hex);
204  } else {
205  m_decoded += currentChar;
206  }
207  }
208 
209  return std::move(m_decoded);
210  }
211  }
212 
213  //If no special character, just return the original string, avoiding any allocations.
214  return data;
215  }
216  };
217 
218  }
219 } // namespace Atlas::Codecs
220 
221 #endif
void mapFloatItem(std::string name, double) override
Definition: Packed.cpp:374
void streamEnd() override
Definition: Packed.cpp:358
void mapMapItem(std::string name) override
Definition: Packed.cpp:362
std::string charToHex(char c)
Convert an ASCII char to its hexadecimal value.
Definition: Utility.h:27
void listStringItem(std::string) override
Definition: Packed.cpp:406
void streamBegin() override
Definition: Packed.cpp:350
void streamMessage() override
Definition: Packed.cpp:354
void listListItem() override
Definition: Packed.cpp:394
std::string m_encoded
Definition: Packed.h:108
void mapStringItem(std::string name, std::string) override
Definition: Packed.cpp:378
void mapNoneItem(std::string name) override
Definition: Packed.cpp:382
char hexToChar(const char *hex)
Convert a string with a hexadecimal value (2 characters) to an ASCII char.
Definition: Utility.h:38
void mapEnd() override
Definition: Packed.cpp:386
void listIntItem(std::int64_t) override
Definition: Packed.cpp:398
void mapIntItem(std::string name, std::int64_t) override
Definition: Packed.cpp:370
void listMapItem() override
Definition: Packed.cpp:390
std::string m_decoded
Definition: Packed.h:112
void listEnd() override
Definition: Packed.cpp:415
void mapListItem(std::string name) override
Definition: Packed.cpp:366
void listFloatItem(double) override
Definition: Packed.cpp:402
Definition: Bridge.h:20
void listNoneItem() override
Definition: Packed.cpp:410