Eclipse SUMO - Simulation of Urban MObility
ParBuffer.h
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-2024 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 /****************************************************************************/
18 // Class for the string serialization and deserialization of parameters
19 /****************************************************************************/
20 
21 #pragma once
22 #include <config.h>
23 
24 #include <cstddef>
25 #include <string>
26 #include <sstream>
27 #include <algorithm>
28 
29 class ParBuffer {
30 public:
31  ParBuffer() : SEP(':'), ESC('\\'), QUO('"'), was_empty(false) {}
32  ParBuffer(std::string buf) : SEP(':'), ESC('\\'), QUO('"'),
33  was_empty(false) {
34  inBuffer = buf;
35  }
36 
37  template<typename T> ParBuffer& operator <<(const T& v) {
38  std::stringstream ss;
39  std::string str_value;
40  ss << v;
41  str_value = escape(ss.str());
42  if (outBuffer.str().length() == 0) {
43  outBuffer << str_value;
44  } else {
45  outBuffer << SEP << str_value;
46  }
47  return *this;
48  }
49 
50  size_t next_escape(std::string str, size_t pos) {
51  size_t c_pos = str.find(SEP, pos);
52  size_t e_pos = str.find(ESC, pos);
53  if (c_pos == std::string::npos) {
54  return e_pos;
55  }
56  if (e_pos == std::string::npos) {
57  return c_pos;
58  }
59  return std::min(c_pos, e_pos);
60  }
61 
62  std::string escape(std::string str) {
63  size_t pos, last_pos = 0;
64  std::stringstream escaping;
65  std::string escaped;
66  while ((pos = next_escape(str, last_pos)) != std::string::npos) {
67  escaping << str.substr(last_pos, pos - last_pos);
68  escaping << ESC << str.substr(pos, 1);
69  last_pos = pos + 1;
70  }
71  if (last_pos != str.size()) {
72  escaping << str.substr(last_pos);
73  }
74  escaped = escaping.str();
75  if (escaped.empty() || (escaped.c_str()[0] == QUO && escaped.c_str()[escaped.length() - 1] == QUO)) {
76  escaping.str("");
77  escaping.clear();
78  escaping << QUO << escaped << QUO;
79  escaped = escaping.str();
80  }
81  return escaped;
82  }
83 
84  std::string unescape(std::string str) {
85  size_t pos, last_pos = 0;
86  std::stringstream unescaped;
87  std::string escaped;
88  if (str.c_str()[0] == QUO && str.c_str()[str.length() - 1] == QUO) {
89  str = str.substr(1, str.length() - 2);
90  }
91  while ((pos = str.find(ESC, last_pos)) != std::string::npos) {
92  unescaped << str.substr(last_pos, pos - last_pos);
93  unescaped << str.substr(pos + 1, 1);
94  last_pos = pos + 2;
95  }
96  if (last_pos != str.size()) {
97  unescaped << str.substr(last_pos);
98  }
99  return unescaped.str();
100  }
101 
102  std::string next() {
103  if (inBuffer.size() == 0) {
104  return "";
105  }
106 
107  size_t sep = std::string::npos;
108  do {
109  sep = inBuffer.find(SEP, sep + 1);
110  } while (!(sep == std::string::npos || sep == 0 || inBuffer.c_str()[sep - 1] != ESC));
111 
112  std::string value;
113  if (sep == std::string::npos) {
114  value = unescape(inBuffer);
115  inBuffer = "";
116  } else {
117  value = unescape(inBuffer.substr(0, sep));
118  inBuffer = inBuffer.substr(sep + 1);
119  }
120  return value;
121  }
122 
123  template <typename T> ParBuffer& operator>>(T& v) {
124  std::string value = next();
125  std::stringstream ss(value);
126  ss >> v;
127  // stringstream doesn't write to v if value is an empty string. the
128  // only solution is letting the user know that the last parsed
129  // portion was empty
130  if (value == "") {
131  was_empty = true;
132  } else {
133  was_empty = false;
134  }
135  return *this;
136  }
137 
138  bool last_empty() {
139  return was_empty;
140  }
141 
142  void set(std::string buf) {
143  inBuffer = buf;
144  }
145  void clear() {
146  outBuffer.clear();
147  }
148  std::string str() const {
149  return outBuffer.str();
150  }
151 
152 private:
153  const char SEP;
154  const char ESC;
155  const char QUO;
156  std::stringstream outBuffer;
157  std::string inBuffer;
158  bool was_empty;
159 
160 };
size_t next_escape(std::string str, size_t pos)
Definition: ParBuffer.h:50
bool was_empty
Definition: ParBuffer.h:158
std::string inBuffer
Definition: ParBuffer.h:157
ParBuffer & operator<<(const T &v)
Definition: ParBuffer.h:37
std::stringstream outBuffer
Definition: ParBuffer.h:156
ParBuffer()
Definition: ParBuffer.h:31
std::string str() const
Definition: ParBuffer.h:148
std::string next()
Definition: ParBuffer.h:102
std::string unescape(std::string str)
Definition: ParBuffer.h:84
const char QUO
Definition: ParBuffer.h:155
const char ESC
Definition: ParBuffer.h:154
ParBuffer & operator>>(T &v)
Definition: ParBuffer.h:123
std::string escape(std::string str)
Definition: ParBuffer.h:62
const char SEP
Definition: ParBuffer.h:153
void set(std::string buf)
Definition: ParBuffer.h:142
void clear()
Definition: ParBuffer.h:145
bool last_empty()
Definition: ParBuffer.h:138