LCOV - code coverage report
Current view: top level - src/utils/xml - SUMOSAXAttributes.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 85.0 % 206 175
Test Date: 2025-12-06 15:35:27 Functions: 100.0 % 27 27

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2007-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    SUMOSAXAttributes.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @date    Fri, 30 Mar 2007
      19              : ///
      20              : // Encapsulated SAX-Attributes
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <string>
      25              : #include <iostream>
      26              : #include <sstream>
      27              : #include <utils/common/MsgHandler.h>
      28              : #include <utils/common/RGBColor.h>
      29              : #include <utils/common/StringTokenizer.h>
      30              : #include <utils/common/StringUtils.h>
      31              : #include <utils/geom/Boundary.h>
      32              : #include <utils/geom/PositionVector.h>
      33              : #include "SUMOSAXAttributes.h"
      34              : 
      35              : 
      36              : // ===========================================================================
      37              : // static members
      38              : // ===========================================================================
      39              : const std::string SUMOSAXAttributes::ENCODING = " encoding=\"UTF-8\"";
      40              : 
      41              : 
      42              : // ===========================================================================
      43              : // method definitions
      44              : // ===========================================================================
      45     15760949 : SUMOSAXAttributes::SUMOSAXAttributes(const std::string& objectType):
      46     15760949 :     myObjectType(objectType) {}
      47              : 
      48              : 
      49              : const std::string invalid_return<std::string>::value = "";
      50              : template<>
      51     32551896 : std::string SUMOSAXAttributes::fromString(const std::string& value) const {
      52     32551896 :     if (value == "") {
      53          682 :         throw EmptyData();
      54              :     }
      55     32551214 :     return value;
      56              : }
      57              : 
      58              : 
      59              : SUMOTime
      60       607531 : SUMOSAXAttributes::getSUMOTimeReporting(int attr, const char* objectid,
      61              :                                         bool& ok, bool report) const {
      62              :     try {
      63       607531 :         bool isPresent = true;
      64       607531 :         const std::string& val = getString(attr, &isPresent);
      65       607531 :         if (!isPresent) {
      66           13 :             if (report) {
      67           50 :                 emitUngivenError(getName(attr), objectid);
      68              :             }
      69           13 :             ok = false;
      70           13 :             return -1;
      71              :         }
      72       607518 :         return string2time(val);
      73           24 :     } catch (EmptyData&) {
      74           12 :         if (report) {
      75           24 :             emitEmptyError(getName(attr), objectid);
      76              :         }
      77           24 :     } catch (ProcessError&) {
      78           12 :         if (report) {
      79           24 :             emitFormatError(getName(attr), "is not a valid time value", objectid);
      80              :         }
      81           12 :     }
      82           24 :     ok = false;
      83           24 :     return -1;
      84              : }
      85              : 
      86              : 
      87              : SUMOTime
      88          559 : SUMOSAXAttributes::getPeriod(const char* objectid, bool& ok, bool report) const {
      89              :     int attr = SUMO_ATTR_PERIOD;
      90              :     try {
      91          559 :         bool isPresent = true;
      92          559 :         const std::string& val = getString(attr, &isPresent);
      93          559 :         if (!isPresent) {
      94              :             // try 'freq' as alias for 'period'
      95              :             attr = SUMO_ATTR_FREQUENCY;
      96          534 :             isPresent = true;
      97          534 :             const std::string& valFreq = getString(attr, &isPresent);
      98          534 :             if (!isPresent) {
      99          534 :                 if (report) {
     100            0 :                     emitUngivenError(getName(SUMO_ATTR_PERIOD), objectid);
     101              :                 }
     102          534 :                 ok = false;
     103          534 :                 return -1;
     104              :             }
     105            0 :             return string2time(valFreq);
     106              :         }
     107           25 :         return string2time(val);
     108            0 :     } catch (EmptyData&) {
     109            0 :         if (report) {
     110            0 :             emitEmptyError(getName(attr), objectid);
     111              :         }
     112            0 :     } catch (ProcessError&) {
     113            0 :         if (report) {
     114            0 :             emitFormatError(getName(attr), "is not a valid time value", objectid);
     115              :         }
     116            0 :     }
     117            0 :     ok = false;
     118            0 :     return -1;
     119              : }
     120              : 
     121              : 
     122              : SUMOTime
     123      5150277 : SUMOSAXAttributes::getOptSUMOTimeReporting(int attr, const char* objectid,
     124              :         bool& ok, SUMOTime defaultValue, bool report) const {
     125              :     try {
     126      5150277 :         bool isPresent = true;
     127      5150277 :         const std::string& val = getString(attr, &isPresent);
     128      5150277 :         if (!isPresent) {
     129              :             return defaultValue;
     130              :         }
     131        78870 :         return string2time(val);
     132           36 :     } catch (EmptyData&) {
     133            0 :         if (report) {
     134            0 :             emitEmptyError(getName(attr), objectid);
     135              :         }
     136           36 :     } catch (ProcessError&) {
     137           36 :         if (report) {
     138           72 :             emitFormatError(getName(attr), "is not a valid time value", objectid);
     139              :         }
     140           36 :     }
     141           36 :     ok = false;
     142           36 :     return -1;
     143              : }
     144              : 
     145              : 
     146              : SUMOTime
     147       109468 : SUMOSAXAttributes::getOptOffsetReporting(int attr, const char* objectid,
     148              :         bool& ok, SUMOTime defaultValue, bool report) const {
     149              :     try {
     150       109468 :         bool isPresent = true;
     151       109468 :         const std::string& val = getString(attr, &isPresent);
     152       109468 :         if (!isPresent) {
     153              :             return defaultValue;
     154              :         }
     155       109360 :         if (val == "begin") {
     156              :             return SUMOTime_MAX;
     157              :         } else {
     158       109357 :             return string2time(val);
     159              :         }
     160            0 :     } catch (EmptyData&) {
     161            0 :         if (report) {
     162            0 :             emitEmptyError(getName(attr), objectid);
     163              :         }
     164            0 :     } catch (ProcessError&) {
     165            0 :         if (report) {
     166            0 :             emitFormatError(getName(attr), "is not a valid time value", objectid);
     167              :         }
     168            0 :     }
     169            0 :     ok = false;
     170            0 :     return -1;
     171              : }
     172              : 
     173              : 
     174              : SUMOTime
     175        48043 : SUMOSAXAttributes::getOptPeriod(const char* objectid, bool& ok, SUMOTime defaultValue, bool report) const {
     176              :     int attr = SUMO_ATTR_PERIOD;
     177              :     try {
     178        48043 :         bool isPresent = true;
     179        48043 :         const std::string& val = getString(attr, &isPresent);
     180        48043 :         if (!isPresent) {
     181              :             // try 'freq' as alias for 'period'
     182              :             attr = SUMO_ATTR_FREQUENCY;
     183        25658 :             isPresent = true;
     184        25658 :             const std::string& valFreq = getString(attr, &isPresent);
     185        25658 :             if (!isPresent) {
     186              :                 return defaultValue;
     187              :             }
     188         7805 :             return string2time(valFreq);
     189              :         }
     190        22385 :         return string2time(val);
     191           40 :     } catch (EmptyData&) {
     192           20 :         if (report) {
     193           40 :             emitEmptyError(getName(attr), objectid);
     194              :         }
     195           40 :     } catch (ProcessError&) {
     196           20 :         if (report) {
     197           40 :             emitFormatError(getName(attr), "is not a valid time value", objectid);
     198              :         }
     199           20 :     }
     200           40 :     ok = false;
     201           40 :     return -1;
     202              : }
     203              : 
     204              : 
     205              : void
     206          292 : SUMOSAXAttributes::emitUngivenError(const std::string& attrname, const char* objectid) const {
     207          292 :     std::ostringstream oss;
     208          292 :     oss << "Attribute '" << attrname << "' is missing in definition of ";
     209          292 :     if (objectid == nullptr || objectid[0] == 0) {
     210              :         oss << "a " << myObjectType;
     211              :     } else {
     212          160 :         oss << myObjectType << " '" << objectid << "'";
     213              :     }
     214          292 :     oss << ".";
     215          292 :     WRITE_ERROR(oss.str());
     216          292 : }
     217              : 
     218              : 
     219              : void
     220          549 : SUMOSAXAttributes::emitEmptyError(const std::string& attrname, const char* objectid) const {
     221          549 :     std::ostringstream oss;
     222          549 :     oss << "Attribute '" << attrname << "' in definition of ";
     223          549 :     if (objectid == nullptr || objectid[0] == 0) {
     224              :         oss << "a " << myObjectType;
     225              :     } else {
     226          392 :         oss << myObjectType << " '" << objectid << "'";
     227              :     }
     228          549 :     oss << " is empty.";
     229          549 :     WRITE_ERROR(oss.str());
     230          549 : }
     231              : 
     232              : 
     233              : void
     234          302 : SUMOSAXAttributes::emitFormatError(const std::string& attrname, const std::string& type, const char* objectid) const {
     235          302 :     std::ostringstream oss;
     236          302 :     oss << "Attribute '" << attrname << "' in definition of ";
     237          302 :     if (objectid == nullptr || objectid[0] == 0) {
     238              :         oss << "a " << myObjectType;
     239              :     } else {
     240          282 :         oss << myObjectType << " '" << objectid << "'";
     241              :     }
     242          302 :     oss << " " << type << ".";
     243          302 :     WRITE_ERROR(oss.str());
     244          302 : }
     245              : 
     246              : 
     247              : const int invalid_return<int>::value = -1;
     248              : template<>
     249     11398973 : int SUMOSAXAttributes::fromString(const std::string& value) const {
     250     11398973 :     return StringUtils::toInt(value);
     251              : }
     252              : 
     253              : 
     254              : const long long int invalid_return<long long int>::value = -1;
     255              : template<>
     256      1001054 : long long int SUMOSAXAttributes::fromString(const std::string& value) const {
     257      1001054 :     return StringUtils::toLong(value);
     258              : }
     259              : 
     260              : 
     261              : const double invalid_return<double>::value = -1;
     262              : template<>
     263      8203841 : double SUMOSAXAttributes::fromString(const std::string& value) const {
     264      8203841 :     return StringUtils::toDouble(value);
     265              : }
     266              : 
     267              : 
     268              : const bool invalid_return<bool>::value = false;
     269              : template<>
     270       853151 : bool SUMOSAXAttributes::fromString(const std::string& value) const {
     271       853151 :     return StringUtils::toBool(value);
     272              : }
     273              : 
     274              : 
     275              : const RGBColor invalid_return<RGBColor>::value = RGBColor();
     276              : template<>
     277        68831 : RGBColor SUMOSAXAttributes::fromString(const std::string& value) const {
     278       137654 :     return RGBColor::parseColor(value);
     279              : }
     280              : 
     281              : 
     282              : const Position invalid_return<Position>::value = Position();
     283              : template<>
     284         1282 : Position SUMOSAXAttributes::fromString(const std::string& value) const {
     285         1282 :     StringTokenizer st(value);
     286              :     // check StringTokenizer
     287         1282 :     while (st.hasNext()) {
     288              :         // obtain position
     289         2564 :         StringTokenizer pos(st.next(), ",");
     290              :         // check that position has X-Y or X-Y-Z
     291         1282 :         if ((pos.size() != 2) && (pos.size() != 3)) {
     292            0 :             throw FormatException("is not a valid position");
     293              :         }
     294              :         // obtain x and y
     295         1282 :         double x = StringUtils::toDouble(pos.next());
     296         1282 :         double y = StringUtils::toDouble(pos.next());
     297              :         // check if return a X-Y or a X-Y-Z Position
     298         1282 :         if (pos.size() == 2) {
     299              :             return Position(x, y);
     300              :         } else {
     301              :             // obtain z
     302            0 :             double z = StringUtils::toDouble(pos.next());
     303              :             return Position(x, y, z);
     304              :         }
     305         1282 :     }
     306              :     // empty positions aren't allowed
     307            0 :     throw FormatException("is not a valid position");
     308         1282 : }
     309              : 
     310              : 
     311              : const PositionVector invalid_return<PositionVector>::value = PositionVector();
     312              : template<>
     313      2837738 : PositionVector SUMOSAXAttributes::fromString(const std::string& value) const {
     314      2837738 :     StringTokenizer st(value);
     315      2837738 :     PositionVector shape;
     316     13485912 :     while (st.hasNext()) {
     317     21296564 :         StringTokenizer pos(st.next(), ",");
     318     10648282 :         if (pos.size() != 2 && pos.size() != 3) {
     319           84 :             throw FormatException("is not a valid list of positions");
     320              :         }
     321     10648240 :         double x = StringUtils::toDouble(pos.next());
     322     10648196 :         double y = StringUtils::toDouble(pos.next());
     323     10648174 :         if (pos.size() == 2) {
     324     10619529 :             shape.push_back(Position(x, y));
     325              :         } else {
     326        28645 :             double z = StringUtils::toDouble(pos.next());
     327        28645 :             shape.push_back(Position(x, y, z));
     328              :         }
     329     10648282 :     }
     330      2837630 :     return shape;
     331      2837846 : }
     332              : 
     333              : 
     334              : const Boundary invalid_return<Boundary>::value = Boundary();
     335              : template<>
     336        89124 : Boundary SUMOSAXAttributes::fromString(const std::string& value) const {
     337       267372 :     StringTokenizer st(value, ",");
     338        89124 :     if (st.size() != 4) {
     339            0 :         throw FormatException("is not a valid boundary");
     340              :     }
     341        89124 :     const double xmin = StringUtils::toDouble(st.next());
     342        89124 :     const double ymin = StringUtils::toDouble(st.next());
     343        89124 :     const double xmax = StringUtils::toDouble(st.next());
     344        89124 :     const double ymax = StringUtils::toDouble(st.next());
     345       178248 :     return Boundary(xmin, ymin, xmax, ymax);
     346        89124 : }
     347              : 
     348              : 
     349              : const SumoXMLEdgeFunc invalid_return<SumoXMLEdgeFunc>::value = SumoXMLEdgeFunc::NORMAL;
     350              : template<>
     351      1247029 : SumoXMLEdgeFunc SUMOSAXAttributes::fromString(const std::string& value) const {
     352              :     if (SUMOXMLDefinitions::EdgeFunctions.hasString(value)) {
     353      1247019 :         return SUMOXMLDefinitions::EdgeFunctions.get(value);
     354              :     }
     355           20 :     throw FormatException("is not a valid edge function");
     356              : }
     357              : 
     358              : 
     359              : const SumoXMLNodeType invalid_return<SumoXMLNodeType>::value = SumoXMLNodeType::UNKNOWN;
     360              : template<>
     361       643229 : SumoXMLNodeType SUMOSAXAttributes::fromString(const std::string& value) const {
     362              :     if (SUMOXMLDefinitions::NodeTypes.hasString(value)) {
     363       643199 :         return SUMOXMLDefinitions::NodeTypes.get(value);
     364              :     }
     365           60 :     throw FormatException("is not a valid node type");
     366              : }
     367              : 
     368              : 
     369              : const RightOfWay invalid_return<RightOfWay>::value = RightOfWay::DEFAULT;
     370              : template<>
     371            4 : RightOfWay SUMOSAXAttributes::fromString(const std::string& value) const {
     372              :     if (SUMOXMLDefinitions::RightOfWayValues.hasString(value)) {
     373            4 :         return SUMOXMLDefinitions::RightOfWayValues.get(value);
     374              :     }
     375            0 :     throw FormatException("is not a valid right of way value");
     376              : }
     377              : 
     378              : 
     379              : const FringeType invalid_return<FringeType>::value = FringeType::DEFAULT;
     380              : template<>
     381          235 : FringeType SUMOSAXAttributes::fromString(const std::string& value) const {
     382              :     if (SUMOXMLDefinitions::FringeTypeValues.hasString(value)) {
     383          235 :         return SUMOXMLDefinitions::FringeTypeValues.get(value);
     384              :     }
     385            0 :     throw FormatException("is not a valid fringe type");
     386              : }
     387              : 
     388              : 
     389              : const RoundaboutType invalid_return<RoundaboutType>::value = RoundaboutType::DEFAULT;
     390              : template<>
     391            1 : RoundaboutType SUMOSAXAttributes::fromString(const std::string& value) const {
     392              :     if (SUMOXMLDefinitions::RoundaboutTypeValues.hasString(value)) {
     393            1 :         return SUMOXMLDefinitions::RoundaboutTypeValues.get(value);
     394              :     }
     395            0 :     throw FormatException("is not a valid roundabout type");
     396              : }
     397              : 
     398              : 
     399              : const ParkingType invalid_return<ParkingType>::value = ParkingType::ONROAD;
     400              : template<>
     401          913 : ParkingType SUMOSAXAttributes::fromString(const std::string& value) const {
     402          913 :     if (value == toString(ParkingType::OPPORTUNISTIC)) {
     403              :         return ParkingType::OPPORTUNISTIC;
     404              :     } else {
     405          913 :         return StringUtils::toBool(value) ? ParkingType::OFFROAD : ParkingType::ONROAD;
     406              :     }
     407              : }
     408              : 
     409              : 
     410              : const std::vector<std::string> invalid_return<std::vector<std::string> >::value = std::vector<std::string>();
     411              : template<>
     412        12265 : std::vector<std::string> SUMOSAXAttributes::fromString(const std::string& value) const {
     413        24530 :     const std::vector<std::string>& ret = StringTokenizer(value).getVector();
     414        12265 :     if (ret.empty()) {
     415          356 :         throw EmptyData();
     416              :     }
     417        23818 :     return ret;
     418        12265 : }
     419              : 
     420              : 
     421              : const std::vector<int> invalid_return<std::vector<int> >::value = std::vector<int>();
     422              : template<>
     423          252 : std::vector<int> SUMOSAXAttributes::fromString(const std::string& value) const {
     424          504 :     const std::vector<std::string>& tmp = StringTokenizer(value).getVector();
     425          252 :     if (tmp.empty()) {
     426            0 :         throw EmptyData();
     427              :     }
     428              :     std::vector<int> ret;
     429          639 :     for (const std::string& s : tmp) {
     430          387 :         ret.push_back(StringUtils::toInt(s));
     431              :     }
     432          252 :     return ret;
     433          252 : }
     434              : 
     435              : 
     436              : const std::vector<double> invalid_return<std::vector<double> >::value = std::vector<double>();
     437              : template<>
     438          903 : std::vector<double> SUMOSAXAttributes::fromString(const std::string& value) const {
     439         1806 :     const std::vector<std::string>& tmp = StringTokenizer(value).getVector();
     440          903 :     if (tmp.empty()) {
     441            0 :         throw EmptyData();
     442              :     }
     443              :     std::vector<double> ret;
     444        66415 :     for (const std::string& s : tmp) {
     445        65512 :         ret.push_back(StringUtils::toDouble(s));
     446              :     }
     447          903 :     return ret;
     448          903 : }
     449              : 
     450              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1