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