ros_field.cpp
Go to the documentation of this file.
1 /***** MIT License ****
2 *
3 * Copyright (c) 2016-2022 Davide Faconti
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23 
24 #include <algorithm>
25 #include <regex>
28 
29 namespace RosMsgParser{
30 
31 
32 ROSField::ROSField(const ROSType &type, const std::string &name):
33  _fieldname(name), _type(type), _is_array(false), _array_size(1)
34 {
35 
36 }
37 
38 ROSField::ROSField(const std::string &definition):
39  _is_array(false), _array_size(1)
40 {
41  static const std::regex type_regex("[a-zA-Z][a-zA-Z0-9_]*"
42  "(/[a-zA-Z][a-zA-Z0-9_]*){0,1}"
43  "(\\[[0-9]*\\]){0,1}");
44 
45  static const std::regex field_regex("[a-zA-Z][a-zA-Z0-9_]*");
46 
47  static const std::regex array_regex("(.+)(\\[([0-9]*)\\])");
48 
49  using std::regex;
50  std::string::const_iterator begin = definition.begin();
51  std::string::const_iterator end = definition.end();
52  std::match_results<std::string::const_iterator> what;
53 
54  // Get type and field
55  std::string type, value;
56 
57  //-------------------------------
58  // Find type, field and array size
59  if( std::regex_search(begin, end, what, type_regex))
60  {
61  type = what[0];
62  begin = what[0].second;
63  }
64  else {
65  throw std::runtime_error("Bad type when parsing field: " + definition);
66  }
67 
68  if (regex_search(begin, end, what, field_regex))
69  {
70  _fieldname = what[0];
71  begin = what[0].second;
72  }
73  else {
74  throw std::runtime_error("Bad field when parsing field: " + definition);
75  }
76 
77  std::string temp_type = type;
78  if (regex_search(temp_type, what, array_regex))
79  {
80  type = what[1];
81 
82  if (what.size() == 3) {
83  _array_size = -1;
84  _is_array = true;
85  }
86  else if (what.size() == 4) {
87  std::string size(what[3].first, what[3].second);
88  _array_size = size.empty() ? -1 : atoi(size.c_str());
89  _is_array = true;
90  }
91  else {
92  throw std::runtime_error("Bad array size when parsing field: " + definition);
93  }
94  }
95 
96  //-------------------------------
97  // Find if Constant or comment
98 
99  // Determine next character
100  // if '=' -> constant, if '#' -> done, if nothing -> done, otherwise error
101  if (regex_search(begin, end, what, std::regex("\\S")))
102  {
103  if (what[0] == "=")
104  {
105  begin = what[0].second;
106  // Copy constant
107  if (type == "string") {
108  value.assign(begin, end);
109  }
110  else
111  {
112  if (regex_search(begin, end, what, std::regex("\\s*#")))
113  {
114  value.assign(begin, what[0].first);
115  }
116  else {
117  value.assign(begin, end);
118  }
119  }
120 
121  TrimString(value);
122  _is_constant = true;
123  }
124  else if (what[0] == "#")
125  {
126  // Ignore comment
127  }
128  else // default value, not constant ?
129  {
130  if (regex_search(begin, end, what, std::regex("\\s*#")))
131  {
132  value.assign(begin, what[0].first);
133  }
134  else {
135  value.assign(begin, end);
136  }
137  }
138  }
139  _type = ROSType( type );
140  // TODO: Raise error if string is not numeric ?
141  _value = value;
142 }
143 
144 std::shared_ptr<ROSMessage> ROSField::getMessagePtr(const RosMessageLibrary &library) const
145 {
146  if( _type.typeID() != BuiltinType::OTHER )
147  {
148  return {};
149  }
150  if( &library == _cache_library && _cache_message )
151  {
152  return _cache_message;
153  }
154  auto it = library.find(_type.baseName());
155  if( it == library.end() )
156  {
157  return nullptr;
158  }
159  _cache_library = &library;
160  _cache_message = it->second;
161  return _cache_message;
162 }
163 
164 void TrimStringLeft(std::string &s)
165 {
166  s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
167  return !std::isspace(ch);
168  }));
169 }
170 
171 void TrimStringRight(std::string &s)
172 {
173  s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
174  return !std::isspace(ch);
175  }).base(), s.end());
176 }
177 
178 void TrimString(std::string &s)
179 {
180  TrimStringLeft(s);
181  TrimStringRight(s);
182 }
183 
184 }
BuiltinType typeID() const
If type is builtin, returns the id. BuiltinType::OTHER otherwise.
Definition: ros_type.hpp:125
void TrimStringRight(std::string &s)
Definition: ros_field.cpp:171
std::shared_ptr< ROSMessage > _cache_message
Definition: ros_field.hpp:88
std::shared_ptr< ROSMessage > getMessagePtr(const RosMessageLibrary &library) const
Definition: ros_field.cpp:144
type
Definition: core.h:1059
const RosMessageLibrary * _cache_library
Definition: ros_field.hpp:87
const std::string & value() const
If constant, value of field, else undefined.
Definition: ros_field.hpp:66
void TrimStringLeft(std::string &s)
Definition: ros_field.cpp:164
void TrimString(std::string &s)
Definition: ros_field.cpp:178
std::unordered_map< ROSType, std::shared_ptr< ROSMessage > > RosMessageLibrary
Definition: ros_field.hpp:37
const T & first(const T &value, const Tail &...)
Definition: compile.h:178
std::string _fieldname
Definition: ros_field.hpp:80
const std::string & baseName() const
Definition: ros_type.hpp:100
const ROSType & type() const
Definition: ros_field.hpp:55
span_constexpr std::size_t size(span< T, Extent > const &spn)
Definition: span.hpp:1485
ROSField(const ROSType &type, const std::string &name)
Definition: ros_field.cpp:32


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Jun 19 2023 03:01:39