GammaLib 2.0.0
Loading...
Searching...
No Matches
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 ***************************************************************************/
80std::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 ***************************************************************************/
94std::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 ***************************************************************************/
131std::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 ***************************************************************************/
168std::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 ***************************************************************************/
214std::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 ***************************************************************************/
393std::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 ***************************************************************************/
421std::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 ***************************************************************************/
465std::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 ***************************************************************************/
489std::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 ***************************************************************************/
503std::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 ***************************************************************************/
517std::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 ***************************************************************************/
531std::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 ***************************************************************************/
545std::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 ***************************************************************************/
560std::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 ***************************************************************************/
582std::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 ***************************************************************************/
596std::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 ***************************************************************************/
615std::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 ***************************************************************************/
652std::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 ***************************************************************************/
688std::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 ***************************************************************************/
727std::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 ***************************************************************************/
767char* 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 ***************************************************************************/
791short 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 ***************************************************************************/
806unsigned 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 ***************************************************************************/
821int 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 ***************************************************************************/
836unsigned 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 ***************************************************************************/
851long 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 ***************************************************************************/
866unsigned 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 ***************************************************************************/
881long 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 ***************************************************************************/
896unsigned 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 ***************************************************************************/
911float 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 ***************************************************************************/
926double 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 ***************************************************************************/
941std::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 ***************************************************************************/
955std::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 ***************************************************************************/
983std::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 ***************************************************************************/
1044std::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 ***************************************************************************/
1070std::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 ***************************************************************************/
1094std::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 ***************************************************************************/
1118std::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 ***************************************************************************/
1143std::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 ***************************************************************************/
1167std::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 ***************************************************************************/
1200double 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 ***************************************************************************/
1248double 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
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 ***************************************************************************/
1312bool 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 ***************************************************************************/
1342bool 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 ***************************************************************************/
1366bool 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 ***************************************************************************/
1386void 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 ***************************************************************************/
1416std::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 ***************************************************************************/
1549std::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 ***************************************************************************/
1596bool 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 ***************************************************************************/
1637GXmlElement* 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 ***************************************************************************/
1689const 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 ***************************************************************************/
1738std::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 ***************************************************************************/
1777void 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 ***************************************************************************/
1819void 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 ***************************************************************************/
1855void 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 ***************************************************************************/
2036int 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 ***************************************************************************/
2107double 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 ***************************************************************************/
2190bool 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 ***************************************************************************/
2230std::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
2326std::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 ***************************************************************************/
2484GFilename 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}
Energy value class definition.
Exception handler interface definition.
Filename class interface definition.
FITS file class interface definition.
Mathematical function definitions.
#define G_CHAR_BUFFER
Definition GTools.cpp:71
#define G_XML2STRING
Definition GTools.cpp:66
#define G_PARFORMAT_LENGTH
Definition GTools.cpp:70
#define G_HTTP_QUERY
Definition GTools.cpp:67
Gammalib tools definition.
XML element node class interface definition.
Abstract XML node base class interface definition.
XML text node class interface definition.
Class that handles energies in a unit independent way.
Definition GEnergy.hpp:48
double MeV(void) const
Return energy in MeV.
Definition GEnergy.cpp:321
double log10MeV(void) const
Return log10 of energy in MeV.
Definition GEnergy.cpp:423
Filename class.
Definition GFilename.hpp:62
std::string path(void) const
Return access path.
std::string file(void) const
Return name of file.
std::string url(void) const
Return Uniform Resource Locator (URL)
bool is_empty(void) const
Signal if filename is empty.
XML element node class.
const GXmlAttribute * attribute(const int &index) const
Return attribute.
bool has_attribute(const std::string &name) const
Check if element has a given attribute.
Abstract XML node base class.
Definition GXmlNode.hpp:57
virtual GXmlNode * append(const GXmlNode &node)
Append XML child node.
Definition GXmlNode.cpp:287
virtual GXmlElement * element(const int &index)
Return pointer to GXMLElement child.
Definition GXmlNode.cpp:640
GFilename filename(void) const
Return filename of XML file.
Definition GXmlNode.cpp:546
virtual int elements(void) const
Return number of GXMLElement children of node.
Definition GXmlNode.cpp:586
XML text node class.
Definition GXmlText.hpp:43
const std::string & text(void) const
Return text.
Definition GXmlText.hpp:97
std::string parformat(const std::string &s, const int &indent=0)
Convert string in parameter format.
Definition GTools.cpp:1143
std::string number(const std::string &noun, const int &number)
Convert singular noun into number noun.
Definition GTools.cpp:1167
GFilename gamma_filename(const std::string &name)
Returns filename in .gamma directory.
Definition GTools.cpp:2484
bool is_infinite(const double &x)
Signal if argument is infinite.
Definition GTools.hpp:184
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
std::string strdate(void)
Return current date.
Definition GTools.cpp:727
std::string http_query(const std::string &host, const std::string &query)
Return response to a HTTP query.
Definition GTools.cpp:2230
bool is_notanumber(const double &x)
Signal if argument is not a number.
Definition GTools.hpp:201
GEnergy elogmean(const GEnergy &a, const GEnergy &b)
Computes log mean energy.
Definition GTools.cpp:1290
char * tochar(const std::string &arg)
Convert string to C string.
Definition GTools.cpp:767
long tolong(const std::string &arg)
Convert string into long value.
Definition GTools.cpp:851
std::string str(const unsigned short int &value)
Convert unsigned short integer value into string.
Definition GTools.cpp:489
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
double todouble(const std::string &arg)
Convert string into double precision value.
Definition GTools.cpp:926
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 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 compare(const double &a, const double &b, const double &tol)
Compare two floating point values with tolerance.
Definition GTools.cpp:2190
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 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 filepath(const std::string &pathname, const std::string &filename)
Build file path from path name and file name.
Definition GTools.cpp:393
std::string tolower(const std::string &s)
Convert string to lower case.
Definition GTools.cpp:955
unsigned long long toulonglong(const std::string &arg)
Convert string into unsigned long long value.
Definition GTools.cpp:896
int toint(const std::string &arg)
Convert string into integer value.
Definition GTools.cpp:821
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
std::string rstrip_chars(const std::string &arg, const std::string &chars)
Strip trailing character from string.
Definition GTools.cpp:131
std::string xml2str(const std::string &arg)
Convert XML character references in string to characters.
Definition GTools.cpp:1416
GFilename xml_file_reduce(const GXmlElement &xml, const std::string &filename)
Reduce file name provided for writing as XML attribute.
Definition GTools.cpp:1946
std::string strip_whitespace(const std::string &arg)
Strip leading and trailing whitespace from string.
Definition GTools.cpp:80
std::string str2xml(const std::string &arg)
Convert special characters in string to XML character references.
Definition GTools.cpp:1549
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
float tofloat(const std::string &arg)
Convert string into single precision value.
Definition GTools.cpp:911
std::string expand_env(const std::string &arg)
Expand environment variables in string.
Definition GTools.cpp:214
unsigned long toulong(const std::string &arg)
Convert string into unsigned long value.
Definition GTools.cpp:866
bool dir_exists(const std::string &dirname)
Checks if directory exists.
Definition GTools.cpp:1312
unsigned int touint(const std::string &arg)
Convert string into unsigned integer value.
Definition GTools.cpp:836
bool contains(const std::string &str, const std::string &substring)
Checks if a substring is in a string.
Definition GTools.cpp:1342
std::string host_country(const bool &force_query=false)
Return two-digit host country code.
Definition GTools.cpp:2326
short toshort(const std::string &arg)
Convert string into short value.
Definition GTools.cpp:791
double acos(const double &arg)
Computes acos by avoiding NaN due to rounding errors.
Definition GMath.cpp:69
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
void xml_check_parnum(const std::string &origin, const GXmlElement &xml, const int &number)
Checks number of parameters.
Definition GTools.cpp:1777
std::string tmpnam(void)
Return temporary file name.
Definition GTools.cpp:421
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
void warning(const std::string &origin, const std::string &message)
Emits warning.
Definition GTools.cpp:1386
const double twopi
Definition GMath.hpp:36
unsigned short toushort(const std::string &arg)
Convert string into unsigned short value.
Definition GTools.cpp:806
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 fill(const std::string &s, const int &n)
Fill string with n strings of same type.
Definition GTools.cpp:1044
std::string getenv(const std::string &arg)
Return value of environment variable.
Definition GTools.cpp:465
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
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
std::vector< std::string > split(const std::string &s, const std::string &sep)
Split string.
Definition GTools.cpp:983
int recv(int fd, char *buffer, int len, int flags, int timeout)
Checks whether a parameter has occured once.
Definition GTools.cpp:2036
std::string toupper(const std::string &s)
Convert string to upper case.
Definition GTools.cpp:941
GFilename xml_file_expand(const GXmlElement &xml, const std::string &filename)
Expand file name provided as XML attribute for loading.
Definition GTools.cpp:1889
long long tolonglong(const std::string &arg)
Convert string into long long value.
Definition GTools.cpp:881
void xml_check_type(const std::string &origin, GXmlElement &xml, const std::string &type)
Checks the model type.
Definition GTools.cpp:1819
std::string strip_chars(const std::string &arg, const std::string &chars)
Strip leading and trailing character from string.
Definition GTools.cpp:94