GammaLib  1.7.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GApplicationPars.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GApplicationPars.cpp - Application parameters *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2010-2018 by Juergen Knoedlseder *
5  * ----------------------------------------------------------------------- *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19  * *
20  ***************************************************************************/
21 /**
22  * @file GApplicationPars.cpp
23  * @brief Application parameter container class implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <pwd.h> // user/passwd function
32 #include <fcntl.h> // for file locking
33 #include <unistd.h> // access() function
34 #include <sys/stat.h> // mkdir() function
35 #include <cstdlib> // std::getenv() function
36 #include <cstdio> // std::fopen(), etc. functions
37 #include <sstream>
38 #include "GTools.hpp"
39 #include "GException.hpp"
40 #include "GFilename.hpp"
41 #include "GApplicationPars.hpp"
42 
43 /* __ Method name definitions ____________________________________________ */
44 #define G_ACCESS "GApplicationPars::operator[](std::string&)"
45 #define G_AT "GApplicationPar& GApplicationPars::at(int&)"
46 #define G_APPEND "GApplicationPars::append(GApplicationPar&)"
47 #define G_INSERT1 "GApplicationPar& GApplicationPars::insert(int&, "\
48  "GApplicationPar&)"
49 #define G_INSERT2 "GApplicationPar& GApplicationPars::insert(std::string&, "\
50  "GApplicationPar&)"
51 #define G_REMOVE1 "GApplicationPars::remove(int&)"
52 #define G_REMOVE2 "GApplicationPars::remove(std::string&)"
53 #define G_EXTEND "GApplicationPars::extend(GApplicationPars&)"
54 #define G_LOAD1 "GApplicationPars::load(GFilename&)"
55 #define G_LOAD2 "GApplicationPars::load(GFilename&, "\
56  "std::vector<std::string>&)"
57 #define G_SAVE "GApplicationPars::save(GFilename&)"
58 #define G_OUTPATH "GApplicationPars::outpath(std::string&)"
59 #define G_READ "GApplicationPars::read(std::string&)"
60 #define G_WRITE "GApplicationPars::write(std::string&)"
61 #define G_PARSE "GApplicationPars::parse()"
62 
63 /* __ Macros _____________________________________________________________ */
64 
65 /* __ Coding definitions _________________________________________________ */
66 #define G_LOCK_PARFILE //!< Enables parfile locking
67 //#define G_CHECK_LOCK_PARFILE //!< Enables check of parfile locking
68 
69 /* __ Debug definitions __________________________________________________ */
70 
71 
72 /*==========================================================================
73  = =
74  = Constructors/destructors =
75  = =
76  ==========================================================================*/
77 
78 /***********************************************************************//**
79  * @brief Void constructor
80  ***************************************************************************/
82 {
83  // Initialise private members for clean destruction
84  init_members();
85 
86  // Return
87  return;
88 }
89 
90 
91 /***********************************************************************//**
92  * @brief Parameter file constructor
93  *
94  * @param[in] filename Parameter filename.
95  ***************************************************************************/
97 {
98  // Initialise private members for clean destruction
99  init_members();
100 
101  // Load parameters
102  load(filename);
103 
104  // Return
105  return;
106 }
107 
108 /***********************************************************************//**
109  * @brief Parameter constructor
110  *
111  * @param[in] filename Parameter filename.
112  * @param[in] args Command line arguments.
113  ***************************************************************************/
115  const std::vector<std::string>& args)
116 {
117  // Initialise private members for clean destruction
118  init_members();
119 
120  // Load parameters
121  load(filename, args);
122 
123  // Return
124  return;
125 }
126 
127 
128 /***********************************************************************//**
129  * @brief Copy constructor
130  *
131  * @param[in] pars Parameter container.
132  ***************************************************************************/
134 {
135  // Initialise private members for clean destruction
136  init_members();
137 
138  // Copy members
139  copy_members(pars);
140 
141  // Return
142  return;
143 }
144 
145 
146 /***********************************************************************//**
147  * @brief Destructor
148  ***************************************************************************/
150 {
151  // Free members
152  free_members();
153 
154  // Return
155  return;
156 }
157 
158 
159 /*==========================================================================
160  = =
161  = Operators =
162  = =
163  ==========================================================================*/
164 
165 /***********************************************************************//**
166  * @brief Assignment operator
167  *
168  * @param[in] pars Parameter container.
169  * @return Parameter container.
170  ***************************************************************************/
172 {
173  // Execute only if object is not identical
174  if (this != &pars) {
175 
176  // Free members
177  free_members();
178 
179  // Initialise private members for clean destruction
180  init_members();
181 
182  // Copy members
183  copy_members(pars);
184 
185  } // endif: object was not identical
186 
187  // Return
188  return *this;
189 }
190 
191 
192 /***********************************************************************//**
193  * @brief Returns reference to parameter
194  *
195  * @param[in] name Parameter name.
196  * @return Parameter.
197  *
198  * @exception GException::invalid_argument
199  * Parameter with specified name not found in container.
200  ***************************************************************************/
202 {
203  // Get parameter index
204  int index = get_index(name);
205 
206  // Throw exception if parameter name has not been found
207  if (index == -1) {
208  std::string msg = "Parameter \""+name+"\" has not been found in "
209  "parameter file. Please specify a valid parameter "
210  "name.";
212  }
213 
214  // Return reference
215  return (m_pars[index]);
216 }
217 
218 
219 /***********************************************************************//**
220  * @brief Returns reference to parameter (const version)
221  *
222  * @param[in] name Parameter name.
223  * @return Parameter.
224  *
225  * @exception GException::invalid_argument
226  * Parameter with specified name not found in container.
227  ***************************************************************************/
228 const GApplicationPar& GApplicationPars::operator[](const std::string& name) const
229 {
230  // Get parameter index
231  int index = get_index(name);
232 
233  // Throw exception if parameter name has not been found
234  if (index == -1) {
235  std::string msg = "Parameter \""+name+"\" has not been found in "
236  "parameter file. Please specify a valid parameter "
237  "name.";
239  }
240 
241  // Return reference
242  return (m_pars[index]);
243 }
244 
245 
246 /*==========================================================================
247  = =
248  = Public methods =
249  = =
250  ==========================================================================*/
251 
252 /***********************************************************************//**
253  * @brief Clear parameter container
254  ***************************************************************************/
256 {
257  // Free members
258  free_members();
259 
260  // Init members
261  init_members();
262 
263  // Return
264  return;
265 }
266 
267 
268 /***********************************************************************//**
269  * @brief Clone parameter container
270  *
271  * @return Pointer to deep copy of parameter container.
272  ***************************************************************************/
274 {
275  return (new GApplicationPars(*this));
276 }
277 
278 
279 /***********************************************************************//**
280  * @brief Returns reference to parameter
281  *
282  * @param[in] index Parameter index [0,...,size()-1].
283  *
284  * @exception GException::out_of_range
285  * Parameter index is out of range.
286  ***************************************************************************/
288 {
289  // Compile option: raise an exception if index is out of range
290  #if defined(G_RANGE_CHECK)
291  if (index < 0 || index >= size()) {
292  throw GException::out_of_range(G_AT, "Parameter index", index, size());
293  }
294  #endif
295 
296  // Return reference
297  return (m_pars[index]);
298 }
299 
300 
301 /***********************************************************************//**
302  * @brief Returns reference to parameter (const version)
303  *
304  * @param[in] index Parameter index [0,...,size()-1].
305  *
306  * @exception GException::out_of_range
307  * Parameter index is out of range.
308  ***************************************************************************/
309 const GApplicationPar& GApplicationPars::at(const int& index) const
310 {
311  // Compile option: raise an exception if index is out of range
312  #if defined(G_RANGE_CHECK)
313  if (index < 0 || index >= size()) {
314  throw GException::out_of_range(G_AT, "Parameter index", index, size());
315  }
316  #endif
317 
318  // Return reference
319  return (m_pars[index]);
320 }
321 
322 
323 /***********************************************************************//**
324  * @brief Append parameter to container
325  *
326  * @param[in] par Parameter.
327  * @return Reference to deep copy of appended parameter.
328  *
329  * @exception GException::invalid_value
330  * Parameter with same name exists already in container.
331  *
332  * This method appends one parameter to the parameter container. The
333  * parameter provided to the method can be deleted after calling this method.
334  ***************************************************************************/
336 {
337  // Check if a parameter with specified name does not yet exist
338  int inx = get_index(par.name());
339  if (inx != -1) {
340  std::string msg =
341  "Attempt to append parameter with name \""+par.name()+"\" in"
342  " parameter container, but a parameter with the same name exists"
343  " already at index "+gammalib::str(inx)+" in the container.\n"
344  "Every parameter in the parameter container needs a unique name.";
346  }
347 
348  // Append parameter
349  m_pars.push_back(par);
350 
351  // Get reference of appended parameter
352  GApplicationPar& parameter = m_pars[m_pars.size()-1];
353 
354  // Build parameter file line
355  size_t start = 0;
356  size_t stop = 0;
357  std::string line = parline(parameter, &start, &stop);
358 
359  // Append parameter file line and attributes
360  m_line.push_back(m_parfile.size());
361  m_parfile.push_back(line);
362  m_vstart.push_back(start);
363  m_vstop.push_back(stop);
364 
365  // Return parameter reference
366  return parameter;
367 }
368 
369 
370 /***********************************************************************//**
371  * @brief Append standard parameters to container
372  *
373  * This method appends the standard parameters to the parameter container.
374  * Standard parameters are: "chatter", "clobber", "debug" and "mode".
375  ***************************************************************************/
377 {
378  // Append standard parameters
379  append(GApplicationPar("chatter","i","h","2","0","4","Chattiness of output"));
380  append(GApplicationPar("clobber","b","h","yes","","","Overwrite existing output files with new output files?"));
381  append(GApplicationPar("debug","b","h","no","","","Debugging mode activated"));
382  append(GApplicationPar("mode","s","h","ql","","","Mode of automatic parameters"));
383 
384  // Return
385  return;
386 }
387 
388 
389 /***********************************************************************//**
390  * @brief Insert parameter into container
391  *
392  * @param[in] index Parameter index [0,...,size()-1].
393  * @param[in] par Parameter.
394  * @return Reference to deep copy of inserted parameter.
395  *
396  * Inserts a parameter into the container before the parameter with the
397  * specified @p index.
398  ***************************************************************************/
400 {
401  // Compile option: raise exception if index is out of range
402  #if defined(G_RANGE_CHECK)
403  if (is_empty()) {
404  if (index > 0) {
405  throw GException::out_of_range(G_INSERT1, "Parameter index", index, size());
406  }
407  }
408  else {
409  if (index < 0 || index >= size()) {
410  throw GException::out_of_range(G_INSERT1, "Parameter index", index, size());
411  }
412  }
413  #endif
414 
415  // Check if a parameter with specified name does not yet exist
416  int inx = get_index(par.name());
417  if (inx != -1) {
418  std::string msg =
419  "Attempt to insert parameter with name \""+par.name()+"\" in"
420  " parameter container before index "+gammalib::str(index)+
421  ", but a parameter with the same name exists already at index "+
422  gammalib::str(inx)+" in the container.\n"
423  "Every parameter in the parameter container needs a unique name.";
425  }
426 
427  // Inserts parameter
428  m_pars.insert(m_pars.begin()+index, par);
429 
430  // Get reference of appended parameter
431  GApplicationPar& parameter = m_pars[m_pars.size()-1];
432 
433  // Build parameter file line
434  size_t start = 0;
435  size_t stop = 0;
436  std::string line = parline(parameter, &start, &stop);
437 
438  // Determine at which line number of the parameter file the parameter
439  // should be inserted
440  int line_number = m_line[index];
441 
442  // Insert parameter file line and parameter attributes
443  m_parfile.insert(m_parfile.begin()+line_number, line);
444  m_line.insert(m_line.begin()+index, line_number);
445  m_vstart.insert(m_vstart.begin()+index, start);
446  m_vstop.insert(m_vstop.begin()+index, stop);
447 
448  // Increment the line numbers for all parameters after the inserted one
449  for (int i = index+1; i < size(); ++i) {
450  m_line[i]++;
451  }
452 
453  // Return parameter reference
454  return parameter;
455 }
456 
457 
458 /***********************************************************************//**
459  * @brief Insert parameter into container
460  *
461  * @param[in] name Parameter name.
462  * @param[in] par Parameter.
463  * @return Reference to deep copy of inserted parameter.
464  *
465  * @exception GException::invalid_argument
466  * Parameter with specified name not found in container.
467  * @exception GException::invalid_value
468  * Name of parameter exists already in container.
469  *
470  * Inserts a parameter into the container before the parameter with the
471  * specified @p name.
472  ***************************************************************************/
473 GApplicationPar& GApplicationPars::insert(const std::string& name, const GApplicationPar& par)
474 {
475  // Get parameter index
476  int index = get_index(name);
477 
478  // Throw exception if parameter name was not found
479  if (index == -1) {
480  std::string msg = "Parameter \""+name+"\" has not been found in"
481  " parameter file.\n"
482  "Please specify a valid parameter name.";
484  }
485 
486  // Insert by index and return parameter reference
487  return (insert(index, par));
488 }
489 
490 
491 /***********************************************************************//**
492  * @brief Remove parameter from container
493  *
494  * @param[in] index Parameter index [0,...,size()-1].
495  *
496  * @exception GException::out_of_range
497  * Parameter index is out of range.
498  *
499  * Remove parameter with specified @p index from container.
500  ***************************************************************************/
501 void GApplicationPars::remove(const int& index)
502 {
503  // Compile option: raise exception if index is out of range
504  #if defined(G_RANGE_CHECK)
505  if (index < 0 || index >= size()) {
506  throw GException::out_of_range(G_REMOVE1, "Parameter index", index, size());
507  }
508  #endif
509 
510  // Erase parameter from container
511  m_pars.erase(m_pars.begin() + index);
512 
513  // Remove parameter file line and parameter attributes
514  m_parfile.erase(m_parfile.begin() + m_line[index]);
515  m_line.erase(m_line.begin() + index);
516  m_vstart.erase(m_vstart.begin() + index);
517  m_vstop.erase(m_vstop.begin() + index);
518 
519  // Decrement the line numbers for all parameters after the removed one
520  for (int i = index; i < size(); ++i) {
521  m_line[i]--;
522  }
523 
524  // Return
525  return;
526 }
527 
528 
529 /***********************************************************************//**
530  * @brief Remove parameter from container
531  *
532  * @param[in] name Parameter name.
533  *
534  * @exception GException::invalid_argument
535  * Parameter with specified name not found in container.
536  *
537  * Remove parameter with specified @p name from container.
538  ***************************************************************************/
539 void GApplicationPars::remove(const std::string& name)
540 {
541  // Get parameter index
542  int index = get_index(name);
543 
544  // Throw exception if parameter name was not found
545  if (index == -1) {
546  std::string msg = "Parameter \""+name+"\" has not been found in"
547  " parameter file.\n"
548  "Please specify a valid parameter name.";
550  }
551 
552  // Remove by index
553  remove(index);
554 
555  // Return
556  return;
557 }
558 
559 
560 /***********************************************************************//**
561  * @brief Append parameter container
562  *
563  * @param[in] pars Parameter container.
564  *
565  * Append parameter container to the container.
566  ***************************************************************************/
568 {
569  // Do nothing if parameter container is empty
570  if (!pars.is_empty()) {
571 
572  // Get size. Note that we extract the size first to avoid an
573  // endless loop that arises when a container is appended to
574  // itself.
575  int num = pars.size();
576 
577  // Reserve enough space
578  reserve(size() + num);
579 
580  // Loop over all parameters and append copies
581  for (int i = 0; i < num; ++i) {
582 
583  // Check if parameter name does not yet exist
584  int inx = get_index(pars[i].name());
585  if (inx != -1) {
586  std::string msg =
587  "Attempt to append parameter with name \""+pars[i].name()+
588  "\" to parameter container, but a parameter with the same name"
589  " exists already at index "+gammalib::str(inx)+" in the"
590  " container.\n"
591  "Every parameter in the parameter container needs a unique"
592  " name.";
594  }
595 
596  // Append parameter to container
597  append(pars[i]);
598 
599  } // endfor: looped over all parameters
600 
601  } // endif: parameter container was not empty
602 
603  // Return
604  return;
605 }
606 
607 
608 /***********************************************************************//**
609  * @brief Check parameter exists
610  *
611  * @param[in] name Parameter name.
612  * @return True if parameter with specified name exists, false otherwise.
613  *
614  * Determines whether a parameter with the specified name exists already in
615  * the parameter container.
616  ***************************************************************************/
617 bool GApplicationPars::contains(const std::string& name) const
618 {
619  // Get parameter index
620  int inx = get_index(name);
621 
622  // Return test result
623  return (inx != -1);
624 }
625 
626 
627 /***********************************************************************//**
628  * @brief Load parameters
629  *
630  * @param[in] filename Parameter filename.
631  *
632  * @exception GException::par_file_not_found
633  * Parameter file not found.
634  *
635  * Loads all parameters from parameter file.
636  *
637  * If the syspfiles path is set then load the parameter file from that
638  * location and update the parameters using a paramater file that is found
639  * in the users "pfiles" directory.
640  *
641  * Otherwise, search the parameter file in the usual location (see the
642  * GApplicationPars::inpath method for more information).
643  ***************************************************************************/
644 void GApplicationPars::load(const GFilename& filename)
645 {
646  // Reset parameters
647  m_parfile.clear();
648 
649  // If a syspfiles path was set then get parfile from this path and
650  // update the parameters using a copy found in the users "pfiles"
651  // directory
652  std::string path = syspfiles_path(filename.url());
653  if (!path.empty()) {
654 
655  // Read parfile
656  read(path);
657 
658  // Parse parfile
659  parse();
660 
661  // Synchronize parfile using a copy found in the users "pfiles"
662  // directory
663  path = pfiles_path(filename.url());
664  if (!path.empty()) {
665  synchronise(path);
666  }
667 
668  }
669 
670  // ... otherwise get path to parameter file for input
671  else {
672 
673  // Get parfile file path
674  path = inpath(filename.url());
675 
676  // If file path is empty then throw an exception
677  if (path.empty()) {
678  throw GException::par_file_not_found(G_LOAD1, filename.url());
679  }
680 
681  // Read parfile
682  read(path);
683 
684  // Parse parfile
685  parse();
686 
687  }
688 
689  // Return
690  return;
691 }
692 
693 
694 /***********************************************************************//**
695  * @brief Load parameters
696  *
697  * @param[in] filename Parameter filename.
698  * @param[in] args Command line arguments.
699  *
700  * @exception GException::bad_cmdline_argument
701  * Invalid command line argument encountered.
702  *
703  * Loads all parameters from parameter file. Parameters are overwritten by
704  * the values specified in the command line arguments.
705  ***************************************************************************/
706 void GApplicationPars::load(const GFilename& filename,
707  const std::vector<std::string>& args)
708 {
709  // Load parameters
710  load(filename);
711 
712  // Overwrite parameter values that are specified in the command line
713  for (int i = 1; i < args.size(); ++i) {
714 
715  // Extract parameter name and value (empty values are permitted)
716  size_t pos = args[i].find("=");
717  if (pos == std::string::npos) {
719  "no \"=\" specified");
720  }
721  std::string name = args[i].substr(0, pos);
722  std::string value = args[i].substr(pos+1);
723  if (name.length() < 1) {
725  "no parameter name before \"=\"");
726  }
727 
728  // Check if parameter exists
729  if (!contains(name)) {
731  "invalid parameter name \""+name+"\"");
732  }
733 
734  // Assign value
735  try {
736  (*this)[name].value(value);
737  }
738  catch (GException::par_error &e) {
740  }
741 
742  // Set mode to hidden to prevent querying the parameter
743  if ((*this)[name].mode() == "q") {
744  (*this)[name].mode("h");
745  }
746  else if ((*this)[name].mode() == "ql") {
747  (*this)[name].mode("hl");
748  }
749  else if ((*this)[name].mode() == "lq") {
750  (*this)[name].mode("lh");
751  }
752 
753  } // endfor: looped over all parameters
754 
755  // Return
756  return;
757 }
758 
759 
760 /***********************************************************************//**
761  * @brief Save parameters
762  *
763  * @param[in] filename Parameter filename.
764  *
765  * @exception GException::par_file_not_found
766  * No valid directory to write the parameter file has been found.
767  ***************************************************************************/
768 void GApplicationPars::save(const GFilename& filename)
769 {
770  // Get path to parameter file for output
771  std::string path = outpath(filename.url());
772  if (path.size() == 0) {
773  throw GException::par_file_not_found(G_SAVE, filename.url());
774  }
775 
776  // Update parameter file
777  update();
778 
779  // Write parfile
780  write(path);
781 
782  // Return
783  return;
784 }
785 
786 
787 /***********************************************************************//**
788  * @brief Set class from pickled string vector
789  *
790  * @param[in] string String vector containing class information.
791  ***************************************************************************/
792 void GApplicationPars::pickle(const std::vector<std::string>& string)
793 {
794  // Clear object
795  clear();
796 
797  // Extract vector sizes
798  int n_parfile = gammalib::toint(string[0]);
799  int n_pars = gammalib::toint(string[1]);
800  int n_line = gammalib::toint(string[2]);
801  int n_vstart = gammalib::toint(string[3]);
802  int n_vstop = gammalib::toint(string[4]);
803 
804  // Initialise string pointer
805  int istring = 5;
806 
807  // Extract parameter file lines
808  for (int i = 0; i < n_parfile; ++i, ++istring) {
809  m_parfile.push_back(string[istring]);
810  }
811 
812  // Extract application parameters
813  for (int i = 0; i < n_pars; ++i) {
814  int n_par = gammalib::toint(string[istring]);
815  int i_start = istring + 1;
816  int i_end = i_start + n_par;
817  //std::vector<std::string> sub(string.begin()+i_start,
818  // string.begin()+i_end);
819  GApplicationPar par;
820  par.pickle(std::vector<std::string>(string.begin()+i_start,
821  string.begin()+i_end));
822  m_pars.push_back(par);
823  istring = i_end;
824  }
825 
826  // Extract line numbers
827  for (int i = 0; i < n_line; ++i, ++istring) {
828  m_line.push_back(gammalib::toint(string[istring]));
829  }
830 
831  // Extract columns of start values
832  for (int i = 0; i < n_vstart; ++i, ++istring) {
833  m_vstart.push_back((size_t)gammalib::toint(string[istring]));
834  }
835 
836  // Extract columns of stop values
837  for (int i = 0; i < n_vstop; ++i, ++istring) {
838  m_vstop.push_back((size_t)gammalib::toint(string[istring]));
839  }
840 
841  // Extract effective mode and location of syspfiles
842  m_mode = string[istring++];
843  m_syspfiles = string[istring++];
844 
845  // Return
846  return;
847 }
848 
849 
850 /***********************************************************************//**
851  * @brief Return pickled string vector
852  *
853  * @return String vector containing class information.
854  ***************************************************************************/
855 std::vector<std::string> GApplicationPars::pickle(void) const
856 {
857  // Allocate vector of strings
858  std::vector<std::string> string;
859 
860  // Store vector lengths
861  string.push_back(gammalib::str(m_parfile.size()));
862  string.push_back(gammalib::str(m_pars.size()));
863  string.push_back(gammalib::str(m_line.size()));
864  string.push_back(gammalib::str(m_vstart.size()));
865  string.push_back(gammalib::str(m_vstop.size()));
866 
867  // Store parfile lines
868  for (int i = 0; i < m_parfile.size(); ++i) {
869  string.push_back(m_parfile[i]);
870  }
871 
872  // Store application parameters
873  for (int i = 0; i < m_pars.size(); ++i) {
874  std::vector<std::string> par = m_pars[i].pickle();
875  string.push_back(gammalib::str(par.size()));
876  for (int k = 0; k < par.size(); ++k) {
877  string.push_back(par[k]);
878  }
879  }
880 
881  // Store line numbers
882  for (int i = 0; i < m_line.size(); ++i) {
883  string.push_back(gammalib::str(m_line[i]));
884  }
885 
886  // Store columns of start values
887  for (int i = 0; i < m_vstart.size(); ++i) {
888  string.push_back(gammalib::str(m_vstart[i]));
889  }
890 
891  // Store columns of stop values
892  for (int i = 0; i < m_vstop.size(); ++i) {
893  string.push_back(gammalib::str(m_vstop[i]));
894  }
895 
896  // Store effective mode and location of syspfiles
897  string.push_back(m_mode);
898  string.push_back(m_syspfiles);
899 
900  // Return string vector
901  return string;
902 }
903 
904 
905 /***********************************************************************//**
906  * @brief Print parameters
907  *
908  * @param[in] chatter Chattiness.
909  * @return String containing parameter information.
910  ***************************************************************************/
911 std::string GApplicationPars::print(const GChatter& chatter) const
912 {
913  // Initialise result string
914  std::string result;
915 
916  // Continue only if chatter is not silent
917  if (chatter != SILENT) {
918 
919  // Append header
920  result.append("=== GApplicationPars ===");
921 
922  // Append parameters
923  for (int i = 0; i < size(); ++i) {
924  result.append("\n"+m_pars[i].print(chatter));
925  }
926 
927  } // endif: chatter was not silent
928 
929  // Return result
930  return result;
931 }
932 
933 
934 /*==========================================================================
935  = =
936  = Private methods =
937  = =
938  ==========================================================================*/
939 
940 /***********************************************************************//**
941  * @brief Initialise class members
942  ***************************************************************************/
944 {
945  // Initialise members
946  m_parfile.clear();
947  m_pars.clear();
948  m_line.clear();
949  m_vstart.clear();
950  m_vstop.clear();
951  m_mode = "h";
952  m_syspfiles.clear();
953 
954  // Return
955  return;
956 }
957 
958 
959 /***********************************************************************//**
960  * @brief Copy class members
961  *
962  * @param[in] pars Object from which members which should be copied.
963  ***************************************************************************/
965 {
966  // Copy attributes
967  m_parfile = pars.m_parfile;
968  m_pars = pars.m_pars;
969  m_line = pars.m_line;
970  m_vstart = pars.m_vstart;
971  m_vstop = pars.m_vstop;
972  m_mode = pars.m_mode;
973  m_syspfiles = pars.m_syspfiles;
974 
975  // Return
976  return;
977 }
978 
979 
980 /***********************************************************************//**
981  * @brief Delete class members
982  ***************************************************************************/
984 {
985  // Return
986  return;
987 }
988 
989 
990 /***********************************************************************//**
991  * @brief Determine filepath for parameter file input
992  *
993  * @param[in] filename Parameter filename to search for.
994  *
995  * Locates parameter file for input.
996  * The parameter file is first searched in the directories that are listed
997  * in the PFILES environment variable. Directories may be separated by : or
998  * by ; in PFILES.
999  *
1000  * If the PFILES environment variable is not set the parameter file is
1001  * searched in the users pfiles directory.
1002  *
1003  * If still no parameter file is found, the parameter file is searched (in
1004  * the given order) in ${GAMMALIB}/syspfiles and in ${prefix}/syspfiles,
1005  * where ${prefix} is the path to the GammaLib installation.
1006  ***************************************************************************/
1007 std::string GApplicationPars::inpath(const std::string& filename) const
1008 {
1009  // Allocate result path
1010  std::string path;
1011 
1012  // Search for parameter file in PFILES directories if the PFILES
1013  // environment variable has been set
1014  char* ptr = std::getenv("PFILES");
1015  if (ptr != NULL) {
1016 
1017  // Extract directories from PFILES environment variable
1018  std::string pfiles = ptr;
1019  std::vector<std::string> dirs = gammalib::split(pfiles, ":;");
1020 
1021  // Search for first occurence of parameter file
1022  for (int i = 0; i < dirs.size(); ++i) {
1023 
1024  // Build filename
1025  std::string fname = dirs[i] + "/" + filename;
1026 
1027  // If file is accessible for reading then exit loop
1028  if (access(fname.c_str(), R_OK) == 0) {
1029  path = fname;
1030  break;
1031  }
1032 
1033  } // endfor: searched all directories given in PFILES
1034 
1035  } // endif: PFILES environment variable has been set
1036 
1037  // ... otherwise, if no PFILES environment variable has been set
1038  // then search in users pfiles directory
1039  else {
1040  uid_t uid = geteuid();
1041  struct passwd* pw = getpwuid(uid);
1042  if (pw != NULL) {
1043  std::string fname = std::string(pw->pw_dir) + "/pfiles/" + filename;
1044  if (access(fname.c_str(), R_OK) == 0) {
1045  path = fname;
1046  }
1047  }
1048  } // endif: searched in users pfiles directory
1049 
1050  // If we have no valid path so far then search file within GAMMALIB
1051  // repository (${GAMMALIB}/syspfiles)
1052  if (path.size() == 0) {
1053  ptr = std::getenv("GAMMALIB");
1054  if (ptr != NULL) {
1055  std::string fname = std::string(ptr) + "/syspfiles/" + filename;
1056  if (access(fname.c_str(), R_OK) == 0) {
1057  path = fname;
1058  }
1059  }
1060  }
1061 
1062  // If we have no valid path so far then search file within GammaLib
1063  // package (${prefix}/syspfiles)
1064  #ifdef PACKAGE_PREFIX
1065  if (path.size() == 0) {
1066  std::string fname = std::string(PACKAGE_PREFIX) + "/syspfiles/" +
1067  filename;
1068  if (access(fname.c_str(), R_OK) == 0) {
1069  path = fname;
1070  }
1071  }
1072  #endif
1073 
1074  //printf("parfile=%s\n", path.c_str());
1075 
1076  // Return path
1077  return path;
1078 }
1079 
1080 
1081 /***********************************************************************//**
1082  * @brief Return path to parfile in $PFILES or $HOME/pfiles folder
1083  *
1084  * @param[in] filename Parameter filename to search for.
1085  * @return Full parameter filename, including absolute access path.
1086  *
1087  * Locates parameter file in the directories that are listed in the PFILES
1088  * environment variable. Directories may be separated by : or by ; in the
1089  * PFILES environment variable.
1090  *
1091  * If the PFILES environment variable is not set the parameter file is
1092  * searched in the users pfiles directory.
1093  *
1094  * If parameter file was not found, or the parameter file is not
1095  * read-accessible, an empty string is returned.
1096  ***************************************************************************/
1097 std::string GApplicationPars::pfiles_path(const std::string& filename) const
1098 {
1099  // Allocate result path
1100  std::string path;
1101 
1102  // Search for parameter file in PFILES directories if the PFILES
1103  // environment variable has been set
1104  char* ptr = std::getenv("PFILES");
1105  if (ptr != NULL) {
1106 
1107  // Extract directories from PFILES environment variable
1108  std::string pfiles = ptr;
1109  std::vector<std::string> dirs = gammalib::split(pfiles, ":;");
1110 
1111  // Search for first occurence of parameter file
1112  for (int i = 0; i < dirs.size(); ++i) {
1113 
1114  // Build filename
1115  std::string fname = dirs[i] + "/" + filename;
1116 
1117  // If file is accessible for reading then exit loop
1118  if (access(fname.c_str(), R_OK) == 0) {
1119  path = fname;
1120  break;
1121  }
1122 
1123  } // endfor: searched all directories given in PFILES
1124 
1125  } // endif: PFILES environment variable has been set
1126 
1127  // ... otherwise, if no PFILES environment variable has been set
1128  // then search in users pfiles directory
1129  else {
1130  uid_t uid = geteuid();
1131  struct passwd* pw = getpwuid(uid);
1132  if (pw != NULL) {
1133  std::string fname = std::string(pw->pw_dir) + "/pfiles/" + filename;
1134  if (access(fname.c_str(), R_OK) == 0) {
1135  path = fname;
1136  }
1137  }
1138  } // endif: searched in users pfiles directory
1139 
1140  // Return path
1141  return path;
1142 }
1143 
1144 
1145 /***********************************************************************//**
1146  * @brief Return path to parfile in m_syspfiles folder
1147  *
1148  * @param[in] filename Parameter filename to search for.
1149  * @return Full parameter filename, including absolute access path.
1150  *
1151  * Locates parameter file in the directory that is specified by the
1152  * m_syspfiles string. If the string is empty, the specified file is not
1153  * found or read accessible, an empty string is returned.
1154  ***************************************************************************/
1155 std::string GApplicationPars::syspfiles_path(const std::string& filename) const
1156 {
1157  // Allocate result path
1158  std::string path;
1159 
1160  // Continue only if m_syspfiles is not empty
1161  if (!m_syspfiles.empty()) {
1162  std::string fname = m_syspfiles + "/" + filename;
1163  if (access(fname.c_str(), R_OK) == 0) {
1164  path = fname;
1165  }
1166  }
1167 
1168  // Return path
1169  return path;
1170 }
1171 
1172 
1173 /***********************************************************************//**
1174  * @brief Determine filepath for parameter file output
1175  *
1176  * @param[in] filename Parameter filename.
1177  *
1178  * @exception GException::home_not_found
1179  * Unable to determine users home directory.
1180  * @exception GException::could_not_create_pfiles
1181  * Unable to create pfiles directory.
1182  * @exception GException::pfiles_not_accessible
1183  * Unable to make pfiles directory accessible to user.
1184  *
1185  * Searchs for first writable directory listed in PFILES environment
1186  * variable. If PFILES is not set then use pfiles directory in users
1187  * home directory. If pfiles directory does not exist then create it.
1188  * If directory exists but is not writable then make it writable.
1189  ***************************************************************************/
1190 std::string GApplicationPars::outpath(const std::string& filename) const
1191 {
1192  // Allocate result path
1193  std::string path;
1194 
1195  // Search for writeable PFILES directories
1196  char* ptr = std::getenv("PFILES");
1197  if (ptr != NULL) {
1198 
1199  // Extract directories from PFILES environment variable
1200  std::string pfiles = ptr;
1201  std::vector<std::string> dirs = gammalib::split(pfiles, ":;");
1202 
1203  // Search for first writeable
1204  for (int i = 0; i < dirs.size(); ++i) {
1205 
1206  // If directory is accessible for writing then exit loop
1207  if (access(dirs[i].c_str(), W_OK) == 0) {
1208  path = dirs[i] + "/" + filename;
1209  break;
1210  }
1211 
1212  }
1213  } // endif: PFILES environment variable exists
1214 
1215  // If no valid directory is found in PFILES environment variable then
1216  // use pfiles directory in users home directory.
1217  if (path.size() == 0) {
1218 
1219  // Get users home directory
1220  uid_t uid = geteuid();
1221  gid_t gid = getegid();
1222  struct passwd* pw = getpwuid(uid);
1223  if (pw == NULL) {
1225  }
1226 
1227  // Set path
1228  path = std::string(pw->pw_dir) + "/pfiles";
1229 
1230  // If directory does not exist then create it
1231  if (access(path.c_str(), F_OK) != 0) {
1232  if (mkdir(path.c_str(),
1233  S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
1235  }
1236  }
1237 
1238  // If directory exists but is not writable then make it writable
1239  else if (access(path.c_str(), W_OK) != 0) {
1240  if (chown(path.c_str(), uid, gid) != 0 ||
1241  chmod(path.c_str(),
1242  S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
1244  }
1245  }
1246 
1247  // Append filename
1248  path = path + "/" + filename;
1249 
1250  } // endif: no valid directory found in PFILES
1251 
1252  // Return path
1253  return path;
1254 }
1255 
1256 
1257 /***********************************************************************//**
1258  * @brief Read parameter file
1259  *
1260  * @param[in] filename Parameter filename (absolut path).
1261  *
1262  * @exception GException::par_file_open_error
1263  * Unable to open parameter file (read access requested).
1264  *
1265  * Read all lines of the parameter file. Each line is terminated by a newline
1266  * character. The file will be locked to avoid simultaneous access by another
1267  * process.
1268  ***************************************************************************/
1269 void GApplicationPars::read(const std::string& filename)
1270 {
1271  // Allocate line buffer
1272  const int n = 1000;
1273  char line[n];
1274 
1275  // Trying to get file lock
1276  #if defined(G_LOCK_PARFILE)
1277  struct flock lock;
1278  lock.l_type = F_RDLCK; // Want a read lock
1279  lock.l_whence = SEEK_SET; // Want beginning of file
1280  lock.l_start = 0; // No offset, lock entire file ...
1281  lock.l_len = 0; // ... to the end
1282  lock.l_pid = getpid(); // Current process ID
1283  int fd;
1284  if ((fd = open(filename.c_str(), O_RDONLY)) == -1) {
1285  throw GException::par_file_open_error(G_READ, filename,
1286  "Could not open file for locking.");
1287  }
1288  #if defined(G_CHECK_LOCK_PARFILE)
1289  if (fcntl(fd, F_SETLKW, &lock) == -1) { // F_SETLKW: wait until unlocked
1290  throw GException::par_file_open_error(G_READ, filename,
1291  "Could not get a lock on the file.");
1292  }
1293  #else
1294  fcntl(fd, F_SETLKW, &lock);
1295  #endif
1296  #endif
1297 
1298  // Open parameter file
1299  FILE* fptr = fopen(filename.c_str(), "r");
1300  if (fptr == NULL) {
1301  throw GException::par_file_open_error(G_READ, filename);
1302  }
1303 
1304  // Read lines
1305  while (fgets(line, n, fptr) != NULL) {
1306  m_parfile.push_back(std::string(line));
1307  }
1308 
1309  // Close file
1310  fclose(fptr);
1311 
1312  // Unlock file
1313  #if defined(G_LOCK_PARFILE)
1314  if (fd != -1) {
1315  lock.l_type = F_UNLCK;
1316  #if defined(G_CHECK_LOCK_PARFILE)
1317  if (fcntl(fd, F_SETLK, &lock) == -1) {
1318  throw GException::par_file_open_error(G_READ, filename,
1319  "Could not unlock the file.");
1320  }
1321  #else
1322  fcntl(fd, F_SETLK, &lock);
1323  #endif
1324  close(fd);
1325  }
1326  #endif
1327 
1328  // Return
1329  return;
1330 }
1331 
1332 
1333 /***********************************************************************//**
1334  * @brief Write parameter file
1335  *
1336  * @param[in] filename Parameter filename (absolut path).
1337  *
1338  * @exception GException::par_file_open_error
1339  * Unable to open parameter file (write access requested).
1340  *
1341  * Writes all lines of the parameter file. The file will be locked to avoid
1342  * simultaneous access by another process.
1343  ***************************************************************************/
1344 void GApplicationPars::write(const std::string& filename) const
1345 {
1346  // Trying to get file lock. We have to do this after opening the file
1347  // using the fopen function, as the file may not exist, hence it needs
1348  // to be created first.
1349  #if defined(G_LOCK_PARFILE)
1350  struct flock lock;
1351  lock.l_type = F_WRLCK; // Want a write lock
1352  lock.l_whence = SEEK_SET; // Want beginning of file
1353  lock.l_start = 0; // No offset, lock entire file ...
1354  lock.l_len = 0; // ... to the end
1355  lock.l_pid = getpid(); // Current process ID
1356  int fd;
1357  if ((fd = open(filename.c_str(), O_WRONLY)) != -1) {
1358  #if defined(G_CHECK_LOCK_PARFILE)
1359  if (fcntl(fd, F_SETLKW, &lock) == -1) { // F_SETLKW: wait until unlocked
1360  throw GException::par_file_open_error(G_WRITE, filename,
1361  "Could not get a lock on the file.");
1362  }
1363  #else
1364  fcntl(fd, F_SETLKW, &lock);
1365  #endif
1366  }
1367  #endif
1368 
1369  // Open parameter file.
1370  FILE* fptr = fopen(filename.c_str(), "w");
1371  if (fptr == NULL) {
1372  throw GException::par_file_open_error(G_WRITE, filename);
1373  }
1374 
1375  // If file is not locked then lock it now.
1376  #if defined(G_LOCK_PARFILE)
1377  if (fd == -1) {
1378  if ((fd = open(filename.c_str(), O_WRONLY)) != -1) {
1379  #if defined(G_CHECK_LOCK_PARFILE)
1380  if (fcntl(fd, F_SETLKW, &lock) == -1) { // F_SETLKW: wait until unlocked
1381  fclose(fptr);
1382  throw GException::par_file_open_error(G_WRITE, filename,
1383  "Could not get a lock on the file.");
1384  }
1385  #else
1386  fcntl(fd, F_SETLKW, &lock);
1387  #endif
1388  }
1389  }
1390  #endif
1391 
1392  // Write lines
1393  for (int i = 0; i < m_parfile.size(); ++i) {
1394  fprintf(fptr, "%s", m_parfile[i].c_str());
1395  }
1396 
1397  // Close file
1398  fclose(fptr);
1399 
1400  // Unlock file
1401  #if defined(G_LOCK_PARFILE)
1402  if (fd != -1) {
1403  lock.l_type = F_UNLCK;
1404  #if defined(G_CHECK_LOCK_PARFILE)
1405  if (fcntl(fd, F_SETLK, &lock) == -1) {
1406  throw GException::par_file_open_error(G_WRITE, filename,
1407  "Could not unlock the file.");
1408  }
1409  #else
1410  fcntl(fd, F_SETLK, &lock);
1411  #endif
1412  close(fd);
1413  }
1414  #endif
1415 
1416  // Return
1417  return;
1418 }
1419 
1420 
1421 /***********************************************************************//**
1422  * @brief Parse parameter file
1423  *
1424  * @exception GException::par_file_syntax_error
1425  * Syntax error encountered in parameter file.
1426  *
1427  * The parameter type has to be one b,i,r,s,f,fr,fw,fe,fn. The fr,fw,fe,fn
1428  * types test for read access, write access, file existence, and file
1429  * absence, respectively.
1430  * The parameter mode has to be one of a,h,l,q,hl,ql,lh,lq. For mode 'a' the
1431  * effective mode equals to the value given by the mode parameter, if it
1432  * exists. Without the presence of the mode parameter the effective mode
1433  * will be 'h'.
1434  ***************************************************************************/
1436 {
1437  // Preset effective mode to 'hidden'
1438  m_mode = "h";
1439 
1440  // Parse all lines
1441  for (int i = 0; i < m_parfile.size(); ++i) {
1442 
1443  // Get line without any leading and trailing whitespace
1444  std::string line = gammalib::strip_whitespace(m_parfile[i]);
1445 
1446  // If line contains a single linefeed then skip the line
1447  if (line.length() == 1 && line[0] == '\n')
1448  continue;
1449 
1450  // If line is empty or if line starts with # then skip the line
1451  if (line.length() == 0 || line[0] == '#') {
1452  continue;
1453  }
1454 
1455  // Get the 7 text fields of valid a parameter line
1456  std::string fields[7];
1457  int quotes = 0;
1458  size_t start = 0;
1459  size_t end = line.length() - 1;
1460  int index = 0;
1461  size_t vstart = 0;
1462  size_t vstop = 0;
1463  for (size_t pos = 0; pos < line.length(); ++pos) {
1464 
1465  // Toggle quotes
1466  if (line[pos] == '"') {
1467  quotes = 1-quotes;
1468  }
1469 
1470  // Search for comma only if we are outside quotes. If comma is
1471  // found or end of line is reached then extract a field and start
1472  // searching again from the position following the comma. Strip
1473  // leading and trailing quotes from the fields.
1474  if (quotes == 0) {
1475  if (line[pos] == ',' || pos == end) {
1476  if (index < 7) {
1477  fields[index] =
1479  pos-start)), "\"");
1480  if (index == 3) {
1481  vstart = start;
1482  vstop = pos;
1483  }
1484  start = pos + 1;
1485  }
1486  index++;
1487  }
1488  }
1489 
1490  } // endfor: looped over line
1491 
1492  // Throw an error if quotes are not balanced
1493  if (quotes != 0) {
1495  gammalib::strip_chars(line,"\n"),
1496  "quotes are not balanced");
1497  }
1498 
1499  // Throw an error if line has not 7 fields
1500  if (index != 7) {
1502  gammalib::strip_chars(line,"\n"),
1503  "found "+gammalib::str(index)+" fields, require 7");
1504  }
1505 
1506  // Verify if parameter name does not yet exist
1507  if (contains(fields[0])) {
1509  gammalib::strip_chars(line,"\n"),
1510  "redefinition of parameter name \""+fields[0]+"\"");
1511  }
1512 
1513  // Add parameter
1514  try {
1515  m_pars.push_back(GApplicationPar(fields[0], fields[1], fields[2],
1516  fields[3], fields[4], fields[5],
1517  fields[6]));
1518  m_line.push_back(i);
1519  m_vstart.push_back(vstart);
1520  m_vstop.push_back(vstop);
1521  }
1522  catch (GException::par_error &e) {
1524  gammalib::strip_chars(line,"\n"),
1525  e.what());
1526  }
1527 
1528  // If parameter name is mode then store the effective mode
1529  if (fields[0] == "mode") {
1530  if (fields[3] != "h" && fields[3] != "q" &&
1531  fields[3] != "hl" && fields[3] != "ql" &&
1532  fields[3] != "lh" && fields[3] != "lq") {
1534  gammalib::strip_chars(line,"\n"),
1535  "mode parameter has invalid value \""+fields[3]+"\"");
1536  }
1537  m_mode = fields[3];
1538  }
1539 
1540  } // endfor: looped over lines
1541 
1542  // Set effective mode for all parameters that have mode 'auto'
1543  for (int i = 0; i < m_pars.size(); ++i) {
1544  if (m_pars[i].mode() == "a") {
1545  m_pars[i].mode(m_mode);
1546  }
1547  }
1548 
1549  // Return
1550  return;
1551 }
1552 
1553 
1554 /***********************************************************************//**
1555  * @brief Update parameter file
1556  *
1557  * Update lines of parameter file according to the parameter values. This
1558  * method handles correctly formatted parameter files by replacing the value
1559  * at its original location within the line (preserving additional
1560  * whitespace).
1561  * Updating is only done of the parameter mode is 'learn'.
1562  ***************************************************************************/
1564 {
1565  // Loop over all parameters
1566  for (int i = 0; i < m_pars.size(); ++i) {
1567 
1568  // Update only if requested and allowed
1569  if (m_pars[i].m_update && m_pars[i].is_learn()) {
1570  m_parfile[m_line[i]] = m_parfile[m_line[i]].substr(0, m_vstart[i]) +
1571  m_pars[i].m_value +
1572  m_parfile[m_line[i]].substr(m_vstop[i]);
1573  m_vstop[i] = m_vstart[i] + m_pars[i].m_value.length();
1574  }
1575 
1576  } // endfor: looped over all parameters
1577 
1578  // Return
1579  return;
1580 }
1581 
1582 
1583 /***********************************************************************//**
1584  * @brief Synchronise parameter file with the parameter values in a another
1585  * parameter file
1586  *
1587  * @param[in] filename File name of other parameter file.
1588  *
1589  * Copies over all values from another parameter file that correspond to
1590  * parameters with the same name and type, and that are signaled as "learn"
1591  * in the other parameter file.
1592  ***************************************************************************/
1593 void GApplicationPars::synchronise(const std::string& filename)
1594 {
1595  // Allocate other application parameters
1596  GApplicationPars pars;
1597 
1598  // Read other application parameters
1599  pars.read(filename);
1600 
1601  // Parse other parameters
1602  pars.parse();
1603 
1604  // Loop over all parameters in parameter file
1605  for (int i = 0; i < m_pars.size(); ++i) {
1606 
1607  // If a parameter with the same name and type exists in the other
1608  // parameter file
1609  int inx = pars.get_index(m_pars[i].name());
1610  if (inx != -1) {
1611 
1612  // If the parameter types match, the mode in the other parameter
1613  // file is "learn", and the parameter values differ, then copy
1614  // over the value and signal value updating
1615  if ((m_pars[i].type() == pars[inx].type()) &&
1616  pars[inx].is_learn() &&
1617  m_pars[i].m_value != pars[inx].m_value) {
1618  m_pars[i].m_value = pars[inx].m_value;
1619  m_pars[i].m_status = pars[inx].m_status;
1620  m_pars[i].m_update = true;
1621  }
1622 
1623  } // endif: parameter with same name existed
1624 
1625  } // endfor: looped over all parameters
1626 
1627  // Return
1628  return;
1629 }
1630 
1631 
1632 /***********************************************************************//**
1633  * @brief Return parameter index by name
1634  *
1635  * @param[in] name Parameter name.
1636  * @return Parameter index (-1 if parameter name has not been found)
1637  *
1638  * Returns parameter index based on the specified @p name. If no parameter
1639  * with the specified @p name is found the method returns -1.
1640  ***************************************************************************/
1641 int GApplicationPars::get_index(const std::string& name) const
1642 {
1643  // Initialise index
1644  int index = -1;
1645 
1646  // Search parameter with specified name
1647  for (int i = 0; i < size(); ++i) {
1648  if (m_pars[i].name() == name) {
1649  index = i;
1650  break;
1651  }
1652  }
1653 
1654  // Return index
1655  return index;
1656 }
1657 
1658 
1659 /***********************************************************************//**
1660  * @brief Return parameter file line for a specific parameter
1661  *
1662  * @param[in] par Parameter.
1663  * @param[out] start Column of value start.
1664  * @param[out] stop Column of value stop.
1665  * @return Parameter file line (termined by \n).
1666  *
1667  * Constructs the parameter file line for a specific parameter and returns
1668  * the line as a string. The line is terminated by a \n character.
1669  ***************************************************************************/
1670 std::string GApplicationPars::parline(GApplicationPar& par, size_t* start, size_t* stop) const
1671 {
1672  // Declate line
1673  std::string line;
1674 
1675  // Build parameter file line
1676  line.append(par.name()+", ");
1677  line.append(par.type()+ ", ");
1678  line.append(par.mode()+ ",");
1679  *start = line.length();
1680  line.append(par.value()+ ",");
1681  *stop = line.length();
1682  line.append(par.min()+ ",");
1683  line.append(par.max()+ ",");
1684  line.append("\""+par.prompt()+"\"\n");
1685 
1686  // Return line
1687  return line;
1688 }
std::vector< size_t > m_vstart
Column of value start.
const std::string & prompt(void) const
Returns parameter prompt.
Application parameter container class definition.
GApplicationPar & append(const GApplicationPar &par)
Append parameter to container.
Application parameter container class.
void init_members(void)
Initialise class members.
std::string m_mode
Effective mode.
void value(const std::string &value)
Set parameter value.
std::string m_syspfiles
Optional location of syspfiles.
void type(const std::string &type)
Set parameter type.
std::string syspfiles_path(const std::string &filename) const
Return path to parfile in m_syspfiles folder.
std::string print(const GChatter &chatter=NORMAL) const
Print parameters.
#define G_READ
void mode(const std::string &mode)
Set parameter mode.
GApplicationPars & operator=(const GApplicationPars &pars)
Assignment operator.
std::vector< GApplicationPar > m_pars
Parameters.
void parse(void)
Parse parameter file.
#define G_WRITE
#define G_EXTEND
std::string parline(GApplicationPar &par, size_t *start, size_t *stop) const
Return parameter file line for a specific parameter.
std::string strip_chars(const std::string &arg, const std::string &chars)
Strip leading and trailing character from string.
Definition: GTools.cpp:87
std::vector< std::string > split(const std::string &s, const std::string &sep)
Split string.
Definition: GTools.cpp:862
Gammalib tools definition.
void reserve(const int &num)
Reserves space for parameters in container.
#define G_AT
std::string inpath(const std::string &filename) const
Determine filepath for parameter file input.
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition: GTools.cpp:73
#define G_REMOVE1
#define G_LOAD1
#define G_SAVE
void synchronise(const std::string &filename)
Synchronise parameter file with the parameter values in a another parameter file. ...
void free_members(void)
Delete class members.
int size(void) const
Return number of parameters in container.
void remove(const int &index)
Remove parameter from container.
const std::string & name(void) const
Returns parameter name.
GApplicationPars(void)
Void constructor.
Filename class.
Definition: GFilename.hpp:62
void pickle(const std::vector< std::string > &string)
Set class from pickled string vector.
#define G_INSERT1
void update(void)
Update parameter file.
virtual ~GApplicationPars(void)
Destructor.
std::vector< std::string > m_parfile
Parameter file lines.
#define G_OUTPATH
const std::string & max(void) const
Returns parameter maximum.
GChatter
Definition: GTypemaps.hpp:33
void save(const GFilename &filename)
Save parameters.
#define G_REMOVE2
std::string pfiles_path(const std::string &filename) const
Return path to parfile in $PFILES or $HOME/pfiles folder.
void copy_members(const GApplicationPars &pars)
Copy class members.
std::vector< std::string > pickle(void) const
Return pickled string vector.
virtual const char * what() const
Exception message.
Definition: GException.cpp:35
#define G_ACCESS
GApplicationPar & at(const int &index)
Returns reference to parameter.
std::string url(void) const
Return Uniform Resource Locator (URL)
Definition: GFilename.hpp:189
#define G_LOAD2
GApplicationPar & operator[](const int &index)
Returns reference to parameter.
void read(const std::string &filename)
Read parameter file.
std::string outpath(const std::string &filename) const
Determine filepath for parameter file output.
void write(const std::string &filename) const
Write parameter file.
Exception handler interface definition.
Application parameter class.
const std::string & min(void) const
Returns parameter minimum.
int toint(const std::string &arg)
Convert string into integer value.
Definition: GTools.cpp:700
std::vector< size_t > m_vstop
Column of value stop.
void append_standard(void)
Append standard parameters to container.
#define G_PARSE
std::vector< int > m_line
Line number of parameter.
#define G_INSERT2
void extend(const GApplicationPars &pars)
Append parameter container.
bool is_empty(void) const
Signals if there are no parameters in container.
int get_index(const std::string &name) const
Return parameter index by name.
Filename class interface definition.
void load(const GFilename &filename)
Load parameters.
GApplicationPar & insert(const int &index, const GApplicationPar &par)
Insert parameter into container.
GApplicationPars * clone(void) const
Clone parameter container.
#define G_APPEND
bool contains(const std::string &name) const
Check parameter exists.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:413
void clear(void)
Clear parameter container.