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