OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
value_parser.hpp
Go to the documentation of this file.
1//
2// Class ValueParser
3// Simple value parser for SDDS data values.
4//
5// Copyright (c) 2026, Paul Scherrer Institute, Villigen PSI, Switzerland
6// All rights reserved
7//
8// This file is part of OPAL.
9//
10// OPAL is free software: you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// You should have received a copy of the GNU General Public License
16// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
17//
18#ifndef VALUE_PARSER_HPP_
19#define VALUE_PARSER_HPP_
20
22
23#include <cctype>
24#include <string>
25#include <string_view>
26#include <type_traits>
27
28namespace SDDS {
29 namespace parser {
30
32 public:
33 ValueParser(std::string_view input, std::size_t start_pos = 0)
34 : input_(input), pos_(start_pos) {}
35
39
40 // ----------------------- Numeric Parsers -----------------------
41 template <typename T>
42 bool parseNumeric(T& value) {
44 std::size_t start = pos_;
45 bool has_dot = false;
46 bool has_exp = false;
47
48 if (pos_ < input_.size() && (input_[pos_] == '+' || input_[pos_] == '-')) {
49 pos_++;
50 }
51
52 while (pos_ < input_.size()) {
53 char c = input_[pos_];
54 if (std::isdigit(static_cast<unsigned char>(c))) {
55 pos_++;
56 } else if (c == '.' && !has_dot) {
57 has_dot = true;
58 pos_++;
59 } else if ((c == 'e' || c == 'E') && !has_exp) {
60 has_exp = true;
61 pos_++;
62 if (pos_ < input_.size() && (input_[pos_] == '+' || input_[pos_] == '-')) pos_++;
63 } else {
64 break;
65 }
66 }
67
68 if (pos_ > start) {
69 try {
70 const std::string token(input_.data() + start, pos_ - start);
71 if constexpr (std::is_same_v<T, float>) {
72 value = std::stof(token);
73 } else {
74 value = std::stod(token);
75 }
76 return true;
77 } catch (...) {
78 pos_ = start;
79 return false;
80 }
81 }
82 pos_ = start;
83 return false;
84 }
85
86 bool parseInteger(long& value) {
88 std::size_t start = pos_;
89 if (pos_ < input_.size() && (input_[pos_] == '+' || input_[pos_] == '-')) {
90 pos_++;
91 }
92
93 while (pos_ < input_.size() && std::isdigit(static_cast<unsigned char>(input_[pos_]))) {
94 pos_++;
95 }
96
97 if (pos_ > start) {
98 try {
99 const std::string token(input_.data() + start, pos_ - start);
100 value = std::stol(token);
101 return true;
102 } catch (...) {
103 pos_ = start;
104 return false;
105 }
106 }
107 pos_ = start;
108 return false;
109 }
110
111 bool parseFloat(float& value) { return parseNumeric(value); }
112 bool parseDouble(double& value) { return parseNumeric(value); }
113
114 bool parseShort(short& value) {
115 long tmp;
116 if (!parseInteger(tmp)) return false;
117 value = static_cast<short>(tmp);
118 return true;
119 }
120
121 bool parseLong(long& value) { return parseInteger(value); }
122
123 bool parseChar(char& value) {
125 if (pos_ < input_.size() && !std::isspace(static_cast<unsigned char>(input_[pos_]))) {
126 value = input_[pos_++];
127 return true;
128 }
129 return false;
130 }
131
132 // ----------------------- String Parsers -----------------------
133 bool parseQuotedString(std::string& value) {
135 if (pos_ >= input_.size() || input_[pos_] != '"') {
136 return false;
137 }
138 pos_++;
139 value.clear();
140 while (pos_ < input_.size() && input_[pos_] != '"') {
141 if (input_[pos_] == '\\' && pos_ + 1 < input_.size()) {
142 pos_++;
143 value += input_[pos_];
144 } else {
145 value += input_[pos_];
146 }
147 pos_++;
148 }
149 if (pos_ < input_.size() && input_[pos_] == '"') {
150 pos_++;
151 return true;
152 }
153 return false;
154 }
155
156 bool parseString(std::string& value) {
158 if (pos_ < input_.size() && input_[pos_] == '"') {
159 return parseQuotedString(value);
160 }
161
162 std::size_t start = pos_;
163 while (pos_ < input_.size()) {
164 char c = input_[pos_];
165 if (std::isalnum(static_cast<unsigned char>(c)) ||
166 c == '@' || c == '#' || c == ':' || c == '+' ||
167 c == '-' || c == '%' || c == '.' || c == '_' ||
168 c == '$' || c == '&' || c == '/') {
169 pos_++;
170 } else {
171 break;
172 }
173 }
174 if (pos_ > start) {
175 value.assign(input_.data() + start, pos_ - start);
176 return true;
177 }
178 return false;
179 }
180
181 bool parseStringToEol(std::string& value) {
183 if (pos_ < input_.size() && input_[pos_] == '"') {
184 return parseQuotedString(value);
185 }
186
187 std::size_t start = pos_;
188 while (pos_ < input_.size() && input_[pos_] != '\n' && input_[pos_] != '\r') {
189 pos_++;
190 }
191
192 std::size_t end = pos_;
193 while (end > start && (input_[end - 1] == ' ' || input_[end - 1] == '\t')) {
194 end--;
195 }
196
197 if (end > start) {
198 value.assign(input_.data() + start, end - start);
199 return true;
200 }
201
202 return false;
203 }
204
205 // ----------------------- Position Control -----------------------
206 std::size_t getPosition() const { return pos_; }
207 void setPosition(std::size_t pos) { pos_ = pos; }
208
209 private:
210 std::string_view input_;
211 std::size_t pos_;
212 };
213
214 } // namespace parser
215} // namespace SDDS
216
217#endif /* VALUE_PARSER_HPP_ */
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
void skipWhitespaceAndComments(std::string_view input, std::size_t &pos)
Definition skipper.hpp:28
bool parseQuotedString(std::string &value)
bool parseLong(long &value)
bool parseString(std::string &value)
ValueParser(std::string_view input, std::size_t start_pos=0)
bool parseChar(char &value)
bool parseFloat(float &value)
std::size_t getPosition() const
bool parseStringToEol(std::string &value)
bool parseInteger(long &value)
void setPosition(std::size_t pos)
bool parseDouble(double &value)
bool parseShort(short &value)