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
Atlas::Codecs::Packed::streamEnd
void streamEnd() override
Definition: Packed.cpp:358
Atlas::Codecs::Packed::listNoneItem
void listNoneItem() override
Definition: Packed.cpp:410
Atlas::Codecs::Packed::mapMapItem
void mapMapItem(std::string name) override
Definition: Packed.cpp:362
Atlas::Codecs::Packed::streamBegin
void streamBegin() override
Definition: Packed.cpp:350
Atlas::Codecs::Packed::listStringItem
void listStringItem(std::string) override
Definition: Packed.cpp:406
Atlas::Codecs::charToHex
std::string charToHex(char c)
Convert an ASCII char to its hexadecimal value.
Definition: Utility.h:27
Utility.h
Atlas::Codec
Definition: Codec.h:27
Atlas::Codecs::Packed::streamMessage
void streamMessage() override
Definition: Packed.cpp:354
Atlas::Codecs::Packed::listIntItem
void listIntItem(std::int64_t) override
Definition: Packed.cpp:398
Atlas::Codecs::Packed::m_encoded
std::string m_encoded
Definition: Packed.h:108
Atlas::Codecs::Packed::listListItem
void listListItem() override
Definition: Packed.cpp:394
Atlas::Codecs::Packed::mapEnd
void mapEnd() override
Definition: Packed.cpp:386
Atlas::Codecs::hexToChar
char hexToChar(const char *hex)
Convert a string with a hexadecimal value (2 characters) to an ASCII char.
Definition: Utility.h:34
Atlas::Codecs::Packed::mapIntItem
void mapIntItem(std::string name, std::int64_t) override
Definition: Packed.cpp:370
Atlas::Bridge
Definition: Bridge.h:35
Atlas::Codecs::Packed::mapNoneItem
void mapNoneItem(std::string name) override
Definition: Packed.cpp:382
Atlas::Codecs::Packed::mapStringItem
void mapStringItem(std::string name, std::string) override
Definition: Packed.cpp:378
Atlas::Codecs::Packed::mapFloatItem
void mapFloatItem(std::string name, double) override
Definition: Packed.cpp:374
Atlas::Codecs::Packed::m_decoded
std::string m_decoded
Definition: Packed.h:112
Atlas::Codecs::Packed::listMapItem
void listMapItem() override
Definition: Packed.cpp:390
Atlas::Codecs::Packed
Definition: Packed.h:40
Atlas::Codecs::Packed::listEnd
void listEnd() override
Definition: Packed.cpp:415
Atlas::Codecs::Packed::listFloatItem
void listFloatItem(double) override
Definition: Packed.cpp:402
Atlas
Definition: Bridge.h:20
Atlas::Codecs::Packed::mapListItem
void mapListItem(std::string name) override
Definition: Packed.cpp:366