util.h
Go to the documentation of this file.
00001 // File: $Id$
00002 // Author: John Wu <John.Wu at acm.org> Lawrence Berkeley National Laboratory
00003 // Copyright 2000-2012 the Regents of the University of California
00004 #ifndef IBIS_UTIL_H
00005 #define IBIS_UTIL_H
00006 
00007 
00008 
00009 
00010 #if defined(_WIN32) && defined(_MSC_VER) && defined(_DEBUG)
00011 #define _CRTDBG_MAP_ALLOC
00012 #include <stdlib.h>
00013 #include <crtdbg.h>
00014 #else
00015 #include <stdlib.h>
00016 #endif
00017 #include "const.h"
00018 
00019 #include <cctype>       // std::isspace
00020 #include <cstring>      // std::strcpy
00021 #include <stdio.h>      // sprintf, remove
00022 //#if HAVE_SYS_STAT_H
00023 #include <sys/stat.h>   // stat, mkdir, chmod
00024 //#endif
00025 //#if HAVE_FCNTL_H
00026 #include <fcntl.h>      // open, close
00027 //#endif
00028 #include <map>          // std::map
00029 #include <string>       // std::string
00030 #include <limits>       // std::numeric_limits
00031 #include <sstream>      // std::ostringstream used by ibis::util::logger
00032 
00033 #include <float.h>
00034 #include <math.h>       // fabs, floor, ceil, log10, ...
00035 #if !defined(unix) && defined(_WIN32)
00036 #include <windows.h>
00037 #include <io.h>
00038 #include <fcntl.h>      // _O_..
00039 int truncate(const char*, uint32_t);
00040 #include <direct.h>     // _rmdir
00041 #include <sys/stat.h>   // _stat, mkdir, chmod
00042 #define rmdir _rmdir
00043 //#elif HAVE_UNISTD_H
00044 #else
00045 #include <unistd.h>     // read, lseek, truncate, rmdir
00046 #endif
00047 
00048 // minimum size for invoking mmap operation, default to 1 MB
00049 #ifndef FASTBIT_MIN_MAP_SIZE
00050 #define FASTBIT_MIN_MAP_SIZE 1048576
00051 #endif
00052 
00053 #if ! (defined(HAVE_MMAP) || defined(_MSC_VER))
00054 #  if defined(_XOPEN_SOURCE)
00055 #    define HAVE_MMAP _XOPEN_SOURCE - 0 >= 500
00056 #  elif defined(_POSIX_C_SOURCE)
00057 #    define HAVE_MMAP _POSIX_C_SOURCE - 0 >= 0
00058 #  else
00059 #    define HAVE_MMAP defined(unix)||defined(linux)||defined(__APPLE__)||defined(__CYGWIN__)
00060 #  endif
00061 #endif
00062 
00063 #if (HAVE_MMAP+0>0) || (defined(_WIN32) && defined(_MSC_VER))
00064 #define HAVE_FILE_MAP 1
00065 #endif
00066 
00067 #ifndef DBL_EPSILON
00068 #define DBL_EPSILON 2.2204460492503131e-16
00069 #else
00070 // some wrongly define it to be 1.1e-16
00071 #undef  DBL_EPSILON
00072 #define DBL_EPSILON 2.2204460492503131e-16
00073 #endif
00074 
00075 #ifndef FASTBIT_FLOAT_NULL
00076 #define FASTBIT_FLOAT_NULL std::numeric_limits<float>::quiet_NaN()
00077 #endif
00078 #ifndef FASTBIT_DOUBLE_NULL
00079 #define FASTBIT_DOUBLE_NULL std::numeric_limits<double>::quiet_NaN()
00080 #endif
00081 
00083 #if !defined(HAVE_GCC_ATOMIC32) && defined(WITHOUT_FASTBIT_CONFIG_H)
00084 #if __GNUC__+0 >= 4 && defined(LINUX)
00085 #define HAVE_GCC_ATOMIC32 2
00086 #endif
00087 #endif
00088 #if !defined(HAVE_GCC_ATOMIC64) && defined(WITHOUT_FASTBIT_CONFIG_H)
00089 #if defined(__IA64__) || defined(__x86_64__) || defined(__ppc64__)
00090 #if __GNUC__+0 >= 4 && defined(LINUX)
00091 #define HAVE_GCC_ATOMIC64 2
00092 #endif
00093 #endif
00094 #endif
00095 
00097 #if defined(_MSC_VER) && defined(_WIN32)
00098 #ifndef HAVE_WIN_ATOMIC32
00099 #if defined(NTDDI_VERSION) && defined(NTDDI_WIN2K)
00100 #if NTDDI_VERSION >= NTDDI_WIN2K
00101 #define HAVE_WIN_ATOMIC32
00102 #endif
00103 #elif defined(WINVER)
00104 #if WINVER >= 0x0500
00105 #define HAVE_WIN_ATOMIC32
00106 #endif
00107 #endif
00108 #endif
00109 #ifndef HAVE_WIN_ATOMIC64
00110 #if defined(NTDDI_VERSION) && defined(NTDDI_WINVISTA)
00111 #if NTDDI_VERSION >= NTDDI_WINVISTA
00112 #define HAVE_WIN_ATOMIC64
00113 #endif
00114 #elif defined(WINVER)
00115 #if WINVER >= 0x0600
00116 #define HAVE_WIN_ATOMIC64
00117 #endif
00118 #endif
00119 #endif
00120 #endif
00121 
00122 // mapping the names of the low level IO functions defined in <unistd.h>
00123 #if defined(_MSC_VER) && defined(_WIN32)
00124 #define UnixOpen  ::_open
00125 #define UnixClose ::_close
00126 #define UnixRead  ::_read
00127 #define UnixWrite ::_write
00128 #define UnixSeek  ::_lseek
00129 #define UnixFlush  ::_commit
00130 #define UnixSnprintf ::_snprintf
00131 #define UnixStat  ::_stat
00132 #define UnixFStat ::_fstat
00133 #define Stat_T    struct _stat
00134 #else
00135 #define UnixOpen  ::open
00136 #define UnixClose ::close
00137 #define UnixRead  ::read
00138 #define UnixWrite ::write
00139 #define UnixSeek  ::lseek
00140 #define UnixFlush ::fsync
00141 #define UnixSnprintf ::snprintf
00142 #define UnixStat  ::stat
00143 #define UnixFStat ::fstat
00144 #define Stat_T    struct stat
00145 #endif
00146 
00147 // define the option for opening a file in read only mode
00148 #if defined(O_RDONLY)
00149 #if defined(O_LARGEFILE)
00150 #if defined(O_BINARY)
00151 #define OPEN_READONLY O_RDONLY | O_BINARY | O_LARGEFILE
00152 #else
00153 #define OPEN_READONLY O_RDONLY | O_LARGEFILE
00154 #endif
00155 #elif defined(O_BINARY)
00156 #define OPEN_READONLY O_RDONLY | O_BINARY
00157 #else
00158 #define OPEN_READONLY O_RDONLY
00159 #endif
00160 #elif defined(_O_RDONLY)
00161 #if defined(_O_LARGEFILE)
00162 #define OPEN_READONLY _O_RDONLY | _O_LARGEFILE | _O_BINARY
00163 #else
00164 #define OPEN_READONLY _O_RDONLY | _O_BINARY
00165 #endif
00166 #endif
00167 // define the option for opening a new file for writing
00168 #if defined(O_WRONLY)
00169 #if defined(O_LARGEFILE)
00170 #if defined(O_BINARY)
00171 #define OPEN_WRITENEW O_WRONLY | O_BINARY | O_CREAT | O_TRUNC | O_LARGEFILE
00172 #else
00173 #define OPEN_WRITENEW O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE
00174 #endif
00175 #elif defined(O_BINARY)
00176 #define OPEN_WRITENEW O_WRONLY | O_BINARY | O_CREAT | O_TRUNC
00177 #else
00178 #define OPEN_WRITENEW O_WRONLY | O_CREAT | O_TRUNC
00179 #endif
00180 #elif defined(_O_WRONLY)
00181 #if defined(_O_LARGEFILE)
00182 #define OPEN_WRITENEW _O_WRONLY|_O_CREAT|_O_TRUNC|_O_LARGEFILE|_O_BINARY
00183 #else
00184 #define OPEN_WRITENEW _O_WRONLY|_O_CREAT|_O_TRUNC|_O_BINARY
00185 #endif
00186 #endif
00187 // define the option for opening an existing file for writing
00188 #if defined(O_WRONLY)
00189 #if defined(O_LARGEFILE)
00190 #if defined(O_BINARY)
00191 #define OPEN_WRITEADD O_WRONLY | O_BINARY | O_CREAT | O_LARGEFILE
00192 #else
00193 #define OPEN_WRITEADD O_WRONLY | O_CREAT| O_LARGEFILE
00194 #endif
00195 #elif defined(O_BINARY)
00196 #define OPEN_WRITEADD O_WRONLY | O_BINARY | O_CREAT
00197 #else
00198 #define OPEN_WRITEADD O_WRONLY | O_CREAT
00199 #endif
00200 #elif defined(_O_WRONLY)
00201 #if defined(_O_LARGEFILE)
00202 #define OPEN_WRITEADD _O_WRONLY | _O_CREAT | _O_LARGEFILE | _O_BINARY
00203 #else
00204 #define OPEN_WRITEADD _O_WRONLY | _O_CREAT | _O_BINARY
00205 #endif
00206 #endif
00207 // define the option for opening a file for reading and writing
00208 #if defined(O_RDWR)
00209 #if defined(O_LARGEFILE)
00210 #if defined(O_BINARY)
00211 #define OPEN_READWRITE O_RDWR | O_BINARY | O_CREAT | O_LARGEFILE
00212 #else
00213 #define OPEN_READWRITE O_RDWR | O_CREAT | O_LARGEFILE
00214 #endif
00215 #elif defined(O_BINARY)
00216 #define OPEN_READWRITE O_RDWR | O_BINARY | O_CREAT
00217 #else
00218 #define OPEN_READWRITE O_RDWR | O_CREAT
00219 #endif
00220 #elif defined(_O_RDWR)
00221 #if defined(_O_LARGEFILE)
00222 #define OPEN_READWRITE _O_RDWR | _O_CREAT | _O_LARGEFILE | _O_BINARY
00223 #else
00224 #define OPEN_READWRITE _O_RDWR | _O_CREAT | _O_BINARY
00225 #endif
00226 #endif
00227 // define the option for opening an existing file for appending only
00228 #if defined(O_WRONLY)
00229 #if defined(O_LARGEFILE)
00230 #if defined(O_BINARY)
00231 #define OPEN_APPENDONLY O_WRONLY | O_BINARY | O_CREAT | O_APPEND | O_LARGEFILE
00232 #else
00233 #define OPEN_APPENDONLY O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE
00234 #endif
00235 #elif defined(O_BINARY)
00236 #define OPEN_APPENDONLY O_WRONLY | O_BINARY | O_CREAT | O_APPEND
00237 #else
00238 #define OPEN_APPENDONLY O_WRONLY | O_CREAT | O_APPEND
00239 #endif
00240 #elif defined(_O_WRONLY)
00241 #if defined(_O_LARGEFILE)
00242 #define OPEN_APPENDONLY _O_WRONLY | _O_CREAT | _O_APPEND | _O_LARGEFILE | _O_BINARY
00243 #else
00244 #define OPEN_APPENDONLY _O_WRONLY | _O_CREAT | _O_APPEND | _O_BINARY
00245 #endif
00246 #endif
00247 // the default file mode (associate with _O_CREAT)
00248 #if defined(_MSC_VER) && defined(_WIN32)
00249 #define OPEN_FILEMODE _S_IREAD | _S_IWRITE
00250 #elif defined(S_IRGRP) && defined(S_IWGRP) && defined(S_IROTH)
00251 #define OPEN_FILEMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
00252 #else
00253 #define OPEN_FILEMODE S_IRUSR | S_IWUSR
00254 #endif
00255 
00256 #if defined(_WIN32) && defined(_MSC_VER)
00257 // needed for numeric_limits<>::max, min function calls
00258 #ifdef max
00259 #undef max
00260 #endif
00261 #ifdef min
00262 #undef min
00263 #endif
00264 #endif
00265 
00266 #ifndef FASTBIT_CS_PATTERN_MATCH
00267 // By default use case sensitive match for string values in evaluating SQL
00268 // LIKE statements.  Explicitly set this to 0 when compiling to allow case
00269 // insensitive evaluations.
00270 #define FASTBIT_CS_PATTERN_MATCH 1
00271 #endif
00272 
00273 // The meta characters used in ibis::util::strMatch.
00274 #define STRMATCH_META_CSH_ANY '*'
00275 #define STRMATCH_META_CSH_ONE '?'
00276 #define STRMATCH_META_SQL_ANY '%'
00277 #define STRMATCH_META_SQL_ONE '_'
00278 #define STRMATCH_META_ESCAPE '\\'
00279 
00280 // // The function isfinite is a macro defined in math.h according to
00281 // // opengroup.org.  As of 2011, only MS visual studio does not have a
00282 // // definition for isfinite, but it has _finite in float,h.
00283 // #if defined(_MSC_VER) && defined(_WIN32)
00284 // inline int isfinite(double x) {return _finite(x);}
00285 // #elif !defined(isfinite)
00286 // #define isfinite finite
00287 // #endif
00288 
00289 #define LOGGER(v) \
00290 if (false == (v)) ; else ibis::util::logger(0)() 
00291 // need these silly intermediate macro functions to force the arguments to
00292 // be evaluated before ## is applied
00293 #define IBIS_JOIN_MACRO2(X, Y) X##Y
00294 #define IBIS_JOIN_MACRO(X, Y) IBIS_JOIN_MACRO2(X, Y)
00295 #ifdef __GNUC__
00296 #define IBIS_GUARD_NAME IBIS_JOIN_MACRO(_guard, __LINE__) __attribute__( ( unused ) )
00297 #else
00298 #define IBIS_GUARD_NAME IBIS_JOIN_MACRO(_guard, __LINE__)
00299 #endif
00300 #define IBIS_BLOCK_GUARD \
00301     ibis::util::guard IBIS_GUARD_NAME = ibis::util::makeGuard
00302 
00303 namespace std { // extend namespace std slightly
00304     // specialization of less<> to work with char*
00305     template <> struct less< char* > {
00306         bool operator()(const char*x, const char*y) const {
00307             return strcmp(x, y) < 0;
00308         }
00309     };
00310 
00311     // specialization of less<> on const char* (case sensitive comparison)
00312     template <> struct less< const char* > {
00313         bool operator()(const char* x, const char* y) const {
00314             return strcmp(x, y) < 0;
00315         }
00316     };
00317 
00318     template <> struct less< ibis::rid_t > {
00319         bool operator()(const ibis::rid_t& x, const ibis::rid_t& y) const {
00320             return (x < y);
00321         }
00322     };
00323 
00324     template <> struct less< const ibis::rid_t* > {
00325         bool operator()(const ibis::rid_t* x, const ibis::rid_t* y) const {
00326             return (*x < *y);
00327         }
00328     };
00329 } // namespace std
00330 
00331 namespace ibis {
00334     class resource;     
00335     class bitvector;    
00336     class column;       
00337     class fileManager;  
00338     class horometer;    
00339     class index;        
00340     class roster;       
00341     class bitvector64;  
00342 
00343     class dictionary;   
00344     class bundle;       
00345     class colValues;    
00346 
00347     class fromClause;   
00348     class whereClause;  
00349     class selectClause; 
00350 
00351 
00353     extern FASTBIT_CXX_DLLSPEC partList datasets;
00354 
00355     typedef std::vector<colValues*> colList; 
00356 
00358     FASTBIT_CXX_DLLSPEC ibis::resource& gParameters();
00359 
00362     class FASTBIT_CXX_DLLSPEC nameList {
00363     public:
00364         nameList() : cstr(0), buff(0) {};
00365         nameList(const char* str) : cstr(0), buff(0) {select(str);}
00366         ~nameList() {if (cstr) clear();}
00367 
00368         bool empty() const {return cstr == 0;}
00369         const char* operator*() const {return cstr;};
00370         uint32_t size() const {return cvec.size();};
00371 
00373         void select(const char* str);
00375         void add(const char* str);
00379         uint32_t find(const char* key) const;
00380 
00381         const char* operator[](uint32_t i) const {return cvec[i];}
00382         typedef std::vector< const char* >::const_iterator const_iterator;
00383         const_iterator begin() const {return cvec.begin();}
00384         const_iterator end() const {return cvec.end();}
00385 
00386         void clear()
00387         {cvec.clear(); delete [] cstr; delete [] buff; buff=0; cstr=0;}
00388 
00389     private:
00390         typedef std::vector< const char * > compStore;
00391         char* cstr;     // copy of the names as a single string
00392         char* buff;     // same as cstr, but delimiter is \0
00393         compStore cvec; // contains pointers to buff, for easier access
00394 
00395         nameList(const nameList&);
00396         nameList& operator=(const nameList&);
00397     }; // class nameList
00398 
00401     typedef std::map< const char*, part*, lessi > partAssoc;
00402 
00404     class bad_alloc : public std::bad_alloc {
00405     public:
00409         bad_alloc(const char *m="unknown") throw() : mesg_(m) {};
00410         virtual ~bad_alloc() throw() {}
00411         virtual const char* what() const throw() {return mesg_;}
00412 
00413     private:
00416         const char *mesg_;
00417     }; // bad_alloc
00418 
00420     namespace util {
00422         extern const char* charTable;
00424         extern const short unsigned charIndex[];
00426         extern const char* delimiters;
00428         extern const int log2table[256];
00435         extern FASTBIT_CXX_DLLSPEC pthread_mutex_t envLock;
00436 
00438         inline char* trim(char* str);
00440         char* strnewdup(const char* s);
00442         char* strnewdup(const char* s, const uint32_t n);
00444         inline void removeTail(char* str, char tail);
00445         char* getString(const char* buf);
00446         const char* getToken(char*& str, const char* tok_chrs);
00447         int readInt(int64_t& val, const char *&str,
00448                     const char* del=ibis::util::delimiters);
00449         int readUInt(uint64_t& val, const char *&str,
00450                      const char* del=ibis::util::delimiters);
00451         int readDouble(double& val, const char *&str,
00452                        const char* del=ibis::util::delimiters);
00453         FASTBIT_CXX_DLLSPEC int readString(std::string& str, const char*& buf,
00454                                            const char *delim=0);
00455 
00456         int64_t read(int, void*, int64_t);
00457 
00460         void removeDir(const char* name, bool leaveDir=false);
00462         int makeDir(const char* dir);
00465         FASTBIT_CXX_DLLSPEC off_t getFileSize(const char* name);
00468         int copy(const char* to, const char* from);
00469 
00473         inline void setVerboseLevel(int v) {ibis::gVerbose=v;}
00475         FASTBIT_CXX_DLLSPEC const char* userName();
00477         uint32_t serialNumber();
00478         void uniformFraction(const long unsigned idx,
00479                              long unsigned &denominator,
00480                              long unsigned &numerator);
00481         inline double rand(); 
00482 
00484         FASTBIT_CXX_DLLSPEC uint32_t checksum(const char* str, uint32_t sz);
00485         inline uint32_t checksum(uint32_t a, uint32_t b);
00486         std::string shortName(const std::string& longname);
00487         std::string randName(const std::string& longname);
00489 
00491         void int2string(std::string &str, unsigned val);
00492         void int2string(std::string &str, unsigned v1, unsigned v2);
00493         void int2string(std::string &str, unsigned v1,
00494                         unsigned v2, unsigned v3);
00495         void int2string(std::string &str, const std::vector<unsigned>& val);
00496         void encode64(uint64_t, std::string&);
00497         int  decode64(uint64_t&, const std::string&);
00498         int  decode16(uint64_t&, const char*);
00499         std::string groupby1000(uint64_t);
00501 
00504         double incrDouble(const double&);
00505         double decrDouble(const double&);
00506         void   eq2range(const double&, double&, double&);
00509         inline double coarsen(const double in, unsigned prec=2);
00512         double compactValue(double left, double right,
00513                             double start=0.0);
00514 
00517         double compactValue2(double left, double right,
00518                              double start=0.0);
00519 
00521         void setNaN(double& val);
00522         void setNaN(float& val);
00523 
00527         template <typename Tin, typename Tout>
00528         void round_down(const Tin& inval, Tout& outval) {
00529             outval = ((double)std::numeric_limits<Tout>::min() > inval ?
00530                       std::numeric_limits<Tout>::min() :
00531                       (double)std::numeric_limits<Tout>::max() <= inval ?
00532                       std::numeric_limits<Tout>::max() :
00533                       static_cast<Tout>(inval));
00534         }
00538         template <typename Tin, typename Tout>
00539         void round_up(const Tin& inval, Tout& outval) {
00540             outval = ((double)std::numeric_limits<Tout>::min() >= inval ?
00541                       std::numeric_limits<Tout>::min() :
00542                       (double) std::numeric_limits<Tout>::max() < inval ?
00543                       std::numeric_limits<Tout>::max() :
00544                       static_cast<Tout>(inval) +
00545                       ((inval-static_cast<Tin>(static_cast<Tout>(inval))) > 0));
00546         }
00548         template <typename Tin>
00549         void round_up(const Tin& inval, float&);
00551         template <typename Tin>
00552         void round_up(const Tin& inval, double& outval) {
00553             outval = static_cast<double>(inval);
00554         }
00555 
00557         inline int log2(uint32_t x) {
00558             register uint32_t xx, xxx;
00559             return (xx = x >> 16)
00560                 ? (xxx = xx >> 8) ? 24 + log2table[xxx] : 16 + log2table[xx]
00561                 : (xxx = x >> 8) ? 8 + log2table[xxx] : log2table[x];
00562         }
00564         inline int log2(uint64_t x) {
00565             register uint32_t xx;
00566             return (xx = x >> 32)
00567                 ? 32 + log2(xx)
00568                 : log2(static_cast<uint32_t>(x));
00569         }
00571 
00572         FASTBIT_CXX_DLLSPEC void
00573         logMessage(const char* event, const char* fmt, ...);
00574         FASTBIT_CXX_DLLSPEC FILE* getLogFile();
00575         int writeLogFileHeader(FILE *fptr, const char* fname);
00576         FASTBIT_CXX_DLLSPEC void closeLogFile();
00577         FASTBIT_CXX_DLLSPEC int setLogFileName(const char* filename);
00578         FASTBIT_CXX_DLLSPEC const char* getLogFileName();
00579 
00583         FASTBIT_CXX_DLLSPEC bool strMatch(const char* str, const char* pat);
00584 
00586         const ibis::bitvector64& outerProduct(const ibis::bitvector& a,
00587                                               const ibis::bitvector& b,
00588                                               ibis::bitvector64& c);
00591         const ibis::bitvector64& outerProductUpper(const ibis::bitvector& a,
00592                                                    const ibis::bitvector& b,
00593                                                    ibis::bitvector64& c);
00594 
00596         long intersect(const std::vector<ibis::bitvector> &bits1,
00597                        const std::vector<ibis::bitvector> &bits2,
00598                        std::vector<ibis::bitvector> &res);
00600         long intersect(const std::vector<ibis::bitvector> &bits1,
00601                        const std::vector<ibis::bitvector> &bits2,
00602                        const std::vector<ibis::bitvector> &bits3,
00603                        std::vector<ibis::bitvector> &res);
00604         void clear(ibis::array_t<ibis::bitvector*> &bv) throw();
00605         void clear(ibis::partList &pl) throw();
00606         void updateDatasets(void);
00607 
00610         inline const char* getVersionString() {
00611             return FASTBIT_STRING;
00612         }
00619         inline int getVersionNumber() {
00620 #ifdef FASTBIT_IBIS_INT_VERSION
00621             return FASTBIT_IBIS_INT_VERSION;
00622 #else
00623             return 1030000;
00624 #endif
00625         }
00626 
00628         void getLocalTime(char *str);
00630         void getGMTime(char *str);
00631         void secondsToString(const time_t, char *str);
00632 
00633 
00634 #if defined(WIN32) && ! defined(__CYGWIN__)
00635         char* getpass_r(const char *prompt, char *buffer, uint32_t buflen);
00636         char* getpass(const char* prompt);
00637 #else
00638         inline char *itoa(int value, char *str, int /* radix */) {
00639             sprintf(str,"%d",value);
00640             return str;
00641         }
00642 #endif
00643 
00645         template <typename T> inline void
00646         clearVec(std::vector<T*> &v) {
00647             const size_t nv = v.size();
00648             for (size_t j = 0; j < nv; ++j)
00649                 delete v[j];
00650             v.clear();
00651         } // clearVec
00652 
00661         class FASTBIT_CXX_DLLSPEC logger {
00662         public:
00664             logger(int blanks=0);
00666             ~logger();
00668             std::ostream& operator()(void) {return mybuffer;}
00669 
00670         protected:
00672             std::ostringstream mybuffer;
00673 
00674         private:
00675             logger(const logger&);
00676             logger& operator=(const logger&);
00677         }; // logger
00678 
00681         class ioLock {
00682         public:
00683             ioLock() {
00684 #if defined(PTW32_STATIC_LIB)
00685                 if (mutex == PTHREAD_MUTEX_INITIALIZER) {
00686                     int ierr = pthread_mutex_init(&mutex, 0);
00687                     if (ierr != 0)
00688                         throw "ioLock failed to initialize the necessary mutex";
00689                 }
00690 #endif
00691                 if (0 != pthread_mutex_lock(&mutex))
00692                     throw "ioLock failed to obtain a lock";
00693             }
00694             ~ioLock() {
00695                 (void) pthread_mutex_unlock(&mutex);
00696             }
00697         private:
00698             // every instantiation of this class locks on the same mutex
00699             static pthread_mutex_t mutex;
00700 
00701             ioLock(const ioLock&) {}; // can not copy
00702             ioLock& operator=(const ioLock&);
00703         };
00704 
00706         class mutexLock {
00707         public:
00708             mutexLock(pthread_mutex_t* lk, const char* m)
00709                 : mesg(m), lock(lk) {
00710                 LOGGER(ibis::gVerbose > 10)
00711                     << "util::mutexLock -- acquiring lock (" << lock
00712                     << ") for " << mesg;
00713                 if (0 != pthread_mutex_lock(lock)) {
00714                     throw "mutexLock failed to obtain a lock";
00715                 }
00716             }
00717             ~mutexLock() {
00718                 LOGGER(ibis::gVerbose > 10)
00719                     << "util::mutexLock -- releasing lock (" << lock
00720                     << ") for " << mesg;
00721                 (void) pthread_mutex_unlock(lock);
00722             }
00723 
00724         private:
00725             const char *mesg;
00726             pthread_mutex_t *lock;
00727 
00728             mutexLock() : mesg(0), lock(0) {}; // no default constructor
00729             mutexLock(const mutexLock&); // can not copy
00730             mutexLock& operator=(const mutexLock&);
00731         }; // mutexLock
00732 
00736         class quietLock {
00737         public:
00738             quietLock(pthread_mutex_t *lk) : lock(lk) {
00739                 if (0 != pthread_mutex_lock(lock))
00740                     throw "quietLock failed to obtain a mutex lock";
00741             }
00742             ~quietLock() {
00743                 (void) pthread_mutex_unlock(lock);
00744             }
00745 
00746         private:
00747             pthread_mutex_t *lock;
00748 
00749             quietLock(); // no default constructor
00750             quietLock(const quietLock&); // can not copy
00751             quietLock& operator=(const quietLock&);
00752         }; // quietLock
00753 
00755         class readLock {
00756         public:
00757             readLock(pthread_rwlock_t* lk, const char* m)
00758                 : mesg(m), lock(lk) {
00759                 if (0 != pthread_rwlock_rdlock(lock)) {
00760                     throw "readLock failed to obtain a lock";
00761                 }
00762             }
00763             ~readLock() {
00764                 (void) pthread_rwlock_unlock(lock);
00765             }
00766 
00767         private:
00768             const char *mesg;
00769             pthread_rwlock_t *lock;
00770 
00771             readLock() : mesg(0), lock(0) {}; // no default constructor
00772             readLock(const readLock&); // can not copy
00773             readLock& operator=(const readLock&);
00774         }; // readLock
00775 
00777         class writeLock {
00778         public:
00779             writeLock(pthread_rwlock_t* lk, const char* m)
00780                 : mesg(m), lock(lk) {
00781                 if (0 != pthread_rwlock_wrlock(lock)) {
00782                     throw "writeLock failed to obtain a lock";
00783                 }
00784             }
00785             ~writeLock() {
00786                 int ierr = pthread_rwlock_unlock(lock);
00787                 if (ierr != 0) {
00788                     throw "writeLock failed to release the lock";
00789                 }
00790             }
00791 
00792         private:
00793             const char *mesg;
00794             pthread_rwlock_t *lock;
00795 
00796             writeLock() : mesg(0), lock(0) {}; // no default constructor
00797             writeLock(const writeLock&); // can not copy
00798             writeLock& operator=(const writeLock&);
00799         }; // writeLock
00800 
00807         class FASTBIT_CXX_DLLSPEC counter {
00808         public:
00809             ~counter() {
00810 #if defined(HAVE_GCC_ATOMIC32)
00811 #elif defined(HAVE_WIN_ATOMIC32)
00812 #else
00813                 (void)pthread_mutex_destroy(&lock_);
00814 #endif
00815             }
00816             counter() : count_(0) {
00817 #if defined(HAVE_GCC_ATOMIC32)
00818 #elif defined(HAVE_WIN_ATOMIC32)
00819 #else
00820                 if (0 != pthread_mutex_init(&lock_, 0))
00821                     throw ibis::bad_alloc
00822                         ("util::counter failed to initialize mutex lock");
00823 #endif
00824             }
00825 
00827             uint32_t operator()() {
00828 #if defined(HAVE_GCC_ATOMIC32)
00829                 return __sync_fetch_and_add(&count_, 1);
00830 #elif defined(HAVE_WIN_ATOMIC32)
00831                 return InterlockedIncrement((volatile long *)&count_)-1;
00832 #else
00833                 ibis::util::quietLock lck(&lock_);
00834                 uint32_t ret = count_;
00835                 ++ count_;
00836                 return ret;
00837 #endif
00838             }
00840             void reset() {
00841 #if defined(HAVE_GCC_ATOMIC32)
00842                 (void) __sync_fetch_and_sub(&count_, count_);
00843 #elif defined(HAVE_WIN_ATOMIC32)
00844                 (void) InterlockedExchange((volatile long *)&count_, 0);
00845 #else
00846                 ibis::util::quietLock lck(&lock_);
00847                 count_ = 0;
00848 #endif
00849             }
00851             uint32_t value() const {
00852                 return count_;
00853             }
00854 
00855         private:
00856 #if defined(HAVE_GCC_ATOMIC32)
00857 #elif defined(HAVE_WIN_ATOMIC32)
00858 #else
00859             mutable pthread_mutex_t lock_; 
00860 #endif
00861             volatile uint32_t count_; 
00862 
00864             counter(const counter&);
00866             counter& operator=(const counter&);
00867         }; // counter
00868 
00883         class FASTBIT_CXX_DLLSPEC sharedInt32 {
00884         public:
00885             sharedInt32() : val_(0) {
00886 #if defined(HAVE_GCC_ATOMIC32)
00887 #elif defined(HAVE_WIN_ATOMIC32)
00888 #else
00889                 if (pthread_mutex_init(&mytex, 0) != 0)
00890                     throw "pthread_mutex_init failed for sharedInt";
00891 #endif
00892             }
00893 
00894             ~sharedInt32() {
00895 #if defined(HAVE_GCC_ATOMIC32)
00896 #elif defined(HAVE_WIN_ATOMIC32)
00897 #else
00898                 (void)pthread_mutex_destroy(&mytex);
00899 #endif
00900             }
00901 
00903             uint32_t operator()() const {return val_;}
00904 
00906             uint32_t operator++() {
00907 #if defined(HAVE_GCC_ATOMIC32)
00908                 return __sync_add_and_fetch(&val_, 1);
00909 #elif defined(HAVE_WIN_ATOMIC32)
00910                 return InterlockedIncrement((volatile long *)&val_);
00911 #else
00912                 ibis::util::quietLock lock(&mytex);
00913                 ++ val_;
00914                 return val_;
00915 #endif
00916             }
00917 
00919             uint32_t operator--() {
00920 #if defined(HAVE_GCC_ATOMIC32)
00921                 return __sync_sub_and_fetch(&val_, 1);
00922 #elif defined(HAVE_WIN_ATOMIC32)
00923                 return InterlockedDecrement((volatile long *)&val_);
00924 #else
00925                 ibis::util::quietLock lock(&mytex);
00926                 -- val_;
00927                 return val_;
00928 #endif
00929             }
00930 
00932             void operator+=(const uint32_t rhs) {
00933 #if defined(HAVE_GCC_ATOMIC32)
00934                 (void) __sync_add_and_fetch(&val_, rhs);
00935 #elif defined(HAVE_WIN_ATOMIC32)
00936                 (void) InterlockedExchangeAdd((volatile long *)&val_, rhs);
00937 #else
00938                 ibis::util::quietLock lock(&mytex);
00939                 val_ += rhs;
00940 #endif
00941             }
00942 
00944             void operator-=(const uint32_t rhs) {
00945 #if defined(HAVE_GCC_ATOMIC32)
00946                 (void) __sync_sub_and_fetch(&val_, rhs);
00947 #elif defined(HAVE_WIN_ATOMIC32)
00948                 (void) InterlockedExchangeAdd((volatile long *)&val_,
00949                                               -(long)rhs);
00950 #else
00951                 ibis::util::quietLock lock(&mytex);
00952                 val_ -= rhs;
00953 #endif
00954             }
00955 
00957             void swap(sharedInt32 &rhs) {
00958                 uint32_t tmp = rhs.val_;
00959                 rhs.val_ = val_;
00960                 val_ = tmp;
00961             }
00962 
00963         private:
00964             uint32_t volatile val_; 
00965 #if defined(HAVE_GCC_ATOMIC32)
00966 #elif defined(HAVE_WIN_ATOMIC32)
00967 #else
00968             pthread_mutex_t mytex; 
00969 #endif
00970 
00971             sharedInt32(const sharedInt32&); // no copy constructor
00972             sharedInt32& operator=(const sharedInt32&); // no assignment
00973         }; // sharedInt32
00974 
00981         class sharedInt64 {
00982         public:
00983             sharedInt64() : val_(0) {
00984 #if defined(HAVE_GCC_ATOMIC64)
00985 #elif defined(HAVE_WIN_ATOMIC64)
00986 #else
00987                 if (pthread_mutex_init(&mytex, 0) != 0)
00988                     throw "pthread_mutex_init failed for sharedInt";
00989 #endif
00990             }
00991 
00992             ~sharedInt64() {
00993 #if defined(HAVE_GCC_ATOMIC64)
00994 #elif defined(HAVE_WIN_ATOMIC64)
00995 #else
00996                 (void)pthread_mutex_destroy(&mytex);
00997 #endif
00998             }
00999 
01001             uint64_t operator()() const {return val_;}
01002 
01004             uint64_t operator++() {
01005 #if defined(HAVE_GCC_ATOMIC64)
01006                 return __sync_add_and_fetch(&val_, 1);
01007 #elif defined(HAVE_WIN_ATOMIC64)
01008                 return InterlockedIncrement64((volatile LONGLONG *)&val_);
01009 #else
01010                 ibis::util::quietLock lock(&mytex);
01011                 ++ val_;
01012                 return val_;
01013 #endif
01014             }
01015 
01017             uint64_t operator--() {
01018 #if defined(HAVE_GCC_ATOMIC64)
01019                 return __sync_sub_and_fetch(&val_, 1);
01020 #elif defined(HAVE_WIN_ATOMIC64)
01021                 return InterlockedDecrement64((volatile LONGLONG *)&val_);
01022 #else
01023                 ibis::util::quietLock lock(&mytex);
01024                 -- val_;
01025                 return val_;
01026 #endif
01027             }
01028 
01030             void operator+=(const uint64_t rhs) {
01031 #if defined(HAVE_GCC_ATOMIC64)
01032                 (void) __sync_add_and_fetch(&val_, rhs);
01033 #elif defined(HAVE_WIN_ATOMIC64)
01034                 (void) InterlockedExchangeAdd64((volatile LONGLONG *)&val_,
01035                                                 rhs);
01036 #else
01037                 ibis::util::quietLock lock(&mytex);
01038                 val_ += rhs;
01039 #endif
01040             }
01041 
01043             void operator-=(const uint64_t rhs) {
01044 #if defined(HAVE_GCC_ATOMIC64)
01045                 (void) __sync_sub_and_fetch(&val_, rhs);
01046 #elif defined(HAVE_WIN_ATOMIC64)
01047                 (void) InterlockedExchangeAdd64((volatile LONGLONG *)&val_,
01048                                                 -(long)rhs);
01049 #else
01050                 ibis::util::quietLock lock(&mytex);
01051                 val_ -= rhs;
01052 #endif
01053             }
01054 
01056             void swap(sharedInt64 &rhs) {
01057                 uint64_t tmp = rhs.val_;
01058                 rhs.val_ = val_;
01059                 val_ = tmp;
01060             }
01061 
01062         private:
01063             uint64_t volatile val_; 
01064 #if defined(HAVE_GCC_ATOMIC64)
01065 #elif defined(HAVE_WIN_ATOMIC64)
01066 #else
01067             pthread_mutex_t mytex; 
01068 #endif
01069 
01070             sharedInt64(const sharedInt64&); // no copy constructor
01071             sharedInt64& operator=(const sharedInt64&); // no assignment
01072         }; // sharedInt64
01073 
01083         class timer {
01084         public:
01085             explicit timer(const char* msg, int lvl=1);
01086             ~timer();
01087 
01088         private:
01089             ibis::horometer *chrono_; 
01090             std::string mesg_; 
01091 
01092             timer(); // no default constructor
01093             timer(const timer&); // no copying
01094             timer& operator=(const timer&); // no assignment
01095         }; // timer
01096 
01098         template <class T> class refHolder {
01099         public:
01100             refHolder(T& r) : ref_(r) {}
01101             operator T& () const {return ref_;}
01102 
01103         private:
01104             T& ref_;
01105 
01106             refHolder();
01107         }; // refHolder
01108 
01110         template <class T>
01111         inline refHolder<T> ref(T& r) {return refHolder<T>(r);}
01112 
01115         class guardBase {
01116         public:
01119             void dismiss() const {done_ = true;}
01120 
01121         protected:
01122             mutable volatile bool done_;
01123 
01125             ~guardBase() {};
01126             guardBase() : done_(false) {}; 
01127 
01128 
01129             guardBase(const guardBase& rhs) : done_(rhs.done_) {
01130                 rhs.dismiss();
01131             }
01132 
01135             template <typename T>
01136             static void cleanup(T& task) throw () {
01137                 try {
01138                     if (!task.done_)
01139                         task.execute();
01140                 }
01141                 catch (const std::exception& e) {
01142                     LOGGER(ibis::gVerbose > 1)
01143                         << " ... caught a std::exception (" << e.what()
01144                         << ") in util::gard";
01145                 }
01146                 catch (const char* s) {
01147                     LOGGER(ibis::gVerbose > 1)
01148                         << " ... caught a string exception (" << s
01149                         << ") in util::guard";
01150                 }
01151                 catch (...) {
01152                     LOGGER(ibis::gVerbose > 1)
01153                         << " ... caught a unknown exception in util::guard";
01154                 }
01155                 task.done_ = true;
01156             }
01157         }; // guardBase
01158 
01172         typedef const guardBase& guard;
01173 
01176         template <typename F>
01177         class guardImpl0 : public guardBase {
01178         public:
01179             static guardImpl0<F> makeGuard(F f) {
01180                 return guardImpl0<F>(f);
01181             }
01182 
01184             ~guardImpl0() {cleanup(*this);}
01185 
01186         protected:
01187             friend class guardBase; // to call function execute
01188             void execute() {fun_();}
01189 
01191             explicit guardImpl0(F f) : fun_(f) {}
01192 
01193         private:
01195             F fun_;
01196 
01197             guardImpl0();
01198             guardImpl0& operator=(const guardImpl0&);
01199         }; // guardImpl0
01200 
01201         template <typename F>
01202         inline guardImpl0<F> makeGuard(F f) {
01203             return guardImpl0<F>::makeGuard(f);
01204         }
01205 
01208         template <typename F, typename A>
01209         class guardImpl1 : public guardBase {
01210         public:
01211             static guardImpl1<F, A> makeGuard(F f, A a) {
01212                 return guardImpl1<F, A>(f, a);
01213             }
01214 
01216             ~guardImpl1() {cleanup(*this);}
01217 
01218         protected:
01219             friend class guardBase; // to call function execute
01220             void execute() {fun_(arg_);}
01221 
01223             explicit guardImpl1(F f, A a) : fun_(f), arg_(a) {}
01224 
01225         private:
01227             F fun_;
01229             A arg_;
01230 
01231             guardImpl1();
01232             guardImpl1& operator=(const guardImpl1&);
01233         }; // guardImpl1
01234 
01235         template <typename F, typename A>
01236         inline guardImpl1<F, A> makeGuard(F f, A a) {
01237             return guardImpl1<F, A>::makeGuard(f, a);
01238         }
01239 
01242         template <typename F, typename A1, typename A2>
01243         class guardImpl2 : public guardBase {
01244         public:
01245             static guardImpl2<F, A1, A2> makeGuard(F f, A1 a1, A2 a2) {
01246                 return guardImpl2<F, A1, A2>(f, a1, a2);
01247             }
01248 
01250             ~guardImpl2() {cleanup(*this);}
01251 
01252         protected:
01253             friend class guardBase; // to call function execute
01254             void execute() {fun_(arg1_, arg2_);}
01255 
01257             explicit guardImpl2(F f, A1 a1, A2 a2)
01258                 : fun_(f), arg1_(a1), arg2_(a2) {}
01259 
01260         private:
01262             F fun_;
01264             A1 arg1_;
01266             A2 arg2_;
01267 
01268             guardImpl2();
01269             //guardImpl2(const guardImpl2&);
01270             guardImpl2& operator=(const guardImpl2&);
01271         }; // guardImpl2
01272 
01273         template <typename F, typename A1, typename A2>
01274         inline guardImpl2<F, A1, A2> makeGuard(F f, A1 a1, A2 a2) {
01275             return guardImpl2<F, A1, A2>::makeGuard(f, a1, a2);
01276         }
01277 
01279         template <class C, typename F>
01280         class guardObj0 : public guardBase {
01281         public:
01282             static guardObj0<C, F> makeGuard(C& o, F f) {
01283                 return guardObj0<C, F>(o, f);
01284             }
01285 
01287             ~guardObj0() {cleanup(*this);}
01288 
01289         protected:
01290             friend class guardBase; // to call function execute
01291             void execute() {(obj_.*fun_)();}
01292 
01294             guardObj0(C& o, F f) : obj_(o), fun_(f) {}
01295 
01296         private:
01297             C& obj_; 
01298             F fun_;  
01299 
01300             guardObj0();
01301             guardObj0& operator=(const guardObj0&);
01302         }; // guardObj0
01303 
01304         template <class C, typename F>
01305         inline guardObj0<C, F> objectGuard(C o, F f) {
01306             return guardObj0<C, F>::makeGuard(o, f);
01307         }
01308     } // namespace util
01309 } // namespace ibis
01310 
01311 #if defined(WIN32) && ! defined(__CYGWIN__)
01312 char* getpass(const char* prompt);
01313 #endif
01314 
01320 inline double ibis::util::rand() {
01321     // The internal variable @c seed is always an odd number.  Don't use it
01322     // directly.
01323     static uint32_t seed = 1;
01324     static const uint32_t alpha = 69069;
01325     static const double scale = ::pow(0.5, 32);
01326     seed = static_cast<uint32_t>(seed * alpha);
01327     return(scale * seed);
01328 } // ibis::util::rand
01329 
01331 inline uint32_t ibis::util::checksum(uint32_t a, uint32_t b) {
01332     uint32_t a0 = (a >> 16);
01333     uint32_t a1 = (a & 0xFFFF);
01334     uint32_t b0 = (b >> 16);
01335     uint32_t b1 = (b & 0xFFFF);
01336     return ((((a0<<2)+a1*3+(b0<<1)+b1) << 16) | ((a0+a1+b0+b1) & 0xFFFF));
01337 } // ibis::util::checksum
01338 
01346 inline double ibis::util::incrDouble(const double& in) {
01347 #if defined(HAVE_NEXTAFTER)
01348     return nextafter(in, DBL_MAX);
01349 #elif defined(_MSC_VER) && defined(_WIN32)
01350     return _nextafter(in, DBL_MAX);
01351 #else
01352     double tmp = fabs(in) * DBL_EPSILON;
01353     if (tmp > 0.0) tmp += in;
01354     else tmp = in + DBL_MIN;
01355     return tmp;
01356 #endif
01357 }
01358 
01361 inline double ibis::util::decrDouble(const double& in) {
01362 #if defined(HAVE_NEXTAFTER)
01363     return nextafter(in, -DBL_MAX);
01364 #elif defined(_MSC_VER) && defined(_WIN32)
01365     return _nextafter(in, -DBL_MAX);
01366 #else
01367     double tmp = fabs(in) * DBL_EPSILON;
01368     if (tmp > 0.0) tmp = in - tmp;
01369     else tmp = in - DBL_MIN;
01370     return tmp;
01371 #endif
01372 }
01373 
01378 inline void ibis::util::eq2range(const double& in,
01379                                  double& left, double& right) {
01380 #if defined(HAVE_NEXTAFTER)
01381     right = nextafter(in, DBL_MAX);
01382 #elif defined(_MSC_VER) && defined(_WIN32)
01383     right = _nextafter(in, DBL_MAX);
01384 #else
01385     double tmp = fabs(in) * DBL_EPSILON;
01386     if (tmp > 0.0) {right = in + tmp;}
01387     else {right = in + DBL_MIN;}
01388 #endif
01389     left = in;
01390 } // ibis::util::eq2range
01391 
01395 template <typename Tin>
01396 inline void ibis::util::round_up(const Tin& inval, float& outval) {
01397     // perform the initial rounding
01398     outval = static_cast<float>(inval);
01399     if (static_cast<Tin>(outval) < inval) {
01400         // if the rounded value is less than the input value, compute the
01401         // next value
01402 #if defined(HAVE_NEXTAFTER)
01403         outval = nextafterf(static_cast<float>(inval), FLT_MAX);
01404 #else
01405         float tmp = fabsf(outval) * FLT_EPSILON;
01406         if (tmp > 0.0) outval += tmp;
01407         else outval += FLT_MIN;
01408 #endif
01409     }
01410 } // ibis::util::round_up
01411 
01412 // remove all the trailing char 'tail'
01413 inline void ibis::util::removeTail(char* str, char tail) {
01414     if (str != 0 && *str != 0) {
01415         char *tmp = str;
01416         while (*tmp != 0) ++ tmp;
01417         -- tmp;
01418         while (tmp > str && *tmp == tail) {
01419             *tmp = static_cast<char>(0);
01420             -- tmp;
01421         }
01422     }
01423 } // ibis::util::removeTail
01424 
01425 // remove the leading and trailing space of the incoming string
01426 inline char* ibis::util::trim(char* str) {
01427     char* head = 0;
01428     if (str == 0) return head;
01429     if (*str == 0) return head;
01430 
01431     head = str;
01432     while (*head) {
01433         if (std::isspace(*head))
01434             ++ head;
01435         else
01436             break;
01437     }
01438     if (*head == 0)
01439         return head;
01440 
01441     for (str = head; *str != 0; ++ str);
01442     -- str;
01443     while (str >= head && std::isspace(*str)) {
01444         *str = static_cast<char>(0);
01445         -- str;
01446     }
01447     return head;
01448 } // ibis::util::trim
01449 
01457 inline double ibis::util::coarsen(const double in, unsigned prec) {
01458     double ret;
01459     if (prec > 15) {
01460         ret = in;
01461     }
01462     else if (in == 0.0) {
01463         ret = in;
01464     }
01465     else {
01466         ret = fabs(in);
01467         if (ret < DBL_MIN) { // denormalized number --> 0
01468             ret = 0.0;
01469         }
01470         else if (ret < DBL_MAX) { // normal numbers
01471             ret = log10(ret);
01472             if (prec > 0)
01473                 -- prec;
01474             const int ixp = static_cast<int>(floor(ret)) -
01475                 static_cast<int>(prec);
01476             ret = floor(0.5 + pow(1e1, ret-ixp));
01477             if (ixp > 0)
01478                 ret *= pow(1e1, ixp);
01479             else if (ixp < 0)
01480                 ret /= pow(1e1, -ixp);
01481             if (in < 0.0)
01482                 ret = -ret;
01483         }
01484         else {
01485             ret = in;
01486         }
01487     }
01488     return ret;
01489 } // ibis::util::coarsen
01490 
01492 inline std::ostream& operator<<(std::ostream& out, const ibis::rid_t& rid) {
01493     out << '(' << rid.num.run << ", " << rid.num.event << ')';
01494     return out;
01495 }
01496 
01498 inline std::istream& operator>>(std::istream& is, ibis::rid_t& rid) {
01499     char c = 0;
01500     is >> c;
01501     if (c == '(') { // (runNumber, EventNumber)
01502         is >> rid.num.run >> c;
01503         if (c == ',')
01504             is >> rid.num.event >> c;
01505         else
01506             rid.num.event = 0;
01507         if (c != ')')
01508             is.clear(std::ios::badbit); // forget the erro
01509     }
01510     else { // runNumber, EventNumber
01511         is.putback(c);
01512         is >> rid.num.run >> c;
01513         if (c != ',') // assume space separator
01514             is.putback(c);
01515         is >> rid.num.event;
01516     }
01517     return is;
01518 }
01519 #endif // IBIS_UTIL_H

Make It A Bit Faster
Contact us
Disclaimers
FastBit source code
FastBit mailing list archive