GammaLib  1.7.0.dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GTools.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * GTools.cpp - GammaLib tools *
3  * ----------------------------------------------------------------------- *
4  * copyright (C) 2008-2019 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 GTools.cpp
23  * @brief Gammalib tools implementation
24  * @author Juergen Knoedlseder
25  */
26 
27 /* __ Includes ___________________________________________________________ */
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <unistd.h> // access() functions
32 #include <fcntl.h> // fcntl() functions
33 #include <sys/stat.h>
34 #include <sys/time.h> // timeval
35 #include <sys/select.h> // select() function
36 #include <sys/types.h>
37 #include <sys/socket.h> // recv() function
38 #include <pwd.h>
39 #include <cmath>
40 #include <cfloat>
41 #include <cctype>
42 #include <cstdlib> // std::getenv() function
43 #include <cstring> // std::strlen() function
44 #include <iostream>
45 #include <sstream>
46 #include <algorithm>
47 #include "GTools.hpp"
48 #include "GException.hpp"
49 #include "GFits.hpp"
50 #include "GEnergy.hpp"
51 #include "GFilename.hpp"
52 #include "GXmlElement.hpp"
53 #include "GXmlNode.hpp"
54 #include "GXmlText.hpp"
55 
56 /* __ Compile options ____________________________________________________ */
57 
58 /* __ Function name definitions __________________________________________ */
59 #define G_XML2STRING "gammalib::xml2string(std::string&)"
60 
61 /* __ Coding definitions _________________________________________________ */
62 #define G_PARFORMAT_LENGTH 29
63 
64 
65 /***********************************************************************//**
66  * @brief Strip leading and trailing whitespace from string
67  *
68  * @param[in] arg String from which whitespace should be stripped.
69  * @return String with stripped whitespace.
70  ***************************************************************************/
71 std::string gammalib::strip_whitespace(const std::string& arg)
72 {
73  // Return result
74  return (strip_chars(arg, " "));
75 }
76 
77 
78 /***********************************************************************//**
79  * @brief Strip leading and trailing character from string
80  *
81  * @param[in] arg String from which character should be stripped.
82  * @param[in] chars Character(s) to be stripped.
83  * @return String with stripped characters.
84  ***************************************************************************/
85 std::string gammalib::strip_chars(const std::string& arg,
86  const std::string& chars)
87 {
88  // Initialise empty result string
89  std::string result;
90 
91  // Continue only if argument is not empty
92  if (!arg.empty()) {
93 
94  // Get start and stop
95  std::string::size_type start = arg.find_first_not_of(chars);
96  std::string::size_type stop = arg.find_last_not_of(chars);
97 
98  // Continue only if start and stop are valid
99  if (start != std::string::npos && stop != std::string::npos) {
100 
101  // Continue only if stop is larger then or equal to start
102  if (start <= stop) {
103  result = arg.substr(start, stop-start+1);
104  }
105 
106  } // endif: start and stop were valid
107 
108  } // endif: argument was not empty
109 
110  // Return result
111  return result;
112 }
113 
114 
115 /***********************************************************************//**
116  * @brief Strip trailing character from string
117  *
118  * @param[in] arg String from which character should be stripped.
119  * @param[in] chars Character(s) to be stripped.
120  * @return String with stripped characters.
121  ***************************************************************************/
122 std::string gammalib::rstrip_chars(const std::string& arg,
123  const std::string& chars)
124 {
125  // Initialise empty result string
126  std::string result;
127 
128  // Continue only if argument is not empty
129  if (!arg.empty()) {
130 
131  // Get stop
132  std::string::size_type stop = arg.find_last_not_of(chars);
133 
134  // Continue only if stop is valid
135  if (stop != std::string::npos) {
136  result = arg.substr(0, stop+1);
137  }
138 
139  } // endif: argument was not empty
140 
141  // Return result
142  return result;
143 }
144 
145 
146 /***********************************************************************//**
147  * @brief Replace string segment in string
148  *
149  * @param[in] arg String in which character segements are to be replaced
150  * @param[in] segment String segment to be replaced.
151  * @param[in] replacement Replacement string.
152  * @return String with replaced segements.
153  *
154  * Replaces string segments by a replacement string in a given string.
155  *
156  * If the input string @p arg is "Wonderful", the @p segment is "onder" and
157  * the @p replacement is "ish" the method will return "Wishful".
158  ***************************************************************************/
159 std::string gammalib::replace_segment(const std::string& arg,
160  const std::string& segment,
161  const std::string& replacement)
162 {
163  // Initialise result string by argument
164  std::string result = arg;
165 
166  // Initialise character pointer
167  std::string::size_type pos = 0;
168  std::string::size_type start = 0;
169 
170  // Loop over string
171  while (start != std::string::npos) {
172  start = result.find(segment, pos);
173  if (start != std::string::npos) {
174  result = result.replace(start, segment.length(), replacement);
175  pos = start + replacement.length();
176  }
177  }
178 
179  // Return result
180  return result;
181 }
182 
183 
184 /***********************************************************************//**
185  * @brief Expand environment variables in string
186  *
187  * @param[in] arg String.
188  * @return String with expected environment variables.
189  *
190  * Expands any environment variable that is found in a string. Valid
191  * delimiters for environment variables are $ENV{<name>}, $ENV(<name>),
192  * ${<name>}, $(<name>) and $<name> (in the last case the terminating
193  * delimiter is either a / or a blank character or the end of the string).
194  * Environment variables occuring within single quotes (') are ignored.
195  * Environment variables that do not exist will be kept as specified.
196  *
197  * The method also replaces ~ or ~user by the user's home directory, ~+
198  * by the value of the PWD environment variable and ~- by the value of the
199  * OLDPWD variable. If the user or the PWD or OLDPWD variable are not found,
200  * no replacement is done.
201  *
202  * This function has been inspired by the function ape_util_expand_env_var
203  * from ape_util.c in the ape software developed at HEASARC.
204  ***************************************************************************/
205 std::string gammalib::expand_env(const std::string& arg)
206 {
207  // Set environment variable delimiters
208  static const char* begin_delim[] = { "$ENV{", "$ENV(", "${", "$(", "$", "~" };
209  static const char* end_delim[] = { "}", ")", "}", ")", "/", "/" };
210  static const int num_delim = 6;
211 
212  // Initialise result with argument
213  std::string result = arg;
214 
215  // Initialise parse parameters
216  size_t index = 0;
217  bool in_quote = false;
218 
219  // Loop over string
220  while (index < result.length()) {
221 
222  // If we have an escaped character then skip the current character
223  // and the next one
224  if (result[index] == '\\') {
225  index += 2;
226  continue;
227  }
228 
229  // If we have a single quote then toggle the quote state
230  if (result[index] == '\'') {
231  in_quote = !in_quote;
232  index++;
233  continue;
234  }
235 
236  // Don't expand environment variables inside single quotes. Note
237  // that double quotes are ok.
238  if (in_quote) {
239  index++;
240  continue;
241  }
242 
243  // Find delimiter which indicates beginning of an environment variable
244  size_t begin_length = 0;
245  int delim_idx = 0;
246  for (; delim_idx < num_delim; ++delim_idx) {
247  size_t len = std::strlen(begin_delim[delim_idx]);
248  if (result.compare(index, len, begin_delim[delim_idx]) == 0) {
249  begin_length = len;
250  break;
251  }
252  }
253 
254  // If we found a delimiter then process the environment variable
255  if (begin_length > 0) {
256 
257  // Search for the termination delimiter of the environment
258  // variable. There is a special case for delimiters 4 and 5:
259  // It has always an end_length of zero as the / is not a real
260  // delimiter, but just an indicator that the environment variable
261  // ends. Another indicator is a blank. If the end of the
262  // string has been reached this is also acceptable.
263  size_t i_start = index + begin_length;
264  size_t i_end = i_start;
265  size_t end_length = 0;
266  if (delim_idx == 4 || delim_idx == 5) {
267  while (i_end < result.length() &&
268  result.compare(i_end, 1, "/") != 0 &&
269  result.compare(i_end, 1, " ") != 0) {
270  i_end++;
271  }
272  }
273  else {
274  end_length = std::strlen(end_delim[delim_idx]);
275  while (i_end < result.length() &&
276  result.compare(i_end, end_length, end_delim[delim_idx]) != 0) {
277  i_end++;
278  }
279  }
280 
281  // If termination delimiter has been found then expand the
282  // environment variable
283  if (i_end < result.length() || delim_idx == 4 || delim_idx == 5) {
284 
285  // Extract environment variable name
286  std::string name = result.substr(i_start, i_end-i_start);
287  size_t name_length = name.length();
288 
289  // Initialise pointer on environment variable
290  const char* env = NULL;
291 
292  // Handle ~
293  if (delim_idx == 5) {
294  if (name_length == 0) {
295  if ((env = std::getenv("HOME")) == NULL) {
296  struct passwd *pw = getpwuid(getuid());
297  if (pw != NULL) {
298  env = pw->pw_dir;
299  }
300  }
301  }
302  else {
303  if (name == "+") {
304  env = std::getenv("PWD");
305  }
306  else if (name == "-") {
307  env = std::getenv("OLDPWD");
308  }
309  else {
310  struct passwd *pw = getpwnam(name.c_str());
311  if (pw != NULL) {
312  env = pw->pw_dir;
313  }
314  }
315  }
316  }
317 
318  // ... otherwise get the environment variable
319  else {
320  env = std::getenv(name.c_str());
321  }
322 
323  // If the environment variable has been found then replace
324  // it by its value
325  if (env != NULL) {
326 
327  // Erase delimiters and environment variable
328  result.erase(index, begin_length+name_length+end_length);
329 
330  // Set replacement string and its length
331  std::string replace(env);
332  size_t replace_length = replace.length();
333 
334  // Insert replacement string
335  result.insert(index, replace);
336 
337  // Advance pointer
338  index += replace_length;
339 
340  } // endif: environment variable has been found
341 
342  // If no environment variable has been found then set
343  // index=i_end+1
344  else {
345  index = i_end + 1;
346  }
347 
348  } // endif: termination delimiter found
349 
350  // If no environment variable has been found then set index=i_end+1
351  else {
352  index = i_end + 1;
353  }
354 
355  } // endif: we found an environment variable delimiter
356 
357  // ... otherwise advance to next character
358  else {
359  index++;
360  }
361 
362  } // endwhile: looped over string
363 
364  // Return result
365  return result;
366 }
367 
368 
369 /***********************************************************************//**
370  * @brief Build file path from path name and file name
371  *
372  * @param[in] pathname Path name.
373  * @param[in] filename File name.
374  * @return File path.
375  *
376  * Builds a file path by combining the @p pathname and the @p filename
377  * following
378  *
379  * filepath = pathname/filename
380  *
381  * If @p pathname is an empty string, the method simply returns the
382  * @p filename.
383  ***************************************************************************/
384 std::string gammalib::filepath(const std::string& pathname,
385  const std::string& filename)
386 {
387  // Initialise filepath
388  std::string filepath;
389 
390  // If path name is empty, simply return the file name
391  if (pathname.empty()) {
392  filepath = filename;
393  }
394 
395  // ... otherwise combine both
396  else {
397  filepath = pathname + "/" + filename;
398  }
399 
400  // Return the file path
401  return filepath;
402 }
403 
404 
405 /***********************************************************************//**
406  * @brief Convert unsigned short integer value into string
407  *
408  * @param[in] value Unsigned short integer to be converted into string.
409  * @return String with unsigned short integer value.
410  ***************************************************************************/
411 std::string gammalib::str(const unsigned short int& value)
412 {
413  std::ostringstream s_value;
414  s_value << value;
415  return s_value.str();
416 }
417 
418 
419 /***********************************************************************//**
420  * @brief Convert unsigned integer value into string
421  *
422  * @param[in] value Unsigned integer to be converted into string.
423  * @return String with unsigned integer value.
424  ***************************************************************************/
425 std::string gammalib::str(const unsigned int& value)
426 {
427  std::ostringstream s_value;
428  s_value << value;
429  return s_value.str();
430 }
431 
432 
433 /***********************************************************************//**
434  * @brief Convert unsigned long integer value into string
435  *
436  * @param[in] value Unsigned long integer to be converted into string.
437  * @return String with unsigned long integer value.
438  ***************************************************************************/
439 std::string gammalib::str(const unsigned long int& value)
440 {
441  std::ostringstream s_value;
442  s_value << value;
443  return s_value.str();
444 }
445 
446 
447 /***********************************************************************//**
448  * @brief Convert unsigned long long integer value into string
449  *
450  * @param[in] value Unsigned long long integer to be converted into string.
451  * @return String with unsigned long long integer value.
452  ***************************************************************************/
453 std::string gammalib::str(const unsigned long long int& value)
454 {
455  std::ostringstream s_value;
456  s_value << value;
457  return s_value.str();
458 }
459 
460 
461 /***********************************************************************//**
462  * @brief Convert short integer value into string
463  *
464  * @param[in] value Short integer to be converted into string.
465  * @return String with short integer value.
466  ***************************************************************************/
467 std::string gammalib::str(const short int& value)
468 {
469  std::ostringstream s_value;
470  s_value << value;
471  return s_value.str();
472 }
473 
474 
475 /***********************************************************************//**
476  * @brief Convert integer value into string
477  *
478  * @param[in] value Integer to be converted into string.
479  * @return String with integer value.
480  ***************************************************************************/
481 std::string gammalib::str(const int& value)
482 {
483  std::ostringstream s_value;
484  s_value << value;
485  return s_value.str();
486 }
487 
488 
489 /***********************************************************************//**
490  * @brief Convert long integer value into string
491  *
492  * @param[in] value Long integer to be converted into string.
493  * @return String with long integer value.
494  ***************************************************************************/
495 std::string gammalib::str(const long int& value)
496 {
497  std::ostringstream s_value;
498  s_value << value;
499  return s_value.str();
500 }
501 
502 
503 /***********************************************************************//**
504  * @brief Convert long long integer value into string
505  *
506  * @param[in] value Long long integer to be converted into string.
507  * @return String with long long integer value.
508  ***************************************************************************/
509 std::string gammalib::str(const long long int& value)
510 {
511  std::ostringstream s_value;
512  s_value << value;
513  return s_value.str();
514 }
515 
516 
517 /***********************************************************************//**
518  * @brief Convert single precision value into string
519  *
520  * @param[in] value Single precision value to be converted into string.
521  * @param[in] precision Floating point precision.
522  * @return String with single precision value.
523  *
524  * Converts a single precision value into a string. Any positive
525  * @p precision argument specifies the exact number of digits after the
526  * comma.
527  ***************************************************************************/
528 std::string gammalib::str(const float& value, const int& precision)
529 {
530  // Allocate output stream
531  std::ostringstream s_value;
532 
533  // If specified then set the requested fixed point precision. Otherwise
534  // use a precision that should be sufficient for floating point values.
535  if (precision > 0) {
536  s_value.precision(precision);
537  s_value.setf(std::ios::fixed, std::ios::floatfield);
538  }
539  else {
540  s_value.precision(7);
541  }
542 
543  // Put floating point value in stream
544  s_value << value;
545 
546  // Convert to a string
547  std::string result = s_value.str();
548 
549  // Return result
550  return result;
551 }
552 
553 
554 /***********************************************************************//**
555  * @brief Convert double precision value into string
556  *
557  * @param[in] value Double precision value to be converted into string.
558  * @param[in] precision Floating point precision.
559  * @return String with double precision value.
560  *
561  * Converts a double precision value into a string. Any positive
562  * @p precision argument specifies the exact number of digits after the
563  * comma.
564  ***************************************************************************/
565 std::string gammalib::str(const double& value, const int& precision)
566 {
567  // Allocate output stream
568  std::ostringstream s_value;
569 
570  // If specified then set the requested fixed point precision. Otherwise
571  // use a precision that should be sufficient for floating point values.
572  if (precision > 0) {
573  s_value.precision(precision);
574  s_value.setf(std::ios::fixed, std::ios::floatfield);
575  }
576  else {
577  s_value.precision(15);
578  }
579 
580  // Put double precision floating point value in stream
581  s_value << value;
582 
583  // Convert to a string
584  std::string result = s_value.str();
585 
586  // Return result
587  return result;
588 }
589 
590 
591 /***********************************************************************//**
592  * @brief Convert complex value into string
593  *
594  * @param[in] value Complex value to be converted into string.
595  * @param[in] precision Floating point precision.
596  * @return String with complex value.
597  *
598  * Converts a complex value into a string. Any positive @p precision argument
599  * specifies the exact number of digits after the comma.
600  ***************************************************************************/
601 std::string gammalib::str(const std::complex<double>& value,
602  const int& precision)
603 {
604  // Allocate output stream
605  std::ostringstream s_value;
606 
607  // If specified then set the requested fixed point precision. Otherwise
608  // use a precision that should be sufficient for floating point values.
609  if (precision > 0) {
610  s_value.precision(precision);
611  s_value.setf(std::ios::fixed, std::ios::floatfield);
612  }
613  else {
614  s_value.precision(15);
615  }
616 
617  // Put double precision floating point value in stream
618  s_value << value.real();
619  if (value.imag() < 0.0) {
620  s_value << "-";
621  }
622  else {
623  s_value << "+";
624  }
625  s_value << std::abs(value.imag()) << "j";
626 
627  // Convert to a string
628  std::string result = s_value.str();
629 
630  // Return result
631  return result;
632 }
633 
634 
635 
636 /***********************************************************************//**
637  * @brief Convert string to C string
638  *
639  * @param[in] arg String to be converted.
640  * @return C string.
641  *
642  * Allocates a C string with the content of a C++ string.
643  ***************************************************************************/
644 char* gammalib::tochar(const std::string& arg)
645 {
646  // Allocate C string
647  char* str = new char[arg.length()+1];
648 
649  // Copy characters
650  for (std::size_t i = 0; i < arg.length(); ++i) {
651  str[i] = arg[i];
652  }
653 
654  // Set line end character
655  str[arg.length()] = '\0';
656 
657  // Return C string
658  return str;
659 }
660 
661 
662 /***********************************************************************//**
663  * @brief Convert string into short value
664  *
665  * @param[in] arg String to be converted.
666  * @return Short value.
667  ***************************************************************************/
668 short gammalib::toshort(const std::string& arg)
669 {
670  std::istringstream iss(arg);
671  short result;
672  iss >> std::dec >> result;
673  return result;
674 }
675 
676 
677 /***********************************************************************//**
678  * @brief Convert string into unsigned short value
679  *
680  * @param[in] arg String to be converted.
681  * @return Unsigned short value.
682  ***************************************************************************/
683 unsigned short gammalib::toushort(const std::string& arg)
684 {
685  std::istringstream iss(arg);
686  unsigned short result;
687  iss >> std::dec >> result;
688  return result;
689 }
690 
691 
692 /***********************************************************************//**
693  * @brief Convert string into integer value
694  *
695  * @param[in] arg String to be converted.
696  * @return Integer value.
697  ***************************************************************************/
698 int gammalib::toint(const std::string& arg)
699 {
700  std::istringstream iss(arg);
701  int result;
702  iss >> std::dec >> result;
703  return result;
704 }
705 
706 
707 /***********************************************************************//**
708  * @brief Convert string into unsigned integer value
709  *
710  * @param[in] arg String to be converted.
711  * @return Unsigned integer value.
712  ***************************************************************************/
713 unsigned int gammalib::touint(const std::string& arg)
714 {
715  std::istringstream iss(arg);
716  unsigned int result;
717  iss >> std::dec >> result;
718  return result;
719 }
720 
721 
722 /***********************************************************************//**
723  * @brief Convert string into long value
724  *
725  * @param[in] arg String to be converted.
726  * @return Long value.
727  ***************************************************************************/
728 long gammalib::tolong(const std::string& arg)
729 {
730  std::istringstream iss(arg);
731  long result;
732  iss >> std::dec >> result;
733  return result;
734 }
735 
736 
737 /***********************************************************************//**
738  * @brief Convert string into unsigned long value
739  *
740  * @param[in] arg String to be converted.
741  * @return Unsigned long value.
742  ***************************************************************************/
743 unsigned long gammalib::toulong(const std::string& arg)
744 {
745  std::istringstream iss(arg);
746  unsigned long result;
747  iss >> std::dec >> result;
748  return result;
749 }
750 
751 
752 /***********************************************************************//**
753  * @brief Convert string into long long value
754  *
755  * @param[in] arg String to be converted.
756  * @return Long long value.
757  ***************************************************************************/
758 long long gammalib::tolonglong(const std::string& arg)
759 {
760  std::istringstream iss(arg);
761  long long result;
762  iss >> std::dec >> result;
763  return result;
764 }
765 
766 
767 /***********************************************************************//**
768  * @brief Convert string into unsigned long long value
769  *
770  * @param[in] arg String to be converted.
771  * @return Unsigned long long value.
772  ***************************************************************************/
773 unsigned long long gammalib::toulonglong(const std::string& arg)
774 {
775  std::istringstream iss(arg);
776  unsigned long long result;
777  iss >> std::dec >> result;
778  return result;
779 }
780 
781 
782 /***********************************************************************//**
783  * @brief Convert string into single precision value
784  *
785  * @param[in] arg String to be converted.
786  * @return Single precision value.
787  ***************************************************************************/
788 float gammalib::tofloat(const std::string& arg)
789 {
790  std::istringstream iss(arg);
791  float result;
792  iss >> std::dec >> result;
793  return result;
794 }
795 
796 
797 /***********************************************************************//**
798  * @brief Convert string into double precision value
799  *
800  * @param[in] arg String to be converted.
801  * @return Double precision value.
802  ***************************************************************************/
803 double gammalib::todouble(const std::string& arg)
804 {
805  std::istringstream iss(arg);
806  double result;
807  iss >> std::dec >> result;
808  return result;
809 }
810 
811 
812 /***********************************************************************//**
813  * @brief Convert string to upper case
814  *
815  * @param[in] arg String to be converted to upper case.
816  * @return String converted to upper case.
817  ***************************************************************************/
818 std::string gammalib::toupper(const std::string& arg)
819 {
820  std::string s = arg;
821  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
822  return s;
823 }
824 
825 
826 /***********************************************************************//**
827  * @brief Convert string to lower case
828  *
829  * @param[in] arg String to be converted to upper case.
830  * @return String converted to lower case.
831  ***************************************************************************/
832 std::string gammalib::tolower(const std::string& arg)
833 {
834  std::string s = arg;
835  std::transform(s.begin(), s.end(), s.begin(), ::tolower);
836  return s;
837 }
838 
839 
840 /***********************************************************************//**
841  * @brief Split string
842  *
843  * @param[in] s String to be splitted.
844  * @param[in] sep Separator(s).
845  * @return Vector of split strings.
846  *
847  * Splits a string on the basis of one or multiple separator characters. The
848  * separator characters are provided by the @p sep argument. Subsequent
849  * separator characters that are not seperated by some other characters will
850  * lead to an empty string element, except for a blank separator where
851  * subsequent blanks are takens as a single separator. Below a few examples
852  * that illustrate how the function will split a given string.
853  *
854  * "Name;RA;DEC" => ["Name","RA","DEC"] (sep=";")
855  * "My house is red" => ["My","house","is","red"] (sep=" ")
856  * "IRF::FRONT" => ["IRF","","FRONT"] (sep=":")
857  * "Fields;RA,DEC,Flux" => ["Fields","RA","DEC","Flux"] (sep=";,")
858  * "Last;Field;" => ["Last","Field",""] (sep=";")
859  ***************************************************************************/
860 std::vector<std::string> gammalib::split(const std::string& s,
861  const std::string& sep)
862 {
863  // Allocate result string vector
864  std::vector<std::string> result;
865 
866  // Initialise counters
867  std::size_t pos = 0;
868  std::size_t len = s.length();
869 
870  // Loop over string
871  while (pos < len && pos != std::string::npos) {
872 
873  // Get index of first separator occurence and preset the length
874  // of the substring to the end of the string
875  std::size_t index = s.find_first_of(sep, pos);
876  std::size_t n = std::string::npos;
877 
878  // If we did not reach the end then compute now the length of the
879  // substring
880  if (index != std::string::npos) {
881  n = index-pos;
882  }
883 
884  // If we have no whitespace separator and the length of the
885  // substring is zero then push back an empty string. If the
886  // length of the substring is positive then push back the
887  // substring.
888  if (sep != " " && n == 0) {
889  result.push_back("");
890  }
891  else if (n > 0) {
892  result.push_back(s.substr(pos, n));
893  }
894 
895  // Go to the string position after the last separator
896  pos = (index != std::string::npos) ? index + 1 : std::string::npos;
897 
898  // If the position is pointing right beyong the last string
899  // character we terminated with a separator, hence we need to push
900  // back one more empty string before we leave
901  if (sep != " " && pos == len) {
902  result.push_back("");
903  }
904 
905  } // endwhile: there were still characters in the string
906 
907  // Return result
908  return result;
909 }
910 
911 
912 /***********************************************************************//**
913  * @brief Fill string with n strings of same type
914  *
915  * @param[in] s String to be filled.
916  * @param[in] n Number of fillings.
917  * @return Filled strings.
918  *
919  * Replicates a given string n time.
920  ***************************************************************************/
921 std::string gammalib::fill(const std::string& s, const int& n)
922 {
923  // Initialise result
924  std::string result = "";
925 
926  // Replicate string
927  for (int i = 0; i < n; ++i) {
928  result.append(s);
929  }
930 
931  // Return result
932  return result;
933 }
934 
935 
936 /***********************************************************************//**
937  * @brief Left justify string to achieve a length of n characters
938  *
939  * @param[in] s String to be centred.
940  * @param[in] n Requested total width.
941  * @param[in] c Fill character.
942  * @return Left justified string.
943  *
944  * Left justify string by adding whitespace to the right to achieve a length
945  * of n characters.
946  ***************************************************************************/
947 std::string gammalib::left(const std::string& s, const int& n, const char& c)
948 {
949  // Compute number of characters to fill right
950  int n_right = n - s.length();
951 
952  // Set result
953  std::string result = s + fill(std::string(1,c), n_right);
954 
955  // Return result
956  return result;
957 }
958 
959 
960 /***********************************************************************//**
961  * @brief Right justify string to achieve a length of n characters
962  *
963  * @param[in] s String to be centred.
964  * @param[in] n Requested total width.
965  * @param[in] c Fill character.
966  * @return Right justified string.
967  *
968  * Right justify string by adding whitespace to the left to achieve a length
969  * of n characters.
970  ***************************************************************************/
971 std::string gammalib::right(const std::string& s, const int& n, const char& c)
972 {
973  // Compute number of characters to fill right
974  int n_left = n - s.length();
975 
976  // Set result
977  std::string result = fill(std::string(1,c), n_left) + s;
978 
979  // Return result
980  return result;
981 }
982 
983 
984 /***********************************************************************//**
985  * @brief Centre string to achieve a length of n characters
986  *
987  * @param[in] s String to be centred.
988  * @param[in] n Requested total width.
989  * @param[in] c Left fill character.
990  * @return Centred string.
991  *
992  * Centre string by adding whitespace to the left and the right to achieve a
993  * length of n characters.
994  ***************************************************************************/
995 std::string gammalib::centre(const std::string& s, const int& n, const char& c)
996 {
997  // Compute number of characters to fill left and right
998  int n_right = (n-s.length()) / 2;
999  int n_left = n - s.length() - n_right;
1000 
1001  // Set result
1002  std::string result = fill(std::string(1,c), n_left) + s +
1003  fill(std::string(1,c), n_right);
1004 
1005  // Return result
1006  return result;
1007 }
1008 
1009 
1010 /***********************************************************************//**
1011  * @brief Convert string in parameter format
1012  *
1013  * @param[in] s String to be converted.
1014  * @param[in] indent Indentation of parameter.
1015  * @return Parameter string.
1016  *
1017  * Converts and string into the parameter format of type "s ......: " with a
1018  * total length of G_PARFORMAT_LENGTH.
1019  ***************************************************************************/
1020 std::string gammalib::parformat(const std::string& s, const int& indent)
1021 {
1022  // Compute number of characters to fill right. Do not clip the string if
1023  // it is too long since we do not want to loose information.
1024  int n_right = G_PARFORMAT_LENGTH - s.length() - 3 - indent;
1025 
1026  // Set result
1027  std::string result = " " + s + " " + fill(".", n_right) + ": ";
1028 
1029  // Return result
1030  return result;
1031 }
1032 
1033 
1034 /***********************************************************************//**
1035  * @brief Convert singular noun into number noun
1036  *
1037  * @param[in] noun Singular noun.
1038  * @param[in] number Number of instance of noun.
1039  * @return Converted noun.
1040  *
1041  * Converts a singular noun into a number noun by appending a "s" to the
1042  * noun if the @p number of the instances of the noun is not one.
1043  ***************************************************************************/
1044 std::string gammalib::number(const std::string& noun, const int& number)
1045 {
1046  // Copy input noun
1047  std::string result(noun);
1048 
1049  // Append "s" if number if not one
1050  if (number != 1) {
1051  result += "s";
1052  }
1053 
1054  // Return result
1055  return result;
1056 }
1057 
1058 
1059 /***********************************************************************//**
1060  * @brief Compute photon flux between two energies for a power law
1061  *
1062  * @param[in] emin Minimum energy.
1063  * @param[in] emax Maximum energy.
1064  * @param[in] epivot Pivot energy.
1065  * @param[in] gamma Spectral index.
1066  * @return Photon flux under power law.
1067  *
1068  * Analytically computes
1069  * \f[\int_{E_{\rm min}}^{E_{\rm max}}
1070  * \left( E/E_{\rm pivot} \right)^{\gamma} dE\f]
1071  * where
1072  * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum
1073  * energy, respectively, and
1074  * \f$E_{\rm pivot}\f$ is the pivot energy, and
1075  * \f$\gamma\f$ is the spectral index.
1076  ***************************************************************************/
1077 double gammalib::plaw_photon_flux(const double& emin, const double& emax,
1078  const double& epivot, const double& gamma)
1079 {
1080  // Initialise flux
1081  double flux = 0.0;
1082 
1083  // Continue only if emax > emin
1084  if (emax > emin) {
1085 
1086  // Compute photon flux. Computations dependend on the exponent. We
1087  // add here a kluge to assure numerical accuracy.
1088  double exponent = gamma + 1.0;
1089  if (std::abs(exponent) > 1.0e-11) {
1090  double xmin = emin / epivot;
1091  double xmax = emax / epivot;
1092  flux = epivot / exponent * (std::pow(xmax, exponent) -
1093  std::pow(xmin, exponent));
1094  }
1095  else {
1096  double ratio = emax / emin;
1097  flux = epivot * std::log(ratio);
1098  }
1099 
1100  } // endif: emax > emin
1101 
1102  // Return result
1103  return flux;
1104 }
1105 
1106 
1107 /***********************************************************************//**
1108  * @brief Compute energy flux between two energies for a power law
1109  *
1110  * @param[in] emin Minimum energy.
1111  * @param[in] emax Maximum energy.
1112  * @param[in] epivot Pivot energy.
1113  * @param[in] gamma Spectral index.
1114  * @return Energy flux under power law.
1115  *
1116  * Analytically computes
1117  * \f[\int_{E_{\rm min}}^{E_{\rm max}}
1118  * \left( E/E_{\rm pivot} \right)^{\gamma} E dE\f]
1119  * where
1120  * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum
1121  * energy, respectively, and
1122  * \f$E_{\rm pivot}\f$ is the pivot energy, and
1123  * \f$\gamma\f$ is the spectral index.
1124  ***************************************************************************/
1125 double gammalib::plaw_energy_flux(const double& emin, const double& emax,
1126  const double& epivot, const double& gamma)
1127 {
1128  // Initialise flux
1129  double flux = 0.0;
1130 
1131  // Continue only if emax > emin
1132  if (emax > emin) {
1133 
1134  // Compute energy flux. Computations dependend on the exponent. We
1135  // add here a kluge to assure numerical accuracy.
1136  double exponent = gamma + 2.0;
1137  double epivot2 = epivot * epivot;
1138  if (std::abs(exponent) > 1.0e-11) {
1139  double xmin = emin / epivot;
1140  double xmax = emax / epivot;
1141  flux = epivot2 / exponent * (std::pow(xmax, exponent) -
1142  std::pow(xmin, exponent));
1143  }
1144  else {
1145  double ratio = emax / emin;
1146  flux = epivot2 * (std::log(ratio));
1147  }
1148 
1149  } // endif: emax > emin
1150 
1151  // Return result
1152  return flux;
1153 }
1154 
1155 
1156 /***********************************************************************//**
1157  * @brief Computes log mean energy
1158  *
1159  * @param[in] a First energy.
1160  * @param[in] b Second energy.
1161  * @return Log mean energy.
1162  *
1163  * Computes the logarithmic mean energy
1164  * \f$10^{0.5 * (\log E_{\rm a} + \log E_{\rm b})}\f$
1165  * for two energies.
1166  ***************************************************************************/
1168 {
1169  // Compute logarithmic mean energy
1170  GEnergy elogmean;
1171  double eloga = a.log10MeV();
1172  double elogb = b.log10MeV();
1173  elogmean.MeV(std::pow(10.0, 0.5 * (eloga + elogb)));
1174 
1175  // Return
1176  return elogmean;
1177 }
1178 
1179 
1180 /***********************************************************************//**
1181  * @brief Checks if directory exists
1182  *
1183  * @param[in] dirname Directory name.
1184  * @return True if directory exists, false otherwise.
1185  *
1186  * Checks if a directory exists. The function expands any environment
1187  * variable prior to checking.
1188  ***************************************************************************/
1189 bool gammalib::dir_exists(const std::string& dirname)
1190 {
1191  // Initialise result
1192  bool result = false;
1193 
1194  // Allocate file information structure
1195  struct stat info;
1196 
1197  // Get file information structure
1198  int ret = stat(gammalib::expand_env(dirname).c_str(), &info);
1199 
1200  // Check if we have a directory
1201  if (ret == 0 && S_ISDIR(info.st_mode)) {
1202  result = true;
1203  }
1204 
1205  // Return result
1206  return result;
1207 }
1208 
1209 
1210 /***********************************************************************//**
1211  * @brief Checks if a substring is in a string
1212  *
1213  * @param[in] str String you want to search in.
1214  * @param[in] substring String you are looking for in @p str.
1215  * @return True if a string contains a sub string.
1216  *
1217  * Checks if substring is contained in str
1218  ***************************************************************************/
1219 bool gammalib::contains(const std::string& str, const std::string& substring)
1220 {
1221  // Initialise result
1222  bool result = false;
1223 
1224  // checks if substring is in str
1225  if (str.find(substring) != std::string::npos) {
1226  result = true;
1227  }
1228 
1229  // Return result
1230  return result;
1231 }
1232 
1233 
1234 /***********************************************************************//**
1235  * @brief Checks if a string is contained in a vector of strings
1236  *
1237  * @param[in] strings Vector of strings you want to search in.
1238  * @param[in] string string you are looking for in strings.
1239  * @return True if a string is contained a vector.
1240  *
1241  * Checks if a string is contained in a vector of strings
1242  ***************************************************************************/
1243 bool gammalib::contains(const std::vector<std::string> strings,
1244  const std::string& string)
1245 {
1246  // Compute result
1247  bool result = std::find(strings.begin(), strings.end(), string) !=
1248  strings.end();
1249 
1250  // Return result
1251  return result;
1252 }
1253 
1254 
1255 /***********************************************************************//**
1256  * @brief Emits warning
1257  *
1258  * @param[in] origin Name of method that emits warning.
1259  * @param[in] message Warning message.
1260  *
1261  * Writes a warning to the console.
1262  ***************************************************************************/
1263 void gammalib::warning(const std::string& origin,
1264  const std::string& message)
1265 {
1266  // Compile option: enable/disable warnings
1267  #if defined(G_WARNINGS)
1268 
1269  // Set warning message
1270  std::string warning = "+++ WARNING in " + origin + ": " + message;
1271 
1272  // Writes warning to the console
1273  std::cout << warning << std::endl;
1274 
1275  // End of compile option
1276  #endif
1277 
1278  // Return
1279  return;
1280 }
1281 
1282 
1283 /***********************************************************************//**
1284  * @brief Convert XML character references in string to characters
1285  *
1286  * @param[in] arg String containing XML character references.
1287  * @return String with character reference replaced by respective characters.
1288  *
1289  * Converts all character references found in a string in their respective
1290  * characters. For more information about XML character references read
1291  * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
1292  ***************************************************************************/
1293 std::string gammalib::xml2str(const std::string& arg)
1294 {
1295  // Initialise string
1296  std::string result;
1297 
1298  // Iitialise position, lenghts and flags
1299  size_t length = arg.length();
1300  size_t pos = 0;
1301  size_t start = 0;
1302  size_t stop = 0;
1303  size_t len = 0; // Length of string preceeding char. reference
1304  bool found = false;
1305 
1306  // Loop over string
1307  while (pos < length) {
1308 
1309  // If we have not yet found a character reference then search for
1310  // the next one. If we do not find one we break here.
1311  if (!found) {
1312  start = arg.find("&", pos);
1313  if (start != std::string::npos) {
1314  len = start - pos;
1315  pos = start;
1316  found = true;
1317  }
1318  else {
1319  break;
1320  }
1321  }
1322 
1323  // ... otherwise search for end of the actual character reference.
1324  // Throw an exception if no end is found.
1325  else {
1326  stop = arg.find(";", pos);
1327  if (stop != std::string::npos) {
1328 
1329  // First attach leading string to the result
1330  if (len > 0) {
1331  result += arg.substr(start-len, len);
1332  }
1333 
1334  // Next extract character reference
1335  std::string cref = arg.substr(start+1, stop-start-1);
1336  len = cref.length();
1337 
1338  // Check for a numerical character reference
1339  //TODO: Check that there are only valid characters in
1340  // numerical field
1341  if (len >= 2 && cref[0] == '#') {
1342  int number = -1;
1343  if (cref[1] == 'x') {
1344  number = (int)std::strtol(cref.substr(2,len-2).c_str(), NULL, 16);
1345  }
1346  else {
1347  number = toint(cref.substr(1,len-1));
1348  }
1349  if (number != -1) {
1350  result.push_back((char)number);
1351  }
1352  else {
1353  std::string msg = "Could not extract number from "
1354  "numerical character reference &"+
1355  cref+";";
1357  }
1358  }
1359 
1360  // ... otherwise check for a character entity reference
1361  // and push back the corresponding character to the result
1362  // string
1363  else {
1364  if (cref == "quot") {
1365  result.push_back((char)34);
1366  }
1367  else if (cref == "amp") {
1368  result.push_back((char)38);
1369  }
1370  else if (cref == "apos") {
1371  result.push_back((char)39);
1372  }
1373  else if (cref == "lt") {
1374  result.push_back((char)60);
1375  }
1376  else if (cref == "gt") {
1377  result.push_back((char)62);
1378  }
1379  else {
1380  std::string msg = "Unknown character entity reference "
1381  "&"+cref+"; encountered in XML string \""+
1382  arg+"\".";
1384  }
1385  }
1386 
1387  // Signal that we're done and that we search for the
1388  // next character reference
1389  found = false;
1390  pos = stop + 1;
1391 
1392  } // endif: end of character reference found
1393 
1394  // ... otherwise throw an exception
1395  else {
1396  std::string msg = "Missing ; character at end of character "
1397  "reference in XML string \""+arg+"\".";
1399  }
1400 
1401  } // endelse: search for end of character reference
1402 
1403  } // endwhile
1404 
1405  // Append any pending string to the result
1406  if (pos < length) {
1407  len = length - pos;
1408  result += arg.substr(pos, len);
1409  }
1410 
1411  // Return result
1412  return result;
1413 }
1414 
1415 
1416 /***********************************************************************//**
1417  * @brief Convert special characters in string to XML character references
1418  *
1419  * @param[in] arg String.
1420  * @return String with special characters replaced by character references.
1421  *
1422  * Converts all special characters found in a string into character
1423  * references. For more information about XML character references read
1424  * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
1425  ***************************************************************************/
1426 std::string gammalib::str2xml(const std::string& arg)
1427 {
1428  // Initialise string
1429  std::string result;
1430 
1431  // Loop over string
1432  for (int i = 0; i < arg.length(); ++i) {
1433 
1434  // Initialize string to add
1435  std::string character = arg.substr(i, 1);
1436 
1437  // Replace special characters
1438  if (character == "\"") {
1439  character = "&quot;";
1440  }
1441  else if (character == "&") {
1442  character = "&amp;";
1443  }
1444  else if (character == "'") {
1445  character = "&apos;";
1446  }
1447  else if (character == "<") {
1448  character = "&lt;";
1449  }
1450  else if (character == ">") {
1451  character = "&gt;";
1452  }
1453 
1454  // Append character
1455  result += character;
1456 
1457  }
1458 
1459  // Return result
1460  return result;
1461 }
1462 
1463 
1464 /***********************************************************************//**
1465  * @brief Checks if parameter with given name in XML element exists
1466  *
1467  * @param[in] xml XML element.
1468  * @param[in] name Parameter name.
1469  * @return True if parameter exists, false otherwise.
1470  *
1471  * Checks whether a parameter with given @p name exists in XML element.
1472  ***************************************************************************/
1473 bool gammalib::xml_has_par(const GXmlElement& xml, const std::string& name)
1474 {
1475  // Initialize flag
1476  bool found = false;
1477 
1478  // Search for parameter with given name
1479  for (int i = 0; i < xml.elements("parameter"); ++i) {
1480  const GXmlElement* element = xml.element("parameter", i);
1481  if (element->attribute("name") == name) {
1482  found = true;
1483  break;
1484  }
1485  }
1486 
1487  // Return
1488  return found;
1489 }
1490 
1491 
1492 /***********************************************************************//**
1493  * @brief Return pointer to parameter with given name in XML element
1494  *
1495  * @param[in] origin Method requesting parameter.
1496  * @param[in] xml XML element.
1497  * @param[in] name Parameter name.
1498  * @return Pointer to parameter XML element.
1499  *
1500  * @exception GException::invalid_value
1501  * Invalid XML format encountered.
1502  *
1503  * Returns pointer to parameter with given @p name in XML element. If the
1504  * @p name is not found, a parameter with the given @p name is added. In
1505  * that respect the function differs from xml_get_par which does not add a
1506  * parameter element.
1507  *
1508  * The function checks for multiple occurences of a parameter and throws an
1509  * exception in case that more than one parameter with a given name is found.
1510  ***************************************************************************/
1511 GXmlElement* gammalib::xml_need_par(const std::string& origin,
1512  GXmlElement& xml,
1513  const std::string& name)
1514 {
1515  // Initialize XML element pointer
1516  GXmlElement* par = NULL;
1517 
1518  // Number of elements
1519  int number = 0;
1520 
1521  // Search for parameter with given name
1522  for (int i = 0; i < xml.elements("parameter"); ++i) {
1523  GXmlElement* element = xml.element("parameter", i);
1524  if (element->attribute("name") == name) {
1525  par = element;
1526  number++;
1527  }
1528  }
1529 
1530  // Create parameter if none was found
1531  if (number == 0) {
1532  par = static_cast<GXmlElement*>(xml.append(GXmlElement("parameter name=\""+name+"\"")));
1533  number++;
1534  }
1535 
1536  // Check that there are no multiple parameters
1537  gammalib::xml_check_par(origin, name, number);
1538 
1539  // Return
1540  return par;
1541 }
1542 
1543 
1544 /***********************************************************************//**
1545  * @brief Return pointer to parameter with given name in XML element
1546  *
1547  * @param[in] origin Method requesting parameter.
1548  * @param[in] xml XML element.
1549  * @param[in] name Parameter name.
1550  * @return Pointer to parameter XML element.
1551  *
1552  * @exception GException::invalid_value
1553  * Invalid XML format encountered.
1554  *
1555  * Returns pointer to parameter with given @p name in XML element. The
1556  * function checks whether the parameter has been found and throws an
1557  * exception if no parameter or multiple occurences of a parameter with given
1558  * @p name are found.
1559  ***************************************************************************/
1560 const GXmlElement* gammalib::xml_get_par(const std::string& origin,
1561  const GXmlElement& xml,
1562  const std::string& name)
1563 {
1564  // Initialize XML element pointer
1565  const GXmlElement* par = NULL;
1566 
1567  // Number of elements
1568  int number = 0;
1569 
1570  // Search for parameter with given name
1571  for (int i = 0; i < xml.elements("parameter"); ++i) {
1572  const GXmlElement* element = xml.element("parameter", i);
1573  if (element->attribute("name") == name) {
1574  par = element;
1575  number++;
1576  }
1577  }
1578 
1579  // Check that there is at least one parameter and that there are no
1580  // multiple parameters
1581  gammalib::xml_check_par(origin, name, number);
1582 
1583  // Return
1584  return par;
1585 }
1586 
1587 
1588 /***********************************************************************//**
1589  * @brief Return attribute value for a given parameter in XML element
1590  *
1591  * @param[in] origin Method requesting parameter.
1592  * @param[in] xml XML element.
1593  * @param[in] name Parameter name.
1594  * @param[in] attribute Attribute name.
1595  * @return Value of attribute.
1596  *
1597  * @exception GException::invalid_value
1598  * Attribute not found.
1599  *
1600  * Returns the value of @p attribute of parameter @p name in XML element.
1601  * The function checks whether the parameter has been found and throws an
1602  * exception if no parameter or multiple occurences of a parameter with given
1603  * @p name are found. The function furthermore checks whether the attribute
1604  * exists.
1605  ***************************************************************************/
1606 std::string gammalib::xml_get_attr(const std::string& origin,
1607  const GXmlElement& xml,
1608  const std::string& name,
1609  const std::string& attribute)
1610 {
1611  // Initialise attribute value
1612  std::string value = "";
1613 
1614  // Get parameter
1615  const GXmlElement* par = gammalib::xml_get_par(origin, xml, name);
1616 
1617  // Throw an exception if a parameter has not the requested attribute
1618  if (!par->has_attribute(attribute)) {
1619  std::string msg = "Attribute \""+attribute+"\" not found in XML "
1620  "parameter \""+name+"\". Please verify the XML "
1621  "format.";
1622  throw GException::invalid_value(origin, msg);
1623  }
1624 
1625  // Extract attribute
1626  value = par->attribute(attribute);
1627 
1628  // Return attribute value
1629  return value;
1630 }
1631 
1632 
1633 /***********************************************************************//**
1634  * @brief Checks whether a parameter has occured once
1635  *
1636  * @param[in] origin Method performing the check.
1637  * @param[in] name Parameter name.
1638  * @param[in] number Number of occurences of parameter.
1639  *
1640  * @exception GException::invalid_value
1641  * Invalid XML format encountered.
1642  *
1643  * Throws an exception if a given parameter has not exactly occured once.
1644  * The exception text is adapted to the case that none or multiple parameters
1645  * have been found.
1646  ***************************************************************************/
1647 void gammalib::xml_check_par(const std::string& origin,
1648  const std::string& name,
1649  const int& number)
1650 {
1651  // Throw case dependent exception
1652  if (number < 1) {
1653  std::string msg = "Parameter \""+name+"\" not found in XML element."
1654  " Please verify the XML format.";
1655  throw GException::invalid_value(origin, msg);
1656  }
1657  else if (number > 1) {
1658  std::string msg = "Parameter \""+name+"\" found "+
1659  gammalib::str(number)+" times in XML element."
1660  " Please verify the XML format.";
1661  throw GException::invalid_value(origin, msg);
1662  }
1663 
1664  // Return
1665  return;
1666 }
1667 
1668 
1669 /***********************************************************************//**
1670  * @brief Expand file name provided as XML attribute for loading
1671  *
1672  * @param[in] xml XML element.
1673  * @param[in] filename File name.
1674  * @return Expanded file name.
1675  *
1676  * Expands file name provided as XML attribute for loading. If the file name
1677  * is not empty and has no path it is assumed that the file is located in the
1678  * same directory as the XML file, and the XML file access path is prepended
1679  * to the file name.
1680  ***************************************************************************/
1682  const std::string& filename)
1683 {
1684  // Set file name
1685  GFilename fname(filename);
1686 
1687  // If the file name is not empty and has no path we assume that the file
1688  // name is a relative file name with respect to the XML file access path
1689  // and we therefore prepend the XML file access path to the file name
1690  if (!fname.is_empty() && fname.path().length() == 0) {
1691  fname = xml.filename().path() + fname;
1692  }
1693 
1694  // Return file name
1695  return fname;
1696 }
1697 
1698 
1699 /***********************************************************************//**
1700  * @brief Reduce file name provided for writing as XML attribute
1701  *
1702  * @param[in] xml XML element.
1703  * @param[in] filename File name.
1704  * @return Reduced file name.
1705  *
1706  * Reduces file name provided for writing as XML attribute. If the file name
1707  * is not empty and has the same access path as the XML file it is assumed
1708  * that both files are located in the same directory, and the access path is
1709  * stripped from the file name.
1710  ***************************************************************************/
1712  const std::string& filename)
1713 {
1714  // Set file name
1715  GFilename fname(filename);
1716 
1717  // If the file name is not empty and has the same access path as the XML
1718  // file it is assumed that both files are located in the same directory,
1719  // and the access path is stripped from the file name.
1720  if (!fname.is_empty() && fname.path() == xml.filename().path()) {
1721  fname = fname.file();
1722  }
1723 
1724  // Return file name
1725  return fname;
1726 }
1727 
1728 
1729 /***********************************************************************//**
1730  * @brief Extract name / value pair from XML node
1731  *
1732  * @param[in] node Pointer to XML node.
1733  * @param[out] name Name string.
1734  * @param[out] value Value string.
1735  *
1736  * Extracts a name / value pair from a XML node. If the XML node pointer is
1737  * NULL, the name and value strings will be empty.
1738  ***************************************************************************/
1740  std::string& name,
1741  std::string& value)
1742 {
1743  // Clear name and value strings
1744  name.clear();
1745  value.clear();
1746 
1747  // Continue only if node is valid
1748  if (node != NULL) {
1749 
1750  // Get name node and extract text content
1751  const GXmlNode* ptr = node->element("name", 0);
1752  if (ptr != NULL) {
1753  const GXmlText* text = static_cast<const GXmlText*>((*ptr)[0]);
1754  if (text != NULL) {
1755  name = text->text();
1756  }
1757  }
1758 
1759  // Get value node and extract text content
1760  ptr = node->element("value", 0);
1761  if (ptr != NULL) {
1762  const GXmlText* text = static_cast<const GXmlText*>((*ptr)[0]);
1763  if (text != NULL) {
1764  value = text->text();
1765  }
1766  }
1767  }
1768 
1769  // Return
1770  return;
1771 }
1772 
1773 
1774 /***********************************************************************//**
1775  * @brief Checks whether a parameter has occured once
1776  *
1777  * @param[in] fd Socket file descriptor.
1778  * @param[out] buffer Buffer to hold data.
1779  * @param[in] len Maximum number of bytes to recv().
1780  * @param[in] flags Flags (as the fourth param to recv() ).
1781  * @param[in] timeout Timeout in milliseconds.
1782  * @return recv() error code, -2 == timeout
1783  *
1784  * This function implements the recv() function with a timeout. The timeout
1785  * is specified in milliseconds.
1786  ***************************************************************************/
1787 int gammalib::recv(int fd, char *buffer, int len, int flags, int timeout)
1788 {
1789  // Initialise error code with time out
1790  int error = -2;
1791 
1792  // Initialize the set
1793  fd_set readset;
1794  FD_ZERO(&readset);
1795  FD_SET(fd, &readset);
1796 
1797  // Initialize time out struct
1798  struct timeval tv;
1799  if (timeout >= 1000) {
1800  tv.tv_sec = timeout/1000;
1801  tv.tv_usec = 0;
1802  }
1803  else {
1804  tv.tv_sec = 0;
1805  tv.tv_usec = timeout*1000;
1806  }
1807 
1808  // select()
1809  int result = select(fd+1, &readset, NULL, NULL, &tv);
1810 
1811  // Check status
1812  if (result < 0) {
1813  error = -1;
1814  }
1815  else if (result > 0 && FD_ISSET(fd, &readset)) {
1816 
1817  // Initialise flags
1818  int iof = -1;
1819 
1820  // Set non-blocking mode
1821  if ((iof = fcntl(fd, F_GETFL, 0)) != -1) {
1822  fcntl(fd, F_SETFL, iof | O_NONBLOCK);
1823  }
1824 
1825  // Receive data
1826  result = ::recv(fd, buffer, len, flags);
1827 
1828  // Set as before
1829  if (iof != -1) {
1830  fcntl(fd, F_SETFL, iof);
1831  }
1832 
1833  // Set error
1834  error = result;
1835  }
1836 
1837  // Return error
1838  return error;
1839 }
Abstract XML node base class.
Definition: GXmlNode.hpp:57
bool contains(const std::string &str, const std::string &substring)
Checks if a substring is in a string.
Definition: GTools.cpp:1219
void xml_get_name_value_pair(const GXmlNode *node, std::string &name, std::string &value)
Extract name / value pair from XML node.
Definition: GTools.cpp:1739
std::string file(void) const
Return name of file.
Definition: GFilename.hpp:231
std::string replace_segment(const std::string &arg, const std::string &segment, const std::string &replacement)
Replace string segment in string.
Definition: GTools.cpp:159
std::string number(const std::string &noun, const int &number)
Convert singular noun into number noun.
Definition: GTools.cpp:1044
GFilename filename(void) const
Return filename of XML file.
Definition: GXmlNode.cpp:540
void xml_check_par(const std::string &origin, const std::string &name, const int &number)
Checks whether a parameter has occured once.
Definition: GTools.cpp:1647
Energy value class definition.
void warning(const std::string &origin, const std::string &message)
Emits warning.
Definition: GTools.cpp:1263
XML element node class interface definition.
GVector abs(const GVector &vector)
Computes absolute of vector elements.
Definition: GVector.cpp:1163
bool is_empty(void) const
Signal if filename is empty.
Definition: GFilename.hpp:160
XML element node class.
Definition: GXmlElement.hpp:47
#define G_XML2STRING
Definition: GTools.cpp:59
int recv(int fd, char *buffer, int len, int flags, int timeout)
Checks whether a parameter has occured once.
Definition: GTools.cpp:1787
std::string strip_chars(const std::string &arg, const std::string &chars)
Strip leading and trailing character from string.
Definition: GTools.cpp:85
std::vector< std::string > split(const std::string &s, const std::string &sep)
Split string.
Definition: GTools.cpp:860
double MeV(void) const
Return energy in MeV.
Definition: GEnergy.cpp:321
virtual int elements(void) const
Return number of GXMLElement children of node.
Definition: GXmlNode.cpp:580
Gammalib tools definition.
FITS file class interface definition.
long tolong(const std::string &arg)
Convert string into long value.
Definition: GTools.cpp:728
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition: GTools.cpp:71
GFilename xml_file_reduce(const GXmlElement &xml, const std::string &filename)
Reduce file name provided for writing as XML attribute.
Definition: GTools.cpp:1711
double plaw_energy_flux(const double &emin, const double &emax, const double &epivot, const double &gamma)
Compute energy flux between two energies for a power law.
Definition: GTools.cpp:1125
std::string centre(const std::string &s, const int &n, const char &c= ' ')
Centre string to achieve a length of n characters.
Definition: GTools.cpp:995
double log10MeV(void) const
Return log10 of energy in MeV.
Definition: GEnergy.cpp:423
std::string right(const std::string &s, const int &n, const char &c= ' ')
Right justify string to achieve a length of n characters.
Definition: GTools.cpp:971
std::string path(void) const
Return access path.
Definition: GFilename.hpp:217
const GXmlAttribute * attribute(const int &index) const
Return attribute.
short toshort(const std::string &arg)
Convert string into short value.
Definition: GTools.cpp:668
char * tochar(const std::string &arg)
Convert string to C string.
Definition: GTools.cpp:644
Filename class.
Definition: GFilename.hpp:62
std::string left(const std::string &s, const int &n, const char &c= ' ')
Left justify string to achieve a length of n characters.
Definition: GTools.cpp:947
bool has_attribute(const std::string &name) const
Check if element has a given attribute.
GXmlElement * xml_need_par(const std::string &origin, GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition: GTools.cpp:1511
XML text node class.
Definition: GXmlText.hpp:43
GVector log(const GVector &vector)
Computes natural logarithm of vector elements.
Definition: GVector.cpp:1184
const std::string & text(void) const
Return text.
Definition: GXmlText.hpp:97
bool dir_exists(const std::string &dirname)
Checks if directory exists.
Definition: GTools.cpp:1189
XML text node class interface definition.
unsigned long long toulonglong(const std::string &arg)
Convert string into unsigned long long value.
Definition: GTools.cpp:773
bool xml_has_par(const GXmlElement &xml, const std::string &name)
Checks if parameter with given name in XML element exists.
Definition: GTools.cpp:1473
std::string xml2str(const std::string &arg)
Convert XML character references in string to characters.
Definition: GTools.cpp:1293
long long tolonglong(const std::string &arg)
Convert string into long long value.
Definition: GTools.cpp:758
unsigned long toulong(const std::string &arg)
Convert string into unsigned long value.
Definition: GTools.cpp:743
std::string rstrip_chars(const std::string &arg, const std::string &chars)
Strip trailing character from string.
Definition: GTools.cpp:122
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition: GXmlNode.cpp:634
GVector pow(const GVector &vector, const double &power)
Computes tanh of vector elements.
Definition: GVector.cpp:1332
unsigned int touint(const std::string &arg)
Convert string into unsigned integer value.
Definition: GTools.cpp:713
unsigned short toushort(const std::string &arg)
Convert string into unsigned short value.
Definition: GTools.cpp:683
Exception handler interface definition.
std::string toupper(const std::string &s)
Convert string to upper case.
Definition: GTools.cpp:818
std::string tolower(const std::string &s)
Convert string to lower case.
Definition: GTools.cpp:832
std::string xml_get_attr(const std::string &origin, const GXmlElement &xml, const std::string &name, const std::string &attribute)
Return attribute value for a given parameter in XML element.
Definition: GTools.cpp:1606
std::string expand_env(const std::string &arg)
Expand environment variables in string.
Definition: GTools.cpp:205
int toint(const std::string &arg)
Convert string into integer value.
Definition: GTools.cpp:698
std::string filepath(const std::string &pathname, const std::string &filename)
Build file path from path name and file name.
Definition: GTools.cpp:384
virtual GXmlNode * append(const GXmlNode &node)
Append XML child node.
Definition: GXmlNode.cpp:284
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1020
std::string str2xml(const std::string &arg)
Convert special characters in string to XML character references.
Definition: GTools.cpp:1426
std::string fill(const std::string &s, const int &n)
Fill string with n strings of same type.
Definition: GTools.cpp:921
#define G_PARFORMAT_LENGTH
Definition: GTools.cpp:62
Abstract XML node base class interface definition.
const GXmlElement * xml_get_par(const std::string &origin, const GXmlElement &xml, const std::string &name)
Return pointer to parameter with given name in XML element.
Definition: GTools.cpp:1560
Filename class interface definition.
GEnergy elogmean(const GEnergy &a, const GEnergy &b)
Computes log mean energy.
Definition: GTools.cpp:1167
double todouble(const std::string &arg)
Convert string into double precision value.
Definition: GTools.cpp:803
Class that handles energies in a unit independent way.
Definition: GEnergy.hpp:48
double plaw_photon_flux(const double &emin, const double &emax, const double &epivot, const double &gamma)
Compute photon flux between two energies for a power law.
Definition: GTools.cpp:1077
float tofloat(const std::string &arg)
Convert string into single precision value.
Definition: GTools.cpp:788
GFilename xml_file_expand(const GXmlElement &xml, const std::string &filename)
Expand file name provided as XML attribute for loading.
Definition: GTools.cpp:1681
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:411