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