GammaLib  2.1.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-2022 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> // geteuid(), 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 <netinet/in.h> // struct sockaddr_in, struct sockaddr
39 #include <netdb.h> // struct hostent, gethostbyname
40 #include <pwd.h> // getpwuid()
41 #include <cmath>
42 #include <cfloat>
43 #include <cctype>
44 #include <ctime>
45 #include <cstdlib> // std::getenv() function
46 #include <cstring> // std::strlen() and std::memcpy functions
47 #include <iostream>
48 #include <sstream>
49 #include <algorithm>
50 #include <cstdio> // sprintf
51 #include "GTools.hpp"
52 #include "GException.hpp"
53 #include "GFits.hpp"
54 #include "GEnergy.hpp"
55 #include "GFilename.hpp"
56 #include "GMath.hpp"
57 #include "GXmlElement.hpp"
58 #include "GXmlNode.hpp"
59 #include "GXmlText.hpp"
60 
61 /* __ Compile options ____________________________________________________ */
62 //#define G_CHECK_FOR_NAN
63 //#define G_USE_CURL //!< Use curl in host_country()
64 
65 /* __ Function name definitions __________________________________________ */
66 #define G_XML2STRING "gammalib::xml2string(std::string&)"
67 #define G_HTTP_QUERY "gammalib::http_query(str::string&, std::string&)"
68 
69 /* __ Coding definitions _________________________________________________ */
70 #define G_PARFORMAT_LENGTH 29
71 #define G_CHAR_BUFFER 256
72 
73 
74 /***********************************************************************//**
75  * @brief Strip leading and trailing whitespace from string
76  *
77  * @param[in] arg String from which whitespace should be stripped.
78  * @return String with stripped whitespace.
79  ***************************************************************************/
80 std::string gammalib::strip_whitespace(const std::string& arg)
81 {
82  // Return result
83  return (strip_chars(arg, " "));
84 }
85 
86 
87 /***********************************************************************//**
88  * @brief Strip leading and trailing character from string
89  *
90  * @param[in] arg String from which character should be stripped.
91  * @param[in] chars Character(s) to be stripped.
92  * @return String with stripped characters.
93  ***************************************************************************/
94 std::string gammalib::strip_chars(const std::string& arg,
95  const std::string& chars)
96 {
97  // Initialise empty result string
98  std::string result;
99 
100  // Continue only if argument is not empty
101  if (!arg.empty()) {
102 
103  // Get start and stop
104  std::string::size_type start = arg.find_first_not_of(chars);
105  std::string::size_type stop = arg.find_last_not_of(chars);
106 
107  // Continue only if start and stop are valid
108  if (start != std::string::npos && stop != std::string::npos) {
109 
110  // Continue only if stop is larger then or equal to start
111  if (start <= stop) {
112  result = arg.substr(start, stop-start+1);
113  }
114 
115  } // endif: start and stop were valid
116 
117  } // endif: argument was not empty
118 
119  // Return result
120  return result;
121 }
122 
123 
124 /***********************************************************************//**
125  * @brief Strip trailing character from string
126  *
127  * @param[in] arg String from which character should be stripped.
128  * @param[in] chars Character(s) to be stripped.
129  * @return String with stripped characters.
130  ***************************************************************************/
131 std::string gammalib::rstrip_chars(const std::string& arg,
132  const std::string& chars)
133 {
134  // Initialise empty result string
135  std::string result;
136 
137  // Continue only if argument is not empty
138  if (!arg.empty()) {
139 
140  // Get stop
141  std::string::size_type stop = arg.find_last_not_of(chars);
142 
143  // Continue only if stop is valid
144  if (stop != std::string::npos) {
145  result = arg.substr(0, stop+1);
146  }
147 
148  } // endif: argument was not empty
149 
150  // Return result
151  return result;
152 }
153 
154 
155 /***********************************************************************//**
156  * @brief Replace string segment in string
157  *
158  * @param[in] arg String in which character segements are to be replaced
159  * @param[in] segment String segment to be replaced.
160  * @param[in] replacement Replacement string.
161  * @return String with replaced segements.
162  *
163  * Replaces string segments by a replacement string in a given string.
164  *
165  * If the input string @p arg is "Wonderful", the @p segment is "onder" and
166  * the @p replacement is "ish" the method will return "Wishful".
167  ***************************************************************************/
168 std::string gammalib::replace_segment(const std::string& arg,
169  const std::string& segment,
170  const std::string& replacement)
171 {
172  // Initialise result string by argument
173  std::string result = arg;
174 
175  // Initialise character pointer
176  std::string::size_type pos = 0;
177  std::string::size_type start = 0;
178 
179  // Loop over string
180  while (start != std::string::npos) {
181  start = result.find(segment, pos);
182  if (start != std::string::npos) {
183  result = result.replace(start, segment.length(), replacement);
184  pos = start + replacement.length();
185  }
186  }
187 
188  // Return result
189  return result;
190 }
191 
192 
193 /***********************************************************************//**
194  * @brief Expand environment variables in string
195  *
196  * @param[in] arg String.
197  * @return String with expected environment variables.
198  *
199  * Expands any environment variable that is found in a string. Valid
200  * delimiters for environment variables are $ENV{<name>}, $ENV(<name>),
201  * ${<name>}, $(<name>) and $<name> (in the last case the terminating
202  * delimiter is either a / or a blank character or the end of the string).
203  * Environment variables occuring within single quotes (') are ignored.
204  * Environment variables that do not exist will be kept as specified.
205  *
206  * The method also replaces ~ or ~user by the user's home directory, ~+
207  * by the value of the PWD environment variable and ~- by the value of the
208  * OLDPWD variable. If the user or the PWD or OLDPWD variable are not found,
209  * no replacement is done.
210  *
211  * This function has been inspired by the function ape_util_expand_env_var
212  * from ape_util.c in the ape software developed at HEASARC.
213  ***************************************************************************/
214 std::string gammalib::expand_env(const std::string& arg)
215 {
216  // Set environment variable delimiters
217  static const char* begin_delim[] = { "$ENV{", "$ENV(", "${", "$(", "$", "~" };
218  static const char* end_delim[] = { "}", ")", "}", ")", "/", "/" };
219  static const int num_delim = 6;
220 
221  // Initialise result with argument
222  std::string result = arg;
223 
224  // Initialise parse parameters
225  size_t index = 0;
226  bool in_quote = false;
227 
228  // Loop over string
229  while (index < result.length()) {
230 
231  // If we have an escaped character then skip the current character
232  // and the next one
233  if (result[index] == '\\') {
234  index += 2;
235  continue;
236  }
237 
238  // If we have a single quote then toggle the quote state
239  if (result[index] == '\'') {
240  in_quote = !in_quote;
241  index++;
242  continue;
243  }
244 
245  // Don't expand environment variables inside single quotes. Note
246  // that double quotes are ok.
247  if (in_quote) {
248  index++;
249  continue;
250  }
251 
252  // Find delimiter which indicates beginning of an environment variable
253  size_t begin_length = 0;
254  int delim_idx = 0;
255  for (; delim_idx < num_delim; ++delim_idx) {
256  size_t len = std::strlen(begin_delim[delim_idx]);
257  if (result.compare(index, len, begin_delim[delim_idx]) == 0) {
258  begin_length = len;
259  break;
260  }
261  }
262 
263  // If we found a delimiter then process the environment variable
264  if (begin_length > 0) {
265 
266  // Search for the termination delimiter of the environment
267  // variable. There is a special case for delimiters 4 and 5:
268  // It has always an end_length of zero as the / is not a real
269  // delimiter, but just an indicator that the environment variable
270  // ends. Another indicator is a blank. If the end of the
271  // string has been reached this is also acceptable.
272  size_t i_start = index + begin_length;
273  size_t i_end = i_start;
274  size_t end_length = 0;
275  if (delim_idx == 4 || delim_idx == 5) {
276  while (i_end < result.length() &&
277  result.compare(i_end, 1, "/") != 0 &&
278  result.compare(i_end, 1, " ") != 0) {
279  i_end++;
280  }
281  }
282  else {
283  end_length = std::strlen(end_delim[delim_idx]);
284  while (i_end < result.length() &&
285  result.compare(i_end, end_length, end_delim[delim_idx]) != 0) {
286  i_end++;
287  }
288  }
289 
290  // If termination delimiter has been found then expand the
291  // environment variable
292  if (i_end < result.length() || delim_idx == 4) {
293 
294  // Extract environment variable name
295  std::string name = result.substr(i_start, i_end-i_start);
296  size_t name_length = name.length();
297 
298  // Initialise pointer on environment variable
299  const char* env = NULL;
300 
301  // Handle ~
302  if (delim_idx == 5) {
303  if (name_length == 0) {
304  if ((env = std::getenv("HOME")) == NULL) {
305  struct passwd *pw = getpwuid(getuid());
306  if (pw != NULL) {
307  env = pw->pw_dir;
308  }
309  }
310  }
311  else {
312  if (name == "+") {
313  env = std::getenv("PWD");
314  }
315  else if (name == "-") {
316  env = std::getenv("OLDPWD");
317  }
318  else {
319  struct passwd *pw = getpwnam(name.c_str());
320  if (pw != NULL) {
321  env = pw->pw_dir;
322  }
323  }
324  }
325  }
326 
327  // ... otherwise get the environment variable
328  else {
329  env = std::getenv(name.c_str());
330  }
331 
332  // If the environment variable has been found then replace
333  // it by its value
334  if (env != NULL) {
335 
336  // Erase delimiters and environment variable
337  result.erase(index, begin_length+name_length+end_length);
338 
339  // Set replacement string and its length
340  std::string replace(env);
341  size_t replace_length = replace.length();
342 
343  // Insert replacement string
344  result.insert(index, replace);
345 
346  // Advance pointer
347  index += replace_length;
348 
349  } // endif: environment variable has been found
350 
351  // If no environment variable has been found then set
352  // index=i_end+1
353  else {
354  index = i_end + 1;
355  }
356 
357  } // endif: termination delimiter found
358 
359  // If no environment variable has been found then set index=i_end+1
360  else {
361  index = i_end + 1;
362  }
363 
364  } // endif: we found an environment variable delimiter
365 
366  // ... otherwise advance to next character
367  else {
368  index++;
369  }
370 
371  } // endwhile: looped over string
372 
373  // Return result
374  return result;
375 }
376 
377 
378 /***********************************************************************//**
379  * @brief Build file path from path name and file name
380  *
381  * @param[in] pathname Path name.
382  * @param[in] filename File name.
383  * @return File path.
384  *
385  * Builds a file path by combining the @p pathname and the @p filename
386  * following
387  *
388  * filepath = pathname/filename
389  *
390  * If @p pathname is an empty string, the method simply returns the
391  * @p filename.
392  ***************************************************************************/
393 std::string gammalib::filepath(const std::string& pathname,
394  const std::string& filename)
395 {
396  // Initialise filepath
397  std::string filepath;
398 
399  // If path name is empty, simply return the file name
400  if (pathname.empty()) {
401  filepath = filename;
402  }
403 
404  // ... otherwise combine both
405  else {
406  filepath = pathname + "/" + filename;
407  }
408 
409  // Return the file path
410  return filepath;
411 }
412 
413 
414 /***********************************************************************//**
415  * @brief Return temporary file name
416  *
417  * @return Temporary file name.
418  *
419  * Returns a temporary file name.
420  ***************************************************************************/
421 std::string gammalib::tmpnam(void)
422 {
423  // Set default temporary directory
424  char default_tmpdir[] = "/tmp";
425 
426  // Get pointer to name of temporary directory by searching various
427  // possible environment variables
428  char *tmpdir = NULL;
429  if ((tmpdir = std::getenv("TEMP")) == NULL) {
430  if ((tmpdir = std::getenv("TMP")) == NULL) {
431  if ((tmpdir = std::getenv("TMPDIR")) == NULL) {
432  tmpdir = default_tmpdir;
433  }
434  }
435  }
436 
437  // Allocate empty filename
438  char filename[256];
439  filename[0] = '\0';
440 
441  // Combine temporary directory with temporary filename
442  strcat(filename, tmpdir);
443  strcat(filename, "/gammalibXXXXXX");
444 
445  // Create temporary file
446  int fd = mkstemp(filename);
447  std::string tmpname(filename);
448  close(fd);
449  unlink(filename);
450 
451  // Return temporary file name
452  return tmpname;
453 }
454 
455 
456 /***********************************************************************//**
457  * @brief Return value of environment variable
458  *
459  * @param[in] arg Environment variable
460  * @return Value of environment variable.
461  *
462  * Returns the value of an environment variable @p arg. If the environment
463  * variable is not found an empty string will be returned.
464  ***************************************************************************/
465 std::string gammalib::getenv(const std::string& arg)
466 {
467  // Initialise environment variable
468  std::string env;
469 
470  // Get pointer to environment variable string
471  const char* ptr = std::getenv(arg.c_str());
472 
473  // If pointer is not NULL then extract value of environment variable
474  if (ptr != NULL) {
475  env = std::string(ptr);
476  }
477 
478  // Return environment variable
479  return env;
480 }
481 
482 
483 /***********************************************************************//**
484  * @brief Convert unsigned short integer value into string
485  *
486  * @param[in] value Unsigned short integer to be converted into string.
487  * @return String with unsigned short integer value.
488  ***************************************************************************/
489 std::string gammalib::str(const unsigned short int& value)
490 {
491  std::ostringstream s_value;
492  s_value << value;
493  return s_value.str();
494 }
495 
496 
497 /***********************************************************************//**
498  * @brief Convert unsigned integer value into string
499  *
500  * @param[in] value Unsigned integer to be converted into string.
501  * @return String with unsigned integer value.
502  ***************************************************************************/
503 std::string gammalib::str(const unsigned int& value)
504 {
505  std::ostringstream s_value;
506  s_value << value;
507  return s_value.str();
508 }
509 
510 
511 /***********************************************************************//**
512  * @brief Convert unsigned long integer value into string
513  *
514  * @param[in] value Unsigned long integer to be converted into string.
515  * @return String with unsigned long integer value.
516  ***************************************************************************/
517 std::string gammalib::str(const unsigned long int& value)
518 {
519  std::ostringstream s_value;
520  s_value << value;
521  return s_value.str();
522 }
523 
524 
525 /***********************************************************************//**
526  * @brief Convert unsigned long long integer value into string
527  *
528  * @param[in] value Unsigned long long integer to be converted into string.
529  * @return String with unsigned long long integer value.
530  ***************************************************************************/
531 std::string gammalib::str(const unsigned long long int& value)
532 {
533  std::ostringstream s_value;
534  s_value << value;
535  return s_value.str();
536 }
537 
538 
539 /***********************************************************************//**
540  * @brief Convert short integer value into string
541  *
542  * @param[in] value Short integer to be converted into string.
543  * @return String with short integer value.
544  ***************************************************************************/
545 std::string gammalib::str(const short int& value)
546 {
547  std::ostringstream s_value;
548  s_value << value;
549  return s_value.str();
550 }
551 
552 
553 /***********************************************************************//**
554  * @brief Convert integer value into string
555  *
556  * @param[in] value Integer to be converted into string.
557  * @param[in] fmt Format string.
558  * @return String with integer value.
559  ***************************************************************************/
560 std::string gammalib::str(const int& value, const std::string& fmt)
561 {
562  // Allocate character buffer
563  char buffer[G_CHAR_BUFFER];
564 
565  // Put integer into buffer
566  sprintf(buffer, fmt.c_str(), value);
567 
568  // Convert buffer into string
569  std::string str_buffer(buffer);
570 
571  // Return string buffer
572  return str_buffer;
573 }
574 
575 
576 /***********************************************************************//**
577  * @brief Convert long integer value into string
578  *
579  * @param[in] value Long integer to be converted into string.
580  * @return String with long integer value.
581  ***************************************************************************/
582 std::string gammalib::str(const long int& value)
583 {
584  std::ostringstream s_value;
585  s_value << value;
586  return s_value.str();
587 }
588 
589 
590 /***********************************************************************//**
591  * @brief Convert long long integer value into string
592  *
593  * @param[in] value Long long integer to be converted into string.
594  * @return String with long long integer value.
595  ***************************************************************************/
596 std::string gammalib::str(const long long int& value)
597 {
598  std::ostringstream s_value;
599  s_value << value;
600  return s_value.str();
601 }
602 
603 
604 /***********************************************************************//**
605  * @brief Convert single precision value into string
606  *
607  * @param[in] value Single precision value to be converted into string.
608  * @param[in] precision Floating point precision.
609  * @return String with single precision value.
610  *
611  * Converts a single precision value into a string. Any positive
612  * @p precision argument specifies the exact number of digits after the
613  * comma.
614  ***************************************************************************/
615 std::string gammalib::str(const float& value, const int& precision)
616 {
617  // Allocate output stream
618  std::ostringstream s_value;
619 
620  // If specified then set the requested fixed point precision. Otherwise
621  // use a precision that should be sufficient for floating point values.
622  if (precision > 0) {
623  s_value.precision(precision);
624  s_value.setf(std::ios::fixed, std::ios::floatfield);
625  }
626  else {
627  s_value.precision(7);
628  }
629 
630  // Put floating point value in stream
631  s_value << value;
632 
633  // Convert to a string
634  std::string result = s_value.str();
635 
636  // Return result
637  return result;
638 }
639 
640 
641 /***********************************************************************//**
642  * @brief Convert double precision value into string
643  *
644  * @param[in] value Double precision value to be converted into string.
645  * @param[in] precision Floating point precision.
646  * @return String with double precision value.
647  *
648  * Converts a double precision value into a string. Any positive
649  * @p precision argument specifies the exact number of digits after the
650  * comma.
651  ***************************************************************************/
652 std::string gammalib::str(const double& value, const int& precision)
653 {
654  // Allocate output stream
655  std::ostringstream s_value;
656 
657  // If specified then set the requested fixed point precision. Otherwise
658  // use a precision that should be sufficient for floating point values.
659  if (precision > 0) {
660  s_value.precision(precision);
661  s_value.setf(std::ios::fixed, std::ios::floatfield);
662  }
663  else {
664  s_value.precision(15);
665  }
666 
667  // Put double precision floating point value in stream
668  s_value << value;
669 
670  // Convert to a string
671  std::string result = s_value.str();
672 
673  // Return result
674  return result;
675 }
676 
677 
678 /***********************************************************************//**
679  * @brief Convert complex value into string
680  *
681  * @param[in] value Complex value to be converted into string.
682  * @param[in] precision Floating point precision.
683  * @return String with complex value.
684  *
685  * Converts a complex value into a string. Any positive @p precision argument
686  * specifies the exact number of digits after the comma.
687  ***************************************************************************/
688 std::string gammalib::str(const std::complex<double>& value,
689  const int& precision)
690 {
691  // Allocate output stream
692  std::ostringstream s_value;
693 
694  // If specified then set the requested fixed point precision. Otherwise
695  // use a precision that should be sufficient for floating point values.
696  if (precision > 0) {
697  s_value.precision(precision);
698  s_value.setf(std::ios::fixed, std::ios::floatfield);
699  }
700  else {
701  s_value.precision(15);
702  }
703 
704  // Put double precision floating point value in stream
705  s_value << value.real();
706  if (value.imag() < 0.0) {
707  s_value << "-";
708  }
709  else {
710  s_value << "+";
711  }
712  s_value << std::abs(value.imag()) << "j";
713 
714  // Convert to a string
715  std::string result = s_value.str();
716 
717  // Return result
718  return result;
719 }
720 
721 
722 /***********************************************************************//**
723  * @brief Return current date
724  *
725  * Returns the current date as string in the format yyyy-mm-ddThh:mm:ss.
726  ***************************************************************************/
727 std::string gammalib::strdate(void)
728 {
729  // Allocate variables
730  struct std::tm timeStruct;
731  std::time_t now;
732  char buffer[100];
733 
734  // Get time
735  now = std::time(NULL);
736  #ifdef HAVE_GMTIME_R
737  std::gmtime_r(&now, &timeStruct);
738  #else
739  std::memcpy(&timeStruct, gmtime(&now), sizeof(struct tm));
740  #endif
741 
742  // Write message type, time and task name to buffer
743  std::sprintf(buffer, "%04d-%02d-%02dT%02d:%02d:%02d",
744  timeStruct.tm_year + 1900,
745  timeStruct.tm_mon + 1,
746  timeStruct.tm_mday,
747  timeStruct.tm_hour,
748  timeStruct.tm_min,
749  timeStruct.tm_sec);
750 
751  // Build string from buffer
752  std::string date = buffer;
753 
754  // Return date
755  return date;
756 }
757 
758 
759 /***********************************************************************//**
760  * @brief Convert string to C string
761  *
762  * @param[in] arg String to be converted.
763  * @return C string.
764  *
765  * Allocates a C string with the content of a C++ string.
766  ***************************************************************************/
767 char* gammalib::tochar(const std::string& arg)
768 {
769  // Allocate C string
770  char* str = new char[arg.length()+1];
771 
772  // Copy characters
773  for (std::size_t i = 0; i < arg.length(); ++i) {
774  str[i] = arg[i];
775  }
776 
777  // Set line end character
778  str[arg.length()] = '\0';
779 
780  // Return C string
781  return str;
782 }
783 
784 
785 /***********************************************************************//**
786  * @brief Convert string into short value
787  *
788  * @param[in] arg String to be converted.
789  * @return Short value.
790  ***************************************************************************/
791 short gammalib::toshort(const std::string& arg)
792 {
793  std::istringstream iss(arg);
794  short result;
795  iss >> std::dec >> result;
796  return result;
797 }
798 
799 
800 /***********************************************************************//**
801  * @brief Convert string into unsigned short value
802  *
803  * @param[in] arg String to be converted.
804  * @return Unsigned short value.
805  ***************************************************************************/
806 unsigned short gammalib::toushort(const std::string& arg)
807 {
808  std::istringstream iss(arg);
809  unsigned short result;
810  iss >> std::dec >> result;
811  return result;
812 }
813 
814 
815 /***********************************************************************//**
816  * @brief Convert string into integer value
817  *
818  * @param[in] arg String to be converted.
819  * @return Integer value.
820  ***************************************************************************/
821 int gammalib::toint(const std::string& arg)
822 {
823  std::istringstream iss(arg);
824  int result;
825  iss >> std::dec >> result;
826  return result;
827 }
828 
829 
830 /***********************************************************************//**
831  * @brief Convert string into unsigned integer value
832  *
833  * @param[in] arg String to be converted.
834  * @return Unsigned integer value.
835  ***************************************************************************/
836 unsigned int gammalib::touint(const std::string& arg)
837 {
838  std::istringstream iss(arg);
839  unsigned int result;
840  iss >> std::dec >> result;
841  return result;
842 }
843 
844 
845 /***********************************************************************//**
846  * @brief Convert string into long value
847  *
848  * @param[in] arg String to be converted.
849  * @return Long value.
850  ***************************************************************************/
851 long gammalib::tolong(const std::string& arg)
852 {
853  std::istringstream iss(arg);
854  long result;
855  iss >> std::dec >> result;
856  return result;
857 }
858 
859 
860 /***********************************************************************//**
861  * @brief Convert string into unsigned long value
862  *
863  * @param[in] arg String to be converted.
864  * @return Unsigned long value.
865  ***************************************************************************/
866 unsigned long gammalib::toulong(const std::string& arg)
867 {
868  std::istringstream iss(arg);
869  unsigned long result;
870  iss >> std::dec >> result;
871  return result;
872 }
873 
874 
875 /***********************************************************************//**
876  * @brief Convert string into long long value
877  *
878  * @param[in] arg String to be converted.
879  * @return Long long value.
880  ***************************************************************************/
881 long long gammalib::tolonglong(const std::string& arg)
882 {
883  std::istringstream iss(arg);
884  long long result;
885  iss >> std::dec >> result;
886  return result;
887 }
888 
889 
890 /***********************************************************************//**
891  * @brief Convert string into unsigned long long value
892  *
893  * @param[in] arg String to be converted.
894  * @return Unsigned long long value.
895  ***************************************************************************/
896 unsigned long long gammalib::toulonglong(const std::string& arg)
897 {
898  std::istringstream iss(arg);
899  unsigned long long result;
900  iss >> std::dec >> result;
901  return result;
902 }
903 
904 
905 /***********************************************************************//**
906  * @brief Convert string into single precision value
907  *
908  * @param[in] arg String to be converted.
909  * @return Single precision value.
910  ***************************************************************************/
911 float gammalib::tofloat(const std::string& arg)
912 {
913  std::istringstream iss(arg);
914  float result;
915  iss >> std::dec >> result;
916  return result;
917 }
918 
919 
920 /***********************************************************************//**
921  * @brief Convert string into double precision value
922  *
923  * @param[in] arg String to be converted.
924  * @return Double precision value.
925  ***************************************************************************/
926 double gammalib::todouble(const std::string& arg)
927 {
928  std::istringstream iss(arg);
929  double result;
930  iss >> std::dec >> result;
931  return result;
932 }
933 
934 
935 /***********************************************************************//**
936  * @brief Convert string to upper case
937  *
938  * @param[in] arg String to be converted to upper case.
939  * @return String converted to upper case.
940  ***************************************************************************/
941 std::string gammalib::toupper(const std::string& arg)
942 {
943  std::string s = arg;
944  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
945  return s;
946 }
947 
948 
949 /***********************************************************************//**
950  * @brief Convert string to lower case
951  *
952  * @param[in] arg String to be converted to upper case.
953  * @return String converted to lower case.
954  ***************************************************************************/
955 std::string gammalib::tolower(const std::string& arg)
956 {
957  std::string s = arg;
958  std::transform(s.begin(), s.end(), s.begin(), ::tolower);
959  return s;
960 }
961 
962 
963 /***********************************************************************//**
964  * @brief Split string
965  *
966  * @param[in] s String to be splitted.
967  * @param[in] sep Separator(s).
968  * @return Vector of split strings.
969  *
970  * Splits a string on the basis of one or multiple separator characters. The
971  * separator characters are provided by the @p sep argument. Subsequent
972  * separator characters that are not seperated by some other characters will
973  * lead to an empty string element, except for a blank separator where
974  * subsequent blanks are takens as a single separator. Below a few examples
975  * that illustrate how the function will split a given string.
976  *
977  * "Name;RA;DEC" => ["Name","RA","DEC"] (sep=";")
978  * "My house is red" => ["My","house","is","red"] (sep=" ")
979  * "IRF::FRONT" => ["IRF","","FRONT"] (sep=":")
980  * "Fields;RA,DEC,Flux" => ["Fields","RA","DEC","Flux"] (sep=";,")
981  * "Last;Field;" => ["Last","Field",""] (sep=";")
982  ***************************************************************************/
983 std::vector<std::string> gammalib::split(const std::string& s,
984  const std::string& sep)
985 {
986  // Allocate result string vector
987  std::vector<std::string> result;
988 
989  // Initialise counters
990  std::size_t pos = 0;
991  std::size_t len = s.length();
992 
993  // Loop over string
994  while (pos < len && pos != std::string::npos) {
995 
996  // Get index of first separator occurence and preset the length
997  // of the substring to the end of the string
998  std::size_t index = s.find_first_of(sep, pos);
999  std::size_t n = std::string::npos;
1000 
1001  // If we did not reach the end then compute now the length of the
1002  // substring
1003  if (index != std::string::npos) {
1004  n = index-pos;
1005  }
1006 
1007  // If we have no whitespace separator and the length of the
1008  // substring is zero then push back an empty string. If the
1009  // length of the substring is positive then push back the
1010  // substring.
1011  if (sep != " " && n == 0) {
1012  result.push_back("");
1013  }
1014  else if (n > 0) {
1015  result.push_back(s.substr(pos, n));
1016  }
1017 
1018  // Go to the string position after the last separator
1019  pos = (index != std::string::npos) ? index + 1 : std::string::npos;
1020 
1021  // If the position is pointing right beyong the last string
1022  // character we terminated with a separator, hence we need to push
1023  // back one more empty string before we leave
1024  if (sep != " " && pos == len) {
1025  result.push_back("");
1026  }
1027 
1028  } // endwhile: there were still characters in the string
1029 
1030  // Return result
1031  return result;
1032 }
1033 
1034 
1035 /***********************************************************************//**
1036  * @brief Fill string with n strings of same type
1037  *
1038  * @param[in] s String to be filled.
1039  * @param[in] n Number of fillings.
1040  * @return Filled strings.
1041  *
1042  * Replicates a given string n time.
1043  ***************************************************************************/
1044 std::string gammalib::fill(const std::string& s, const int& n)
1045 {
1046  // Initialise result
1047  std::string result = "";
1048 
1049  // Replicate string
1050  for (int i = 0; i < n; ++i) {
1051  result.append(s);
1052  }
1053 
1054  // Return result
1055  return result;
1056 }
1057 
1058 
1059 /***********************************************************************//**
1060  * @brief Left justify string to achieve a length of n characters
1061  *
1062  * @param[in] s String to be left justified.
1063  * @param[in] n Requested total width.
1064  * @param[in] c Fill character.
1065  * @return Left justified string.
1066  *
1067  * Left justify string by adding @p c to the right to achieve a length of
1068  * @p n characters.
1069  ***************************************************************************/
1070 std::string gammalib::left(const std::string& s, const int& n, const char& c)
1071 {
1072  // Compute number of characters to fill right
1073  int n_right = n - s.length();
1074 
1075  // Set result
1076  std::string result = s + fill(std::string(1,c), n_right);
1077 
1078  // Return result
1079  return result;
1080 }
1081 
1082 
1083 /***********************************************************************//**
1084  * @brief Right justify string to achieve a length of n characters
1085  *
1086  * @param[in] s String to be right justified.
1087  * @param[in] n Requested total width.
1088  * @param[in] c Fill character.
1089  * @return Right justified string.
1090  *
1091  * Right justify string by adding @p c to the left to achieve a length of
1092  * @p n characters.
1093  ***************************************************************************/
1094 std::string gammalib::right(const std::string& s, const int& n, const char& c)
1095 {
1096  // Compute number of characters to fill right
1097  int n_left = n - s.length();
1098 
1099  // Set result
1100  std::string result = fill(std::string(1,c), n_left) + s;
1101 
1102  // Return result
1103  return result;
1104 }
1105 
1106 
1107 /***********************************************************************//**
1108  * @brief Centre string to achieve a length of n characters
1109  *
1110  * @param[in] s String to be centred.
1111  * @param[in] n Requested total width.
1112  * @param[in] c Fill character.
1113  * @return Centred string.
1114  *
1115  * Centre string by adding @p c to the left and the right to achieve a length
1116  * of @p n characters.
1117  ***************************************************************************/
1118 std::string gammalib::centre(const std::string& s, const int& n, const char& c)
1119 {
1120  // Compute number of characters to fill left and right
1121  int n_right = (n-s.length()) / 2;
1122  int n_left = n - s.length() - n_right;
1123 
1124  // Set result
1125  std::string result = fill(std::string(1,c), n_left) + s +
1126  fill(std::string(1,c), n_right);
1127 
1128  // Return result
1129  return result;
1130 }
1131 
1132 
1133 /***********************************************************************//**
1134  * @brief Convert string in parameter format
1135  *
1136  * @param[in] s String to be converted.
1137  * @param[in] indent Indentation of parameter.
1138  * @return Parameter string.
1139  *
1140  * Converts and string into the parameter format of type "s ......: " with a
1141  * total length of G_PARFORMAT_LENGTH.
1142  ***************************************************************************/
1143 std::string gammalib::parformat(const std::string& s, const int& indent)
1144 {
1145  // Compute number of characters to fill right. Do not clip the string if
1146  // it is too long since we do not want to loose information.
1147  int n_right = G_PARFORMAT_LENGTH - s.length() - 3 - indent;
1148 
1149  // Set result
1150  std::string result = " " + s + " " + fill(".", n_right) + ": ";
1151 
1152  // Return result
1153  return result;
1154 }
1155 
1156 
1157 /***********************************************************************//**
1158  * @brief Convert singular noun into number noun
1159  *
1160  * @param[in] noun Singular noun.
1161  * @param[in] number Number of instance of noun.
1162  * @return Converted noun.
1163  *
1164  * Converts a singular noun into a number noun by appending a "s" to the
1165  * noun if the @p number of the instances of the noun is not one.
1166  ***************************************************************************/
1167 std::string gammalib::number(const std::string& noun, const int& number)
1168 {
1169  // Copy input noun
1170  std::string result(noun);
1171 
1172  // Append "s" if number if not one
1173  if (number != 1) {
1174  result += "s";
1175  }
1176 
1177  // Return result
1178  return result;
1179 }
1180 
1181 
1182 /***********************************************************************//**
1183  * @brief Compute photon flux between two energies for a power law
1184  *
1185  * @param[in] emin Minimum energy.
1186  * @param[in] emax Maximum energy.
1187  * @param[in] epivot Pivot energy.
1188  * @param[in] gamma Spectral index.
1189  * @return Photon flux under power law.
1190  *
1191  * Analytically computes
1192  * \f[\int_{E_{\rm min}}^{E_{\rm max}}
1193  * \left( E/E_{\rm pivot} \right)^{\gamma} dE\f]
1194  * where
1195  * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum
1196  * energy, respectively, and
1197  * \f$E_{\rm pivot}\f$ is the pivot energy, and
1198  * \f$\gamma\f$ is the spectral index.
1199  ***************************************************************************/
1200 double gammalib::plaw_photon_flux(const double& emin, const double& emax,
1201  const double& epivot, const double& gamma)
1202 {
1203  // Initialise flux
1204  double flux = 0.0;
1205 
1206  // Continue only if emax > emin
1207  if (emax > emin) {
1208 
1209  // Compute photon flux. Computations dependend on the exponent. We
1210  // add here a kluge to assure numerical accuracy.
1211  double exponent = gamma + 1.0;
1212  if (std::abs(exponent) > 1.0e-11) {
1213  double xmin = emin / epivot;
1214  double xmax = emax / epivot;
1215  flux = epivot / exponent * (std::pow(xmax, exponent) -
1216  std::pow(xmin, exponent));
1217  }
1218  else {
1219  double ratio = emax / emin;
1220  flux = epivot * std::log(ratio);
1221  }
1222 
1223  } // endif: emax > emin
1224 
1225  // Return result
1226  return flux;
1227 }
1228 
1229 
1230 /***********************************************************************//**
1231  * @brief Compute energy flux between two energies for a power law
1232  *
1233  * @param[in] emin Minimum energy.
1234  * @param[in] emax Maximum energy.
1235  * @param[in] epivot Pivot energy.
1236  * @param[in] gamma Spectral index.
1237  * @return Energy flux under power law.
1238  *
1239  * Analytically computes
1240  * \f[\int_{E_{\rm min}}^{E_{\rm max}}
1241  * \left( E/E_{\rm pivot} \right)^{\gamma} E dE\f]
1242  * where
1243  * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum
1244  * energy, respectively, and
1245  * \f$E_{\rm pivot}\f$ is the pivot energy, and
1246  * \f$\gamma\f$ is the spectral index.
1247  ***************************************************************************/
1248 double gammalib::plaw_energy_flux(const double& emin, const double& emax,
1249  const double& epivot, const double& gamma)
1250 {
1251  // Initialise flux
1252  double flux = 0.0;
1253 
1254  // Continue only if emax > emin
1255  if (emax > emin) {
1256 
1257  // Compute energy flux. Computations dependend on the exponent. We
1258  // add here a kluge to assure numerical accuracy.
1259  double exponent = gamma + 2.0;
1260  double epivot2 = epivot * epivot;
1261  if (std::abs(exponent) > 1.0e-11) {
1262  double xmin = emin / epivot;
1263  double xmax = emax / epivot;
1264  flux = epivot2 / exponent * (std::pow(xmax, exponent) -
1265  std::pow(xmin, exponent));
1266  }
1267  else {
1268  double ratio = emax / emin;
1269  flux = epivot2 * (std::log(ratio));
1270  }
1271 
1272  } // endif: emax > emin
1273 
1274  // Return result
1275  return flux;
1276 }
1277 
1278 
1279 /***********************************************************************//**
1280  * @brief Computes log mean energy
1281  *
1282  * @param[in] a First energy.
1283  * @param[in] b Second energy.
1284  * @return Log mean energy.
1285  *
1286  * Computes the logarithmic mean energy
1287  * \f$10^{0.5 * (\log E_{\rm a} + \log E_{\rm b})}\f$
1288  * for two energies.
1289  ***************************************************************************/
1291 {
1292  // Compute logarithmic mean energy
1293  GEnergy elogmean;
1294  double eloga = a.log10MeV();
1295  double elogb = b.log10MeV();
1296  elogmean.MeV(std::pow(10.0, 0.5 * (eloga + elogb)));
1297 
1298  // Return
1299  return elogmean;
1300 }
1301 
1302 
1303 /***********************************************************************//**
1304  * @brief Checks if directory exists
1305  *
1306  * @param[in] dirname Directory name.
1307  * @return True if directory exists, false otherwise.
1308  *
1309  * Checks if a directory exists. The function expands any environment
1310  * variable prior to checking.
1311  ***************************************************************************/
1312 bool gammalib::dir_exists(const std::string& dirname)
1313 {
1314  // Initialise result
1315  bool result = false;
1316 
1317  // Allocate file information structure
1318  struct stat info;
1319 
1320  // Get file information structure
1321  int ret = stat(gammalib::expand_env(dirname).c_str(), &info);
1322 
1323  // Check if we have a directory
1324  if (ret == 0 && S_ISDIR(info.st_mode)) {
1325  result = true;
1326  }
1327 
1328  // Return result
1329  return result;
1330 }
1331 
1332 
1333 /***********************************************************************//**
1334  * @brief Checks if a substring is in a string
1335  *
1336  * @param[in] str String you want to search in.
1337  * @param[in] substring String you are looking for in @p str.
1338  * @return True if a string contains a sub string.
1339  *
1340  * Checks if substring is contained in str
1341  ***************************************************************************/
1342 bool gammalib::contains(const std::string& str, const std::string& substring)
1343 {
1344  // Initialise result
1345  bool result = false;
1346 
1347  // checks if substring is in str
1348  if (str.find(substring) != std::string::npos) {
1349  result = true;
1350  }
1351 
1352  // Return result
1353  return result;
1354 }
1355 
1356 
1357 /***********************************************************************//**
1358  * @brief Checks if a string is contained in a vector of strings
1359  *
1360  * @param[in] strings Vector of strings you want to search in.
1361  * @param[in] string string you are looking for in strings.
1362  * @return True if a string is contained a vector.
1363  *
1364  * Checks if a string is contained in a vector of strings
1365  ***************************************************************************/
1366 bool gammalib::contains(const std::vector<std::string>& strings,
1367  const std::string& string)
1368 {
1369  // Compute result
1370  bool result = std::find(strings.begin(), strings.end(), string) !=
1371  strings.end();
1372 
1373  // Return result
1374  return result;
1375 }
1376 
1377 
1378 /***********************************************************************//**
1379  * @brief Emits warning
1380  *
1381  * @param[in] origin Name of method that emits warning.
1382  * @param[in] message Warning message.
1383  *
1384  * Writes a warning to the console.
1385  ***************************************************************************/
1386 void gammalib::warning(const std::string& origin,
1387  const std::string& message)
1388 {
1389  // Compile option: enable/disable warnings
1390  #if defined(G_WARNINGS)
1391 
1392  // Set warning message
1393  std::string warning = "+++ WARNING in " + origin + ": " + message;
1394 
1395  // Writes warning to the console
1396  std::cout << warning << std::endl;
1397 
1398  // End of compile option
1399  #endif
1400 
1401  // Return
1402  return;
1403 }
1404 
1405 
1406 /***********************************************************************//**
1407  * @brief Convert XML character references in string to characters
1408  *
1409  * @param[in] arg String containing XML character references.
1410  * @return String with character reference replaced by respective characters.
1411  *
1412  * Converts all character references found in a string in their respective
1413  * characters. For more information about XML character references read
1414  * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
1415  ***************************************************************************/
1416 std::string gammalib::xml2str(const std::string& arg)
1417 {
1418  // Initialise string
1419  std::string result;
1420 
1421  // Iitialise position, lenghts and flags
1422  size_t length = arg.length();
1423  size_t pos = 0;
1424  size_t start = 0;
1425  size_t stop = 0;
1426  size_t len = 0; // Length of string preceeding char. reference
1427  bool found = false;
1428 
1429  // Loop over string
1430  while (pos < length) {
1431 
1432  // If we have not yet found a character reference then search for
1433  // the next one. If we do not find one we break here.
1434  if (!found) {
1435  start = arg.find("&", pos);
1436  if (start != std::string::npos) {
1437  len = start - pos;
1438  pos = start;
1439  found = true;
1440  }
1441  else {
1442  break;
1443  }
1444  }
1445 
1446  // ... otherwise search for end of the actual character reference.
1447  // Throw an exception if no end is found.
1448  else {
1449  stop = arg.find(";", pos);
1450  if (stop != std::string::npos) {
1451 
1452  // First attach leading string to the result
1453  if (len > 0) {
1454  result += arg.substr(start-len, len);
1455  }
1456 
1457  // Next extract character reference
1458  std::string cref = arg.substr(start+1, stop-start-1);
1459  len = cref.length();
1460 
1461  // Check for a numerical character reference
1462  //TODO: Check that there are only valid characters in
1463  // numerical field
1464  if (len >= 2 && cref[0] == '#') {
1465  int number = -1;
1466  if (cref[1] == 'x') {
1467  number = (int)std::strtol(cref.substr(2,len-2).c_str(), NULL, 16);
1468  }
1469  else {
1470  number = toint(cref.substr(1,len-1));
1471  }
1472  if (number != -1) {
1473  result.push_back((char)number);
1474  }
1475  else {
1476  std::string msg = "Could not extract number from "
1477  "numerical character reference &"+
1478  cref+";";
1480  }
1481  }
1482 
1483  // ... otherwise check for a character entity reference
1484  // and push back the corresponding character to the result
1485  // string
1486  else {
1487  if (cref == "quot") {
1488  result.push_back((char)34);
1489  }
1490  else if (cref == "amp") {
1491  result.push_back((char)38);
1492  }
1493  else if (cref == "apos") {
1494  result.push_back((char)39);
1495  }
1496  else if (cref == "lt") {
1497  result.push_back((char)60);
1498  }
1499  else if (cref == "gt") {
1500  result.push_back((char)62);
1501  }
1502  else {
1503  std::string msg = "Unknown character entity reference "
1504  "&"+cref+"; encountered in XML string \""+
1505  arg+"\".";
1507  }
1508  }
1509 
1510  // Signal that we're done and that we search for the
1511  // next character reference
1512  found = false;
1513  pos = stop + 1;
1514 
1515  } // endif: end of character reference found
1516 
1517  // ... otherwise throw an exception
1518  else {
1519  std::string msg = "Missing ; character at end of character "
1520  "reference in XML string \""+arg+"\".";
1522  }
1523 
1524  } // endelse: search for end of character reference
1525 
1526  } // endwhile
1527 
1528  // Append any pending string to the result
1529  if (pos < length) {
1530  len = length - pos;
1531  result += arg.substr(pos, len);
1532  }
1533 
1534  // Return result
1535  return result;
1536 }
1537 
1538 
1539 /***********************************************************************//**
1540  * @brief Convert special characters in string to XML character references
1541  *
1542  * @param[in] arg String.
1543  * @return String with special characters replaced by character references.
1544  *
1545  * Converts all special characters found in a string into character
1546  * references. For more information about XML character references read
1547  * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
1548  ***************************************************************************/
1549 std::string gammalib::str2xml(const std::string& arg)
1550 {
1551  // Initialise string
1552  std::string result;
1553 
1554  // Loop over string
1555  for (int i = 0; i < arg.length(); ++i) {
1556 
1557  // Initialize string to add
1558  std::string character = arg.substr(i, 1);
1559 
1560  // Replace special characters
1561  if (character == "\"") {
1562  character = "&quot;";
1563  }
1564  else if (character == "&") {
1565  character = "&amp;";
1566  }
1567  else if (character == "'") {
1568  character = "&apos;";
1569  }
1570  else if (character == "<") {
1571  character = "&lt;";
1572  }
1573  else if (character == ">") {
1574  character = "&gt;";
1575  }
1576 
1577  // Append character
1578  result += character;
1579 
1580  }
1581 
1582  // Return result
1583  return result;
1584 }
1585 
1586 
1587 /***********************************************************************//**
1588  * @brief Checks if parameter with given name in XML element exists
1589  *
1590  * @param[in] xml XML element.
1591  * @param[in] name Parameter name.
1592  * @return True if parameter exists, false otherwise.
1593  *
1594  * Checks whether a parameter with given @p name exists in XML element.
1595  ***************************************************************************/
1596 bool gammalib::xml_has_par(const GXmlElement& xml, const std::string& name)
1597 {
1598  // Initialize flag
1599  bool found = false;
1600 
1601  // Get number of elements
1602  int n = xml.elements("parameter");
1603 
1604  // Search for parameter with given name
1605  for (int i = 0; i < n; ++i) {
1606  const GXmlElement* element = xml.element("parameter", i);
1607  if (element->attribute("name") == name) {
1608  found = true;
1609  break;
1610  }
1611  }
1612 
1613  // Return
1614  return found;
1615 }
1616 
1617 
1618 /***********************************************************************//**
1619  * @brief Return pointer to parameter with given name in XML element
1620  *
1621  * @param[in] origin Method requesting parameter.
1622  * @param[in] xml XML element.
1623  * @param[in] name Parameter name.
1624  * @return Pointer to parameter XML element.
1625  *
1626  * @exception GException::invalid_value
1627  * Invalid XML format encountered.
1628  *
1629  * Returns pointer to parameter with given @p name in XML element. If the
1630  * @p name is not found, a parameter with the given @p name is added. In
1631  * that respect the function differs from xml_get_par which does not add a
1632  * parameter element.
1633  *
1634  * The function checks for multiple occurences of a parameter and throws an
1635  * exception in case that more than one parameter with a given name is found.
1636  ***************************************************************************/
1637 GXmlElement* gammalib::xml_need_par(const std::string& origin,
1638  GXmlElement& xml,
1639  const std::string& name)
1640 {
1641  // Initialize XML element pointer
1642  GXmlElement* par = NULL;
1643 
1644  // Number of elements
1645  int number = 0;
1646 
1647  // Get number of elements in XML element
1648  int n = xml.elements("parameter");
1649 
1650  // Search for parameter with given name
1651  for (int i = 0; i < n; ++i) {
1652  GXmlElement* element = xml.element("parameter", i);
1653  if (element->attribute("name") == name) {
1654  par = element;
1655  number++;
1656  }
1657  }
1658 
1659  // Create parameter if none was found
1660  if (number == 0) {
1661  par = static_cast<GXmlElement*>(xml.append(GXmlElement("parameter name=\""+name+"\"")));
1662  number++;
1663  }
1664 
1665  // Check that there are no multiple parameters
1666  gammalib::xml_check_par(origin, name, number);
1667 
1668  // Return
1669  return par;
1670 }
1671 
1672 
1673 /***********************************************************************//**
1674  * @brief Return pointer to parameter with given name in XML element
1675  *
1676  * @param[in] origin Method requesting parameter.
1677  * @param[in] xml XML element.
1678  * @param[in] name Parameter name.
1679  * @return Pointer to parameter XML element.
1680  *
1681  * @exception GException::invalid_value
1682  * Invalid XML format encountered.
1683  *
1684  * Returns pointer to parameter with given @p name in XML element. The
1685  * function checks whether the parameter has been found and throws an
1686  * exception if no parameter or multiple occurences of a parameter with given
1687  * @p name are found.
1688  ***************************************************************************/
1689 const GXmlElement* gammalib::xml_get_par(const std::string& origin,
1690  const GXmlElement& xml,
1691  const std::string& name)
1692 {
1693  // Initialize XML element pointer
1694  const GXmlElement* par = NULL;
1695 
1696  // Number of elements
1697  int number = 0;
1698 
1699  // Get number of elements in XML element
1700  int n = xml.elements("parameter");
1701 
1702  // Search for parameter with given name
1703  for (int i = 0; i < n; ++i) {
1704  const GXmlElement* element = xml.element("parameter", i);
1705  if (element->attribute("name") == name) {
1706  par = element;
1707  number++;
1708  }
1709  }
1710 
1711  // Check that there is at least one parameter and that there are no
1712  // multiple parameters
1713  gammalib::xml_check_par(origin, name, number);
1714 
1715  // Return
1716  return par;
1717 }
1718 
1719 
1720 /***********************************************************************//**
1721  * @brief Return attribute value for a given parameter in XML element
1722  *
1723  * @param[in] origin Method requesting parameter.
1724  * @param[in] xml XML element.
1725  * @param[in] name Parameter name.
1726  * @param[in] attribute Attribute name.
1727  * @return Value of attribute.
1728  *
1729  * @exception GException::invalid_value
1730  * Attribute not found.
1731  *
1732  * Returns the value of @p attribute of parameter @p name in XML element.
1733  * The function checks whether the parameter has been found and throws an
1734  * exception if no parameter or multiple occurences of a parameter with given
1735  * @p name are found. The function furthermore checks whether the attribute
1736  * exists.
1737  ***************************************************************************/
1738 std::string gammalib::xml_get_attr(const std::string& origin,
1739  const GXmlElement& xml,
1740  const std::string& name,
1741  const std::string& attribute)
1742 {
1743  // Initialise attribute value
1744  std::string value = "";
1745 
1746  // Get parameter
1747  const GXmlElement* par = gammalib::xml_get_par(origin, xml, name);
1748 
1749  // Throw an exception if a parameter has not the requested attribute
1750  if (!par->has_attribute(attribute)) {
1751  std::string msg = "Attribute \""+attribute+"\" not found in XML "
1752  "parameter \""+name+"\". Please verify the XML "
1753  "format.";
1754  throw GException::invalid_value(origin, msg);
1755  }
1756 
1757  // Extract attribute
1758  value = par->attribute(attribute);
1759 
1760  // Return attribute value
1761  return value;
1762 }
1763 
1764 
1765 /***********************************************************************//**
1766  * @brief Checks number of parameters
1767  *
1768  * @param[in] origin Method performing the check.
1769  * @param[in] xml XML element.
1770  * @param[in] number Expected number of parameters.
1771  *
1772  * @exception GException::invalid_value
1773  * Invalid XML format encountered.
1774  *
1775  * Checks the number of parameter in an XML element.
1776  ***************************************************************************/
1777 void gammalib::xml_check_parnum(const std::string& origin,
1778  const GXmlElement& xml,
1779  const int& number)
1780 {
1781  // Throw exception if number of elements does not correspond to the
1782  // expected number
1783  if (xml.elements() != number) {
1784  std::string msg = "Number of "+gammalib::str(xml.elements())+
1785  " child elements in XML file does not correspond "
1786  "to expected number of "+gammalib::str(number)+
1787  " elements. Please verify the XML format.";
1788  throw GException::invalid_value(origin, msg);
1789  }
1790 
1791  // Throw exception if number of "parameter" elements does not correspond
1792  // to the xpected number
1793  int npars = xml.elements("parameter");
1794  if (npars != number) {
1795  std::string msg = "Number of "+gammalib::str(npars)+" \"parameter\" "
1796  "child elements in XML file does not correspond to "
1797  "expected number of "+gammalib::str(number)+
1798  " elements. Please verify the XML format.";
1799  throw GException::invalid_value(origin, msg);
1800  }
1801 
1802  // Return
1803  return;
1804 }
1805 
1806 
1807 /***********************************************************************//**
1808  * @brief Checks the model type
1809  *
1810  * @param[in] origin Method performing the check.
1811  * @param[in,out] xml XML element.
1812  * @param[in] type Expected model typeN.
1813  *
1814  * @exception GException::invalid_value
1815  * Invalid XML format encountered.
1816  *
1817  * Checks the number of parameter in an XML element.
1818  ***************************************************************************/
1819 void gammalib::xml_check_type(const std::string& origin,
1820  GXmlElement& xml,
1821  const std::string& type)
1822 {
1823  // If XML element has no model type then set model type
1824  if (xml.attribute("type") == "") {
1825  xml.attribute("type", type);
1826  }
1827 
1828  // Throw an exception if the model type is not the expected one
1829  if (xml.attribute("type") != type) {
1830  std::string msg = "Model type \""+xml.attribute("type")+"\" is not "
1831  "the expected type \""+type+"\". Please verify "
1832  "the XML format.";
1833  throw GException::invalid_value(origin, msg);
1834  }
1835 
1836  // Return
1837  return;
1838 }
1839 
1840 
1841 /***********************************************************************//**
1842  * @brief Checks whether a parameter has occured once
1843  *
1844  * @param[in] origin Method performing the check.
1845  * @param[in] name Parameter name.
1846  * @param[in] number Number of occurences of parameter.
1847  *
1848  * @exception GException::invalid_value
1849  * Invalid XML format encountered.
1850  *
1851  * Throws an exception if a given parameter has not exactly occured once.
1852  * The exception text is adapted to the case that none or multiple parameters
1853  * have been found.
1854  ***************************************************************************/
1855 void gammalib::xml_check_par(const std::string& origin,
1856  const std::string& name,
1857  const int& number)
1858 {
1859  // Throw case dependent exception
1860  if (number < 1) {
1861  std::string msg = "Parameter \""+name+"\" not found in XML element."
1862  " Please verify the XML format.";
1863  throw GException::invalid_value(origin, msg);
1864  }
1865  else if (number > 1) {
1866  std::string msg = "Parameter \""+name+"\" found "+
1867  gammalib::str(number)+" times in XML element."
1868  " Please verify the XML format.";
1869  throw GException::invalid_value(origin, msg);
1870  }
1871 
1872  // Return
1873  return;
1874 }
1875 
1876 
1877 /***********************************************************************//**
1878  * @brief Expand file name provided as XML attribute for loading
1879  *
1880  * @param[in] xml XML element.
1881  * @param[in] filename File name.
1882  * @return Expanded file name.
1883  *
1884  * Expands file name provided as XML attribute for loading. The XML file
1885  * access path will be prepended to the file name access path if the file
1886  * name has not an absolute path and if the file name access path does not
1887  * start with the XML file access path.
1888  ***************************************************************************/
1890  const std::string& filename)
1891 {
1892  // Set file name
1893  GFilename fname(filename);
1894 
1895  // If the file name is not empty and is not an absolute path then we
1896  // assume that the filename is a relative file name with respect to the
1897  // XML file access path and we therefore prepend the XML file access path
1898  // to the file name
1899  if (!fname.is_empty()) {
1900  size_t access_length = fname.path().length();
1901  size_t xml_length = xml.filename().path().length();
1902 
1903  // If filename has no access path and the XML file has an access path
1904  // then preprend the XML file access path
1905  if (access_length == 0) {
1906  if (xml_length > 0) {
1907  fname = xml.filename().path() + fname;
1908  }
1909  }
1910 
1911  // If filename assess path is not absolute then continue ...
1912  else if (fname.path()[0] != '/') {
1913 
1914  // If XML file access path is not contained in file name access
1915  // path then prepend the XML file access path
1916  if (access_length >= xml_length) {
1917  if (fname.path().compare(0, xml_length, xml.filename().path()) != 0) {
1918  fname = xml.filename().path() + fname;
1919  }
1920  }
1921 
1922  // If file name access pass is shorter than XML file access path
1923  // then prepend the XML file access path
1924  else {
1925  fname = xml.filename().path() + fname;
1926  }
1927  }
1928  }
1929 
1930  // Return file name
1931  return fname;
1932 }
1933 
1934 
1935 /***********************************************************************//**
1936  * @brief Reduce file name provided for writing as XML attribute
1937  *
1938  * @param[in] xml XML element.
1939  * @param[in] filename File name.
1940  * @return Reduced file name.
1941  *
1942  * Reduces file name provided for writing as XML attribute. If the file name
1943  * is not empty and its access path starts has the same access path as the
1944  * XML file the XML file access path is stripped from the file name.
1945  ***************************************************************************/
1947  const std::string& filename)
1948 {
1949  // Set file name
1950  GFilename fname(filename);
1951 
1952  // If the file name is not empty and the access path starts with the
1953  // same characters as the XML file access path then we assume that the
1954  // access path has been added and hence we strip it now
1955  if (!fname.is_empty()) {
1956  size_t access_length = fname.path().length();
1957  size_t xml_length = xml.filename().path().length();
1958  if (xml_length > 0) {
1959  if (access_length == xml_length) {
1960  if (fname.path() == xml.filename().path()) {
1961  fname = fname.file();
1962  }
1963  }
1964  else if (access_length > xml_length) {
1965  if (fname.path().compare(0, xml_length, xml.filename().path()) == 0) {
1966  std::string relpath = fname.path().substr(xml_length, access_length-xml_length);
1967  fname = GFilename(relpath + fname.file());
1968  }
1969  }
1970  }
1971  }
1972 
1973  // Return file name
1974  return fname;
1975 }
1976 
1977 
1978 /***********************************************************************//**
1979  * @brief Extract name / value pair from XML node
1980  *
1981  * @param[in] node Pointer to XML node.
1982  * @param[out] name Name string.
1983  * @param[out] value Value string.
1984  *
1985  * Extracts a name / value pair from a XML node. If the XML node pointer is
1986  * NULL, the name and value strings will be empty.
1987  ***************************************************************************/
1989  std::string& name,
1990  std::string& value)
1991 {
1992  // Clear name and value strings
1993  name.clear();
1994  value.clear();
1995 
1996  // Continue only if node is valid
1997  if (node != NULL) {
1998 
1999  // Get name node and extract text content
2000  const GXmlNode* ptr = node->element("name", 0);
2001  if (ptr != NULL) {
2002  const GXmlText* text = static_cast<const GXmlText*>((*ptr)[0]);
2003  if (text != NULL) {
2004  name = text->text();
2005  }
2006  }
2007 
2008  // Get value node and extract text content
2009  ptr = node->element("value", 0);
2010  if (ptr != NULL) {
2011  const GXmlText* text = static_cast<const GXmlText*>((*ptr)[0]);
2012  if (text != NULL) {
2013  value = text->text();
2014  }
2015  }
2016  }
2017 
2018  // Return
2019  return;
2020 }
2021 
2022 
2023 /***********************************************************************//**
2024  * @brief Checks whether a parameter has occured once
2025  *
2026  * @param[in] fd Socket file descriptor.
2027  * @param[out] buffer Buffer to hold data.
2028  * @param[in] len Maximum number of bytes to recv().
2029  * @param[in] flags Flags (as the fourth param to recv() ).
2030  * @param[in] timeout Timeout in milliseconds.
2031  * @return recv() error code, -2 == timeout
2032  *
2033  * This function implements the recv() function with a timeout. The timeout
2034  * is specified in milliseconds.
2035  ***************************************************************************/
2036 int gammalib::recv(int fd, char *buffer, int len, int flags, int timeout)
2037 {
2038  // Initialise error code with time out
2039  int error = -2;
2040 
2041  // Initialize the set
2042  fd_set readset;
2043  FD_ZERO(&readset);
2044  FD_SET(fd, &readset);
2045 
2046  // Initialize time out struct
2047  struct timeval tv;
2048  if (timeout >= 1000) {
2049  tv.tv_sec = timeout/1000;
2050  tv.tv_usec = 0;
2051  }
2052  else {
2053  tv.tv_sec = 0;
2054  tv.tv_usec = timeout*1000;
2055  }
2056 
2057  // select()
2058  int result = select(fd+1, &readset, NULL, NULL, &tv);
2059 
2060  // Check status
2061  if (result < 0) {
2062  error = -1;
2063  }
2064  else if (result > 0 && FD_ISSET(fd, &readset)) {
2065 
2066  // Initialise flags
2067  int iof = -1;
2068 
2069  // Set non-blocking mode
2070  if ((iof = fcntl(fd, F_GETFL, 0)) != -1) {
2071  fcntl(fd, F_SETFL, iof | O_NONBLOCK);
2072  }
2073 
2074  // Receive data
2075  result = ::recv(fd, buffer, len, flags);
2076 
2077  // Set as before
2078  if (iof != -1) {
2079  fcntl(fd, F_SETFL, iof);
2080  }
2081 
2082  // Set error
2083  error = result;
2084  }
2085 
2086  // Return error
2087  return error;
2088 }
2089 
2090 
2091 /***********************************************************************//**
2092  * @brief Returns length of circular arc within circular ROI
2093  *
2094  * @param[in] rad Circle radius in radians (<pi).
2095  * @param[in] dist Circle centre distance to ROI centre (<pi).
2096  * @param[in] cosdist Cosine of circle centre distance to ROI centre.
2097  * @param[in] sindist Sinus of circle centre distance to ROI centre.
2098  * @param[in] roi Radius of ROI in radians.
2099  * @param[in] cosroi Cosine of ROI radius.
2100  *
2101  * This method returns the arclength in radians of a circle of radius 'rad'
2102  * with a centre that is offset by 'dist' from the ROI centre, where the ROI
2103  * radius is given by 'roi'. To speed-up computations, the cosines and sinus
2104  * of 'roi' and 'psf' should be calculated by the client and be passed to
2105  * the method.
2106  ***************************************************************************/
2107 double gammalib::roi_arclength(const double& rad, const double& dist,
2108  const double& cosdist, const double& sindist,
2109  const double& roi, const double& cosroi)
2110 {
2111  // Declare arclength
2112  double arclength;
2113 
2114  // Handle special case that circle centre matches ROI centre
2115  if (dist == 0.0) {
2116  if (rad > roi) arclength = 0.0; // Circle outside ROI
2117  else arclength = gammalib::twopi; // Circle inside ROI
2118  }
2119 
2120  // ... otherwise circle and ROI centres are not identical
2121  else {
2122 
2123  // Handle special case that we evaluate exactly at the circle
2124  // centre. In this case we have in fact a point, and if this point
2125  // falls within the ROI it has a formal arclength of 2pi.
2126  //
2127  if (rad == 0.0) {
2128  if (dist > roi) arclength = 0.0; // Circle centre outside ROI
2129  else arclength = gammalib::twopi; // Circle centre inside ROI
2130  }
2131 
2132  // ... otherwise we have to handle the general case
2133  else {
2134  double d = roi - dist;
2135  if (-rad >= d) {
2136  arclength = 0.0;
2137  }
2138  else if (rad <= d) {
2139  arclength = gammalib::twopi;
2140  }
2141  else {
2142  double cosrad = std::cos(rad);
2143  double sinrad = std::sin(rad);
2144  double cosang = (cosroi - cosdist*cosrad) / (sindist*sinrad);
2145  arclength = 2.0 * gammalib::acos(cosang);
2146  #if defined(G_CHECK_FOR_NAN)
2147  if (gammalib::is_infinite(arclength) ||
2148  gammalib::is_notanumber(arclength)) {
2149  std::cout << "roi_arclength: NaN occured";
2150  std::cout << " rad=" << rad;
2151  std::cout << " sinrad=" << sinrad;
2152  std::cout << " cosrad=" << cosrad;
2153  std::cout << " sindist=" << sindist;
2154  std::cout << " cosdist=" << cosdist;
2155  std::cout << " cosang=" << cosang;
2156  std::cout << std::endl;
2157  }
2158  #endif
2159  }
2160  }
2161 
2162  } // endelse: Circle and ROI centres were not identical
2163 
2164  // Return arclength
2165  return arclength;
2166 }
2167 
2168 
2169 /***********************************************************************//**
2170  * @brief Compare two floating point values with tolerance
2171  *
2172  * @param[in] a First floating point value.
2173  * @param[in] b Second floating point value.
2174  * @param[in] tol Relative tolerance.
2175  * @return True if both floating point values are identical within
2176  * the tolerance.
2177  *
2178  * This method tests whether @p a is identical to @p b within a given
2179  * relative tolerance @p tol. The test verifies whether
2180  *
2181  * \f[|a - b| \le |a \times tol|\f]
2182  *
2183  * for \f$a \ne 0\f$ or whether
2184  *
2185  * \f[|a - b| \le |b \times tol|\f]
2186  *
2187  * for \f$b \ne 0\f$. If both \f$a = 0\f$ and \f$b = 0\f$ the method
2188  * returns true.
2189  ***************************************************************************/
2190 bool gammalib::compare(const double& a, const double& b, const double& tol)
2191 {
2192  // Initialise identity
2193  bool identity = false;
2194 
2195  // Case A: a is not zero
2196  if (a != 0.0) {
2197  identity = std::abs(a - b) <= std::abs(a * tol);
2198  }
2199 
2200  // Case B: b is not zero
2201  else if (b != 0.0) {
2202  identity = std::abs(a - b) <= std::abs(b * tol);
2203  }
2204 
2205  // Case C: a and b are zero
2206  else {
2207  identity = true;
2208  }
2209 
2210  // Return identity
2211  return identity;
2212 }
2213 
2214 
2215 /***********************************************************************//**
2216  * @brief Return response to a HTTP query
2217  *
2218  * @param[in] host Host address.
2219  * @param[in] query Query string.
2220  * @return Response to a HTTP query.
2221  *
2222  * @exception GException::runtime_error
2223  * Unable to open or to connect to socket.
2224  * @exception GException::invalid_argument
2225  * Host not found.
2226  *
2227  * Returns response to a HTTP query. Be aware that this method will not
2228  * work for https servers.
2229  ***************************************************************************/
2230 std::string gammalib::http_query(const std::string& host, const std::string& query)
2231 {
2232  // Set constants
2233  const int portno = 80;
2234 
2235  // Initialise buffers
2236  char message[1024];
2237  char response[4096];
2238  memset(message, 0, sizeof(message));
2239  memset(response, 0, sizeof(response));
2240 
2241  // Build message string
2242  sprintf(message, "GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", query.c_str(), host.c_str());
2243 
2244  // Create the socket
2245  int sockfd = socket(AF_INET, SOCK_STREAM, 0);
2246  if (sockfd < 0) {
2247  std::string msg = "Unable to open socket.";
2249  }
2250 
2251  // Lookup IP address
2252  struct hostent* server = gethostbyname(host.c_str());
2253  if (server == NULL) {
2254  std::string msg = "Unable to find host \""+host+"\".";
2256  }
2257 
2258  // Fill in structure
2259  struct sockaddr_in serveraddr;
2260  memset(&serveraddr, 0, sizeof(serveraddr));
2261  serveraddr.sin_family = AF_INET;
2262  memcpy(&serveraddr.sin_addr.s_addr, server->h_addr, server->h_length);
2263  serveraddr.sin_port = htons(portno);
2264 
2265  // Connect the socket
2266  if (connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0) {
2267  std::string msg = "Unable to connect to socket for host \""+host+"\".";
2269  }
2270 
2271  // Send request
2272  write(sockfd, message, strlen(message));
2273 
2274  // Receive response
2275  read(sockfd, response, sizeof(response)-1);
2276 
2277  // Close socket
2278  close(sockfd);
2279 
2280  // Return response
2281  return std::string(response);
2282 }
2283 
2284 
2285 #if defined(G_USE_CURL)
2286 /***********************************************************************//**
2287  * @brief Return two-digit host country code
2288  *
2289  * @param[in] force_query Force query of host country code?
2290  * @return Host two-digit host country code.
2291  *
2292  * Returns two-digit host country code, either by reading the code from the
2293  * $HOME/.gamma/host-country file, or if the file does not exist, by using
2294  * the http query
2295  * http://ip-api.com/line/?fields=countryCode.
2296  *
2297  * The result is saved in a static variable, hence once the country code is
2298  * retrieved no queries will be executed anymore. The http query is issued
2299  * using the curl tool with a timeout of one second. If the query fails,
2300  * or the curl tool is not available, the method returns an empty string.
2301  *
2302  * If no host-country file exists and the method retrieved a two-digit
2303  * country code it will write the results into a host-country file.
2304  ***************************************************************************/
2305 #else
2306 /***********************************************************************//**
2307  * @brief Return two-digit host country code
2308  *
2309  * @param[in] force_query Force query of host country code?
2310  * @return Host two-digit host country code.
2311  *
2312  * Returns two-digit host country code, either by reading the code from the
2313  * $HOME/.gamma/host-country file, or if the file does not exist, by using
2314  * the http query
2315  * http://ip-api.com/line/?fields=countryCode.
2316  *
2317  * The result is saved in a static variable, hence once the country code is
2318  * retrieved no queries will be executed anymore. The http query is issued
2319  * using the http_query() method. If the query fails the method returns an
2320  * empty string.
2321  *
2322  * If no host-country file exists and the method retrieved a two-digit
2323  * country code it will write the results into a host-country file.
2324  ***************************************************************************/
2325 #endif
2326 std::string gammalib::host_country(const bool& force_query)
2327 {
2328  // Initialise country as static variable
2329  static std::string country;
2330 
2331  // Continue only if host country is empty
2332  if (country.empty()) {
2333 
2334  // Attempt to get host country from $HOME/.gamma/host-country file
2335  GFilename filename = gammalib::gamma_filename("host-country");
2336 
2337  // Continue only if file exists
2338  if ((!force_query) && (access(filename.url().c_str(), R_OK) == 0)) {
2339 
2340  // OpenMP critical zone to read host-country file
2341  #pragma omp critical(GammaLib_host_country)
2342  {
2343 
2344  // Get file lock. Continue only in case of success.
2345  struct flock lock;
2346  lock.l_type = F_RDLCK; // Want a read lock
2347  lock.l_whence = SEEK_SET; // Want beginning of file
2348  lock.l_start = 0; // No offset, lock entire file ...
2349  lock.l_len = 0; // ... to the end
2350  lock.l_pid = getpid(); // Current process ID
2351  int fd = open(filename.url().c_str(), O_RDONLY);
2352  if (fd != -1) {
2353 
2354  // Lock file
2355  fcntl(fd, F_SETLKW, &lock);
2356 
2357  // Open host-country file. Continue only if opening was
2358  // successful.
2359  FILE* fptr = fopen(filename.url().c_str(), "r");
2360  if (fptr != NULL) {
2361 
2362  // Allocate line buffer
2363  const int n = 1000;
2364  char line[n];
2365 
2366  // Read line
2367  fgets(line, n-1, fptr);
2368 
2369  // Close file
2370  fclose(fptr);
2371 
2372  // Extract country string
2373  country = gammalib::strip_chars(std::string(line), "\n");
2374 
2375  } // endif: host-country file opened successfully
2376 
2377  // Unlock file
2378  lock.l_type = F_UNLCK;
2379  fcntl(fd, F_SETLK, &lock);
2380  close(fd);
2381 
2382  } // endif: file locking successful
2383 
2384  } // end of OMP critial zone
2385 
2386  } // endif: file existed
2387 
2388  // ... otherwise there is no host-country file then get the
2389  // information from a geolocalisation web site
2390  else {
2391 
2392  // If curl should be used, the curl tool is available and the
2393  // country code is not set then determine the country code
2394  // from a geolocalisation web site
2395  #if defined(G_USE_CURL)
2396  #if defined(G_HAS_CURL)
2397  // If curl is available then use curl to infer the country code
2398  char command[256];
2399 
2400  // Setup curl command with timeout if possible to avoid lock up
2401  #if defined(G_HAS_PERL)
2402  sprintf(command, "a=$(perl -e 'alarm shift; exec \"curl --silent"
2403  " http://ip-api.com/line/?fields=countryCode"
2404  " 2>/dev/null\"' \"1\";);echo $a");
2405  #elif defined(G_HAS_TIMEOUT)
2406  sprintf(command, "timeout 1s curl --silent http://ip-api.com/line/"
2407  "?fields=countryCode 2>/dev/null");
2408  #else
2409  sprintf(command, "curl --silent http://ip-api.com/line/?fields=countryCode"
2410  " 2>/dev/null");
2411  #endif
2412 
2413  // Open the process with given 'command' for reading
2414  FILE* file = popen(command, "r");
2415 
2416  // Retrieve curl output
2417  char output[1024];
2418  if (fgets(output, sizeof(output)-1, file) != NULL) {
2419  country = strip_chars(std::string(output), "\n");
2420  }
2421 
2422  // Close process
2423  pclose(file);
2424  #endif
2425 
2426  // ... otherwise use the http_query method. Catch any exceptions.
2427  #else
2428  try {
2429  std::string response = http_query("ip-api.com", "line/?fields=countryCode");
2430  std::vector<std::string> lines = split(response, "\n");
2431  bool body = false;
2432  for (int i = 0; i < lines.size(); ++i) {
2433  if (body) {
2434  country = lines[i];
2435  break;
2436  }
2437  if ((lines[i] == "\n") || (lines[i] == "\r") || (lines[i] == " ")) {
2438  body = true;
2439  }
2440  }
2441  } // endtry
2442  catch (const std::exception& e) {
2443  //
2444  }
2445  #endif
2446 
2447  // If we have a two-digit country code then write the code into
2448  // host-country file
2449  if (country.length() == 2) {
2450 
2451  // OpenMP critical zone to write host-country file
2452  #pragma omp critical(GammaLib_host_country)
2453  {
2454 
2455  // Open host-country file, and in case of success, write
2456  // country
2457  FILE* fptr = fopen(filename.url().c_str(), "w");
2458  if (fptr != NULL) {
2459  fprintf(fptr, "%s\n", country.c_str());
2460  fclose(fptr);
2461  }
2462 
2463  } // end of OMP critial zone
2464 
2465  } // endif: had no two digit country code
2466 
2467  } // endelse: there was no host country file
2468 
2469  } // endif: host country was empty
2470 
2471  // Return country
2472  return country;
2473 }
2474 
2475 
2476 /***********************************************************************//**
2477  * @brief Returns filename in .gamma directory
2478  *
2479  * @param[in] name Name of file in .gamma directory.
2480  * @return Filename in .gamma directory.
2481  *
2482  * Returns the filename of the name of a file in the .gamma directory.
2483  ***************************************************************************/
2484 GFilename gammalib::gamma_filename(const std::string& name)
2485 {
2486  // Initialise lock filename
2487  GFilename filename;
2488 
2489  // First try accessing the user ID to get the home directory
2490  uid_t uid = geteuid();
2491  struct passwd* pw = getpwuid(uid);
2492  if (pw != NULL) {
2493  filename = std::string(pw->pw_dir) + "/.gamma/" + name;
2494  }
2495 
2496  // ... otherwise try using the $HOME environment variable
2497  else {
2498 
2499  // First attempt fetching $HOME environment variable
2500  char* home_ptr = std::getenv("HOME");
2501  if (home_ptr != NULL) {
2502  filename = std::string(home_ptr) + "/.gamma/" + name;
2503  }
2504 
2505  // ... otherwise use ~ as home directory
2506  else {
2507  filename = "~/.gamma/" + name;
2508  }
2509  }
2510 
2511  // Return filename
2512  return filename;
2513 }
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:1342
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:1988
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:168
std::string getenv(const std::string &arg)
Return value of environment variable.
Definition: GTools.cpp:465
double roi_arclength(const double &rad, const double &dist, const double &cosdist, const double &sindist, const double &roi, const double &cosroi)
Returns length of circular arc within circular ROI.
Definition: GTools.cpp:2107
std::string number(const std::string &noun, const int &number)
Convert singular noun into number noun.
Definition: GTools.cpp:1167
GFilename filename(void) const
Return filename of XML file.
Definition: GXmlNode.cpp:546
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:1855
Energy value class definition.
void warning(const std::string &origin, const std::string &message)
Emits warning.
Definition: GTools.cpp:1386
XML element node class interface definition.
GVector abs(const GVector &vector)
Computes absolute of vector elements.
Definition: GVector.cpp:1253
GVector cos(const GVector &vector)
Computes cosine of vector elements.
Definition: GVector.cpp:1190
std::string strdate(void)
Return current date.
Definition: GTools.cpp:727
bool is_empty(void) const
Signal if filename is empty.
Definition: GFilename.hpp:160
XML element node class.
Definition: GXmlElement.hpp:48
#define G_XML2STRING
Definition: GTools.cpp:66
int recv(int fd, char *buffer, int len, int flags, int timeout)
Checks whether a parameter has occured once.
Definition: GTools.cpp:2036
double acos(const double &arg)
Computes acos by avoiding NaN due to rounding errors.
Definition: GMath.cpp:69
std::string strip_chars(const std::string &arg, const std::string &chars)
Strip leading and trailing character from string.
Definition: GTools.cpp:94
std::vector< std::string > split(const std::string &s, const std::string &sep)
Split string.
Definition: GTools.cpp:983
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:586
Gammalib tools definition.
FITS file class interface definition.
#define G_CHAR_BUFFER
Definition: GTools.cpp:71
long tolong(const std::string &arg)
Convert string into long value.
Definition: GTools.cpp:851
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition: GTools.cpp:80
GFilename xml_file_reduce(const GXmlElement &xml, const std::string &filename)
Reduce file name provided for writing as XML attribute.
Definition: GTools.cpp:1946
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:1248
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:1118
double log10MeV(void) const
Return log10 of energy in MeV.
Definition: GEnergy.cpp:423
bool is_notanumber(const double &x)
Signal if argument is not a number.
Definition: GTools.hpp:201
bool is_infinite(const double &x)
Signal if argument is infinite.
Definition: GTools.hpp:184
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:1094
std::string path(void) const
Return access path.
Definition: GFilename.hpp:217
#define G_HTTP_QUERY
Definition: GTools.cpp:67
std::string http_query(const std::string &host, const std::string &query)
Return response to a HTTP query.
Definition: GTools.cpp:2230
const GXmlAttribute * attribute(const int &index) const
Return attribute.
short toshort(const std::string &arg)
Convert string into short value.
Definition: GTools.cpp:791
char * tochar(const std::string &arg)
Convert string to C string.
Definition: GTools.cpp:767
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:1070
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:1637
XML text node class.
Definition: GXmlText.hpp:43
GVector log(const GVector &vector)
Computes natural logarithm of vector elements.
Definition: GVector.cpp:1274
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:1312
GFilename gamma_filename(const std::string &name)
Returns filename in .gamma directory.
Definition: GTools.cpp:2484
void xml_check_parnum(const std::string &origin, const GXmlElement &xml, const int &number)
Checks number of parameters.
Definition: GTools.cpp:1777
XML text node class interface definition.
unsigned long long toulonglong(const std::string &arg)
Convert string into unsigned long long value.
Definition: GTools.cpp:896
bool xml_has_par(const GXmlElement &xml, const std::string &name)
Checks if parameter with given name in XML element exists.
Definition: GTools.cpp:1596
std::string xml2str(const std::string &arg)
Convert XML character references in string to characters.
Definition: GTools.cpp:1416
long long tolonglong(const std::string &arg)
Convert string into long long value.
Definition: GTools.cpp:881
unsigned long toulong(const std::string &arg)
Convert string into unsigned long value.
Definition: GTools.cpp:866
std::string rstrip_chars(const std::string &arg, const std::string &chars)
Strip trailing character from string.
Definition: GTools.cpp:131
std::string url(void) const
Return Uniform Resource Locator (URL)
Definition: GFilename.hpp:189
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition: GXmlNode.cpp:640
std::string host_country(const bool &force_query=false)
Return two-digit host country code.
Definition: GTools.cpp:2326
std::string tmpnam(void)
Return temporary file name.
Definition: GTools.cpp:421
GVector pow(const GVector &vector, const double &power)
Computes tanh of vector elements.
Definition: GVector.cpp:1422
unsigned int touint(const std::string &arg)
Convert string into unsigned integer value.
Definition: GTools.cpp:836
unsigned short toushort(const std::string &arg)
Convert string into unsigned short value.
Definition: GTools.cpp:806
GVector sin(const GVector &vector)
Computes sine of vector elements.
Definition: GVector.cpp:1316
Exception handler interface definition.
std::string toupper(const std::string &s)
Convert string to upper case.
Definition: GTools.cpp:941
std::string tolower(const std::string &s)
Convert string to lower case.
Definition: GTools.cpp:955
bool compare(const double &a, const double &b, const double &tol)
Compare two floating point values with tolerance.
Definition: GTools.cpp:2190
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:1738
std::string expand_env(const std::string &arg)
Expand environment variables in string.
Definition: GTools.cpp:214
int toint(const std::string &arg)
Convert string into integer value.
Definition: GTools.cpp:821
const double twopi
Definition: GMath.hpp:36
std::string filepath(const std::string &pathname, const std::string &filename)
Build file path from path name and file name.
Definition: GTools.cpp:393
virtual GXmlNode * append(const GXmlNode &node)
Append XML child node.
Definition: GXmlNode.cpp:287
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition: GTools.cpp:1143
std::string str2xml(const std::string &arg)
Convert special characters in string to XML character references.
Definition: GTools.cpp:1549
std::string fill(const std::string &s, const int &n)
Fill string with n strings of same type.
Definition: GTools.cpp:1044
#define G_PARFORMAT_LENGTH
Definition: GTools.cpp:70
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:1689
Filename class interface definition.
Mathematical function definitions.
GEnergy elogmean(const GEnergy &a, const GEnergy &b)
Computes log mean energy.
Definition: GTools.cpp:1290
double todouble(const std::string &arg)
Convert string into double precision value.
Definition: GTools.cpp:926
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:1200
float tofloat(const std::string &arg)
Convert string into single precision value.
Definition: GTools.cpp:911
GFilename xml_file_expand(const GXmlElement &xml, const std::string &filename)
Expand file name provided as XML attribute for loading.
Definition: GTools.cpp:1889
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition: GTools.cpp:489
void xml_check_type(const std::string &origin, GXmlElement &xml, const std::string &type)
Checks the model type.
Definition: GTools.cpp:1819