src/support/GTools.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *                       GTools.cpp - GammaLib tools                       *
00003  * ----------------------------------------------------------------------- *
00004  *  copyright (C) 2008-2016 by Juergen Knoedlseder                         *
00005  * ----------------------------------------------------------------------- *
00006  *                                                                         *
00007  *  This program is free software: you can redistribute it and/or modify   *
00008  *  it under the terms of the GNU General Public License as published by   *
00009  *  the Free Software Foundation, either version 3 of the License, or      *
00010  *  (at your option) any later version.                                    *
00011  *                                                                         *
00012  *  This program is distributed in the hope that it will be useful,        *
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
00015  *  GNU General Public License for more details.                           *
00016  *                                                                         *
00017  *  You should have received a copy of the GNU General Public License      *
00018  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
00019  *                                                                         *
00020  ***************************************************************************/
00021 /**
00022  * @file GTools.cpp
00023  * @brief Gammalib tools implementation
00024  * @author Juergen Knoedlseder
00025  */
00026 
00027 /* __ Includes ___________________________________________________________ */
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 #include <unistd.h>        // access() functions
00032 #include <fcntl.h>         // fcntl() functions
00033 #include <sys/stat.h>
00034 #include <sys/time.h>      // timeval
00035 #include <sys/select.h>    // select() function
00036 #include <sys/types.h>
00037 #include <sys/socket.h>    // recv() function
00038 #include <pwd.h>
00039 #include <cmath>
00040 #include <cfloat>
00041 #include <cctype>
00042 #include <cstdlib>         // std::getenv() function
00043 #include <cstring>         // std::strlen() function
00044 #include <iostream>
00045 #include <sstream>
00046 #include <algorithm>
00047 #include "GTools.hpp"
00048 #include "GException.hpp"
00049 #include "GFits.hpp"
00050 #include "GEnergy.hpp"
00051 #include "GFilename.hpp"
00052 #include "GXmlElement.hpp"
00053 
00054 /* __ Compile options ____________________________________________________ */
00055 
00056 /* __ Function name definitions __________________________________________ */
00057 #define G_XML2STRING                     "gammalib::xml2string(std::string&)"
00058 
00059 /* __ Coding definitions _________________________________________________ */
00060 #define G_PARFORMAT_LENGTH 29
00061 
00062 
00063 /***********************************************************************//**
00064  * @brief Strip leading and trailing whitespace from string
00065  *
00066  * @param[in] arg String from which whitespace should be stripped.
00067  * @return String with stripped whitespace.
00068  ***************************************************************************/
00069 std::string gammalib::strip_whitespace(const std::string& arg)
00070 {
00071     // Return result
00072     return (strip_chars(arg, " "));
00073 }
00074 
00075 
00076 /***********************************************************************//**
00077  * @brief Strip leading and trailing character from string
00078  *
00079  * @param[in] arg String from which character should be stripped.
00080  * @param[in] chars Character(s) to be stripped.
00081  * @return String with stripped characters.
00082  ***************************************************************************/
00083 std::string gammalib::strip_chars(const std::string& arg,
00084                                   const std::string& chars)
00085 {
00086     // Initialise empty result string
00087     std::string result;
00088 
00089     // Continue only if argument is not empty
00090     if (!arg.empty()) {
00091 
00092         // Get start and stop
00093         std::string::size_type start = arg.find_first_not_of(chars);
00094         std::string::size_type stop  = arg.find_last_not_of(chars);
00095 
00096         // Continue only if start and stop are valid
00097         if (start != std::string::npos && stop != std::string::npos) {
00098 
00099             // Continue only if stop is larger then or equal to  start
00100             if (start <= stop) {
00101                 result = arg.substr(start, stop-start+1);
00102             }
00103 
00104         } // endif: start and stop were valid
00105 
00106     } // endif: argument was not empty
00107 
00108     // Return result
00109     return result;
00110 }
00111 
00112 
00113 /***********************************************************************//**
00114  * @brief Strip trailing character from string
00115  *
00116  * @param[in] arg String from which character should be stripped.
00117  * @param[in] chars Character(s) to be stripped.
00118  * @return String with stripped characters.
00119  ***************************************************************************/
00120 std::string gammalib::rstrip_chars(const std::string& arg,
00121                                    const std::string& chars)
00122 {
00123     // Initialise empty result string
00124     std::string result;
00125 
00126     // Continue only if argument is not empty
00127     if (!arg.empty()) {
00128 
00129         // Get stop
00130         std::string::size_type stop = arg.find_last_not_of(chars);
00131 
00132         // Continue only if stop is valid
00133         if (stop != std::string::npos) {
00134             result = arg.substr(0, stop+1);
00135         }
00136 
00137     } // endif: argument was not empty
00138 
00139     // Return result
00140     return result;
00141 }
00142 
00143 
00144 /***********************************************************************//**
00145  * @brief Expand environment variables in string
00146  *
00147  * @param[in] arg String.
00148  * @return String with expected environment variables.
00149  *
00150  * Expands any environment variable that is found in a string. Valid
00151  * delimiters for environment variables are $ENV{<name>}, $ENV(<name>),
00152  * ${<name>}, $(<name>) and $<name> (in the last case the terminating
00153  * delimiter is either a / or a blank character or the end of the string).
00154  * Environment variables occuring within single quotes (') are ignored.
00155  * Environment variables that do not exist will be kept as specified.
00156  *
00157  * The method also replaces ~ or ~user by the user's home directory, ~+
00158  * by the value of the PWD environment variable and ~- by the value of the
00159  * OLDPWD variable. If the user or the PWD or OLDPWD variable are not found,
00160  * no replacement is done.
00161  *
00162  * This function has been inspired by the function ape_util_expand_env_var
00163  * from ape_util.c in the ape software developed at HEASARC.
00164  ***************************************************************************/
00165 std::string gammalib::expand_env(const std::string& arg)
00166 {
00167     // Set environment variable delimiters
00168     static const char* begin_delim[] = { "$ENV{", "$ENV(", "${", "$(", "$", "~" };
00169     static const char* end_delim[]   = { "}", ")", "}", ")", "/", "/" };
00170     static const int   num_delim     = 6;
00171 
00172     // Initialise result with argument
00173     std::string result = arg;
00174 
00175     // Initialise parse parameters
00176     size_t index    = 0;
00177     bool   in_quote = false;
00178 
00179     // Loop over string
00180     while (index < result.length()) {
00181 
00182         // If we have an escaped character then skip the current character
00183         // and the next one
00184         if (result[index] == '\\') {
00185             index += 2;
00186             continue;
00187         }
00188 
00189         // If we have a single quote then toggle the quote state
00190         if (result[index] == '\'') {
00191             in_quote = !in_quote;
00192             index++;
00193             continue;
00194         }
00195 
00196         // Don't expand environment variables inside single quotes. Note
00197         // that double quotes are ok.
00198         if (in_quote) {
00199             index++;
00200             continue;
00201         }
00202 
00203         // Find delimiter which indicates beginning of an environment variable
00204         size_t begin_length = 0;
00205         int    delim_idx    = 0;
00206         for (; delim_idx < num_delim; ++delim_idx) {
00207             size_t len = std::strlen(begin_delim[delim_idx]);
00208             if (result.compare(index, len, begin_delim[delim_idx]) == 0) {
00209                 begin_length = len;
00210                 break;
00211             }
00212         }
00213 
00214         // If we found a delimiter then process the environment variable
00215         if (begin_length > 0) {
00216 
00217             // Search for the termination delimiter of the environment
00218             // variable. There is a special case for delimiters 4 and 5:
00219             // It has always an end_length of zero as the / is not a real
00220             // delimiter, but just an indicator that the environment variable
00221             // ends. Another indicator is a blank. If the end of the
00222             // string has been reached this is also acceptable.
00223             size_t i_start    = index + begin_length;
00224             size_t i_end      = i_start;
00225             size_t end_length = 0;
00226             if (delim_idx == 4 || delim_idx == 5) {
00227                 while (i_end < result.length() &&
00228                        result.compare(i_end, 1, "/") != 0 &&
00229                        result.compare(i_end, 1, " ") != 0) {
00230                     i_end++;
00231                 }
00232             }
00233             else {
00234                 end_length = std::strlen(end_delim[delim_idx]);
00235                 while (i_end < result.length() &&
00236                        result.compare(i_end, end_length, end_delim[delim_idx]) != 0) {
00237                     i_end++;
00238                 }
00239             }
00240 
00241             // If termination delimiter has been found then expand the
00242             // environment variable
00243             if (i_end < result.length() || delim_idx == 4 || delim_idx == 5) {
00244 
00245                 // Extract environment variable name
00246                 std::string name        = result.substr(i_start, i_end-i_start);
00247                 size_t      name_length = name.length();
00248 
00249                 // Initialise pointer on environment variable
00250                 const char* env = NULL;
00251 
00252                 // Handle ~
00253                 if (delim_idx == 5) {
00254                     if (name_length == 0) {
00255                         if ((env = std::getenv("HOME")) == NULL) {
00256                             struct passwd *pw = getpwuid(getuid());
00257                             if (pw != NULL) {
00258                                 env = pw->pw_dir;
00259                             }
00260                         }
00261                     }
00262                     else {
00263                         if (name == "+") {
00264                             env = std::getenv("PWD");
00265                         }
00266                         else if (name == "-") {
00267                             env = std::getenv("OLDPWD");
00268                         }
00269                         else {
00270                             struct passwd *pw = getpwnam(name.c_str());
00271                             if (pw != NULL) {
00272                                 env = pw->pw_dir;
00273                             }
00274                         }
00275                     }
00276                 }
00277 
00278                 // ... otherwise get the environment variable
00279                 else {
00280                     env = std::getenv(name.c_str());
00281                 }
00282 
00283                 // If the environment variable has been found then replace
00284                 // it by its value
00285                 if (env != NULL) {
00286 
00287                     // Erase delimiters and environment variable
00288                     result.erase(index, begin_length+name_length+end_length);
00289 
00290                     // Set replacement string and its length
00291                     std::string replace(env);
00292                     size_t      replace_length = replace.length();
00293 
00294                     // Insert replacement string
00295                     result.insert(index, replace);
00296 
00297                     // Advance pointer
00298                     index += replace_length;
00299 
00300                 } // endif: environment variable has been found
00301 
00302                 // If no environment variable has been found then set
00303                 // index=i_end+1
00304                 else {
00305                     index = i_end + 1;
00306                 }
00307 
00308             } // endif: termination delimiter found
00309 
00310             // If no environment variable has been found then set index=i_end+1
00311             else {
00312                 index = i_end + 1;
00313             }
00314 
00315         } // endif: we found an environment variable delimiter
00316 
00317         // ... otherwise advance to next character
00318         else {
00319             index++;
00320         }
00321 
00322     } // endwhile: looped over string
00323 
00324     // Return result
00325     return result;
00326 }
00327 
00328 
00329 /***********************************************************************//**
00330  * @brief Build file path from path name and file name
00331  *
00332  * @param[in] pathname Path name.
00333  * @param[in] filename File name.
00334  * @return File path.
00335  *
00336  * Builds a file path by combining the @p pathname and the @p filename
00337  * following
00338  *
00339  *      filepath = pathname/filename
00340  *
00341  * If @p pathname is an empty string, the method simply returns the
00342  * @p filename.
00343  ***************************************************************************/
00344 std::string gammalib::filepath(const std::string& pathname,
00345                                const std::string& filename)
00346 {
00347     // Initialise filepath
00348     std::string filepath;
00349 
00350     // If path name is empty, simply return the file name
00351     if (pathname.empty()) {
00352         filepath = filename;
00353     }
00354 
00355     // ... otherwise combine both
00356     else {
00357         filepath = pathname + "/" + filename;
00358     }
00359 
00360     // Return the file path
00361     return filepath;
00362 }
00363 
00364 
00365 /***********************************************************************//**
00366  * @brief Convert unsigned short integer value into string
00367  *
00368  * @param[in] value Unsigned short integer to be converted into string.
00369  * @return String with unsigned short integer value.
00370  ***************************************************************************/
00371 std::string gammalib::str(const unsigned short int& value)
00372 {
00373     std::ostringstream s_value;
00374     s_value << value;
00375     return s_value.str();
00376 }
00377 
00378 
00379 /***********************************************************************//**
00380  * @brief Convert unsigned integer value into string
00381  *
00382  * @param[in] value Unsigned integer to be converted into string.
00383  * @return String with unsigned integer value.
00384  ***************************************************************************/
00385 std::string gammalib::str(const unsigned int& value)
00386 {
00387     std::ostringstream s_value;
00388     s_value << value;
00389     return s_value.str();
00390 }
00391 
00392 
00393 /***********************************************************************//**
00394  * @brief Convert unsigned long integer value into string
00395  *
00396  * @param[in] value Unsigned long integer to be converted into string.
00397  * @return String with unsigned long integer value.
00398  ***************************************************************************/
00399 std::string gammalib::str(const unsigned long int& value)
00400 {
00401     std::ostringstream s_value;
00402     s_value << value;
00403     return s_value.str();
00404 }
00405 
00406 
00407 /***********************************************************************//**
00408  * @brief Convert unsigned long long integer value into string
00409  *
00410  * @param[in] value Unsigned long long integer to be converted into string.
00411  * @return String with unsigned long long integer value.
00412  ***************************************************************************/
00413 std::string gammalib::str(const unsigned long long int& value)
00414 {
00415     std::ostringstream s_value;
00416     s_value << value;
00417     return s_value.str();
00418 }
00419 
00420 
00421 /***********************************************************************//**
00422  * @brief Convert short integer value into string
00423  *
00424  * @param[in] value Short integer to be converted into string.
00425  * @return String with short integer value.
00426  ***************************************************************************/
00427 std::string gammalib::str(const short int& value)
00428 {
00429     std::ostringstream s_value;
00430     s_value << value;
00431     return s_value.str();
00432 }
00433 
00434 
00435 /***********************************************************************//**
00436  * @brief Convert integer value into string
00437  *
00438  * @param[in] value Integer to be converted into string.
00439  * @return String with integer value.
00440  ***************************************************************************/
00441 std::string gammalib::str(const int& value)
00442 {
00443     std::ostringstream s_value;
00444     s_value << value;
00445     return s_value.str();
00446 }
00447 
00448 
00449 /***********************************************************************//**
00450  * @brief Convert long integer value into string
00451  *
00452  * @param[in] value Long integer to be converted into string.
00453  * @return String with long integer value.
00454  ***************************************************************************/
00455 std::string gammalib::str(const long int& value)
00456 {
00457     std::ostringstream s_value;
00458     s_value << value;
00459     return s_value.str();
00460 }
00461 
00462 
00463 /***********************************************************************//**
00464  * @brief Convert long long integer value into string
00465  *
00466  * @param[in] value Long long integer to be converted into string.
00467  * @return String with long long integer value.
00468  ***************************************************************************/
00469 std::string gammalib::str(const long long int& value)
00470 {
00471     std::ostringstream s_value;
00472     s_value << value;
00473     return s_value.str();
00474 }
00475 
00476   
00477 /***********************************************************************//**
00478  * @brief Convert single precision value into string
00479  *
00480  * @param[in] value Single precision value to be converted into string.
00481  * @param[in] precision Floating point precision.
00482  * @return String with single precision value.
00483  *
00484  * Converts a single precision value into a string. Any positive
00485  * @p precision argument specifies the exact number of digits after the
00486  * comma.
00487  ***************************************************************************/
00488 std::string gammalib::str(const float& value, const int& precision)
00489 {
00490     // Allocate output stream
00491     std::ostringstream s_value;
00492 
00493     // If specified then set the requested fixed point precision. Otherwise
00494     // use a precision that should be sufficient for floating point values.
00495     if (precision > 0) {
00496         s_value.precision(precision);
00497         s_value.setf(std::ios::fixed, std::ios::floatfield);
00498     }
00499     else {
00500         s_value.precision(7);
00501     }
00502 
00503     // Put floating point value in stream
00504     s_value << value;
00505 
00506     // Convert to a string
00507     std::string result = s_value.str();
00508 
00509     // Return result
00510     return result;
00511 }
00512 
00513 
00514 /***********************************************************************//**
00515  * @brief Convert double precision value into string
00516  *
00517  * @param[in] value Double precision value to be converted into string.
00518  * @param[in] precision Floating point precision.
00519  * @return String with double precision value.
00520  *
00521  * Converts a double precision value into a string. Any positive
00522  * @p precision argument specifies the exact number of digits after the
00523  * comma.
00524  ***************************************************************************/
00525 std::string gammalib::str(const double& value, const int& precision)
00526 {
00527     // Allocate output stream
00528     std::ostringstream s_value;
00529 
00530     // If specified then set the requested fixed point precision. Otherwise
00531     // use a precision that should be sufficient for floating point values.
00532     if (precision > 0) {
00533         s_value.precision(precision);
00534         s_value.setf(std::ios::fixed, std::ios::floatfield);
00535     }
00536     else {
00537         s_value.precision(15);
00538     }
00539 
00540     // Put double precision floating point value in stream
00541     s_value << value;
00542 
00543     // Convert to a string
00544     std::string result = s_value.str();
00545 
00546     // Return result
00547     return result;
00548 }
00549 
00550 
00551 /***********************************************************************//**
00552  * @brief Convert complex value into string
00553  *
00554  * @param[in] value Complex value to be converted into string.
00555  * @param[in] precision Floating point precision.
00556  * @return String with complex value.
00557  *
00558  * Converts a complex value into a string. Any positive @p precision argument
00559  * specifies the exact number of digits after the comma.
00560  ***************************************************************************/
00561 std::string gammalib::str(const std::complex<double>& value,
00562                           const int&                  precision)
00563 {
00564     // Allocate output stream
00565     std::ostringstream s_value;
00566 
00567     // If specified then set the requested fixed point precision. Otherwise
00568     // use a precision that should be sufficient for floating point values.
00569     if (precision > 0) {
00570         s_value.precision(precision);
00571         s_value.setf(std::ios::fixed, std::ios::floatfield);
00572     }
00573     else {
00574         s_value.precision(15);
00575     }
00576 
00577     // Put double precision floating point value in stream
00578     s_value << value.real();
00579     if (value.imag() < 0.0) {
00580         s_value << "-";
00581     }
00582     else {
00583         s_value << "+";
00584     }
00585     s_value << std::abs(value.imag()) << "j";
00586 
00587     // Convert to a string
00588     std::string result = s_value.str();
00589 
00590     // Return result
00591     return result;
00592 }
00593 
00594 
00595 
00596 /***********************************************************************//**
00597  * @brief Convert string to C string
00598  *
00599  * @param[in] arg String to be converted.
00600  * @return C string.
00601  *
00602  * Allocates a C string with the content of a C++ string.
00603  ***************************************************************************/
00604 char* gammalib::tochar(const std::string& arg)
00605 {
00606     // Allocate C string
00607     char* str = new char[arg.length()+1];
00608 
00609     // Copy characters
00610     for (std::size_t i = 0; i < arg.length(); ++i) {
00611         str[i] = arg[i];
00612     }
00613 
00614     // Set line end character
00615     str[arg.length()] = '\0';
00616 
00617     // Return C string
00618     return str;
00619 }
00620 
00621 
00622 /***********************************************************************//**
00623  * @brief Convert string into short value
00624  *
00625  * @param[in] arg String to be converted.
00626  * @return Short value.
00627  ***************************************************************************/
00628 short gammalib::toshort(const std::string& arg)
00629 {
00630     std::istringstream iss(arg);
00631     short              result;
00632     iss >> std::dec >> result;
00633     return result;
00634 }
00635 
00636 
00637 /***********************************************************************//**
00638  * @brief Convert string into unsigned short value
00639  *
00640  * @param[in] arg String to be converted.
00641  * @return Unsigned short value.
00642  ***************************************************************************/
00643 unsigned short gammalib::toushort(const std::string& arg)
00644 {
00645     std::istringstream iss(arg);
00646     unsigned short     result;
00647     iss >> std::dec >> result;
00648     return result;
00649 }
00650 
00651 
00652 /***********************************************************************//**
00653  * @brief Convert string into integer value
00654  *
00655  * @param[in] arg String to be converted.
00656  * @return Integer value.
00657  ***************************************************************************/
00658 int gammalib::toint(const std::string& arg)
00659 {
00660     std::istringstream iss(arg);
00661     int                result;
00662     iss >> std::dec >> result;
00663     return result;
00664 }
00665 
00666 
00667 /***********************************************************************//**
00668  * @brief Convert string into unsigned integer value
00669  *
00670  * @param[in] arg String to be converted.
00671  * @return Unsigned integer value.
00672  ***************************************************************************/
00673 unsigned int gammalib::touint(const std::string& arg)
00674 {
00675     std::istringstream iss(arg);
00676     unsigned int       result;
00677     iss >> std::dec >> result;
00678     return result;
00679 }
00680 
00681 
00682 /***********************************************************************//**
00683  * @brief Convert string into long value
00684  *
00685  * @param[in] arg String to be converted.
00686  * @return Long value.
00687  ***************************************************************************/
00688 long gammalib::tolong(const std::string& arg)
00689 {
00690     std::istringstream iss(arg);
00691     long               result;
00692     iss >> std::dec >> result;
00693     return result;
00694 }
00695 
00696 
00697 /***********************************************************************//**
00698  * @brief Convert string into unsigned long value
00699  *
00700  * @param[in] arg String to be converted.
00701  * @return Unsigned long value.
00702  ***************************************************************************/
00703 unsigned long gammalib::toulong(const std::string& arg)
00704 {
00705     std::istringstream iss(arg);
00706     unsigned long      result;
00707     iss >> std::dec >> result;
00708     return result;
00709 }
00710 
00711 
00712 /***********************************************************************//**
00713  * @brief Convert string into long long value
00714  *
00715  * @param[in] arg String to be converted.
00716  * @return Long long value.
00717  ***************************************************************************/
00718 long long gammalib::tolonglong(const std::string& arg)
00719 {
00720     std::istringstream iss(arg);
00721     long long          result;
00722     iss >> std::dec >> result;
00723     return result;
00724 }
00725 
00726 
00727 /***********************************************************************//**
00728  * @brief Convert string into unsigned long long value
00729  *
00730  * @param[in] arg String to be converted.
00731  * @return Unsigned long long value.
00732  ***************************************************************************/
00733 unsigned long long gammalib::toulonglong(const std::string& arg)
00734 {
00735     std::istringstream iss(arg);
00736     unsigned long long result;
00737     iss >> std::dec >> result;
00738     return result;
00739 }
00740 
00741 
00742 /***********************************************************************//**
00743  * @brief Convert string into single precision value
00744  *
00745  * @param[in] arg String to be converted.
00746  * @return Single precision value.
00747  ***************************************************************************/
00748 float gammalib::tofloat(const std::string& arg)
00749 {
00750     std::istringstream iss(arg);
00751     float              result;
00752     iss >> std::dec >> result;
00753     return result;
00754 }
00755 
00756 
00757 /***********************************************************************//**
00758  * @brief Convert string into double precision value
00759  *
00760  * @param[in] arg String to be converted.
00761  * @return Double precision value.
00762  ***************************************************************************/
00763 double gammalib::todouble(const std::string& arg)
00764 {
00765     std::istringstream iss(arg);
00766     double             result;
00767     iss >> std::dec >> result;
00768     return result;
00769 }
00770 
00771 
00772 /***********************************************************************//**
00773  * @brief Convert string to upper case
00774  *
00775  * @param[in] arg String to be converted to upper case.
00776  * @return String converted to upper case.
00777  ***************************************************************************/
00778 std::string gammalib::toupper(const std::string& arg)
00779 {
00780     std::string s = arg;
00781     std::transform(s.begin(), s.end(), s.begin(), ::toupper);
00782     return s;
00783 }
00784 
00785 
00786 /***********************************************************************//**
00787  * @brief Convert string to lower case
00788  *
00789  * @param[in] arg String to be converted to upper case.
00790  * @return String converted to lower case.
00791  ***************************************************************************/
00792 std::string gammalib::tolower(const std::string& arg)
00793 {
00794     std::string s = arg;
00795     std::transform(s.begin(), s.end(), s.begin(), ::tolower);
00796     return s;
00797 }
00798 
00799 
00800 /***********************************************************************//**
00801  * @brief Split string
00802  *
00803  * @param[in] s String to be splitted.
00804  * @param[in] sep Separator(s).
00805  * @return Vector of split strings.
00806  *
00807  * Splits a string on the basis of one or multiple separator characters. The
00808  * separator characters are provided by the @p sep argument. Subsequent
00809  * separator characters that are not seperated by some other characters will
00810  * lead to an empty string element, except for a blank separator where
00811  * subsequent blanks are takens as a single separator. Below a few examples
00812  * that illustrate how the function will split a given string.
00813  *
00814  *     "Name;RA;DEC" => ["Name","RA","DEC"] (sep=";")
00815  *     "My house is    red" => ["My","house","is","red"] (sep=" ")
00816  *     "IRF::FRONT" => ["IRF","","FRONT"] (sep=":")
00817  *     "Fields;RA,DEC,Flux" => ["Fields","RA","DEC","Flux"] (sep=";,")
00818  *     "Last;Field;" => ["Last","Field",""] (sep=";")
00819  ***************************************************************************/
00820 std::vector<std::string> gammalib::split(const std::string& s,
00821                                          const std::string& sep)
00822 {
00823     // Allocate result string vector
00824     std::vector<std::string> result;
00825 
00826     // Initialise counters
00827     std::size_t pos = 0;
00828     std::size_t len = s.length();
00829 
00830     // Loop over string
00831     while (pos < len && pos != std::string::npos) {
00832 
00833         // Get index of first separator occurence and preset the length
00834         // of the substring to the end of the string
00835         std::size_t index = s.find_first_of(sep, pos);
00836         std::size_t n     = std::string::npos;
00837 
00838         // If we did not reach the end then compute now the length of the
00839         // substring
00840         if (index != std::string::npos) {
00841             n = index-pos;
00842         }
00843 
00844         // If we have no whitespace separator and the length of the
00845         // substring is zero then push back an empty string. If the
00846         // length of the substring is positive then push back the
00847         // substring.
00848         if (sep != " " && n == 0) {
00849             result.push_back("");
00850         }
00851         else if (n > 0) {
00852             result.push_back(s.substr(pos, n));
00853         }
00854 
00855         // Go to the string position after the last separator
00856         pos = (index != std::string::npos) ? index + 1 : std::string::npos;
00857 
00858         // If the position is pointing right beyong the last string
00859         // character we terminated with a separator, hence we need to push
00860         // back one more empty string before we leave
00861         if (sep != " " && pos == len) {
00862             result.push_back("");
00863         }
00864 
00865     } // endwhile: there were still characters in the string
00866 
00867     // Return result
00868     return result;
00869 }
00870 
00871 
00872 /***********************************************************************//**
00873  * @brief Fill string with n strings of same type
00874  *
00875  * @param[in] s String to be filled.
00876  * @param[in] n Number of fillings.
00877  * @return Filled strings.
00878  *
00879  * Replicates a given string n time.
00880  ***************************************************************************/
00881 std::string gammalib::fill(const std::string& s, const int& n)
00882 {
00883     // Initialise result
00884     std::string result = "";
00885 
00886     // Replicate string
00887     for (int i = 0; i < n; ++i) {
00888         result.append(s);
00889     }
00890 
00891     // Return result
00892     return result;
00893 }
00894 
00895 
00896 /***********************************************************************//**
00897  * @brief Left justify string to achieve a length of n characters
00898  *
00899  * @param[in] s String to be centred.
00900  * @param[in] n Requested total width.
00901  * @param[in] c Fill character.
00902  * @return Left justified string.
00903  *
00904  * Left justify string by adding whitespace to the right to achieve a length
00905  * of n characters.
00906  ***************************************************************************/
00907 std::string gammalib::left(const std::string& s, const int& n, const char& c)
00908 {
00909     // Compute number of characters to fill right
00910     int n_right  = n - s.length();
00911 
00912     // Set result
00913     std::string result = s + fill(std::string(1,c), n_right);
00914 
00915     // Return result
00916     return result;
00917 }
00918 
00919 
00920 /***********************************************************************//**
00921  * @brief Right justify string to achieve a length of n characters
00922  *
00923  * @param[in] s String to be centred.
00924  * @param[in] n Requested total width.
00925  * @param[in] c Fill character.
00926  * @return Right justified string.
00927  *
00928  * Right justify string by adding whitespace to the left to achieve a length
00929  * of n characters.
00930  ***************************************************************************/
00931 std::string gammalib::right(const std::string& s, const int& n, const char& c)
00932 {
00933     // Compute number of characters to fill right
00934     int n_left  = n - s.length();
00935 
00936     // Set result
00937     std::string result = fill(std::string(1,c), n_left) + s;
00938 
00939     // Return result
00940     return result;
00941 }
00942 
00943 
00944 /***********************************************************************//**
00945  * @brief Centre string to achieve a length of n characters
00946  *
00947  * @param[in] s String to be centred.
00948  * @param[in] n Requested total width.
00949  * @param[in] c Left fill character.
00950  * @return Centred string.
00951  *
00952  * Centre string by adding whitespace to the left and the right to achieve a
00953  * length of n characters.
00954  ***************************************************************************/
00955 std::string gammalib::centre(const std::string& s, const int& n, const char& c)
00956 {
00957     // Compute number of characters to fill left and right
00958     int n_right = (n-s.length()) / 2;
00959     int n_left  = n - s.length() - n_right;
00960 
00961     // Set result
00962     std::string result = fill(std::string(1,c), n_left) + s + 
00963                          fill(std::string(1,c), n_right);
00964 
00965     // Return result
00966     return result;
00967 }
00968 
00969 
00970 /***********************************************************************//**
00971  * @brief Convert string in parameter format
00972  *
00973  * @param[in] s String to be converted.
00974  * @param[in] indent Indentation of parameter.
00975  * @return Parameter string.
00976  *
00977  * Converts and string into the parameter format of type "s ......: " with a
00978  * total length of G_PARFORMAT_LENGTH.
00979  ***************************************************************************/
00980 std::string gammalib::parformat(const std::string& s, const int& indent)
00981 {
00982     // Compute number of characters to fill right. Do not clip the string if
00983     // it is too long since we do not want to loose information.
00984     int n_right = G_PARFORMAT_LENGTH - s.length() - 3 - indent;
00985 
00986     // Set result
00987     std::string result = " " + s + " " + fill(".", n_right) + ": ";
00988 
00989     // Return result
00990     return result;
00991 }
00992 
00993 
00994 /***********************************************************************//**
00995  * @brief Convert singular noun into number noun
00996  *
00997  * @param[in] noun Singular noun.
00998  * @param[in] number Number of instance of noun.
00999  * @return Converted noun.
01000  *
01001  * Converts a singular noun into a number noun by appending a "s" to the
01002  * noun if the @p number of the instances of the noun is not one.
01003  ***************************************************************************/
01004 std::string gammalib::number(const std::string& noun, const int& number)
01005 {
01006     // Copy input noun
01007     std::string result(noun);
01008 
01009     // Append "s" if number if not one
01010     if (number != 1) {
01011         result += "s";
01012     }
01013 
01014     // Return result
01015     return result;
01016 }
01017 
01018 
01019 /***********************************************************************//**
01020  * @brief Compute photon flux between two energies for a power law
01021  *
01022  * @param[in] emin Minimum energy.
01023  * @param[in] emax Maximum energy.
01024  * @param[in] epivot Pivot energy.
01025  * @param[in] gamma Spectral index.
01026  * @return Photon flux under power law.
01027  *
01028  * Analytically computes
01029  * \f[\int_{E_{\rm min}}^{E_{\rm max}} 
01030  *                             \left( E/E_{\rm pivot} \right)^{\gamma} dE\f]
01031  * where
01032  * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum
01033  * energy, respectively, and
01034  * \f$E_{\rm pivot}\f$ is the pivot energy, and
01035  * \f$\gamma\f$ is the spectral index.
01036  ***************************************************************************/
01037 double gammalib::plaw_photon_flux(const double& emin, const double& emax,
01038                                   const double& epivot, const double& gamma)
01039 {
01040     // Initialise flux
01041     double flux = 0.0;
01042 
01043     // Continue only if emax > emin
01044     if (emax > emin) {
01045 
01046         // Compute photon flux. Computations dependend on the exponent. We
01047         // add here a kluge to assure numerical accuracy.
01048         double xmin     = emin/epivot;
01049         double xmax     = emax/epivot;
01050         double exponent = gamma + 1.0;
01051         if (std::abs(exponent) > 1.0e-11) {
01052             flux = epivot / exponent * (std::pow(xmax, exponent) -
01053                                         std::pow(xmin, exponent));
01054         }
01055         else {
01056             flux = epivot * (std::log(xmax) - std::log(xmin));
01057         }
01058 
01059     } // endif: emax > emin
01060 
01061     // Return result
01062     return flux;
01063 }
01064 
01065 
01066 /***********************************************************************//**
01067  * @brief Compute energy flux between two energies for a power law
01068  *
01069  * @param[in] emin Minimum energy.
01070  * @param[in] emax Maximum energy.
01071  * @param[in] epivot Pivot energy.
01072  * @param[in] gamma Spectral index.
01073  * @return Energy flux under power law.
01074  *
01075  * Analytically computes
01076  * \f[\int_{E_{\rm min}}^{E_{\rm max}} 
01077  *                           \left( E/E_{\rm pivot} \right)^{\gamma} E dE\f]
01078  * where
01079  * \f$E_{\rm min}\f$ and \f$E_{\rm max}\f$ are the minimum and maximum
01080  * energy, respectively, and
01081  * \f$E_{\rm pivot}\f$ is the pivot energy, and
01082  * \f$\gamma\f$ is the spectral index.
01083  ***************************************************************************/
01084 double gammalib::plaw_energy_flux(const double& emin, const double& emax,
01085                                   const double& epivot, const double& gamma)
01086 {
01087     // Initialise flux
01088     double flux = 0.0;
01089 
01090     // Continue only if emax > emin
01091     if (emax > emin) {
01092 
01093         // Compute energy flux. Computations dependend on the exponent. We
01094         // add here a kluge to assure numerical accuracy.
01095         double xmin     = emin/epivot;
01096         double xmax     = emax/epivot;
01097         double exponent = gamma + 2.0;
01098         double epivot2  = epivot * epivot;
01099         if (std::abs(exponent) > 1.0e-11) {
01100             flux = epivot2 / exponent * (std::pow(xmax, exponent) -
01101                                          std::pow(xmin, exponent));
01102         }
01103         else {
01104             flux = epivot2 * (std::log(xmax) - std::log(xmin));
01105         }
01106 
01107     } // endif: emax > emin
01108 
01109     // Return result
01110     return flux;
01111 }
01112 
01113 
01114 /***********************************************************************//**
01115  * @brief Computes log mean energy
01116  *
01117  * @param[in] a First energy.
01118  * @param[in] b Second energy.
01119  * @return Log mean energy.
01120  *
01121  * Computes the logarithmic mean energy
01122  * \f$10^{0.5 * (\log E_{\rm a} + \log E_{\rm b})}\f$
01123  * for two energies.
01124  ***************************************************************************/
01125 GEnergy gammalib::elogmean(const GEnergy& a, const GEnergy& b)
01126 {
01127     // Compute logarithmic mean energy
01128     GEnergy elogmean;
01129     double  eloga = a.log10MeV();
01130     double  elogb = b.log10MeV();
01131     elogmean.MeV(std::pow(10.0, 0.5 * (eloga + elogb)));
01132 
01133     // Return
01134     return elogmean;
01135 }
01136 
01137 
01138 /***********************************************************************//**
01139  * @brief Checks if directory exists
01140  *
01141  * @param[in] dirname Directory name.
01142  * @return True if directory exists, false otherwise.
01143  *
01144  * Checks if a directory exists. The function expands any environment
01145  * variable prior to checking.
01146  ***************************************************************************/
01147 bool gammalib::dir_exists(const std::string& dirname)
01148 {
01149     // Initialise result
01150     bool result = false;
01151 
01152     // Allocate file information structure
01153     struct stat info;
01154 
01155     // Get file information structure
01156     int ret = stat(gammalib::expand_env(dirname).c_str(), &info);
01157 
01158     // Check if we have a directory
01159     if (ret == 0 && S_ISDIR(info.st_mode)) {
01160         result = true;
01161     }
01162 
01163     // Return result
01164     return result;
01165 }
01166 
01167 
01168 /***********************************************************************//**
01169  * @brief Checks if a substring is in a string
01170  *
01171  * @param[in] str String you want to search in.
01172  * @param[in] substring String you are looking for in @p str.
01173  * @return True if a string contains a sub string.
01174  *
01175  * Checks if substring is contained in str
01176  ***************************************************************************/
01177 bool gammalib::contains(const std::string& str, const std::string& substring)
01178 {
01179     // Initialise result
01180     bool result = false;
01181 
01182     // checks if substring is in str
01183     if (str.find(substring) != std::string::npos) {
01184         result = true;
01185     }
01186 
01187     // Return result
01188     return result;
01189 }
01190 
01191 
01192 /***********************************************************************//**
01193  * @brief Checks if a string is contained in a vector of strings
01194  *
01195  * @param[in] strings Vector of strings you want to search in.
01196  * @param[in] string string you are looking for in strings.
01197  * @return True if a string is contained a vector.
01198  *
01199  * Checks if a string is contained in a vector of strings
01200  ***************************************************************************/
01201 bool gammalib::contains(const std::vector<std::string> strings,
01202                         const std::string&             string)
01203 {
01204     // Compute result
01205     bool result = std::find(strings.begin(), strings.end(), string) !=
01206                   strings.end();
01207 
01208     // Return result
01209     return result;
01210 }
01211 
01212 
01213 /***********************************************************************//**
01214  * @brief Emits warning
01215  *
01216  * @param[in] origin Name of method that emits warning.
01217  * @param[in] message Warning message.
01218  *
01219  * Writes a warning to the console.
01220  ***************************************************************************/
01221 void gammalib::warning(const std::string& origin,
01222                        const std::string& message)
01223 {
01224     // Compile option: enable/disable warnings
01225     #if defined(G_WARNINGS)
01226 
01227     // Set warning message
01228     std::string warning = "+++ WARNING in " + origin + ": " + message;
01229 
01230     // Writes warning to the console
01231     std::cout << warning << std::endl;
01232 
01233     // End of compile option
01234     #endif
01235 
01236     // Return
01237     return;
01238 }
01239 
01240 
01241 /***********************************************************************//**
01242  * @brief Convert XML character references in string to characters
01243  *
01244  * @param[in] arg String containing XML character references.
01245  * @return String with character reference replaced by respective characters.
01246  *
01247  * Converts all character references found in a string in their respective
01248  * characters. For more information about XML character references read
01249  * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
01250  ***************************************************************************/
01251 std::string gammalib::xml2str(const std::string& arg)
01252 {
01253     // Initialise string
01254     std::string result;
01255 
01256     // Iitialise position, lenghts and flags
01257     size_t length = arg.length();
01258     size_t pos    = 0;
01259     size_t start  = 0;
01260     size_t stop   = 0;
01261     size_t len    = 0;      // Length of string preceeding char. reference
01262     bool   found  = false;
01263 
01264     // Loop over string
01265     while (pos < length) {
01266 
01267         // If we have not yet found a character reference then search for
01268         // the next one. If we do not find one we break here.
01269         if (!found) {
01270             start = arg.find("&", pos);
01271             if (start != std::string::npos) {
01272                 len   = start - pos;
01273                 pos   = start;
01274                 found = true;
01275             }
01276             else {
01277                 break;
01278             }
01279         }
01280 
01281         // ... otherwise search for end of the actual character reference.
01282         // Throw an exception if no end is found.
01283         else {
01284             stop = arg.find(";", pos);
01285             if (stop != std::string::npos) {
01286 
01287                 // First attach leading string to the result
01288                 if (len > 0) {
01289                     result += arg.substr(start-len, len);
01290                 }
01291 
01292                 // Next extract character reference
01293                 std::string cref = arg.substr(start+1, stop-start-1);
01294                 len              = cref.length();
01295 
01296                 // Check for a numerical character reference
01297                 //TODO: Check that there are only valid characters in
01298                 //      numerical field
01299                 if (len >= 2 && cref[0] == '#') {
01300                     int number = -1;
01301                     if (cref[1] == 'x') {
01302                         number = (int)std::strtol(cref.substr(2,len-2).c_str(), NULL, 16);
01303                     }
01304                     else {
01305                         number = toint(cref.substr(1,len-1));
01306                     }
01307                     if (number != -1) {
01308                         result.push_back((char)number);
01309                     }
01310                     else {
01311                         std::string msg = "Could not extract number from "
01312                                           "numerical character reference &"+
01313                                           cref+";";
01314                         throw GException::invalid_argument(G_XML2STRING, msg);
01315                     }
01316                 }
01317 
01318                 // ... otherwise check for a character entity reference
01319                 // and push back the corresponding character to the result
01320                 // string
01321                 else {
01322                     if (cref == "quot") {
01323                         result.push_back((char)34);
01324                     }
01325                     else if (cref == "amp") {
01326                         result.push_back((char)38);
01327                     }
01328                     else if (cref == "apos") {
01329                         result.push_back((char)39);
01330                     }
01331                     else if (cref == "lt") {
01332                         result.push_back((char)60);
01333                     }
01334                     else if (cref == "gt") {
01335                         result.push_back((char)62);
01336                     }
01337                     else {
01338                         std::string msg = "Unknown character entity reference "
01339                                           "&"+cref+"; encountered in XML string \""+
01340                                           arg+"\".";
01341                         throw GException::invalid_argument(G_XML2STRING, msg);
01342                     }
01343                 }
01344 
01345                 // Signal that we're done and that we search for the
01346                 // next character reference
01347                 found = false;
01348                 pos   = stop + 1;
01349 
01350             } // endif: end of character reference found
01351 
01352             // ... otherwise throw an exception
01353             else {
01354                 std::string msg = "Missing ; character at end of character "
01355                                   "reference in XML string \""+arg+"\".";
01356                 throw GException::invalid_argument(G_XML2STRING, msg);
01357             }
01358 
01359         } // endelse: search for end of character reference
01360 
01361     } // endwhile
01362 
01363     // Append any pending string to the result
01364     if (pos < length) {
01365         len     = length - pos;
01366         result += arg.substr(pos, len);
01367     }
01368 
01369     // Return result
01370     return result;
01371 }
01372 
01373 
01374 /***********************************************************************//**
01375  * @brief Convert special characters in string to XML character references
01376  *
01377  * @param[in] arg String.
01378  * @return String with special characters replaced by character references.
01379  *
01380  * Converts all special characters found in a string into character
01381  * references. For more information about XML character references read
01382  * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
01383  ***************************************************************************/
01384 std::string gammalib::str2xml(const std::string& arg)
01385 {
01386     // Initialise string
01387     std::string result;
01388 
01389     // Loop over string
01390     for (int i = 0; i < arg.length(); ++i) {
01391 
01392         // Initialize string to add
01393         std::string character = arg.substr(i, 1);
01394 
01395         // Replace special characters
01396         if (character == "\"") {
01397             character = "&quot;";
01398         }
01399         else if (character == "&") {
01400             character = "&amp;";
01401         }
01402         else if (character == "'") {
01403             character = "&apos;";
01404         }
01405         else if (character == "<") {
01406             character = "&lt;";
01407         }
01408         else if (character == ">") {
01409             character = "&gt;";
01410         }
01411 
01412         // Append character
01413         result += character;
01414 
01415     }
01416 
01417     // Return result
01418     return result;
01419 }
01420 
01421 
01422 /***********************************************************************//**
01423  * @brief Checks if parameter with given name in XML element exists
01424  *
01425  * @param[in] xml XML element.
01426  * @param[in] name Parameter name.
01427  * @return True if parameter exists, false otherwise.
01428  *
01429  * Checks whether a parameter with given @p name exists in XML element.
01430  ***************************************************************************/
01431 bool gammalib::xml_has_par(const GXmlElement& xml, const std::string& name)
01432 {
01433     // Initialize flag
01434     bool found = false;
01435 
01436     // Search for parameter with given name
01437     for (int i = 0; i < xml.elements("parameter"); ++i) {
01438         const GXmlElement* element = xml.element("parameter", i);
01439         if (element->attribute("name") == name) {
01440             found = true;
01441             break;
01442         }
01443     }
01444 
01445     // Return
01446     return found;
01447 }
01448 
01449 
01450 /***********************************************************************//**
01451  * @brief Return pointer to parameter with given name in XML element
01452  *
01453  * @param[in] origin Method requesting parameter.
01454  * @param[in] xml XML element.
01455  * @param[in] name Parameter name.
01456  * @return Pointer to parameter XML element.
01457  *
01458  * @exception GException::invalid_value
01459  *            Invalid XML format encountered.
01460  *
01461  * Returns pointer to parameter with given @p name in XML element. If the
01462  * @p name is not found, a parameter with the given @p name is added. In
01463  * that respect the function differs from xml_get_par which does not add a
01464  * parameter element.
01465  *
01466  * The function checks for multiple occurences of a parameter and throws an
01467  * exception in case that more than one parameter with a given name is found.
01468  ***************************************************************************/
01469 GXmlElement* gammalib::xml_need_par(const std::string& origin,
01470                                     GXmlElement&       xml,
01471                                     const std::string& name)
01472 {
01473     // Initialize XML element pointer
01474     GXmlElement* par = NULL;
01475 
01476     // Number of elements
01477     int number = 0;
01478 
01479     // Search for parameter with given name
01480     for (int i = 0; i < xml.elements("parameter"); ++i) {
01481         GXmlElement* element = xml.element("parameter", i);
01482         if (element->attribute("name") == name) {
01483             par = element;
01484             number++;
01485         }
01486     }
01487 
01488     // Create parameter if none was found
01489     if (number == 0) {
01490         par = static_cast<GXmlElement*>(xml.append(GXmlElement("parameter name=\""+name+"\"")));
01491         number++;
01492     }
01493 
01494     // Check that there are no multiple parameters
01495     gammalib::xml_check_par(origin, name, number);
01496 
01497     // Return
01498     return par;
01499 }
01500 
01501 
01502 /***********************************************************************//**
01503  * @brief Return pointer to parameter with given name in XML element
01504  *
01505  * @param[in] origin Method requesting parameter.
01506  * @param[in] xml XML element.
01507  * @param[in] name Parameter name.
01508  * @return Pointer to parameter XML element.
01509  *
01510  * @exception GException::invalid_value
01511  *            Invalid XML format encountered.
01512  *
01513  * Returns pointer to parameter with given @p name in XML element. The
01514  * function checks whether the parameter has been found and throws an
01515  * exception if no parameter or multiple occurences of a parameter with given
01516  * @p name are found.
01517  ***************************************************************************/
01518 const GXmlElement* gammalib::xml_get_par(const std::string& origin,
01519                                          const GXmlElement& xml,
01520                                          const std::string& name)
01521 {
01522     // Initialize XML element pointer
01523     const GXmlElement* par = NULL;
01524 
01525     // Number of elements
01526     int number = 0;
01527 
01528     // Search for parameter with given name
01529     for (int i = 0; i < xml.elements("parameter"); ++i) {
01530         const GXmlElement* element = xml.element("parameter", i);
01531         if (element->attribute("name") == name) {
01532             par = element;
01533             number++;
01534         }
01535     }
01536 
01537     // Check that there is at least one parameter and that there are no
01538     // multiple parameters
01539     gammalib::xml_check_par(origin, name, number);
01540 
01541     // Return
01542     return par;
01543 }
01544 
01545 
01546 /***********************************************************************//**
01547  * @brief Return attribute value for a given parameter in XML element
01548  *
01549  * @param[in] origin Method requesting parameter.
01550  * @param[in] xml XML element.
01551  * @param[in] name Parameter name.
01552  * @param[in] attribute Attribute name.
01553  * @return Value of attribute.
01554  *
01555  * @exception GException::invalid_value
01556  *            Attribute not found.
01557  *
01558  * Returns the value of @p attribute of parameter @p name in XML element.
01559  * The function checks whether the parameter has been found and throws an
01560  * exception if no parameter or multiple occurences of a parameter with given
01561  * @p name are found. The function furthermore checks whether the attribute
01562  * exists. 
01563  ***************************************************************************/
01564 std::string gammalib::xml_get_attr(const std::string& origin,
01565                                    const GXmlElement& xml,
01566                                    const std::string& name,
01567                                    const std::string& attribute)
01568 {
01569     // Initialise attribute value
01570     std::string value = "";
01571 
01572     // Get parameter
01573     const GXmlElement* par = gammalib::xml_get_par(origin, xml, name);
01574 
01575     // Throw an exception if a parameter has not the requested attribute
01576     if (!par->has_attribute(attribute)) {
01577         std::string msg = "Attribute \""+attribute+"\" not found in XML "
01578                           "parameter \""+name+"\". Please verify the XML "
01579                           "format.";
01580         throw GException::invalid_value(origin, msg);
01581     }
01582 
01583     // Extract attribute
01584     value = par->attribute(attribute);
01585 
01586     // Return attribute value
01587     return value;
01588 }
01589 
01590 
01591 /***********************************************************************//**
01592  * @brief Checks whether a parameter has occured once
01593  *
01594  * @param[in] origin Method performing the check.
01595  * @param[in] name Parameter name.
01596  * @param[in] number Number of occurences of parameter.
01597  *
01598  * @exception GException::invalid_value
01599  *            Invalid XML format encountered.
01600  *
01601  * Throws an exception if a given parameter has not exactly occured once.
01602  * The exception text is adapted to the case that none or multiple parameters
01603  * have been found.
01604  ***************************************************************************/
01605 void gammalib::xml_check_par(const std::string& origin,
01606                              const std::string& name,
01607                              const int&         number)
01608 {
01609     // Throw case dependent exception
01610     if (number < 1) {
01611         std::string msg = "Parameter \""+name+"\" not found in XML element."
01612                           " Please verify the XML format.";
01613          throw GException::invalid_value(origin, msg);
01614     }
01615     else if (number > 1) {
01616         std::string msg = "Parameter \""+name+"\" found "+
01617                           gammalib::str(number)+" times in XML element."
01618                           " Please verify the XML format.";
01619         throw GException::invalid_value(origin, msg);
01620     }
01621 
01622     // Return
01623     return;
01624 }
01625 
01626 
01627 /***********************************************************************//**
01628  * @brief Expand file name provided as XML attribute for loading
01629  *
01630  * @param[in] xml XML element.
01631  * @param[in] filename File name.
01632  * @return Expanded file name.
01633  *
01634  * Expands file name provided as XML attribute for loading. If the file name
01635  * is not empty and has no path it is assumed that the file is located in the
01636  * same directory as the XML file, and the XML file access path is prepended
01637  * to the file name.
01638  ***************************************************************************/
01639 GFilename gammalib::xml_file_expand(const GXmlElement& xml,
01640                                     const std::string& filename)
01641 {
01642     // Set file name
01643     GFilename fname(filename);
01644 
01645     // If the file name is not empty and has no path we assume that the file
01646     // name is a relative file name with respect to the XML file access path
01647     // and we therefore prepend the XML file access path to the file name
01648     if (!fname.is_empty() && fname.path().length() == 0) {
01649         fname = xml.filename().path() + fname;
01650     }
01651 
01652     // Return file name
01653     return fname;
01654 }
01655 
01656 
01657 /***********************************************************************//**
01658  * @brief Reduce file name provided for writing as XML attribute
01659  *
01660  * @param[in] xml XML element.
01661  * @param[in] filename File name.
01662  * @return Reduced file name.
01663  *
01664  * Reduces file name provided for writing as XML attribute. If the file name
01665  * is not empty and has the same access path as the XML file it is assumed
01666  * that both files are located in the same directory, and the access path is
01667  * stripped from the file name.
01668  ***************************************************************************/
01669 GFilename gammalib::xml_file_reduce(const GXmlElement& xml,
01670                                     const std::string& filename)
01671 {
01672     // Set file name
01673     GFilename fname(filename);
01674 
01675     // If the file name is not empty and has the same access path as the XML
01676     // file it is assumed that both files are located in the same directory,
01677     // and the access path is stripped from the file name.
01678     if (!fname.is_empty() && fname.path() == xml.filename().path()) {
01679         fname = fname.file();
01680     }
01681 
01682     // Return file name
01683     return fname;
01684 }
01685 
01686 
01687 /***********************************************************************//**
01688  * @brief Checks whether a parameter has occured once
01689  *
01690  * @param[in] fd Socket file descriptor.
01691  * @param[out] buffer Buffer to hold data.
01692  * @param[in] len Maximum number of bytes to recv().
01693  * @param[in] flags Flags (as the fourth param to recv() ).
01694  * @param[in] timeout Timeout in milliseconds.
01695  * @return recv() error code, -2 == timeout
01696  *
01697  * This function implements the recv() function with a timeout. The timeout
01698  * is specified in milliseconds.
01699  ***************************************************************************/
01700 int gammalib::recv(int fd, char *buffer, int len, int flags, int timeout)
01701 {
01702     // Initialise error code with time out
01703     int error = -2;
01704     
01705     // Initialize the set
01706     fd_set readset;
01707     FD_ZERO(&readset);
01708     FD_SET(fd, &readset);
01709    
01710     // Initialize time out struct
01711     struct timeval tv;
01712     if (timeout >= 1000) {
01713         tv.tv_sec  = timeout/1000;
01714         tv.tv_usec = 0;
01715     }
01716     else {
01717         tv.tv_sec  = 0;
01718         tv.tv_usec = timeout*1000;
01719     }
01720     
01721     // select()
01722     int result = select(fd+1, &readset, NULL, NULL, &tv);
01723 
01724     // Check status
01725     if (result < 0) {
01726         error = -1;
01727     }
01728     else if (result > 0 && FD_ISSET(fd, &readset)) {
01729 
01730         // Initialise flags
01731         int iof = -1;
01732 
01733         // Set non-blocking mode
01734         if ((iof = fcntl(fd, F_GETFL, 0)) != -1) {
01735             fcntl(fd, F_SETFL, iof | O_NONBLOCK);
01736         }
01737         
01738         // Receive data
01739         result = ::recv(fd, buffer, len, flags);
01740         
01741         // Set as before
01742         if (iof != -1) {
01743             fcntl(fd, F_SETFL, iof);
01744         }
01745         
01746         // Set error
01747         error = result;
01748     }
01749     
01750     // Return error
01751     return error;
01752 }

Generated on Tue Jan 24 12:37:25 2017 for GammaLib by  doxygen 1.4.7