BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSMySQLWrapper.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "BDSDebug.hh"
19#include "BDSException.hh"
20#include "BDSMySQLWrapper.hh"
21#include "BDSMySQLTable.hh"
22#include "BDSMySQLVariable.hh"
23#include "BDSUtilities.hh"
24
25#include "globals.hh"
26#include "G4String.hh"
27#include "G4Version.hh"
28
29#include "CLHEP/Units/SystemOfUnits.h"
30
31#include <cstdlib>
32#include <iostream>
33#include <regex>
34#include <string>
35#include <vector>
36
37
38BDSMySQLWrapper::BDSMySQLWrapper(const G4String& SQLFileName):
39 ifs(SQLFileName.c_str()),
40 ComponentN(0),
41 tableN(-1)
42{
43 _startOfFile=true;
44 BeginTokens();
45
46 if(ifs)
47 {
48#ifdef BDSDEBUG
49 G4cout << __METHOD_NAME__ << "loading SQL Filename: " << SQLFileName << G4endl;
50#endif
51 }
52 else
53 {throw BDSException(__METHOD_NAME__, "Unable to load SQL file: " + SQLFileName);}
54}
55
56BDSMySQLWrapper::~BDSMySQLWrapper()
57{;}
58
59std::vector<BDSMySQLTable*> BDSMySQLWrapper::ConstructTable()
60{
61 ComponentN=0;
62 tableN=-1;
63 while(NextToken())
64 {ParseComponent();}
65 return table;
66}
67
68void BDSMySQLWrapper::TokenizeLine()
69{
70 // empty old tokens
71 _tokens.clear();
72
73 // Separate with comma and space, separate and keep with ; ( ) and \n
74 // Done in 2 steps, once for dropped delimiters and then for the kept delimiters
75 // Delimiters are spaces, tabs (changed from earlier versions) and/or commas, but no newlines
76 std::regex drop_delimiters("[ \t,]+");
77
78 std::string &s = _currentLine;
79 // Specifying -1 as the fourth argument makes the function skip over any patterns matching
80 // the regex_obj, causing the iterator to iterate through the tokens—which consist of text
81 // between each occurrence of the pattern.
82 std::sregex_token_iterator tok_iter(s.begin(), s.end(), drop_delimiters, -1);
83
84 // default constructor = end-of-sequence:
85 std::sregex_token_iterator rend;
86 for (; tok_iter!=rend; ++tok_iter) {
87 std::string subtoken = *tok_iter;
88 // G4cout << __METHOD_NAME__ << " - subtoken: = <" << subtoken << ">" << G4endl;
89
90 // keep ; ( )
91 std::regex keep_delimiters("[;\\(\\)]");
92 // delimiters (0) and remaining (-1)
93 std::sregex_token_iterator tok_iter2(subtoken.begin(), subtoken.end(), keep_delimiters, {-1, 0});
94
95 for (; tok_iter2!=rend; ++tok_iter2) {
96
97 std::string token = *tok_iter2;
98
99 // only put non-empty tokens, but put empty strings ""
100 if (token.empty())
101 {continue;}
102 RemoveQuotesFromLine(token);
103 RemoveWhitespace(token);
104 _tokens.push_back(token);
105#ifdef BDSDEBUG
106 G4cout << __METHOD_NAME__ << "- token: = <" << token << ">" << G4endl;
107#endif
108 }
109 }
110 BeginTokens();
111}
112
113bool BDSMySQLWrapper::NextToken()
114{
115 ++_tokens_iter;
116 if(_startOfFile)
117 {--_tokens_iter;}
118 if(_startOfFile || EndTokens()){
119 if(ifs.good()){
120 ReadLine();
121 TokenizeLine();
122#ifdef BDSDEBUG
123 G4cout << __METHOD_NAME__ << "- Token() = " << Token() << G4endl;
124#endif
125 }else{
126 return false;
127 }
128 } else {
129#ifdef BDSDEBUG
130 G4cout << __METHOD_NAME__ << "- Token() = " << Token() << G4endl;
131#endif
132 }
133 return true;
134}
135
136G4int BDSMySQLWrapper::ParseComponent()
137{
138 // not using these commands yet...
139 if(Token()==CMD_DROP) { return 0;}
140 else if(Token()==CMD_DATABASE) { return 0;}
141 else if(Token()==CMD_IF) { return 0;}
142 else if(Token()==CMD_EXISTS) { return 0;}
143 else if(Token()==CMD_USE) { return 0;}
144 //The following commands are used...
145 else if(Token()==CMD_CREATE) {Create(); return 0;}
146 else if(Token()==CMD_INSERT) {Insert(); ComponentN++; return 0;}
147 return 0;
148}
149
150void BDSMySQLWrapper::CreateDatabase()
151{;}
152
153void BDSMySQLWrapper::CreateTable()
154{
155 G4String varname;
156 G4String vartype;
157
158 _NEXTINPUT
159 CurrentTableName=Token();
160#ifdef BDSDEBUG
161 G4cout << __METHOD_NAME__ << " reading CurrentTableName: " << CurrentTableName << G4endl;
162#endif
163 ProceedToEndOfLine();
164 table.push_back(new BDSMySQLTable(CurrentTableName));
165 tableN++;
166#if G4VERSION_NUMBER > 1099
167 while(!G4StrUtil::contains(varname,";") && (!G4StrUtil::contains(vartype,";")))
168#else
169 while((!varname.contains(";")) && (!vartype.contains(";")))
170#endif
171 {
172 //Get next variable, skipping blanks.
173 do{
174 _NEXTINPUT
175 } while((EmptyToken()) || (EndOfLine()));
176 varname=Token();
177#ifdef BDSDEBUG
178 G4cout << __METHOD_NAME__ << " reading varname: " << varname << G4endl;
179#endif
180 if (BDS::StrContains(varname, ";")) {return;}
181 _NEXTINPUT
182 vartype=Token();
183#ifdef BDSDEBUG
184 G4cout << __METHOD_NAME__ << " reading vartype: " << vartype << G4endl;
185#endif
186 if (BDS::StrContains(vartype,";")) return; //Semicolon indicates end of table.
187 if(BDS::StrContains(vartype, "DOUBLE")) vartype="DOUBLE";
188 else if(BDS::StrContains(vartype, "VARCHAR")) vartype="STRING";
189 else if(BDS::StrContains(vartype, "INTEGER")) vartype="INTEGER";
190 table[tableN]->AddVariable(varname,vartype);
191 ProceedToEndOfLine();
192 }
193}
194
195void BDSMySQLWrapper::Create()
196{
197 _NEXT
198#ifdef BDSDEBUG
199 G4cout << __METHOD_NAME__ << " reading input: " << Token() << G4endl;
200#endif
201 if(Token()==CMD_DATABASE) {CreateDatabase();}
202 else if(Token()==CMD_TABLE) {CreateTable();}
203}
204
205void BDSMySQLWrapper::Insert(){
206 _NEXT
207#ifdef BDSDEBUG
208 G4cout << __METHOD_NAME__ << " reading input: " << Token() << G4endl;
209#endif
210 if(Token()==CMD_INTO){InsertInto();}
211}
212
213void BDSMySQLWrapper::InsertInto() {
214 _NEXT
215 InsertTableName=Token();
216 _NEXT
217 if(Token()==CMD_VALUES){Values();}
218}
219
220void BDSMySQLWrapper::Values() {
221 for(G4int j=0; j<(G4int)table.size(); j++){
222 if(table[j]->GetName()==InsertTableName){
223 for(G4int k=0; k<table[j]->GetNVariables(); k++){
224 _NEXTINPUT
225 //Skip first bracket...
226 while (Token()=="(") {
227 _NEXTINPUT
228 }
229 if (Token()==")") {
230 // std::stringstream excptnSstrm;
231 // excptnSstrm<<__METHOD_NAME__<< " - expected " << table[j]->GetNVariables() << " values for insertion into table " << InsertTableName << "\n";
232 // G4Exception(excptnSstrm.str().c_str(), "-1", FatalException, "");
233 // return;
234 }
235#ifdef BDSDEBUG
236 G4cout << __METHOD_NAME__ << " inserting value " << Token() << G4endl;
237#endif
238 if(table[j]->GetVariable(k)->GetVarType()=="DOUBLE")
239 table[j]->GetVariable(k)->AddValue(std::atoi(Token().c_str())*CLHEP::mm);
240 else if(table[j]->GetVariable(k)->GetVarType()=="STRING")
241 table[j]->GetVariable(k)->AddValue(Token());
242 else if(table[j]->GetVariable(k)->GetVarType()=="INTEGER")
243 table[j]->GetVariable(k)->AddValue(std::atoi(Token().c_str()));
244 }
245 }
246 }
247}
248
249void BDSMySQLWrapper::BeginTokens(){
250 _tokens_iter=_tokens.begin();
251}
252
253bool BDSMySQLWrapper::NextInputToken(){
254 if(ifs.good()){
255 bool status;
256 do{
257 status=NextToken();
258 } while (EndOfLine());
259 return status;
260 } else {
261 return false;
262 }
263}
264
265bool BDSMySQLWrapper::EndTokens()
266{
267 return(_tokens_iter==_tokens.end());
268}
269
270bool BDSMySQLWrapper::EndOfLine()
271{
272 return((*_tokens_iter)=="\n");
273}
274
275bool BDSMySQLWrapper::EmptyToken()
276{
277 return((*_tokens_iter)=="");
278}
279
280std::string BDSMySQLWrapper::Token()
281{
282 return *_tokens_iter;
283}
284
285void BDSMySQLWrapper::ProceedToEndOfLine()
286{
287 while(!EndOfLine()){
288 _NEXT
289#ifdef BDSDEBUG
290 G4cout << __METHOD_NAME__ << " " << Token() << G4endl;
291#endif
292 }
293#ifdef BDSDEBUG
294 G4cout << __METHOD_NAME__ << " finished." << G4endl;
295#endif
296}
297
298void BDSMySQLWrapper::ReadLine(){
299 _currentLine.clear();
300 _startOfFile=false;
301 //returns non zero if unsuccessful
302 char buffer[512];
303 ifs.getline(buffer,512);
304 _currentLine=buffer;
305 RemoveCommentsFromLine(_currentLine);
306 //Put back the new line character
307 _currentLine += ' ';
308 _currentLine += '\n';
309#ifdef BDSDEBUG
310 G4cout << __METHOD_NAME__ << " - _currentLine = " << _currentLine << G4endl;
311#endif
312}
313
314void BDSMySQLWrapper::RemoveCommentsFromLine(std::string& value){
315 //Strip all characters after and including '#'
316 unsigned pos = value.find('#');
317 std::string uncommented = value.substr(0,pos);
318 value=uncommented;
319}
320
321void BDSMySQLWrapper::RemoveQuotesFromLine(std::string& value){
322 //Strip all "
323 value.erase (std::remove(value.begin(), value.end(), '\"'), value.end());
324}
325
326
327void BDSMySQLWrapper::RemoveWhitespace(G4String& val){
328 std::string s = val;
329 RemoveWhitespace(s);
330 val=(G4String)s;
331}
332
333void BDSMySQLWrapper::RemoveWhitespace(std::string& val){
334 val.erase( std::remove_if( val.begin(), val.end(), ::isblank ), val.end() );
335}
336
337/*
338void Log(const G4String& tag, int depth, ostream& os)
339{
340 static const char* tab = "----|";
341 while(depth--) os<<tab;
342 os<<' '<<tag<<endl;
343}
344*/
345
346
347
348
349
General exception with possible name of object and message.
Representation of a mysql table.
G4bool StrContains(const G4String &str, const G4String &test)
Utility function to simplify lots of syntax changes for pedantic g4 changes.
const char * GetName(int)
Name of element.
Definition parserROOT.cc:37