GammaLib  2.0.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GApplicationPar.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GApplicationPar.cpp - Application parameter *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2010-2021 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 GApplicationPar.cpp
23  * @brief Application parameter class implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #ifdef HAVE_LIBREADLINE
32 #include <cstdio> //!< Needed for declaration of FILE in readline
33 #include <readline/readline.h>
34 #endif
35 #include <climits> //!< Needed for declaration of LONG_MAX
36 #include "GException.hpp"
37 #include "GTools.hpp"
38 #include "GFilename.hpp"
39 #include "GTime.hpp"
40 #include "GApplicationPar.hpp"
41 
42 /* __ Method name definitions ____________________________________________ */
43 #define G_STRING_SET "GApplicationPar::string(std::string&)"
44 #define G_FILENAME_SET "GApplicationPar::filename(GFilename&)"
45 #define G_TIME_SET "GApplicationPar::time(GTime&)"
46 #define G_BOOLEAN_SET "GApplicationPar::boolean(bool&)"
47 #define G_INTEGER_SET "GApplicationPar::integer(int&)"
48 #define G_REAL_SET "GApplicationPar::real(double&)"
49 #define G_STRING_GET "GApplicationPar::string()"
50 #define G_FILENAME_GET "GApplicationPar::filename()"
51 #define G_TIME_GET "GApplicationPar::time()"
52 #define G_BOOLEAN_GET "GApplicationPar::boolean()"
53 #define G_INTEGER_GET "GApplicationPar::integer()"
54 #define G_REAL_GET "GApplicationPar::real()"
55 #define G_CHECK_TYPE "GApplicationPar::check_type(std::string)"
56 #define G_CHECK_MODE "GApplicationPar::check_mode(std::string)"
57 #define G_CHECK_VALUE_BOOL "GApplicationPar::check_value_bool(std::string)"
58 #define G_CHECK_VALUE_INT "GApplicationPar::check_value_int(std::string&)"
59 #define G_CHECK_VALUE_REAL "GApplicationPar::check_value_real(std::string&)"
60 #define G_CHECK_OPTIONS "GApplicationPar::check_options(std::string&)"
61 
62 /* __ Macros _____________________________________________________________ */
63 
64 /* __ Coding definitions _________________________________________________ */
65 
66 /* __ Debug definitions __________________________________________________ */
67 
68 
69 /*==========================================================================
70  = =
71  = Constructors/destructors =
72  = =
73  ==========================================================================*/
74 
75 /***********************************************************************//**
76  * @brief Void constructor
77  ***************************************************************************/
79 {
80  // Initialise members
81  init_members();
82 
83  // Return
84  return;
85 }
86 
87 
88 /***********************************************************************//**
89  * @brief Parameter constructor
90  *
91  * @param[in] name Parameter name.
92  * @param[in] type Parameter type.
93  * @param[in] mode Parameter mode.
94  * @param[in] value Parameter value.
95  * @param[in] min Parameter minimum.
96  * @param[in] max Parameter maximum.
97  * @param[in] prompt Parameter prompt string.
98  *
99  * Constructs a parameter from parameter attributes.
100  ***************************************************************************/
101 GApplicationPar::GApplicationPar(const std::string& name,
102  const std::string& type,
103  const std::string& mode,
104  const std::string& value,
105  const std::string& min,
106  const std::string& max,
107  const std::string& prompt)
108 {
109  // Initialise members
110  init_members();
111 
112  // Set parameter attributes
113  m_name = name;
114  this->mode(mode);
115  this->type(type);
116  m_min = min;
117  m_max = max;
118  this->value(value);
119  m_prompt = prompt;
120 
121  // Since the call to the value method stops the query, we reset the
122  // queried flag so that the parameter will get queried.
123  m_queried = false;
124 
125  // Return
126  return;
127 }
128 
129 
130 /***********************************************************************//**
131  * @brief Copy constructor
132  *
133  * @param[in] par Parameter.
134  ***************************************************************************/
136 {
137  // Initialise members
138  init_members();
139 
140  // Copy members
141  copy_members(par);
142 
143  // Return
144  return;
145 }
146 
147 
148 /***********************************************************************//**
149  * @brief Destructor
150  ***************************************************************************/
152 {
153  // Free members
154  free_members();
155 
156  // Return
157  return;
158 }
159 
160 
161 /*==========================================================================
162  = =
163  = Operators =
164  = =
165  ==========================================================================*/
166 
167 /***********************************************************************//**
168  * @brief Assignment operator
169  *
170  * @param[in] par Parameter.
171  * @return Parameter.
172  ***************************************************************************/
174 {
175  // Execute only if object is not identical
176  if (this != &par) {
177 
178  // Free members
179  free_members();
180 
181  // Initialise private members for clean destruction
182  init_members();
183 
184  // Copy members
185  copy_members(par);
186 
187  } // endif: object was not identical
188 
189  // Return
190  return *this;
191 }
192 
193 
194 /*==========================================================================
195  = =
196  = Public methods =
197  = =
198  ==========================================================================*/
199 
200 /***********************************************************************//**
201  * @brief Clear parameter
202  ***************************************************************************/
204 {
205  // Free members
206  free_members();
207 
208  // Initialise members
209  init_members();
210 
211  // Return
212  return;
213 }
214 
215 
216 /***********************************************************************//**
217  * @brief Clone parameter
218  *
219  * @return Pointer to deep copy of parameter.
220  ***************************************************************************/
222 {
223  return (new GApplicationPar(*this));
224 }
225 
226 
227 /***********************************************************************//**
228  * @brief Set parameter type
229  *
230  * @param[in] type Parameter type.
231  *
232  * Sets the parameter type. Valid parameter types are:
233  * b,i,r,s,f,fr,fw,fe,fn,t.
234  ***************************************************************************/
235 void GApplicationPar::type(const std::string& type)
236 {
237  // Verify that type is valid
238  check_type(type);
239 
240  // Set type
241  m_type = type;
242 
243  // Return
244  return;
245 }
246 
247 
248 /***********************************************************************//**
249  * @brief Set parameter mode
250  *
251  * @param[in] mode Parameter mode.
252  *
253  * Sets the parameter model. Valid parameter modes are: a,h,l,q,hl,ql,lh,lq.
254  ***************************************************************************/
255 void GApplicationPar::mode(const std::string& mode)
256 {
257  // Verify that mode is valid
258  check_mode(mode);
259 
260  // Set mode
261  m_mode = mode;
262 
263  // Return
264  return;
265 }
266 
267 
268 /***********************************************************************//**
269  * @brief Set parameter value
270  *
271  * @param[in] value Parameter value.
272  *
273  * Sets the parameter value dependent on the parameter type.
274  *
275  * It is a parser method that verifies that the given parameter value is
276  * compatible with the parameter type.
277  ***************************************************************************/
278 void GApplicationPar::value(const std::string& value)
279 {
280  // Set value
281  set_value(value);
282 
283  // Return
284  return;
285 }
286 
287 
288 /***********************************************************************//**
289  * @brief Set string parameter value
290  *
291  * @param[in] value Parameter value.
292  *
293  * @exception GException::invalid_value
294  * Parameter is not of string type.
295  *
296  * This method sets a string parameter. The method only applies to parameters
297  * of type "s". Other parameter types will produce an exception.
298  ***************************************************************************/
299 void GApplicationPar::string(const std::string& value)
300 {
301  // Check if parameter is a string parameter
302  if (m_type != "s") {
303  std::string msg = "Attempt to set "+par_type_string(m_type)+
304  " parameter \""+m_name+"\" with string value.";
306  }
307 
308  // Set value
309  set_value(value);
310 
311  // Return
312  return;
313 }
314 
315 
316 /***********************************************************************//**
317  * @brief Set filename parameter value
318  *
319  * @param[in] value Parameter value.
320  *
321  * @exception GException::invalid_value
322  * Parameter is not of filename type.
323  *
324  * This method sets a filename parameter. The method only applies to filename
325  * parameters. Other parameter types will produce an exception.
326  ***************************************************************************/
328 {
329  // Check if parameter is a filename parameter
330  if (!is_filename()) {
331  std::string msg = "Attempt to set "+par_type_string(m_type)+
332  " parameter \""+m_name+"\" with filename value.";
334  }
335 
336  // Set value
337  set_value(value);
338 
339  // Return
340  return;
341 }
342 
343 
344 /***********************************************************************//**
345  * @brief Set time parameter value
346  *
347  * @param[in] value Parameter value.
348  *
349  * @exception GException::invalid_value
350  * Parameter is not of time type.
351  *
352  * This method sets a time parameter with a UTC string. The method only
353  * applies to time parameters. Other parameter types will produce an
354  * exception.
355  ***************************************************************************/
356 void GApplicationPar::time(const GTime& value)
357 {
358  // Check if parameter is a filename parameter
359  if (m_type != "t") {
360  std::string msg = "Attempt to set "+par_type_string(m_type)+
361  " parameter \""+m_name+"\" with filename value.";
363  }
364 
365  // Set value
366  set_value(value.utc());
367 
368  // Return
369  return;
370 }
371 
372 
373 /***********************************************************************//**
374  * @brief Set bool parameter value
375  *
376  * @param[in] value Parameter value.
377  *
378  * @exception GException::invalid_value
379  * Parameter is not of boolean type.
380  *
381  * This method sets a boolean parameter. The method only applies to parameters
382  * of type "b". Other parameter types will produce an exception.
383  ***************************************************************************/
384 void GApplicationPar::boolean(const bool& value)
385 {
386  // Check if parameter is boolean
387  if (m_type != "b") {
388  std::string msg = "Attempt to set "+par_type_string(m_type)+
389  " parameter \""+m_name+"\" with boolean value.";
391  }
392 
393  // Set value string
394  std::string value_string = (value) ? "yes" : "no";
395 
396  // Set value
397  set_value(value_string);
398 
399  // Return
400  return;
401 }
402 
403 
404 /***********************************************************************//**
405  * @brief Set integer parameter value
406  *
407  * @param[in] value Parameter value.
408  *
409  * @exception GException::invalid_value
410  * Parameter is not of integer type.
411  *
412  * This method sets an integer parameter. The method only applies to
413  * parameters of type "i". Other parameter types will produce an exception.
414  ***************************************************************************/
415 void GApplicationPar::integer(const int& value)
416 {
417  // Check if parameter is integer
418  if (m_type != "i") {
419  std::string msg = "Attempt to set "+par_type_string(m_type)+
420  " parameter \""+m_name+"\" with integer value.";
422  }
423 
424  // Set value string
425  std::string value_string = gammalib::str(value);
426 
427  // Set value
428  set_value(value_string);
429 
430  // Return
431  return;
432 }
433 
434 
435 /***********************************************************************//**
436  * @brief Set real parameter value
437  *
438  * @param[in] value Parameter value.
439  *
440  * @exception GException::invalid_value
441  * Parameter is not of real type.
442  *
443  * This method sets a real parameter. The method only applies to parameters
444  * of type "r". Other parameter types will produce an exception.
445  ***************************************************************************/
446 void GApplicationPar::real(const double& value)
447 {
448  // Check if parameter is boolean
449  if (m_type != "r") {
450  std::string msg = "Attempt to set "+par_type_string(m_type)+
451  " parameter \""+m_name+"\" with real value.";
453  }
454 
455  // Set value string
456  std::string value_string = gammalib::str(value);
457 
458  // Set value
459  set_value(value_string);
460 
461  // Return
462  return;
463 }
464 
465 
466 /***********************************************************************//**
467  * @brief Query parameter if required
468  *
469  * This method queries the parameter from the stardard input if it is needed
470  * to be input by the user.
471  ***************************************************************************/
473 {
474  // Continue only if parameter has query mode and it was not yet queried
475  if (is_query() && !was_queried()) {
476 
477  // Dump prompt string
478  std::string prompt = m_prompt;
479  if (m_min.length() > 0 && m_max.length() > 0) {
480  prompt += " ("+m_min+"-"+m_max+")";
481  }
482  else if (m_min.length() > 0) {
483  prompt += " ("+m_min+")";
484  }
485  else if (m_max.length() > 0) {
486  prompt += " ("+m_max+")";
487  }
488  prompt += " ["+m_value+"] ";
489 
490  // Get value
491  #ifdef HAVE_LIBREADLINE
492  std::string value;
493  char* line = readline(prompt.c_str());
494  if (line != NULL) {
495  value = std::string(line);
496  delete line;
497  }
498  #else
499  std::cout << prompt;
500  char line[1000];
501  std::cin.getline(line, 1000);
502  std::string value = std::string(line);
503  #endif
504 
505  // Strip any whitespace from string
506  value = gammalib::strip_whitespace(value);
507 
508  // Update value if value is not the default
509  if (value.length() > 0) {
510  set_value(value);
511  m_update = true;
512  }
513 
514  // Don't query parameter again
515  stop_query();
516 
517  } // endif: parameter had query mode
518 
519  // Return
520  return;
521 }
522 
523 
524 /***********************************************************************//**
525  * @brief Returns parameter value as string
526  *
527  * This method queries any parameter and returns it as a string. No parameter
528  * type checking is performed.
529  ***************************************************************************/
530 std::string GApplicationPar::value(void)
531 {
532  // Query parameter
533  query();
534 
535  // Return value
536  return m_value;
537 }
538 
539 
540 /***********************************************************************//**
541  * @brief Returns string parameter value
542  *
543  * @exception GException::invalid_value
544  * Parameter is not of string type.
545  *
546  * This method queries and returns a string parameter. The method only
547  * applies to parameters of type "s". Other parameter types will produce an
548  * exception.
549  ***************************************************************************/
550 std::string GApplicationPar::string(void)
551 {
552  // Check if parameter is a string parameter
553  if (m_type != "s") {
554  std::string msg = "Attempt to read "+par_type_string(m_type)+
555  " parameter \""+m_name+"\" as a string value.";
557  }
558 
559  // Query parameter
560  query();
561 
562  // Check if parameter is valid
563  if (m_status != ST_VALID) {
564  std::string msg = "Parameter \""+m_name+"\" is "+
565  par_status_string()+". Please specify a valid"
566  " parameter value.";
568  }
569 
570  // Return value
571  return m_value;
572 }
573 
574 
575 /***********************************************************************//**
576  * @brief Returns filename parameter value
577  *
578  * @exception GException::invalid_value
579  * Parameter is not of filename type.
580  *
581  * This method queries and returns a filename parameter. The method only
582  * applies to filename parameters. Other parameter types will produce an
583  * exception. Any environment variables that are encountered within the
584  * filename are expanded automatically.
585  ***************************************************************************/
587 {
588  // Check if parameter is a filename parameter
589  if (!is_filename()) {
590  std::string msg = "Attempt to read "+par_type_string(m_type)+
591  " parameter \""+m_name+"\" as a filename value.";
593  }
594 
595  // Query parameter
596  query();
597 
598  // Check if parameter is valid
599  if (m_status != ST_VALID) {
600  std::string msg = "Parameter \""+m_name+"\" is "+
601  par_status_string()+". Please specify a valid"
602  " parameter value.";
604  }
605 
606  // Return value
607  return (GFilename(m_value));
608 }
609 
610 
611 /***********************************************************************//**
612  * @brief Returns time parameter value
613  *
614  * @param[in] ref Time reference system.
615  * @return Time.
616  *
617  * @exception GException::invalid_value
618  * Parameter is not of time type.
619  *
620  * This method queries and returns a time parameter. The method only applies
621  * to time parameters. Other parameter types will produce an exception. If
622  * the time is specified as "Mission Elapsed Time" (MET) the specified
623  * time reference system will be used for conversion.
624  ***************************************************************************/
626 {
627  // Check if parameter is a time parameter
628  if (m_type != "t") {
629  std::string msg = "Attempt to read "+par_type_string(m_type)+
630  " parameter \""+m_name+"\" as a time value.";
632  }
633 
634  // Query parameter
635  query();
636 
637  // Check if parameter is valid
638  if (m_status != ST_VALID) {
639  std::string msg = "Parameter \""+m_name+"\" is "+
640  par_status_string()+". Please specify a valid"
641  " parameter value.";
643  }
644 
645  // Return value
646  return (GTime(m_value, ref));
647 }
648 
649 
650 /***********************************************************************//**
651  * @brief Returns boolean
652  *
653  * @exception GException::invalid_value
654  * Parameter is not of boolean type.
655  *
656  * This method queries and returns a boolean parameter. The method only
657  * applies to parameters of type "b". Other parameter types will produce an
658  * exception.
659  ***************************************************************************/
661 {
662  // Check if parameter is boolean
663  if (m_type != "b") {
664  std::string msg = "Attempt to read "+par_type_string(m_type)+
665  " parameter \""+m_name+"\" as a boolean value.";
667  }
668 
669  // Query parameter
670  query();
671 
672  // Check if parameter is valid
673  if (m_status != ST_VALID) {
674  std::string msg = "Parameter \""+m_name+"\" is "+
675  par_status_string()+". Please specify a valid"
676  " parameter value.";
678  }
679 
680  // Convert boolean value to upper case
681  std::string uvalue = gammalib::toupper(m_value);
682 
683  // Set result
684  bool result = (uvalue == "YES" || uvalue == "Y" ||
685  uvalue == "TRUE" || uvalue == "T");
686 
687  // Return result
688  return result;
689 }
690 
691 
692 /***********************************************************************//**
693  * @brief Returns integer
694  *
695  * @exception GException::invalid_value
696  * Parameter is not of integer type.
697  *
698  * This method queries and returns an integer parameter. The method only
699  * applies to parameters of type "i". Other parameter types will produce an
700  * exception.
701  ***************************************************************************/
703 {
704  // Check if parameter is integer
705  if (m_type != "i") {
706  std::string msg = "Attempt to read "+par_type_string(m_type)+
707  " parameter \""+m_name+"\" as a integer value.";
709  }
710 
711  // Query parameter
712  query();
713 
714  // Check if parameter is valid
715  if (m_status != ST_VALID) {
716  std::string msg = "Parameter \""+m_name+"\" is "+
717  par_status_string()+". Please specify a valid"
718  " parameter value.";
720  }
721 
722  // Set result
723  int result = gammalib::toint(m_value);
724 
725  // Return result
726  return result;
727 }
728 
729 
730 /***********************************************************************//**
731  * @brief Returns real
732  *
733  * @exception GException::invalid_value
734  * Parameter is not of real type.
735  *
736  * This method queries and returns a real parameter. The method only
737  * applies to parameters of type "r". Other parameter types will produce an
738  * exception.
739  ***************************************************************************/
741 {
742  // Check if parameter is integer
743  if (m_type != "r") {
744  std::string msg = "Attempt to read "+par_type_string(m_type)+
745  " parameter \""+m_name+"\" as a real value.";
747  }
748 
749  // Query parameter
750  query();
751 
752  // Check if parameter is valid
753  if (m_status != ST_VALID) {
754  std::string msg = "Parameter \""+m_name+"\" is "+
755  par_status_string()+". Please specify a valid"
756  " parameter value.";
758  }
759 
760  // Set result
761  double result = gammalib::todouble(m_value);
762 
763  // Return result
764  return result;
765 }
766 
767 
768 /***********************************************************************//**
769  * @brief Signals if parameter mode is "learn"
770  *
771  * A parameter is in mode learn when it has one of the following modes:
772  * hl,ql,lh, or lq.
773  ***************************************************************************/
775 {
776  // Assign result
777  bool result = (m_mode == "hl" || m_mode == "ql" || m_mode == "lh" ||
778  m_mode == "lq");
779 
780  // Return result
781  return result;
782 }
783 
784 
785 /***********************************************************************//**
786  * @brief Signals if parameter mode is "query"
787  *
788  * A parameter will be queried when it has one of the following modes:
789  * q, ql, or lq.
790  ***************************************************************************/
792 {
793  // Assign result
794  bool result = (m_mode == "q" || m_mode == "ql" || m_mode == "lq");
795 
796  // Return result
797  return result;
798 }
799 
800 
801 /***********************************************************************//**
802  * @brief Signals if parameter mode is of type "filename"
803  *
804  * A parameter is of type "filename" if it has one of the following types:
805  * f, fr, fw, fe, or fn.
806  ***************************************************************************/
808 {
809  // Assign result
810  bool result = (m_type == "f" || m_type == "fr" || m_type == "fw" ||
811  m_type == "fe" || m_type == "fn");
812 
813  // Return result
814  return result;
815 }
816 
817 
818 /***********************************************************************//**
819  * @brief Signals if parameter is valid
820  ***************************************************************************/
822 {
823  // Query parameter
824  query();
825 
826  // Return validity
827  return (m_status == ST_VALID);
828 }
829 
830 
831 /***********************************************************************//**
832  * @brief Signals if parameter is undefined
833  ***************************************************************************/
835 {
836  // Query parameter
837  query();
838 
839  // Return validity
840  return (m_status == ST_UNDEFINED);
841 }
842 
843 
844 /***********************************************************************//**
845  * @brief Signals if parameter is not a number
846  ***************************************************************************/
848 {
849  // Query parameter
850  query();
851 
852  // Return validity
853  return (m_status == ST_NAN);
854 }
855 
856 
857 /***********************************************************************//**
858  * @brief Set class from pickled string vector
859  *
860  * @param[in] string String vector containing class information.
861  ***************************************************************************/
862 void GApplicationPar::pickle(const std::vector<std::string>& string)
863 {
864  // Clear object
865  clear();
866 
867  // Extract members
868  m_update = (bool)gammalib::toint(string[0]);
869  m_queried = (bool)gammalib::toint(string[1]);
870  m_name = string[2];
871  m_type = string[3];
872  m_mode = string[4];
873  m_value = string[5];
874  m_min = string[6];
875  m_max = string[7];
876  m_prompt = string[8];
877  m_status = (Status)gammalib::toint(string[9]);
878 
879  // Return
880  return;
881 }
882 
883 
884 /***********************************************************************//**
885  * @brief Return pickled string vector
886  *
887  * @return String vector containing class information.
888  ***************************************************************************/
889 std::vector<std::string> GApplicationPar::pickle(void) const
890 {
891  // Allocate vector of strings with 10 elements
892  std::vector<std::string> string(10);
893 
894  // Set vector elements from class members
895  string[0] = gammalib::str(m_update);
896  string[1] = gammalib::str(m_queried);
897  string[2] = m_name;
898  string[3] = m_type;
899  string[4] = m_mode;
900  string[5] = m_value;
901  string[6] = m_min;
902  string[7] = m_max;
903  string[8] = m_prompt;
904  string[9] = gammalib::str((int)m_status);
905 
906  // Return string vector
907  return (string);
908 }
909 
910 
911 /***********************************************************************//**
912  * @brief Print parameter
913  *
914  * @param[in] chatter Chattiness.
915  * @return String containing parameter information.
916  ***************************************************************************/
917 std::string GApplicationPar::print(const GChatter& chatter) const
918 {
919  // Initialise result string
920  std::string result;
921 
922  // Continue only if chatter is not silent
923  if (chatter != SILENT) {
924 
925  // Write parameter name
926  result = gammalib::parformat(name());
927 
928  // Write value (use m_value here to avoid querying when printing)
929  switch (m_status) {
930  case ST_VALID:
931  result.append(m_value);
932  break;
933  case ST_UNDEFINED:
934  result.append("undefined");
935  break;
936  case ST_NAN:
937  result.append("nan");
938  break;
939  case ST_UNDERFLOW:
940  result.append(m_value+" (underflow)");
941  break;
942  case ST_OVERFLOW:
943  result.append(m_value+" (overflow)");
944  break;
945  }
946 
947  // Write limits
948  if (min().length() > 0 && max().length() > 0) {
949  result.append(" ("+min()+"-"+max()+")");
950  }
951  else if (min().length() > 0) {
952  result.append(" ("+min()+")");
953  }
954 
955  // Write type information
956  result.append(" [t="+type()+", m="+mode()+"]");
957 
958  } // endif: chatter was not silent
959 
960  // Return result
961  return result;
962 }
963 
964 
965 /*==========================================================================
966  = =
967  = Private methods =
968  = =
969  ==========================================================================*/
970 
971 /***********************************************************************//**
972  * @brief Initialise class members
973  ***************************************************************************/
975 {
976  // Initialise members
977  m_update = false;
978  m_queried = false;
979  m_name.clear();
980  m_type.clear();
981  m_mode.clear();
982  m_value.clear();
983  m_min.clear();
984  m_max.clear();
985  m_prompt.clear();
986  m_status = ST_VALID;
987 
988  // Return
989  return;
990 }
991 
992 
993 /***********************************************************************//**
994  * @brief Copy class members
995  *
996  * @param[in] par Parameter.
997  ***************************************************************************/
999 {
1000  // Copy attributes
1001  m_update = par.m_update;
1002  m_queried = par.m_queried;
1003  m_name = par.m_name;
1004  m_type = par.m_type;
1005  m_mode = par.m_mode;
1006  m_value = par.m_value;
1007  m_min = par.m_min;
1008  m_max = par.m_max;
1009  m_prompt = par.m_prompt;
1010  m_status = par.m_status;
1011 
1012  // Return
1013  return;
1014 }
1015 
1016 
1017 /***********************************************************************//**
1018  * @brief Delete class members
1019  ***************************************************************************/
1021 {
1022  // Return
1023  return;
1024 }
1025 
1026 
1027 /***********************************************************************//**
1028  * @brief Test validity of type string
1029  *
1030  * @param[in] type Type string.
1031  *
1032  * @exception GException::invalid_value
1033  * Invalid parameter type.
1034  *
1035  * The parameter type has to be one of b,i,r,s,f,fr,fw,fe,fn,t.
1036  * The fr,fw,fe,fn types test for read access, write access, file existence,
1037  * and file absence, respectively.
1038  ***************************************************************************/
1039 void GApplicationPar::check_type(const std::string& type) const
1040 {
1041  // Check if type is valid
1042  if (type != "b" && type != "i" && type != "r" && type != "s" &&
1043  type != "f" && type != "fr" && type != "fw" && type != "fe" &&
1044  type != "fn" && type != "t") {
1045  std::string msg = "Invalid parameter type \""+type+"\" encountered"
1046  " for parameter \""+m_name+"\".";
1048  }
1049 
1050  // Return
1051  return;
1052 }
1053 
1054 
1055 /***********************************************************************//**
1056  * @brief Test validity of mode string
1057  *
1058  * @param[in] mode Mode string.
1059  *
1060  * @exception GException::invalid_value
1061  * Invalid parameter mode.
1062  *
1063  * The parameter mode has to be one of a,h,l,q,hl,ql,lh,lq.
1064  ***************************************************************************/
1065 void GApplicationPar::check_mode(const std::string& mode) const
1066 {
1067  // Check of mode is valid
1068  if (mode != "a" && mode != "h" && mode != "q" && mode != "hl" &&
1069  mode != "ql" && mode != "lh" && mode != "lq") {
1070  std::string msg = "Invalid parameter mode \""+mode+"\" encountered"
1071  " for parameter \""+m_name+"\".";
1073  }
1074 
1075  // Return
1076  return;
1077 }
1078 
1079 
1080 /***********************************************************************//**
1081  * @brief Test validity of value string
1082  *
1083  * @param[in] value Value string.
1084  *
1085  * Requires that m_type, m_min and m_max are set. The method does not verify
1086  * if m_type is valid.
1087  ***************************************************************************/
1088 void GApplicationPar::check_value(const std::string& value) const
1089 {
1090  // Make type dependent check
1091  if (m_type == "b") {
1092  check_value_bool(value);
1093  }
1094  else if (m_type == "i") {
1095  check_value_int(value);
1096  }
1097  else if (m_type == "r") {
1098  check_value_real(value);
1099  }
1100  else if (m_type == "s") {
1101  check_value_string(value);
1102  }
1103  else if (m_type == "t") {
1104  check_value_time(value);
1105  }
1106  else if (is_filename()) {
1107  check_value_filename(value);
1108  }
1109 
1110  // Return
1111  return;
1112 }
1113 
1114 
1115 /***********************************************************************//**
1116  * @brief Test validity of boolean value string
1117  *
1118  * @param[in] value Value string.
1119  *
1120  * @exception GException::invalid_value
1121  * Boolean value string is not valid.
1122  *
1123  * The Boolean value string has to be one of y,yes,true,t or n,no,false,f
1124  * (case insensitive).
1125  ***************************************************************************/
1126 void GApplicationPar::check_value_bool(const std::string& value) const
1127 {
1128  // Turn value to lower case for testing
1129  std::string lvalue = gammalib::tolower(value);
1130 
1131  // Test for validity
1132  if (lvalue != "y" && lvalue != "yes" && lvalue != "true" && lvalue != "t" &&
1133  lvalue != "n" && lvalue != "no" && lvalue != "false" && lvalue != "f") {
1134  std::string msg = "Invalid boolean value \""+value+"\" encountered"
1135  " for parameter \""+m_name+"\". Use"
1136  " y/n/yes/no/t/f/true/false";
1138  }
1139 
1140  // Return
1141  return;
1142 }
1143 
1144 
1145 /***********************************************************************//**
1146  * @brief Test validity of integer parameter value
1147  *
1148  * @param[in] value Parameter value.
1149  *
1150  * @exception GException::invalid_value
1151  * Integer parameter value outside validity range
1152  *
1153  * If either options or a validity range has been specified, check if the
1154  * integer parameter value satisfies the validity constraints.
1155  *
1156  * Requires that m_type, m_status, m_min and m_max are set. The method does
1157  * not verify if m_type is valid.
1158  ***************************************************************************/
1159 void GApplicationPar::check_value_int(const std::string& value) const
1160 {
1161  // Check only if value is not undefined
1162  if (m_status != ST_UNDEFINED) {
1163 
1164  // Check for options
1165  bool has_options = check_options(value);
1166 
1167  // If no options check has been done and if there is a m_min and
1168  // m_max value then perform an integer check
1169  if (!has_options && m_min.length() > 0 && m_max.length() > 0) {
1170 
1171  // Throw an exception if we have a NAN parameter
1172  if (m_status == ST_NAN) {
1173  std::string msg = "Parameter \""+m_name+"\" value \""+value+
1174  "\" outside validity range ["+m_min+","+
1175  m_max+"].";
1177  }
1178 
1179  // Convert value and range to integers
1180  int ivalue = gammalib::toint(value);
1181  int imin = gammalib::toint(m_min);
1182  int imax = gammalib::toint(m_max);
1183 
1184  // Check if value is outside range
1185  if (imin > ivalue || imax < ivalue) {
1186  std::string msg = "Parameter \""+m_name+"\" value \""+value+
1187  "\" outside validity range ["+m_min+","+
1188  m_max+"].";
1190  }
1191 
1192  } // endif: there was no options check and there was a range specified
1193 
1194  } // endif: value was not undefined
1195 
1196  // Return
1197  return;
1198 }
1199 
1200 
1201 /***********************************************************************//**
1202  * @brief Test validity of real parameter value
1203  *
1204  * @param[in] value Parameter value.
1205  *
1206  * @exception GException::invalid_value
1207  * Real parameter value outside validity range
1208  *
1209  * If either options or a validity range has been specified, check if the
1210  * real parameter value satisfies the validity constraints.
1211  *
1212  * Requires that m_type, m_status, m_min and m_max are set. The method does
1213  * not verify if m_type is valid.
1214  ***************************************************************************/
1215 void GApplicationPar::check_value_real(const std::string& value) const
1216 {
1217  // Check only if value is not undefined
1218  if (m_status != ST_UNDEFINED) {
1219 
1220  // Check for options
1221  bool has_options = check_options(value);
1222 
1223  // If no options check has been done and if there is a m_min and
1224  // m_max value then perform an integer check
1225  if (!has_options && m_min.length() > 0 && m_max.length() > 0) {
1226 
1227  // Throw an exception if we have a NAN parameter
1228  if (m_status == ST_NAN) {
1229  std::string msg = "Parameter \""+m_name+"\" value \""+value+
1230  "\" outside validity range ["+m_min+","+
1231  m_max+"].";
1233  }
1234 
1235  // Convert value and range to doubles
1236  double dvalue = gammalib::todouble(value);
1237  double dmin = gammalib::todouble(m_min);
1238  double dmax = gammalib::todouble(m_max);
1239 
1240  // Check if value is outside range
1241  if (dmin > dvalue || dmax < dvalue) {
1242  std::string msg = "Parameter \""+m_name+"\" value \""+value+
1243  "\" outside validity range ["+m_min+","+
1244  m_max+"].";
1246  }
1247 
1248  } // endif: there was no options check and there was a range specified
1249 
1250  } // endif: value was not undefined
1251 
1252  // Return
1253  return;
1254 }
1255 
1256 
1257 /***********************************************************************//**
1258  * @brief Test validity of string parameter value
1259  *
1260  * @param[in] value Parameter value.
1261  *
1262  * If options have been specified, check if the string parameter value
1263  * satisfies the options.
1264  *
1265  * Requires that m_type, m_min and m_max are set. The method does not verify
1266  * if m_type is valid.
1267  ***************************************************************************/
1268 void GApplicationPar::check_value_string(const std::string& value) const
1269 {
1270  // Check for options
1271  check_options(value);
1272 
1273  // Return
1274  return;
1275 }
1276 
1277 
1278 /***********************************************************************//**
1279  * @brief Test validity of filename parameter value
1280  *
1281  * @param[in] value Parameter value.
1282  *
1283  * If options have been specified, check if the filename parameter value
1284  * satisfies the options.
1285  *
1286  * Requires that m_type, m_min and m_max are set. The method does not verify
1287  * if m_type is valid.
1288  *
1289  * @todo NONE is equivalent to an empty string.
1290  ***************************************************************************/
1291 void GApplicationPar::check_value_filename(const std::string& value) const
1292 {
1293  // Check for options
1294  check_options(value);
1295 
1296  // Return
1297  return;
1298 }
1299 
1300 
1301 /***********************************************************************//**
1302  * @brief Test validity of time parameter value
1303  *
1304  * @param[in] value Parameter value.
1305  *
1306  * If options have been specified, check if the time parameter value
1307  * satisfies the options.
1308  *
1309  * Requires that m_type, m_min and m_max are set. The method does not verify
1310  * if m_type is valid.
1311  ***************************************************************************/
1312 void GApplicationPar::check_value_time(const std::string& value) const
1313 {
1314  // Check for options
1315  check_options(value);
1316 
1317  // Return
1318  return;
1319 }
1320 
1321 
1322 /***********************************************************************//**
1323  * @brief Test if parameter value satisfies possible options
1324  *
1325  * @param[in] value Parameter value.
1326  * @return True if there were options, false otherwise.
1327  *
1328  * @exception GException::invalid_value
1329  * Value does not satisfy one of the possible options.
1330  *
1331  * In case that the parameter has different options (m_max field not set and
1332  * at least one character chain in m_min field, multiple chains separated by
1333  * pipe symbol), check that the parameter value corresponds to one of the
1334  * values in the m_min field. For strings, and for strings only, the
1335  * parameter check is case insensitive.
1336  ***************************************************************************/
1337 bool GApplicationPar::check_options(const std::string& value) const
1338 {
1339  // Initialise options flags
1340  bool has_options = false;
1341 
1342  // Continue only if the m_max field is not set
1343  if (m_max.length() == 0) {
1344 
1345  // Get parameter options
1346  std::vector<std::string> options = gammalib::split(m_min, "|");
1347 
1348  // Determine number of options
1349  int num_options = options.size();
1350 
1351  // Continue only if there are options
1352  if (num_options > 0) {
1353 
1354  // Signal that there were options
1355  has_options = true;
1356 
1357  // Initalise found flag
1358  bool found = false;
1359 
1360  // Strip whitespace from all options, and for strings, convert
1361  // to upper case
1362  for (int i = 0; i < num_options; ++i) {
1363  options[i] = gammalib::strip_whitespace(options[i]);
1364  if (m_type == "s") {
1365  options[i] = gammalib::toupper(options[i]);
1366  }
1367  }
1368 
1369  // Set parameter value
1370  std::string v = (m_type == "s") ? gammalib::toupper(value) : value;
1371 
1372  // Now check if we can find one of the options
1373  for (int i = 0; i < num_options; ++i) {
1374  if (options[i] == v) {
1375  found = true;
1376  break;
1377  }
1378  }
1379 
1380  // If no option was found then throw exception
1381  if (!found) {
1382  std::string msg = "Parameter \""+m_name+"\" value \""+value+
1383  "\" invalid. Must be one of \""+m_min+"\".";
1385  }
1386 
1387  } // endif: there were parameter options
1388 
1389  } // endif: the m_max field was not set
1390 
1391  // Return options flag
1392  return has_options;
1393 }
1394 
1395 
1396 /***********************************************************************//**
1397  * @brief Set parameter status
1398  *
1399  * @param[in] value Parameter value.
1400  * @return Updated parameter value.
1401  *
1402  * Set parameter status depending on the content of the value field.
1403  *
1404  * For an integer parameter, INDEF, NONE, UNDEF or UNDEFINED will result in
1405  * a status of "undefined". INF, INFINITY or NAN will be transformed in the
1406  * maximum long number.
1407  *
1408  * For a real parameter, INDEF, NONE, UNDEF or UNDEFINED will result in a
1409  * status of "undefined", while INF, INFINITY or NAN will result in a status
1410  * of "nan".
1411  *
1412  * For a time parameter, INDEF, NONE, UNDEF or UNDEFINED will result in a
1413  * status of "undefined".
1414  *
1415  * For a filename parameter, an empty string or INDEF, NONE, UNDEF or
1416  * UNDEFINED will result in a status of "undefined".
1417  ***************************************************************************/
1418 std::string GApplicationPar::set_status(const std::string& value)
1419 {
1420  // Initialise result value
1421  std::string result = value;
1422 
1423  // Set integer status. Catch the special values that signal that a
1424  // parameter is undefined. Any infinity or nan is set to the maximum
1425  // long value (APE standard)
1426  if (m_type == "i") {
1427  std::string lvalue = gammalib::tolower(value);
1428  if (lvalue == "indef" ||
1429  lvalue == "none" ||
1430  lvalue == "undef" ||
1431  lvalue == "undefined") {
1433  }
1434  else if (lvalue == "inf" ||
1435  lvalue == "infinity" ||
1436  lvalue == "nan") {
1437  result = gammalib::str(LONG_MAX);
1438  m_status = ST_VALID;
1439  }
1440  else {
1441  m_status = ST_VALID;
1442  }
1443  }
1444 
1445  // Set real status. Catch the special values that signal that a
1446  // parameter is undefined, infinity or nan (APE standard).
1447  else if (m_type == "r") {
1448  std::string lvalue = gammalib::tolower(value);
1449  if (lvalue == "indef" ||
1450  lvalue == "none" ||
1451  lvalue == "undef" ||
1452  lvalue == "undefined") {
1454  }
1455  else if (lvalue == "inf" ||
1456  lvalue == "infinity" ||
1457  lvalue == "nan") {
1458  m_status = ST_NAN;
1459  }
1460  else {
1461  m_status = ST_VALID;
1462  }
1463  }
1464 
1465  // Set time status. Catch the special values that signal that a parameter
1466  // is undefined.
1467  else if (m_type == "t") {
1468  std::string lvalue = gammalib::tolower(value);
1469  if (lvalue == "indef" ||
1470  lvalue == "none" ||
1471  lvalue == "undef" ||
1472  lvalue == "undefined") {
1474  }
1475  else {
1476  m_status = ST_VALID;
1477  }
1478  }
1479 
1480  // Set filename status. Catch the special values that signal that a
1481  // parameter is undefined.
1482  else if (m_type == "f") {
1483  std::string lvalue = gammalib::tolower(value);
1484  if (lvalue == "" ||
1485  lvalue == "indef" ||
1486  lvalue == "none" ||
1487  lvalue == "undef" ||
1488  lvalue == "undefined") {
1490  }
1491  else {
1492  m_status = ST_VALID;
1493  }
1494  }
1495 
1496  // Set other status
1497  else {
1498  m_status = ST_VALID;
1499  }
1500 
1501  // Return result value
1502  return result;
1503 }
1504 
1505 
1506 /***********************************************************************//**
1507  * @brief Set parameter value
1508  *
1509  * @param[in] value Parameter value.
1510  *
1511  * Set parameter value, signal it for update and disable parameter querying.
1512  ***************************************************************************/
1513 void GApplicationPar::set_value(const std::string& value)
1514 {
1515  // Set parameter status
1516  std::string par_value = set_status(value);
1517 
1518  // Check parameter value
1519  check_value(par_value);
1520 
1521  // Set parameter value
1522  m_value = par_value;
1523 
1524  // Signal update
1525  m_update = true;
1526 
1527  // Don't query parameter again
1528  stop_query();
1529 
1530  // Return
1531  return;
1532 }
1533 
1534 
1535 /***********************************************************************//**
1536  * @brief Don't query parameter again
1537  ***************************************************************************/
1539 {
1540  // Don't query parameter again
1541  m_queried = true;
1542 
1543  // Return
1544  return;
1545 }
1546 
1547 
1548 /***********************************************************************//**
1549  * @brief Return type string
1550  *
1551  * @param[in] type Parameter type.
1552  *
1553  * Translates parameter type character(s) into a human readable type string.
1554  * Valid parameter types are: b,i,r,s,f,fr,fw,fe,fn,t. If the parameter type
1555  * is not valid, the method returns "unknown".
1556  ***************************************************************************/
1557 std::string GApplicationPar::par_type_string(const std::string& type) const
1558 {
1559  // Initialize empty type string
1560  std::string type_string = "";
1561 
1562  // Set type dependent string
1563  if (type == "b") {
1564  type_string.append("boolean");
1565  }
1566  else if (type == "i") {
1567  type_string.append("integer");
1568  }
1569  else if (type == "r") {
1570  type_string.append("real");
1571  }
1572  else if (type == "s") {
1573  type_string.append("string");
1574  }
1575  else if (type == "f" || type == "fr" || type == "fw" ||
1576  type == "fe" || type == "fn") {
1577  type_string.append("filename");
1578  }
1579  else if (type == "t") {
1580  type_string.append("time");
1581  }
1582  else {
1583  type_string.append("unknown");
1584  }
1585 
1586  // Return type string
1587  return type_string;
1588 }
1589 
1590 
1591 /***********************************************************************//**
1592  * @brief Return status string
1593  *
1594  * @return Returns the parameter status in human readable form.
1595  ***************************************************************************/
1596 std::string GApplicationPar::par_status_string(void) const
1597 {
1598  // Allocate status string
1599  std::string status;
1600 
1601  // Set status
1602  switch (m_status) {
1603  case ST_VALID:
1604  status.append("valid");
1605  break;
1606  case ST_UNDEFINED:
1607  status.append("undefined");
1608  break;
1609  case ST_NAN:
1610  status.append("NaN");
1611  break;
1612  case ST_UNDERFLOW:
1613  status.append("underflow");
1614  break;
1615  case ST_OVERFLOW:
1616  status.append("overflow");
1617  break;
1618  }
1619 
1620  // Return status
1621  return status;
1622 }
const std::string & prompt(void) const
Returns parameter prompt.
bool is_learn(void) const
Signals if parameter mode is &quot;learn&quot;.
void copy_members(const GApplicationPar &par)
Copy class members.
Status m_status
Parameter status.
#define G_CHECK_VALUE_REAL
bool m_queried
Signal that parameter was queried.
#define G_CHECK_VALUE_BOOL
bool was_queried(void) const
Signals if parameter was queried.
#define G_CHECK_OPTIONS
std::string m_name
Parameter name.
GApplicationPar & operator=(const GApplicationPar &par)
Assignment operator.
bool is_valid(void)
Signals if parameter is valid.
bool m_update
Signal value updating.
void check_value_bool(const std::string &value) const
Test validity of boolean value string.
virtual ~GApplicationPar(void)
Destructor.
std::string par_type_string(const std::string &type) const
Return type string.
bool is_undefined(void)
Signals if parameter is undefined.
std::vector< std::string > split(const std::string &s, const std::string &sep)
Split string.
Definition: GTools.cpp:983
bool boolean(void)
Returns boolean.
Time class.
Definition: GTime.hpp:55
Gammalib tools definition.
void check_type(const std::string &type) const
Test validity of type string.
Application parameter class definition.
void check_value_real(const std::string &value) const
Test validity of real parameter value.
double min(const GVector &vector)
Computes minimum vector element.
Definition: GVector.cpp:886
#define G_STRING_SET
&lt; Needed for declaration of LONG_MAX
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition: GTools.cpp:80
#define G_FILENAME_GET
int integer(void)
Returns integer.
GTime time(void)
Return time in native reference system.
GApplicationPar(void)
Void constructor.
#define G_INTEGER_GET
#define G_INTEGER_SET
std::string print(const GChatter &chatter=NORMAL) const
Print parameter.
bool is_notanumber(void)
Signals if parameter is not a number.
#define G_TIME_GET
bool is_filename(void) const
Signals if parameter mode is of type &quot;filename&quot;.
bool check_options(const std::string &value) const
Test if parameter value satisfies possible options.
void check_value_time(const std::string &value) const
Test validity of time parameter value.
void stop_query(void)
Don&#39;t query parameter again.
void clear(void)
Clear parameter.
std::string m_mode
Parameter mode.
#define G_CHECK_VALUE_INT
const std::string & type(void) const
Returns parameter type.
const std::string & name(void) const
Returns parameter name.
Filename class.
Definition: GFilename.hpp:62
GApplicationPar * clone(void) const
Clone parameter.
const std::string & mode(void) const
Returns parameter mode.
std::string m_type
Parameter type.
std::vector< std::string > pickle(void) const
Return pickled string vector.
#define G_REAL_GET
#define G_REAL_SET
const std::string & max(void) const
Returns parameter maximum.
#define G_BOOLEAN_GET
GChatter
Definition: GTypemaps.hpp:33
void check_value_filename(const std::string &value) const
Test validity of filename parameter value.
#define G_BOOLEAN_SET
void init_members(void)
Initialise class members.
double real(void)
Returns real.
bool is_query(void) const
Signals if parameter mode is &quot;query&quot;.
#define G_CHECK_TYPE
double max(const GVector &vector)
Computes maximum vector element.
Definition: GVector.cpp:915
#define G_TIME_SET
void check_value_string(const std::string &value) const
Test validity of string parameter value.
std::string m_prompt
Parameter prompt.
#define G_CHECK_MODE
#define G_FILENAME_SET
void set_value(const std::string &value)
Set parameter value.
std::string m_min
Parameter minimum.
Exception handler interface definition.
void check_value_int(const std::string &value) const
Test validity of integer parameter value.
Application parameter class.
GFilename filename(void)
Returns filename parameter value.
std::string toupper(const std::string &s)
Convert string to upper case.
Definition: GTools.cpp:941
Implements a time reference.
std::string tolower(const std::string &s)
Convert string to lower case.
Definition: GTools.cpp:955
std::string string(void)
Returns string parameter value.
void free_members(void)
Delete class members.
void check_mode(const std::string &mode) const
Test validity of mode string.
const std::string & min(void) const
Returns parameter minimum.
int toint(const std::string &arg)
Convert string into integer value.
Definition: GTools.cpp:821
std::string par_status_string(void) const
Return status string.
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
#define G_STRING_GET
void query(void)
Query parameter if required.
std::string utc(const int &precision=0) const
Return time as string in UTC time system.
Definition: GTime.cpp:465
Time class interface definition.
std::string m_max
Parameter maximum.
std::string set_status(const std::string &value)
Set parameter status.
Filename class interface definition.
double todouble(const std::string &arg)
Convert string into double precision value.
Definition: GTools.cpp:926
std::string value(void)
Returns parameter value as string.
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489
std::string m_value
Parameter value.
void check_value(const std::string &value) const
Test validity of value string.