1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2002-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file SUMOSAXAttributesImpl_Binary.cpp
11 /// @author Daniel Krajzewicz
12 /// @author Jakob Erdmann
13 /// @author Michael Behrisch
14 /// @date Sept 2002
15 /// @version $Id$
16 ///
17 // Encapsulated xml-attributes that are retrieved from the sumo-binary-xml format (already typed)
18 /****************************************************************************/
19
20
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25
26 #include <cassert>
27 #include <sstream>
28 #include <utils/common/RGBColor.h>
29 #include <utils/common/StringUtils.h>
30 #include <utils/geom/Boundary.h>
31 #include <utils/geom/PositionVector.h>
32 #include <utils/iodevices/BinaryFormatter.h>
33 #include <utils/iodevices/BinaryInputDevice.h>
34 #include "SUMOSAXAttributesImpl_Binary.h"
35 #include "SUMOSAXAttributesImpl_Cached.h"
36
37
38 // ===========================================================================
39 // class definitions
40 // ===========================================================================
SUMOSAXAttributesImpl_Binary(const std::map<int,std::string> & predefinedTagsMML,const std::string & objectType,BinaryInputDevice * in,const char version)41 SUMOSAXAttributesImpl_Binary::SUMOSAXAttributesImpl_Binary(
42 const std::map<int, std::string>& predefinedTagsMML,
43 const std::string& objectType,
44 BinaryInputDevice* in, const char version) : SUMOSAXAttributes(objectType), myAttrIds(predefinedTagsMML) {
45 while (in->peek() == BinaryFormatter::BF_XML_ATTRIBUTE) {
46 int attr;
47 unsigned char attrByte;
48 *in >> attrByte;
49 attr = attrByte;
50 if (version > 1) {
51 in->putback(BinaryFormatter::BF_BYTE);
52 *in >> attrByte;
53 attr += 256 * attrByte;
54 }
55 int type = in->peek();
56 switch (type) {
57 case BinaryFormatter::BF_BYTE:
58 *in >> myCharValues[attr];
59 break;
60 case BinaryFormatter::BF_INTEGER:
61 *in >> myIntValues[attr];
62 break;
63 case BinaryFormatter::BF_FLOAT:
64 case BinaryFormatter::BF_SCALED2INT:
65 *in >> myFloatValues[attr];
66 break;
67 case BinaryFormatter::BF_STRING:
68 *in >> myStringValues[attr];
69 break;
70 case BinaryFormatter::BF_LIST: {
71 int size;
72 *in >> size;
73 while (size > 0) {
74 const int type = in->peek();
75 if (type != BinaryFormatter::BF_POSITION_2D && type != BinaryFormatter::BF_POSITION_3D &&
76 type != BinaryFormatter::BF_SCALED2INT_POSITION_2D &&
77 type != BinaryFormatter::BF_SCALED2INT_POSITION_3D) {
78 throw ProcessError("Invalid binary file, only supporting position vectors.");
79 }
80 size--;
81 Position p;
82 *in >> p;
83 myPositionVectors[attr].push_back(p);
84 }
85 break;
86 }
87 case BinaryFormatter::BF_EDGE:
88 *in >> myIntValues[attr];
89 break;
90 case BinaryFormatter::BF_LANE:
91 *in >> myIntValues[attr];
92 in->putback(BinaryFormatter::BF_BYTE);
93 *in >> myCharValues[attr];
94 break;
95 case BinaryFormatter::BF_POSITION_2D:
96 case BinaryFormatter::BF_POSITION_3D:
97 case BinaryFormatter::BF_SCALED2INT_POSITION_2D:
98 case BinaryFormatter::BF_SCALED2INT_POSITION_3D: {
99 Position p;
100 *in >> p;
101 myPositionVectors[attr].push_back(p);
102 break;
103 }
104 case BinaryFormatter::BF_BOUNDARY: {
105 Position p;
106 *in >> p;
107 myPositionVectors[attr].push_back(p);
108 in->putback(BinaryFormatter::BF_POSITION_2D);
109 *in >> p;
110 myPositionVectors[attr].push_back(p);
111 break;
112 }
113 case BinaryFormatter::BF_COLOR:
114 *in >> myIntValues[attr];
115 break;
116 case BinaryFormatter::BF_NODE_TYPE:
117 *in >> myCharValues[attr];
118 break;
119 case BinaryFormatter::BF_EDGE_FUNCTION:
120 *in >> myCharValues[attr];
121 break;
122 case BinaryFormatter::BF_ROUTE: {
123 std::ostringstream into(std::ios::binary);
124 int size;
125 *in >> size;
126 FileHelpers::writeByte(into, BinaryFormatter::BF_ROUTE);
127 FileHelpers::writeInt(into, size);
128 if (size > 0) {
129 int intsToRead = size - 1;
130 int bitsOrEntry;
131 in->putback(BinaryFormatter::BF_INTEGER);
132 *in >> bitsOrEntry;
133 FileHelpers::writeInt(into, bitsOrEntry);
134 if (bitsOrEntry < 0) {
135 intsToRead = (-bitsOrEntry * (size - 1) - 1) / sizeof(int) / 8 + 2;
136 }
137 while (intsToRead > 0) {
138 in->putback(BinaryFormatter::BF_INTEGER);
139 *in >> bitsOrEntry;
140 FileHelpers::writeInt(into, bitsOrEntry);
141 intsToRead--;
142 }
143 }
144 myStringValues[attr] = into.str();
145 break;
146 }
147 default:
148 throw ProcessError("Binary file is invalid, attribute type is unknown.");
149 }
150 myAttrs.insert(attr);
151 }
152 }
153
154
~SUMOSAXAttributesImpl_Binary()155 SUMOSAXAttributesImpl_Binary::~SUMOSAXAttributesImpl_Binary() {
156 }
157
158
159 bool
hasAttribute(int id) const160 SUMOSAXAttributesImpl_Binary::hasAttribute(int id) const {
161 return myAttrs.find(id) != myAttrs.end();
162 }
163
164
165 bool
getBool(int id) const166 SUMOSAXAttributesImpl_Binary::getBool(int id) const {
167 const std::map<int, char>::const_iterator i = myCharValues.find(id);
168 if (i == myCharValues.end()) {
169 throw EmptyData();
170 }
171 return i->second != 0;
172 }
173
174
175 int
getInt(int id) const176 SUMOSAXAttributesImpl_Binary::getInt(int id) const {
177 const std::map<int, int>::const_iterator i = myIntValues.find(id);
178 if (i == myIntValues.end()) {
179 throw EmptyData();
180 }
181 return i->second;
182 }
183
184
185 long long int
getLong(int id) const186 SUMOSAXAttributesImpl_Binary::getLong(int id) const {
187 return StringUtils::toLong(getString(id));
188 }
189
190
191 std::string
getString(int id) const192 SUMOSAXAttributesImpl_Binary::getString(int id) const {
193 const std::map<int, std::string>::const_iterator i = myStringValues.find(id);
194 if (i == myStringValues.end()) {
195 throw EmptyData();
196 }
197 return i->second;
198 }
199
200
201 std::string
getStringSecure(int id,const std::string & str) const202 SUMOSAXAttributesImpl_Binary::getStringSecure(int id,
203 const std::string& str) const {
204 const std::map<int, std::string>::const_iterator i = myStringValues.find(id);
205 if (i == myStringValues.end()) {
206 return str;
207 }
208 return i->second;
209 }
210
211
212 double
getFloat(int id) const213 SUMOSAXAttributesImpl_Binary::getFloat(int id) const {
214 const std::map<int, double>::const_iterator i = myFloatValues.find(id);
215 if (i == myFloatValues.end()) {
216 return StringUtils::toDouble(getString(id));
217 }
218 return i->second;
219 }
220
221
222 double
getFloat(const std::string &) const223 SUMOSAXAttributesImpl_Binary::getFloat(const std::string& /* id */) const {
224 throw ProcessError("not implemented for binary data");
225 }
226
227
228 bool
hasAttribute(const std::string &) const229 SUMOSAXAttributesImpl_Binary::hasAttribute(const std::string& /* id */) const {
230 throw ProcessError("not implemented for binary data");
231 }
232
233
234 std::string
getStringSecure(const std::string &,const std::string &) const235 SUMOSAXAttributesImpl_Binary::getStringSecure(const std::string& /* id */,
236 const std::string& /* str */) const {
237 throw ProcessError("not implemented for binary data");
238 }
239
240
241 SumoXMLEdgeFunc
getEdgeFunc(bool & ok) const242 SUMOSAXAttributesImpl_Binary::getEdgeFunc(bool& ok) const {
243 const std::map<int, char>::const_iterator i = myCharValues.find(SUMO_ATTR_FUNCTION);
244 if (i != myCharValues.end()) {
245 const char func = i->second;
246 if (func < (char)SUMOXMLDefinitions::EdgeFunctions.size()) {
247 return (SumoXMLEdgeFunc)func;
248 }
249 ok = false;
250 }
251 return EDGEFUNC_NORMAL;
252 }
253
254
255 SumoXMLNodeType
getNodeType(bool & ok) const256 SUMOSAXAttributesImpl_Binary::getNodeType(bool& ok) const {
257 const std::map<int, char>::const_iterator i = myCharValues.find(SUMO_ATTR_TYPE);
258 if (i != myCharValues.end()) {
259 const char type = i->second;
260 if (type < (char)SUMOXMLDefinitions::NodeTypes.size()) {
261 return (SumoXMLNodeType)type;
262 }
263 ok = false;
264 }
265 return NODETYPE_UNKNOWN;
266 }
267
268
269 RightOfWay
getRightOfWay(bool & ok) const270 SUMOSAXAttributesImpl_Binary::getRightOfWay(bool& ok) const {
271 try {
272 return SUMOXMLDefinitions::RightOfWayValues.get(getString(SUMO_ATTR_RIGHT_OF_WAY));
273 } catch (InvalidArgument) {
274 ok = false;
275 return RIGHT_OF_WAY_DEFAULT;
276 } catch (EmptyData) {
277 return RIGHT_OF_WAY_DEFAULT;
278 }
279 }
280
281
282 FringeType
getFringeType(bool & ok) const283 SUMOSAXAttributesImpl_Binary::getFringeType(bool& ok) const {
284 try {
285 return SUMOXMLDefinitions::FringeTypeValues.get(getString(SUMO_ATTR_FRINGE));
286 } catch (InvalidArgument) {
287 ok = false;
288 return FRINGE_TYPE_DEFAULT;
289 } catch (EmptyData) {
290 return FRINGE_TYPE_DEFAULT;
291 }
292 }
293
294
295 RGBColor
getColor() const296 SUMOSAXAttributesImpl_Binary::getColor() const {
297 const std::map<int, int>::const_iterator i = myIntValues.find(SUMO_ATTR_COLOR);
298 if (i == myIntValues.end()) {
299 throw EmptyData();
300 }
301 const int val = i->second;
302 return RGBColor(val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, (val >> 24) & 0xff);
303 }
304
305
306 PositionVector
getShape(int attr) const307 SUMOSAXAttributesImpl_Binary::getShape(int attr) const {
308 const std::map<int, PositionVector>::const_iterator i = myPositionVectors.find(attr);
309 if (i == myPositionVectors.end() || i->second.size() == 0) {
310 throw EmptyData();
311 }
312 return i->second;
313 }
314
315
316 Boundary
getBoundary(int attr) const317 SUMOSAXAttributesImpl_Binary::getBoundary(int attr) const {
318 const std::map<int, PositionVector>::const_iterator i = myPositionVectors.find(attr);
319 if (i == myPositionVectors.end() || i->second.size() == 0) {
320 throw EmptyData();
321 }
322 if (i->second.size() != 2) {
323 throw FormatException("boundary format");
324 }
325 return Boundary(i->second[0].x(), i->second[0].y(), i->second[1].x(), i->second[1].y());
326 }
327
328
329 std::string
getName(int attr) const330 SUMOSAXAttributesImpl_Binary::getName(int attr) const {
331 if (myAttrIds.find(attr) == myAttrIds.end()) {
332 return "?";
333 }
334 return myAttrIds.find(attr)->second;
335 }
336
337
338 void
serialize(std::ostream & os) const339 SUMOSAXAttributesImpl_Binary::serialize(std::ostream& os) const {
340 for (std::set<int>::const_iterator i = myAttrs.begin(); i != myAttrs.end(); ++i) {
341 os << " " << getName(*i);
342 os << "=\"" << getStringSecure(*i, "?") << "\"";
343 }
344 }
345
346 std::vector<std::string>
getAttributeNames() const347 SUMOSAXAttributesImpl_Binary::getAttributeNames() const {
348 std::vector<std::string> result;
349 for (std::set<int>::const_iterator i = myAttrs.begin(); i != myAttrs.end(); ++i) {
350 result.push_back(getName(*i));
351 }
352 return result;
353 }
354
355
356 SUMOSAXAttributes*
clone() const357 SUMOSAXAttributesImpl_Binary::clone() const {
358 std::map<std::string, std::string> attrs;
359 for (std::map<int, char>::const_iterator it = myCharValues.begin(); it != myCharValues.end(); ++it) {
360 const std::string attrName = myAttrIds.find(it->first)->second;
361 attrs[attrName] = toString(it->second);
362 }
363 for (std::map<int, int>::const_iterator it = myIntValues.begin(); it != myIntValues.end(); ++it) {
364 const std::string attrName = myAttrIds.find(it->first)->second;
365 attrs[attrName] = toString(it->second);
366 }
367 for (std::map<int, double>::const_iterator it = myFloatValues.begin(); it != myFloatValues.end(); ++it) {
368 const std::string attrName = myAttrIds.find(it->first)->second;
369 attrs[attrName] = toString(it->second);
370 }
371 for (std::map<int, std::string>::const_iterator it = myStringValues.begin(); it != myStringValues.end(); ++it) {
372 const std::string attrName = myAttrIds.find(it->first)->second;
373 attrs[attrName] = it->second;
374 }
375 for (std::map<int, PositionVector>::const_iterator it = myPositionVectors.begin(); it != myPositionVectors.end(); ++it) {
376 const std::string attrName = myAttrIds.find(it->first)->second;
377 attrs[attrName] = toString(it->second);
378 }
379 return new SUMOSAXAttributesImpl_Cached(attrs, myAttrIds, getObjectType());
380 }
381
382 /****************************************************************************/
383
384