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