ConfDataReader.cpp
Go to the documentation of this file.
1 //==============================================================================
2 //
3 // This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
4 //
5 // The GNSSTk is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation; either version 3.0 of the License, or
8 // any later version.
9 //
10 // The GNSSTk is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with GNSSTk; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 // This software was developed by Applied Research Laboratories at the
20 // University of Texas at Austin.
21 // Copyright 2004-2022, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 // This software was developed by Applied Research Laboratories at the
28 // University of Texas at Austin, under contract to an agency or agencies
29 // within the U.S. Department of Defense. The U.S. Government retains all
30 // rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 // Pursuant to DoD Directive 523024
33 //
34 // DISTRIBUTION STATEMENT A: This software has been approved for public
35 // release, distribution is unlimited.
36 //
37 //==============================================================================
38 
44 #include "ConfDataReader.hpp"
45 
46 using namespace std;
47 
48 namespace gnsstk
49 {
50 
51  // Method to store conf data in this class' data map
52  void ConfDataReader::loadData(void)
53  {
54 
55  // By default, section name is "DEFAULT"
56  std::string sectionName("DEFAULT");
57 
58  // Do this until end-of-file reached or something else happens
59  while(1)
60  {
61  try
62  {
63 
64  std::string line;
65  std::string variable;
66  std::string value;
67 
68  formattedGetLine(line, true);
69 
70  // If line is too long, we throw an exception
71  if (line.size()>255)
72  {
73  ConfigurationException e(
74  "Line too long in configuration file '" +
75  filename + "'." );
76  GNSSTK_THROW(e);
77  }
78  // Skip the blank line
79  if(line.size()<1) continue;
80 
81  // Let's find and strip comment lines
82  if( (StringUtils::firstWord(line)[0] == '#') ||
83  (StringUtils::firstWord(line)[0] == ';') )
84  {
85  formattedGetLine(line, true);
86  }
87 
88  // Let's strip comments at the end of lines
89  std::string::size_type idx(line.find('#'));
90  if( !(idx == std::string::npos) )
91  {
92  line = line.substr(0, idx);
93  }
94 
95  idx = line.find(';');
96  if( !(idx == std::string::npos) )
97  {
98  line = line.substr(0, idx);
99  }
100 
101  // Remove trailing and leading blanks
102  line = StringUtils::strip(line);
103 
104  // Skip blank lines
105  if (line.size()==0)
106  {
107  continue;
108  }
109 
110 
111  // Let's start to get data out of file
112 
113  // First, handle section names
114 
115  // Test if this line declares a new section. Check for '['
116  idx = line.find('[');
117  if( !(idx == std::string::npos) )
118  {
119 
120  // Now, check if there is a closing ']'
121  std::string::size_type idx2(line.find(']'));
122  if( !(idx2 == std::string::npos) )
123  {
124  // Extract name and remove trailing and leading blanks
125  line = StringUtils::strip( line.substr(idx+1, idx2-idx-1) );
126 
127  // Check if section name is appropriate
128  if( checkName(line) )
129  {
130 
131  // Update 'sectionName': make it uppercase
132  sectionName = StringUtils::upperCase(line);
133 
134  }
135  else
136  {
137  // Throw an exception if section name isn't appropriate
138  ConfigurationException e(
139  "Section name '" +
140  line + "' in configuration file '" +
141  filename +
142  "' does not comply with rules.");
143 
144  GNSSTK_THROW(e);
145  }
146 
147  // If this was a section line, continue with next line
148  continue;
149 
150  }
151  else
152  {
153  // Throw an exception if section line is not closed
154  ConfigurationException e(
155  "Section line '" +
156  line +
157  "' in configuration file '" +
158  filename +
159  "' was improperly closed" );
160 
161  GNSSTK_THROW(e);
162  }
163 
164  }
165 
166  // Second, handle variables
167 
168  // Separate variable name from value. Look for separators
169  idx = line.find('=');
170  if( idx == std::string::npos )
171  {
172  idx = line.find(':');
173  }
174 
175 
176  // If we found a separator, keep processing
177  if( !(idx == std::string::npos) )
178  {
179 
180  // Read variable and value
181  variable = StringUtils::strip( line.substr(0, idx) );
182  value = StringUtils::strip( line.substr(idx+1) );
183 
184  // Now separate comments
185 
186  // Work on 'variable'
187  std::string varComment;
188 
189  idx = variable.find(',');
190  if( !(idx == std::string::npos) )
191  {
192  varComment = StringUtils::strip(variable.substr(idx+1));
193  variable = StringUtils::strip(variable.substr(0, idx));
194  }
195 
196  // Check if variable name is appropriate
197  if( checkName(variable) )
198  {
199  // Make 'variable' uppercase
200  variable = StringUtils::upperCase(variable);
201 
202  }
203  else
204  {
205  // Throw an exception if variable name isn't appropriate
206  ConfigurationException e(
207  "Variable name '" +
208  variable + "' in configuration file '" +
209  filename +
210  "' does not comply with rules.");
211 
212  GNSSTK_THROW(e);
213  }
214 
215  // Now work on 'value'
216  std::string valueComment;
217 
218  idx = value.find(',');
219  if( !(idx == std::string::npos) )
220  {
221  valueComment = StringUtils::strip(value.substr(idx+1));
222  value = StringUtils::strip(value.substr(0, idx));
223  }
224 
225  // Store configuration data
226  variableData varData;
227  varData.varComment = varComment;
228  varData.value = value;
229  varData.valueComment = valueComment;
230 
231  confData[sectionName][variable] = varData;
232 
233  }
234 
235  } // End of try block
236  catch (ConfigurationException& e)
237  {
238  GNSSTK_THROW(e);
239  }
240  catch (EndOfFile& e)
241  {
242 
243  // Initialize itCurrentSection
244  itCurrentSection = confData.begin();
245 
246  return;
247 
248  }
249  catch (...)
250  {
251 
252  return;
253 
254  }
255 
256  } // End of 'while(1)'
257 
258  } // End of method 'ConfDataReader::loadData()'
259 
260 
261 
262  /* Method to get the value of a given variable as a string
263  *
264  * @param variable Variable name.
265  * @param section Section the variable belongs to.
266  *
267  */
268  string ConfDataReader::getValue( string variable,
269  string section,
270  string defaultVal )
271  {
272 
273  // Let's make sure that section and variable names are uppercase
274  section = StringUtils::upperCase(section);
275  variable = StringUtils::upperCase(variable);
276 
277 
278  try
279  {
280 
281  // Auxiliar variable to store current 'issueException' state
282  bool exceptionState( getIssueException() );
283 
284  // If 'fallback2Default' is set, and this is NOT the 'DEFAULT'
285  // section, we need to temporarily disable 'issueException'.
286  // This implies that there is no fallback for 'DEFAULT' variables
287  if( (section != "DEFAULT") && (section != "") )
288  {
289  if( getFallback2Default() )
290  {
291  setIssueException(false);
292  }
293  }
294 
295 
296  // Check if section and variable exist
297  if( ifExist(variable, section) )
298  {
299 
300  // Reset 'issueException' to its correct value before continue
301  setIssueException( exceptionState );
302 
303  return confData[section][variable].value;
304 
305  }
306  else
307  {
308 
309  // Reset 'issueException' to its correct value before continue
310  setIssueException( exceptionState );
311 
312  // If 'fallback2Default' is set, check also in 'DEFAULT' section
313  if ( getFallback2Default() )
314  {
315 
316  if( ifExist(variable) )
317  {
318 
319  return confData["DEFAULT"][variable].value;
320 
321  }
322  else
323  {
324 
325  return defaultVal;
326 
327  }
328 
329  }
330  else
331  {
332 
333  return defaultVal;
334 
335  } // End of 'if ( getFallback2Default() )'
336 
337  } // End of 'if( ifExist(variable, section) )'
338 
339  }
340  catch (ConfigurationException& e)
341  {
342 
343  GNSSTK_RETHROW(e);
344 
345  } // End of 'try-catch' block
346 
347  } // End of method 'ConfDataReader::getValue()'
348 
349 
350 
351  /* Method to get the value of a given variable as a boolean
352  *
353  * @param variable Variable name.
354  * @param section Section the variable belongs to.
355  *
356  */
357  bool ConfDataReader::getValueAsBoolean( string variable,
358  string section,
359  bool defaultVal )
360  {
361 
362  // Let's make sure that section and variable names are uppercase
363  section = StringUtils::upperCase(section);
364  variable = StringUtils::upperCase(variable);
365 
366  try
367  {
368 
369  // Declare result variable
370  string result( getValue( variable, section ) );
371 
372 
373  // Test if result is empty (variable does not exist)
374  if( result == "" )
375  {
376  // Return false if variable is empty. Be aware that an empty
377  // variable is NOT the same as an unexistent variable
378  return defaultVal;
379 
380  }
381 
382 
383  // 'result' isn't empty. Convert it to uppercase
384  result = StringUtils::upperCase(result);
385 
386  // Test if it is "TRUE" or "FALSE"
387  if( result == "TRUE" )
388  {
389 
390  return true;
391 
392  }
393  else
394  {
395 
396  if( result == "FALSE" )
397  {
398 
399  return false;
400 
401  }
402  else
403  {
404 
405  // Throw an exception if value is neither TRUE nor FALSE
406  ConfigurationException e(
407  "Variable name '" +
408  variable + "' in configuration file '" +
409  filename +
410  "' is neither TRUE nor FALSE.");
411 
412  GNSSTK_THROW(e);
413 
414  } // End of 'if( result == "FALSE" )'
415 
416  } // End of 'if( result == "TRUE" )'
417 
418  }
419  catch (ConfigurationException& e)
420  {
421  GNSSTK_RETHROW(e);
422  }
423 
424  } // End of method 'ConfDataReader::getValueAsBoolean()'
425 
426 
427 
428  /* Method to fetch (as string) the first value of a given
429  * variable list.
430  *
431  * In this context, a variable list is the same as a variable but
432  * it is composed of several parts (words), separated by spaces.
433  *
434  * @param variableList Variable list name.
435  * @param section Section the variable list belongs to.
436  *
437  * @warning This method will MODIFY the original content of
438  * 'variableList'.
439  */
440  string ConfDataReader::fetchListValue( string variableList,
441  string section,
442  string defaultVal )
443  {
444 
445  try
446  {
447 
448  // Let's make sure that section and variable names are uppercase
449  section = StringUtils::upperCase(section);
450  variableList = StringUtils::upperCase(variableList);
451 
452  // Store the original value of 'variableList'
453  string origValue( getValue(variableList, section) );
454 
455  // Get the first word in 'originalValue'
456  string firstValue( StringUtils::stripFirstWord(origValue) );
457 
458  // Modify the originalValue value
459  confData[section][variableList].value = StringUtils::strip(origValue);
460 
461  // Return the first value
462  string value = StringUtils::strip(firstValue);
463  return ( (value=="") ? string(defaultVal) : value );
464 
465  }
466  catch (ConfigurationException& e)
467  {
468  GNSSTK_RETHROW(e);
469  }
470 
471  } // End of method 'ConfDataReader::fetchListValue()'
472 
473 
474 
475  /* Method to fetch (as boolean) the first value of a given
476  * variable list.
477  *
478  * In this context, a variable list is the same as a variable but
479  * it is composed of several parts (words), separated by spaces.
480  *
481  * @param variableList Variable list name.
482  * @param section Section the variable list belongs to.
483  *
484  * @warning This method will MODIFY the original content of
485  * 'variableList'.
486  */
487  bool ConfDataReader::fetchListValueAsBoolean( string variableList,
488  string section,
489  bool defaultVal )
490  {
491 
492  try
493  {
494 
495  // Let's make sure that section and variable names are uppercase
496  section = StringUtils::upperCase(section);
497  variableList = StringUtils::upperCase(variableList);
498 
499  // Get first value in 'variableList' and make it uppercase
500  string result( fetchListValue(variableList,section) );
501 
502  result = StringUtils::upperCase(result);
503 
504  // Test if it is "TRUE" or "FALSE"
505  if( result == "TRUE" )
506  {
507 
508  return true;
509 
510  }
511  else
512  {
513 
514  if( (result == "FALSE") ||
515  (result == "") ) // If list is empty returns false
516  {
517 
518  return defaultVal;
519 
520  }
521  else
522  {
523 
524  // Throw an exception if value is neither TRUE nor FALSE
525  ConfigurationException e(
526  "Variable list '" +
527  variableList + "' in configuration file '" +
528  filename +
529  "' have a value that is neither TRUE " +
530  "nor FALSE.");
531 
532  GNSSTK_THROW(e);
533 
534  } // End of 'if( result == "FALSE" )'
535 
536  } // End of 'if( result == "TRUE" )'
537 
538  } // End of 'try' block
539  catch (ConfigurationException& e)
540  {
541  GNSSTK_RETHROW(e);
542  }
543 
544  } // End of method 'ConfDataReader::fetchListValueAsBoolean()'
545 
546 
547 
548  /* Method to get the description of a given variable
549  *
550  * @param variable Variable name.
551  * @param section Section the variable belongs to.
552  *
553  */
554  string ConfDataReader::getVariableDescription( string variable,
555  string section )
556  {
557 
558  // Let's make sure that section and variable names are uppercase
559  section = StringUtils::upperCase(section);
560  variable = StringUtils::upperCase(variable);
561 
562  try
563  {
564 
565  // Auxiliar variable to store current 'issueException' state
566  bool exceptionState( getIssueException() );
567 
568  // If 'fallback2Default' is set, and this is NOT the 'DEFAULT'
569  // section, we need to temporarily disable 'issueException'.
570  // This implies that there is no fallback for 'DEFAULT' variables
571  if( (section != "DEFAULT") && (section != "") )
572  {
573  if( getFallback2Default() )
574  {
575  setIssueException(false);
576  }
577  }
578 
579 
580  // Check if section and variable exist
581  if( ifExist(variable, section) )
582  {
583 
584  // Reset 'issueException' to its correct value before continue
585  setIssueException( exceptionState );
586 
587  return confData[section][variable].varComment;
588 
589  }
590  else
591  {
592 
593  // Reset 'issueException' to its correct value before continue
594  setIssueException( exceptionState );
595 
596  // If 'fallback2Default' is set, check also in 'DEFAULT' section
597  if ( getFallback2Default() )
598  {
599 
600  if( ifExist(variable) )
601  {
602 
603  return confData["DEFAULT"][variable].varComment;
604 
605  }
606  else
607  {
608 
609  return "";
610 
611  }
612 
613  }
614  else
615  {
616 
617  return "";
618 
619  } // End of 'if ( getFallback2Default() )'
620 
621  } // End of 'if( ifExist(variable, section) )'
622 
623  }
624  catch (ConfigurationException& e)
625  {
626  GNSSTK_RETHROW(e);
627  }
628 
629  } // End of method 'ConfDataReader::getVariableDescription()'
630 
631 
632 
633  /* Method to get the description of a given value
634  *
635  * @param variable Variable name.
636  * @param section Section the variable belongs to.
637  *
638  */
639  string ConfDataReader::getValueDescription( string variable,
640  string section )
641  {
642 
643  // Let's make sure that section and variable names are uppercase
644  section = StringUtils::upperCase(section);
645  variable = StringUtils::upperCase(variable);
646 
647  try
648  {
649 
650  // Auxiliar variable to store current 'issueException' state
651  bool exceptionState( getIssueException() );
652 
653  // If 'fallback2Default' is set, and this is NOT the 'DEFAULT'
654  // section, we need to temporarily disable 'issueException'.
655  // This implies that there is no fallback for 'DEFAULT' variables
656  if( (section != "DEFAULT") && (section != "") )
657  {
658  if( getFallback2Default() )
659  {
660  setIssueException(false);
661  }
662  }
663 
664 
665  // Check if section and variable exist
666  if( ifExist(variable, section) )
667  {
668 
669  // Reset 'issueException' to its correct value before continue
670  setIssueException( exceptionState );
671 
672  return confData[section][variable].valueComment;
673 
674  }
675  else
676  {
677 
678  // Reset 'issueException' to its correct value before continue
679  setIssueException( exceptionState );
680 
681  // If 'fallback2Default' is set, check also in 'DEFAULT' section
682  if ( getFallback2Default() )
683  {
684 
685  if( ifExist(variable) )
686  {
687 
688  return confData["DEFAULT"][variable].valueComment;
689 
690  }
691  else
692  {
693 
694  return "";
695 
696  }
697 
698  }
699  else
700  {
701 
702  return "";
703 
704  } // End of 'if ( getFallback2Default() )'
705 
706  } // End of 'if( ifExist(variable, section) )'
707 
708  }
709  catch (ConfigurationException& e)
710  {
711  GNSSTK_RETHROW(e);
712  }
713 
714  } // End of method 'ConfDataReader::getValueDescription()'
715 
716 
717 
718  /* Method to check if a given section/variable pair exists.
719  *
720  * @param variable Variable name.
721  * @param section Section the variable belongs to.
722  *
723  */
724  bool ConfDataReader::ifExist( string variable,
725  string section )
726  {
727 
728  // Let's make sure that section and variable names are uppercase
729  section = StringUtils::upperCase(section);
730  variable = StringUtils::upperCase(variable);
731 
732  // Check if section and variable exist
733  confMap::const_iterator it;
734  it = confData.find(section);
735  if( it != confData.end() )
736  {
737  variableMap::const_iterator it2;
738  it2 = (*it).second.find(variable);
739  if( it2 != (*it).second.end() )
740  {
741 
742  // Return the corresponding value, if it exists
743  return true;
744 
745  }
746  else
747  {
748 
749  if(issueException)
750  {
751 
752  // Throw an exception if variable name doesn't exist
753  ConfigurationException e(
754  "Variable '" + variable
755  + "' in section '" + section
756  + "' of configuration file '" + filename
757  + "' does not exist.");
758 
759  GNSSTK_THROW(e);
760 
761  }
762  else
763  {
764 
765  return false;
766 
767  } // End of 'if(issueException)'
768 
769  } // End of 'if( it2 != (*it).second.end() )'
770 
771  }
772  else
773  {
774 
775  if(issueException)
776  {
777 
778  // Check if problem is with section "DEFAULT"
779  if ( section == "DEFAULT" )
780  {
781 
782  // Throw an exception if section name doesn't exist
783  ConfigurationException e(
784  "Section 'DEFAULT' in configuration file '"
785  + filename
786  + "' does not exist. Does file '"
787  + filename + "' exist?. Do you have "
788  + "permission to read it?." );
789 
790  GNSSTK_THROW(e);
791 
792  }
793  else
794  {
795 
796  // Throw an exception if section name doesn't exist
797  ConfigurationException e(
798  "Section '" + section
799  + "' in configuration file '" + filename
800  + "' does not exist.");
801 
802  GNSSTK_THROW(e);
803 
804  } // End of 'if ( section == "DEFAULT" )'
805 
806  }
807  else
808  {
809 
810  return false;
811 
812  } // End of 'if(issueException)'
813 
814  } // End of 'if( it != confData.end() )'
815 
816  } // End of method 'ConfDataReader::ifExist()'
817 
818 
819 
820  // Method to open AND load configuration data file.
821  void ConfDataReader::open(const char* fn)
822  {
823 
824  // We always open configuration file as "read-only"
825  FFTextStream::open(fn, std::ios::in);
826 
827  loadData();
828 
829  return;
830 
831  } // End of method 'ConfDataReader::open()'
832 
833 
834 
835  // Method to get the name of each section in order.
836  string ConfDataReader::getEachSection(void)
837  {
838 
839  if ( itCurrentSection != confData.end() )
840  {
841 
842  // Store result
843  string result( (*itCurrentSection).first );
844 
845  // Increment iterator for next time
846  ++itCurrentSection;
847 
848  // Return result
849  return result;
850 
851  }
852  else
853  {
854  // If we are at the end, return an empty string
855  return "";
856  }
857 
858  } // End of method 'ConfDataReader::getEachSection()'
859 
860 
861 
862  /* Method to check if the given name is properly formed.
863  *
864  * @param name Name to the checked.
865  */
866  bool ConfDataReader::checkName(string name)
867  {
868 
869  try
870  {
871 
872  // Test if first character is alphabetic
873  if( StringUtils::isAlphaString(name.substr(0, 1)) )
874  {
875 
876  // Translate all allowed characters to 'a'
877  name = StringUtils::translate( name,"0123456789-_", "a", 'a');
878 
879  // If the result is an alphabetic string, the name is valid
880  return ( StringUtils::isAlphaString(name) );
881 
882  }
883  else
884  {
885  // If first character is not alphabetic, we return false
886  return false;
887  }
888 
889  }
890  catch (...)
891  {
892  // In case of any problem we return false
893  return false;
894  }
895 
896  } // End of method 'ConfDataReader::checkName()'
897 
898 
899 
900 } // End of namespace gnsstk
gnsstk::StringUtils::upperCase
std::string & upperCase(std::string &s)
Definition: StringUtils.hpp:2117
gnsstk::ConfDataReader::variableData::value
std::string value
Value of variable.
Definition: ConfDataReader.hpp:468
gnsstk::StringUtils::isAlphaString
bool isAlphaString(const std::string &s)
Definition: StringUtils.hpp:1922
gnsstk::ConfDataReader::variableData::valueComment
std::string valueComment
Value comment.
Definition: ConfDataReader.hpp:469
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::ConfDataReader::variableData
A structure used to store variable's data.
Definition: ConfDataReader.hpp:462
ConfDataReader.hpp
gnsstk::StringUtils::stripFirstWord
std::string stripFirstWord(std::string &s, const char delimiter=' ')
Definition: StringUtils.hpp:2253
gnsstk::ConfDataReader::variableData::varComment
std::string varComment
Variable comment.
Definition: ConfDataReader.hpp:465
GNSSTK_RETHROW
#define GNSSTK_RETHROW(exc)
Definition: Exception.hpp:369
std
Definition: Angle.hpp:142
gnsstk::StringUtils::firstWord
std::string firstWord(const std::string &s, const char delimiter=' ')
Definition: StringUtils.hpp:2138
gnsstk::StringUtils::strip
std::string & strip(std::string &s, const std::string &aString, std::string::size_type num=std::string::npos)
Definition: StringUtils.hpp:1482
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
example5.fn
string fn
Definition: example5.py:10
gnsstk::StringUtils::translate
std::string translate(const std::string &aString, const std::string &inputChars, const std::string &outputChars, const char pad=' ')
Definition: StringUtils.hpp:1491


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:38