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