VM2D 1.14
Vortex methods for 2D flows simulation
Loading...
Searching...
No Matches
StreamParser.cpp
Go to the documentation of this file.
1/*--------------------------------*- VM2D -*-----------------*---------------*\
2| ## ## ## ## #### ##### | | Version 1.14 |
3| ## ## ### ### ## ## ## ## | VM2D: Vortex Method | 2026/03/06 |
4| ## ## ## # ## ## ## ## | for 2D Flow Simulation *----------------*
5| #### ## ## ## ## ## | Open Source Code |
6| ## ## ## ###### ##### | https://www.github.com/vortexmethods/VM2D |
7| |
8| Copyright (C) 2017-2026 I. Marchevsky, K. Sokol, E. Ryatina, A. Kolganova |
9*-----------------------------------------------------------------------------*
10| File name: StreamParser.cpp |
11| Info: Source code of VM2D |
12| |
13| This file is part of VM2D. |
14| VM2D is free software: you can redistribute it and/or modify it |
15| under the terms of the GNU General Public License as published by |
16| the Free Software Foundation, either version 3 of the License, or |
17| (at your option) any later version. |
18| |
19| VM2D is distributed in the hope that it will be useful, but WITHOUT |
20| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
21| FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
22| for more details. |
23| |
24| You should have received a copy of the GNU General Public License |
25| along with VM2D. If not, see <http://www.gnu.org/licenses/>. |
26\*---------------------------------------------------------------------------*/
27
28
40#include "StreamParser.h"
41
42using namespace VMlib;
43
44//Конструктор, принимающий четыре потока
45StreamParser::StreamParser(LogStream& infoStream, const std::string& label, std::istream& mainStream, std::istream& defaultsStream, std::istream& switchersStream, std::istream& varsStream, std::vector<std::string> specificKey)
46{
47 info.inheritStream(infoStream, label);
48
49 ParseStream(varsStream, vars);
50 ParseStream(defaultsStream, defaults);
51
52 //Добавление defaults в vars
54
55 ParseStream(switchersStream, switchers);
56 ParseStream(mainStream, database, specificKey, true);
57}//StreamParser(...)
58
59
60//Конструктор, принимающий два потока
61StreamParser::StreamParser(LogStream& infoStream, const std::string& label, std::istream& mainStream, std::istream& defaultsStream, std::vector<std::string> specificKey)
62{
63 info.inheritStream(infoStream, label);
64
65 ParseStream(mainStream, database, specificKey);
66 ParseStream(defaultsStream, defaults);
67
68 switchers.clear();
69 vars.clear();
70}//StreamParser(...)
71
72
73//Конструктор, принимающий один поток
74StreamParser::StreamParser(LogStream& infoStream, const std::string& label, std::istream& mainStream, char openBracket, char closeBracket)
75{
76 info.inheritStream(infoStream, label);
77
78 ParseStream(mainStream, database, {}, false, openBracket, closeBracket);
79
80 defaults.clear();
81 switchers.clear();
82 vars.clear();
83}//StreamParser(...)
84
85//Перевод строки в верхний регистр
86std::string StreamParser::UpperCase(const std::string& line)
87{
88 std::string str(line);
89 bool flag = true;
90
91 for (auto & c : str)
92 {
93 if (c == '"')
94 flag = !flag;
95 if (flag)
96 c = toupper(c);
97 }
98
99 //std::transform(str.begin(), str.end(), str.begin(), ::toupper);
100 return str;
101};//UpperCase(...)
102
103
104//Pазбор строки, содержащей запятые, на отдельные строки
105std::vector<std::string> StreamParser::StringToVector(std::string line, char openBracket, char closeBracket) //строка передается по значению, т.к. изменяется изнутри!
106{
107 //LogStream info;
108 //info.inheritStream(infoStream, label);
109
110 if (line[0] != '{')
111 {
112 if (line.length() > 0)
113 return { line };
114 else
115 {
116 //info('i') << "empty parameter" << std::endl;
117 return std::vector<std::string>({});
118 }
119 }
120 else
121 {
122 if (line[1] != '}')
123 {
124 std::vector<std::string> vecLine;
125 size_t pos;
126 while ( ((pos = line.find(',', 0)) < line.find(openBracket, 1)) ||
127 ( (pos = line.find(',', std::max(1, static_cast<int>(line.find(closeBracket, 1)) ))) != std::string::npos) ||
128 (pos = line.length()-1) )
129 {
130 std::string subline = line.substr(1, pos - 1);
131 if (subline != "")
132 vecLine.push_back(subline);
133
134 line.erase(1, subline.size() + 1);
135 }
136 return vecLine;
137 }
138 else
139 {
140 //info('i') << "empty parameter list" << std::endl;
141 return std::vector<std::string>({});
142 }//else if (line[1] != '}')
143 }//else if (st[0] != '{')
144}//StringToVector(...)
145
146
147
148//Объединение вектора (списка) из строк в одну строку
149std::string StreamParser::VectorStringToString(const std::vector<std::string>& _vecString)
150{
151 std::string buf;
152 for (size_t q = 0; q < _vecString.size(); ++q)
153 {
154 buf.append(_vecString[q]);
155 buf.append("\n");
156 }
157
158 return buf;
159}//VectorStringToString(...)
160
161
162//Разбор строки на пару ключ-значение
163std::pair<std::string, std::string> StreamParser::SplitString(LogStream& info, std::string line, bool upcase)
164{
165 size_t posBegin = line.find('(', 0);
166 size_t posEnd = line.find(')', 0);
167 if ((posBegin != -1) && (posEnd == -1))
168 {
169 info('e') << "error while parsing line " << line << std::endl;
170 exit(-1);
171 }
172 else
173 {
174 std::string sub = line.substr(0, posBegin);
175 if ((posBegin == -1) && (posEnd == -1))
176 return std::pair<std::string, std::string>(upcase ? UpperCase(sub) : sub, "{}");
177 else
178 return std::pair<std::string, std::string>(upcase ? UpperCase(sub) : sub, "{" + line.substr(posBegin + 1, posEnd - posBegin - 1) + "}");
179 }
180}//SplitString(...)
181
182
183//Парсинг заданного потока
184void StreamParser::ParseStream(std::istream& stream, std::unordered_map<std::string, std::vector<std::string>>& database, std::vector<std::string> specificKey, bool replaceVars, char openBracket, char closeBracket)
185{
186 std::string line, readline;
187 size_t defVarNum = 0;
188
189 while (stream.good())
190 {
191 line = "";
192
193 do
194 {
195 getline(stream, readline);
196
197 size_t posComment = std::min(readline.find('#'), readline.find("//"));
198 //min, так как если не найдено -- то find возвращает string::npos, которое равно (-1), но приводится к большому положительному size_t
199 if (posComment != std::string::npos)
200 readline = readline.substr(0, posComment);
201
202 line += readline;
203
204 readline.erase(remove(readline.begin(), readline.end(), ' '), readline.end());
205 readline.erase(remove(readline.begin(), readline.end(), '\t'), readline.end());
206
207 } while ( (readline.size()>0) && (readline[readline.size() - 1] == '\\') && (stream.good()));
208
209 line.erase(remove(line.begin(), line.end(), '\\'), line.end());
210 line.erase(remove(line.begin(), line.end(), ' '), line.end());
211 line.erase(remove(line.begin(), line.end(), '\t'), line.end());
212
213 size_t posEqual = line.find('=');
214 if (posEqual != -1)
215 {
216 std::string key = line.substr(0, posEqual);
217 auto search_it = database.find(UpperCase(key));
218
219 if (search_it == database.end())
220 {
221 if ((specificKey.size() == 0) || (std::find(specificKey.begin(),specificKey.end(),key) != specificKey.end()) )
222 {
223 std::string value = line.substr(posEqual + 1, line.length());
224 if (replaceVars)
225 ReplaceVarsInString(value);
226 database.insert(make_pair(UpperCase(key), StringToVector(value, openBracket, closeBracket)));
227 }
228 }
229 else
230 {
231 info('e') << "key <" << key << "> is found twice" << std::endl;
232 exit(-1);
233 }
234 }//if (posEqual != -1)
235 else if (line.size() > 0)
236 {
237 std::string value = line;
238 if (replaceVars)
239 ReplaceVarsInString(value);
240
241 std::stringstream ssDef;
242 ssDef << "_defVar_" << defVarNum;
243
244 database.insert(make_pair(UpperCase(ssDef.str()), StringToVector(value, openBracket, closeBracket)));
245
246 ++defVarNum;
247 }
248 }//while (streamName.good())
249
250 //Указатель возвращаем в начало потока
251 stream.clear();
252 stream.seekg(0, std::ios::beg);
253}//ParseStream(...)
254
255
256// Мерджинг двух баз данных без повторений
257void StreamParser::MergeDbsWithoutRepeats(std::unordered_map<std::string, std::vector<std::string>>& database, const std::unordered_map<std::string, std::vector<std::string>>& add)
258{
259 for (const auto& rec : add)
260 {
261 auto positionKey = database.find(rec.first);
262 if (positionKey == database.end())
263 database.insert(rec);
264 }
265}
266
267
268// Замена переменных в строке их значениями
270{
271 while (st.find("$") != -1)
272 {
273 size_t startVar = st.find('$');
274
275 size_t endVar = -1 + std::min({
276 st.find(" ", startVar + 1),
277 st.find(",", startVar + 1),
278 st.find(";", startVar + 1),
279 st.find("$", startVar + 1),
280 st.find("(", startVar + 1),
281 st.find(")", startVar + 1),
282 st.find("{", startVar + 1),
283 st.find("}", startVar + 1),
284 st.find("\n", startVar + 1),
285 st.length()
286 });
287
288 std::string var = st.substr(startVar + 1, endVar - startVar);
289
290 auto search_var = vars.find(UpperCase(var));
291 if ((search_var != vars.end()) && ((search_var->second).size() > 0))
292 {
293 std::vector<std::string> findString = search_var->second;
294
295 std::stringstream ss;
296
297 ss << st.substr(0, startVar);
298
299 if (findString.size() == 1)
300 {
301 ss << findString[0];
302 }
303 else
304 {
305 ss << "{" << findString[0];
306 if (findString.size() > 0)
307 {
308 for (size_t sz = 1; sz < findString.size(); ++sz)
309 ss << "," << findString[sz];
310 }
311 ss << "}";
312 }
313
314
315 size_t startP = endVar+1;
316 size_t endP = st.length() - 1;
317
318 if (startP <= endP)
319 ss << st.substr(startP, endP);
320
321 st = ss.str();
322 }
323 else
324 {
325 info('e') << "substitution $" << var << " is undefined" << std::endl;
326 exit(1);
327 }
328 }
329}//ReplaceVarsInDataBaseValues(...)
Заголовочный файл с описанием класса StreamParser.
Класс, определяющий работу с потоком логов
Definition LogStream.h:57
void inheritStream(LogStream &infoStream_, const std::string &label_)
Связывание потока логов с потоком вывода от другого потока логов
Definition LogStream.h:93
std::unordered_map< std::string, std::vector< std::string > > switchers
Данные считываемые из перечня параметров-переключателей
static std::vector< std::string > StringToVector(std::string line, char openBracket='(', char closeBracket=')')
Pазбор строки, содержащей запятые, на отдельные строки
StreamParser(LogStream &infoStream, const std::string &label, std::istream &mainStream, std::istream &defaultsStream, std::istream &switchersStream, std::istream &varsStream, std::vector< std::string > specificKey={})
Конструктор, принимающий четыре потока
static std::pair< std::string, std::string > SplitString(LogStream &info, std::string line, bool upcase=true)
Разбор строки на пару ключ-значение
static std::string VectorStringToString(const std::vector< std::string > &_vecString)
Объединение вектора (списка) из строк в одну строку
std::unordered_map< std::string, std::vector< std::string > > database
Данные считываемые из основного файла-паспорта расчета
void MergeDbsWithoutRepeats(std::unordered_map< std::string, std::vector< std::string > > &database, const std::unordered_map< std::string, std::vector< std::string > > &)
Слияние двух баз данных
void ParseStream(std::istream &stream, std::unordered_map< std::string, std::vector< std::string > > &database, std::vector< std::string > specificKey={}, bool replaceVars=false, char openBracket='(', char closeBracket=')')
Парсинг заданного потока
LogStream info
Поток для вывода логов и сообщений об ошибках
std::unordered_map< std::string, std::vector< std::string > > vars
Данные считываемые из параметров конкретной задачи
static std::string UpperCase(const std::string &line)
Перевод строки в верхний регистр
void ReplaceVarsInString(std::string &st)
Замена переменных в строке их значениями
Глобальные параметры по умолчанию
Definition defs.h:100