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 = """; 01398 } 01399 else if (character == "&") { 01400 character = "&"; 01401 } 01402 else if (character == "'") { 01403 character = "'"; 01404 } 01405 else if (character == "<") { 01406 character = "<"; 01407 } 01408 else if (character == ">") { 01409 character = ">"; 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 }