Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
LUPI_misc.cc
Go to the documentation of this file.
1/*
2# <<BEGIN-copyright>>
3# Copyright 2019, Lawrence Livermore National Security, LLC.
4# This file is part of the gidiplus package (https://github.com/LLNL/gidiplus).
5# gidiplus is licensed under the MIT license (see https://opensource.org/licenses/MIT).
6# SPDX-License-Identifier: MIT
7# <<END-copyright>>
8*/
9
10#include <limits.h>
11#include <stdlib.h>
12#include <sstream>
13#include <iostream>
14#include <iomanip>
15#include <ctype.h>
16
17#include <nf_utilities.h>
18
19#include <LUPI.hpp>
20
21namespace LUPI {
22
23/* *********************************************************************************************************//**
24 * If the build of GIDI+ defines the MACRO LUPI_printDeprecatedInformation, then all deprecated functions will
25 * print a message that they are deprecated.
26 *
27 * @param a_functionName [in] The name of the function (or method) that is deprecated.
28 * @param a_replacementName [in] The name of the function that replaces the deprecated function.
29 * @param a_asOf [in] Specifies the version of GIDI+ for which the function will no longer be available.
30 ***********************************************************************************************************/
31
32void deprecatedFunction( LUPI_maybeUnused std::string const &a_functionName, LUPI_maybeUnused std::string const &a_replacementName, LUPI_maybeUnused std::string const &a_asOf ) {
33
34#ifdef LUPI_printDeprecatedInformation
35 std::cerr << "The function '" << a_functionName << "' is decreated";
36 if( a_asOf != "" ) std::cerr << " and will no longer be available starting with GIDI+ '" << a_asOf << "'";
37 std::cerr << ".";
38 if( a_replacementName != "" ) std::cerr << " Please use '" << a_replacementName << "' instead.";
39 std::cerr << std::endl;
40#endif
41}
42
43/*! \class Exception
44 * Exception class for all GIDI exceptions thrown by GIDI functions.
45 */
46
47/* *********************************************************************************************************//**
48 * @param a_message [in] The message that the function what() will return.
49 ***********************************************************************************************************/
50
51Exception::Exception( std::string const & a_message ) :
52 std::runtime_error( a_message ) {
53
54}
55
56namespace Misc {
57
58/* *********************************************************************************************************//**
59 * This returns a copy of *a_string* with its leading (if *a_left* is **true**) and trailing (if *a_left* is **true**) white spaces removed.
60 *
61 * @param a_string [in] The string to copy and strip leading and trailing white spaces from.
62 * @param a_left [in] If **true**, white spaces are removed from the beginning of the string.
63 * @param a_right [in] If **true**, white spaces are removed from the ending of the string.
64 *
65 * @return The list of strings.
66 ***********************************************************************************************************/
67
68std::string stripString( std::string const &a_string, bool a_left, bool a_right ) {
69
70 std::string stripped( a_string );
71 std::string::iterator beginning = stripped.begin( ), ending = stripped.end( );
72
73 if( a_left ) {
74 for( ; beginning != ending; ++beginning )
75 if( !std::isspace( *beginning ) ) break;
76 }
77
78 if( ( beginning != ending ) && a_right ) {
79 --ending;
80 for( ; beginning != ending; --ending )
81 if( !std::isspace( *ending ) ) break;
82 ++ending;
83 }
84
85 stripped.erase( ending, stripped.end( ) );
86 stripped.erase( stripped.begin( ), beginning );
87
88 return( stripped );
89}
90
91/* *********************************************************************************************************//**
92 * This function splits that string *a_string* into separate strings using the delimiter character *a_delimiter*.
93 * If the delimiter is the space character, consecutive spaces are treated as one space, and leading and trailing
94 * white spaces are ignored.
95 *
96 * @param a_string [in] The string to split.
97 * @param a_delimiter [in] The delimiter character.
98 * @param a_strip [in] If **true**, white spaces are removed from the begining and ending of each string in the list returned.
99 *
100 * @return The list of strings.
101 ***********************************************************************************************************/
102
103std::vector<std::string> splitString( std::string const &a_string, char a_delimiter, bool a_strip ) {
104
105 std::stringstream stringStream( a_string );
106 std::string segment;
107 std::vector<std::string> segments;
108
109 while( std::getline( stringStream, segment, a_delimiter ) ) {
110 if( ( a_delimiter == ' ' ) && ( segment.size( ) == 0 ) ) continue;
111
112 if( a_strip ) segment = stripString( segment );
113 segments.push_back( segment );
114 }
115
116 return( segments );
117}
118
119/* *********************************************************************************************************//**
120 * This function splits that string *a_string* into separate strings using the delimiter string *a_delimiter*.
121 *
122 * @param a_string [in] The string to split.
123 * @param a_delimiter [in] The delimiter string.
124 * @param a_strip [in] If **true**, white spaces are removed from the begining and ending of each string in the list returned.
125 *
126 * @return The list of strings.
127 ***********************************************************************************************************/
128
129std::vector<std::string> splitString( std::string const &a_string, std::string const &a_delimiter, bool a_strip ) {
130
131 std::string segment;
132 std::vector<std::string> segments;
133
134 for( std::size_t index1 = 0; ; ) {
135 std::size_t index2 = a_string.find( a_delimiter, index1 );
136
137 segment = a_string.substr( index1, index2 - index1 );
138
139 if( a_strip ) segment = stripString( segment );
140 segments.push_back( segment );
141 if( index2 == std::string::npos ) break;
142
143 index1 = index2 + a_delimiter.size( );
144 }
145
146 return( segments );
147}
148
149/* *********************************************************************************************************//**
150 * This function adds together the strings in *a_strings* with *a_sep* between the strings in **a_strings**.
151 *
152 * @param a_delimiter [in] The delimiter string.
153 * @param a_strings [in] The string to split.
154 *
155 * @return A **std::string**.
156 ***********************************************************************************************************/
157
158std::string joinStrings( std::string const &a_sep, std::vector<std::string> a_strings ) {
159
160 std::string string;
161 std::string sep = "";
162 std::string const *sepPointer = &sep;
163
164 for( auto iter = a_strings.begin( ); iter != a_strings.end( ); ++iter ) {
165 string += *sepPointer + *iter;
166 sepPointer = &a_sep;
167 }
168
169 return( string );
170}
171
172/* *********************************************************************************************************//**
173 * This function replace one (or all if *a_all* is true) occurrence(s) of *a_old* in *a_string* with *a_new*.
174 *
175 * @param a_string [in] The string to split.
176 * @param a_old [in] The current sub-string in *a_string* that is replaced by *a_new*.
177 * @param a_new [in] The new sub-string that replace *a_old*..
178 * @param a_all [in] If **true** all occurrence of *a_old* are replaced by *a_new*; otherwise, only the first occurrence is replaced.
179 *
180 * @return A **std::string**.
181 ***********************************************************************************************************/
182
183std::string replaceString( std::string const &a_string, std::string const &a_old, std::string const &a_new, bool a_all ) {
184
185 std::string string( a_string );
186
187 while( true ) {
188 std::size_t index = string.find( a_old );
189 if( index == std::string::npos ) break;
190 string.replace( index, a_old.size( ), a_new );
191 if( !a_all ) break;
192 }
193
194 return( string );
195}
196
197/* *********************************************************************************************************//**
198 * This function splits that string *a_string* into separate strings using the delimiter character "/" as
199 * for a XLink. The delimiter character "/"'s in each quoted region of the string is not split.
200 *
201 * @param a_string [in] The XLink string to split.
202 *
203 * @return The XLink parts as a list of strings.
204 ***********************************************************************************************************/
205
206std::vector<std::string> splitXLinkString( std::string const &a_XLink ) {
207
208 char quote = ' ';
209 std::vector<std::string> elements;
210
211 std::size_t start = 0;
212
213 while( a_XLink[start] == '/' ) ++start;
214
215 std::size_t end = start;
216 std::size_t size = a_XLink.size( );
217
218 if( start != 0 ) {
219 elements.push_back( "" );
220 }
221
222 for( ; end < size ; ++end ) {
223 char current = a_XLink[end];
224 if( quote != ' ' ) { // Are we inside a quote?
225 if( current == quote ) quote = ' ';
226 continue;
227 }
228
229 if( ( current == '\'' ) || ( current == '"' ) ) { // Are we starting a quote?
230 quote = current;
231 continue;
232 }
233
234 if( current == '/' ) {
235 std::string element = a_XLink.substr( start, end - start );
236 elements.push_back( std::move( element ) );
237 while( a_XLink[end] == '/' ) ++end;
238 start = end;
239 if( end == size ) break; // Happens when XLink ends with '/'.
240 }
241 }
242
243 if( start < end ) {
244 std::string element = a_XLink.substr( start, end - start );
245 elements.push_back( element );
246 }
247
248 return( elements );
249}
250
251/* *********************************************************************************************************//**
252 * Converts a string to an integer. All characteros of the string must be valid int characters except for the trailing 0.
253 *
254 * @param a_string [in] The string to convert to an int.
255 * @param a_value [in] The converted int value.
256 *
257 * @return true if successful and false otherwise.
258 ***********************************************************************************************************/
259
260bool stringToInt( std::string const &a_string, int &a_value ) {
261
262 char const *digits = a_string.c_str( );
263 char *nonDigit;
264 long value = strtol( digits, &nonDigit, 10 );
265
266 if( digits == nonDigit ) return( false );
267 if( *nonDigit != 0 ) return( false );
268 if( ( value < INT_MIN ) || ( value > INT_MAX ) ) return( false );
269
270 a_value = static_cast<int>( value );
271 return( true );
272}
273
274/* *********************************************************************************************************//**
275 * Converts a string to an integer. All characteros of the string must be valid int characters except for the trailing 0.
276 *
277 * @param a_string [in] The string to convert to an int.
278 * @param a_value [in] The converted int value.
279 *
280 * @return true if successful and false otherwise.
281 ***********************************************************************************************************/
282
283bool stringToSize_t( std::string const &a_string, std::size_t &a_value ) {
284
285 char const *digits = a_string.c_str( );
286 char *nonDigit;
287 long value = strtol( digits, &nonDigit, 10 );
288
289 if( digits == nonDigit ) return( false );
290 if( *nonDigit != 0 ) return( false );
291 if( ( value < 0 ) || ( value > LONG_MAX ) ) return( false );
292
293 a_value = static_cast<std::size_t>( value );
294 return( true );
295}
296
297/* *********************************************************************************************************//**
298 * Returns a string that represent the arguments formatted per *a_format*.
299 *
300 * @param a_format [in] A *printf* like format specifier for converting a double to a string.
301 *
302 * @return The string representing the arguments formatted per *a_format*.
303 ***********************************************************************************************************/
304
305std::string argumentsToString( char const *a_format, ... ) {
306
307 va_list args;
308
309 va_start( args, a_format );
310 char *charStr = smr_vallocateFormatMessage( a_format, &args );
311 va_end( args );
312
313 std::string string( charStr );
314
315 free( charStr );
316 return( string );
317}
318
319/* *********************************************************************************************************//**
320 * Returns a string that represent the double **a_value** using a *printf* like format specifier.
321 *
322 * @param a_format [in] A *printf* like format specifier for converting a double to a string.
323 * @param a_value [in] The **double** to be converted to a string.
324 * @param a_reduceBits [in] If **true** the lowest digit or two are altered in an attempt to convert numbers like 4.764999999999999 and 4.765 to the same string.
325 ***********************************************************************************************************/
326
327std::string doubleToString3( char const *a_format, double a_value, bool a_reduceBits ) {
328
329
330 if( a_reduceBits ) { // The next line is an attempt to convert numbers like 4.764999999999999 and 4.765 to the same value.
331 a_value = std::stod( LUPI::Misc::argumentsToString("%.14e", a_value ) );
332 }
333
334 return( LUPI::Misc::argumentsToString( a_format, a_value ) );
335}
336
337/* *********************************************************************************************************//**
338 * Returns a string representation of *a_value* that contains the smallest number of character yet still agrees with *a_value*
339 * to *a_significantDigits* significant digits. For example, for *a_value* = 1.20000000001, "1.2" will be returned if *a_significantDigits*
340 * is less than 11, otherwise "1.20000000001" is returned.
341 *
342 * @param a_value [in/out] The double to convert to a string.
343 * @param a_significantDigits [in] The number of significant digits the string representation should agree with the double.
344 * @param a_favorEFormBy [in] The bigger this value the more likely an e-form will be favored in the string representation.
345 *
346 * @return A *std::string* instance.
347 ***********************************************************************************************************/
348
349std::string doubleToShortestString( double a_value, int a_significantDigits, int a_favorEFormBy ) {
350
351 char *charValue = nf_floatToShortestString( a_value, a_significantDigits, a_favorEFormBy, nf_floatToShortestString_trimZeros );
352
353 std::string stringValue( charValue );
354 free( charValue );
355
356 return( stringValue );
357}
358
359/* *********************************************************************************************************//**
360 * For internal use only.
361 *
362 * @param a_indent [in] A string containing the help line for an argument up to the description string.
363 * @param a_argc [in] The number of command arguments.
364 * @param a_argv [in] The list of command arguments.
365 ***********************************************************************************************************/
366
367void printCommand( std::string const &a_indent, int a_argc, char **a_argv ) {
368
369 std::cout << a_indent << a_argv[0];
370 for( int iargc = 1; iargc < a_argc; ++iargc ) std::cout << " " << a_argv[iargc];
371 std::cout << std::endl;
372}
373
374} // End of namespace Misc.
375
376} // End of namespace LUPI.
377
378#if defined (GIDIP_HAVE_COMPILER_FLOATING_POINT_EXCEPTIONS)
379
380#include <fenv.h>
381
382/* *********************************************************************************************************//**
383 * Turn on floating point exception sigfpe behavior.
384 * Possible exceptions are:
385 *
386 * FE_INEXACT The inexact exception.
387 * FE_DIVBYZERO The divide by zero exception.
388 * FE_UNDERFLOW The underflow exception.
389 * FE_OVERFLOW The overflow exception.
390 * FE_INVALID The invalid exception.
391 * FE_ALL_EXCEPT All of the above
392 *
393 * @param a_file [in] Filename this function is called from.
394 * @param a_line [in] Line this function is called from.
395 ***********************************************************************************************************/
396
397void LUPI_FPE_enable( char const *a_file, int a_line ) {
398
399 static int num_errors = 0;
400
401// feenableexcept() is gnu specific according to documentation, but appears to work using the intel compilers as well.
402// We are linking in a gnu library which enables this call.
403 int result = feenableexcept( FE_DIVBYZERO | FE_OVERFLOW | FE_INVALID );
404
405 if( result == -1 && num_errors < 3 ) {
406 num_errors++;
407 std::cerr << "LUPI_FPE_enable:: feenableexcept() returned -1: called from file " << a_file << " at line" << a_line << ".\n";
408 }
409}
410
411/* *********************************************************************************************************//**
412 * Disable floating point exception sigfpe behavior, and clear exception flags.
413 *
414 * @param a_file [in] Filename this function is called from.
415 * @param a_line [in] Line this function is called from.
416 ***********************************************************************************************************/
417
418void LUPI_FPE_disable_and_clear( char const *a_file, int a_line ) {
419
420 static int num_errors = 0;
421 fenv_t envp;
422
423// The feclearexcept() call is gnu specific and does not appear to work when I use it with the intel compiler.
424// However, the posix compliant feholdexcept() can be used to clear exceptions, so I am using it.
425 int result = feholdexcept(&envp);
426
427 if( result != 0 && num_errors < 3 ) {
428 num_errors++;
429 std::cerr << "LUPI_FPE_disable_and_clear:: feholdexcept returned error " << result << ": called from file " << a_file << " at line " << a_line << ".\n";
430 }
431}
432
433/* *********************************************************************************************************//**
434 * Test the fpe exception flags, and print out warnings or abort with fatal if they are set.
435 *
436 * @param a_file [in] Filename this function is called from.
437 * @param a_line [in] Line this function is called from.
438 ***********************************************************************************************************/
439
440void LUPI_FPE_test( char const *a_file, int a_line ) {
441
442 static int num_errors = 0;
443
444 if( fetestexcept(FE_DIVBYZERO) != 0 && num_errors < 10 ) {
445 num_errors++;
446 std::cerr << "LUPI_FPE_test:: division by 0.error: called from file " << a_file << " at line " << a_line << ".\n";
447 }
448
449 if( fetestexcept(FE_UNDERFLOW) != 0 && num_errors < 10 ) {
450 num_errors++;
451 std::cerr << "LUPI_FPE_test:: underflow error: called from file " << a_file << " at line " << a_line << ".\n";
452 }
453
454 if( fetestexcept(FE_OVERFLOW) != 0 && num_errors < 10 ) {
455 num_errors++;
456 std::cerr << "LUPI_FPE_test:: overflow error: called from file " << a_file << " at line " << a_line << ".\n";
457 }
458
459 if( fetestexcept(FE_INVALID) != 0 && num_errors < 10) {
460 num_errors++;
461 std::cerr << "LUPI_FPE_test:: invalid error: called from file " << a_file << " at line " << a_line << ".\n";
462 }
463}
464#endif
#define LUPI_maybeUnused
Exception(std::string const &a_message)
Definition LUPI_misc.cc:51
void free(voidpf ptr)
std::string doubleToShortestString(double a_value, int a_significantDigits=15, int a_favorEFormBy=0)
Definition LUPI_misc.cc:349
std::vector< std::string > splitXLinkString(std::string const &a_string)
Definition LUPI_misc.cc:206
std::string replaceString(std::string const &a_string, std::string const &a_old, std::string const &a_new, bool a_all)
Definition LUPI_misc.cc:183
std::string joinStrings(std::string const &a_sep, std::vector< std::string > a_strings)
Definition LUPI_misc.cc:158
void printCommand(std::string const &a_indent, int a_argc, char **a_argv)
Definition LUPI_misc.cc:367
std::vector< std::string > splitString(std::string const &a_string, char a_delimiter, bool a_strip=false)
Definition LUPI_misc.cc:103
std::string argumentsToString(char const *a_format,...)
Definition LUPI_misc.cc:305
bool stringToSize_t(std::string const &a_string, std::size_t &a_value)
Definition LUPI_misc.cc:283
std::string stripString(std::string const &a_string, bool a_left=true, bool a_right=true)
Definition LUPI_misc.cc:68
std::string doubleToString3(char const *a_format, double a_value, bool a_reduceBits=false)
Definition LUPI_misc.cc:327
bool stringToInt(std::string const &a_string, int &a_value)
Definition LUPI_misc.cc:260
Definition LUPI.hpp:40
void deprecatedFunction(std::string const &a_functionName, std::string const &a_replacementName, std::string const &a_asOf)
#define nf_floatToShortestString_trimZeros
char * nf_floatToShortestString(double value, int significantDigits, int favorEFormBy, int flags)
char * smr_vallocateFormatMessage(char const *fmt, va_list *args)
#define INT_MIN
Definition templates.hh:94
#define INT_MAX
Definition templates.hh:90