Main Page | Class Hierarchy | Class List | File List | Class Members

prom_options.hh

00001 // $Id: prom_options.hh,v 1.2 2004/01/27 21:15:54 adams Exp $ 00002 // Author: Mark F. Adams 00003 // Copyright (c) 2000 by Mark F. Adams 00004 // Filename: prom_options.hh 00005 // 00006 #ifndef __PROM_OPTIONS_H__ 00007 #define __PROM_OPTIONS_H__ 00008 00009 #if defined(PROM_USE_PETSC) 00010 #define PROM_USE_PETSC_OPTIONS 00011 #endif 00012 00013 #if defined(PROM_USE_PETSC_OPTIONS) 00014 00015 class PromOptions 00016 { 00017 public: 00018 PromOptions() : matrix_(FALSE), verbose_(FALSE), files_(FALSE) {} 00019 // methods 00020 int InsertOptions( int *argc, char ***argv, char *file ) { 00021 int ierr = PetscOptionsInsert( argc, argv, file ); CHKERRQ(ierr); 00022 return 0; 00023 } 00024 // methods 00025 int HasOptionName( const char name[], bool *flg ) const { 00026 PetscTruth f; 00027 int ierr = PetscOptionsHasName(PETSC_NULL,name,&f); CHKERRQ(ierr); 00028 *flg = (f == PETSC_TRUE); 00029 return 0; 00030 } 00031 // 00032 int GetOptionDouble(const char name[], double *dvalue, bool *flg)const{ 00033 PetscTruth f; 00034 int ierr = PetscOptionsGetReal(PETSC_NULL,name,dvalue,&f); CHKERRQ(ierr); 00035 *flg = (f == PETSC_TRUE); 00036 return 0; 00037 } 00038 // 00039 int GetOptionInt( const char name[],int*ivalue, bool *flg)const{ 00040 PetscTruth f; 00041 int ierr = PetscOptionsGetInt(PETSC_NULL,name,ivalue,&f); CHKERRQ(ierr); 00042 *flg = (f == PETSC_TRUE); 00043 return 0; 00044 } 00045 // 00046 int GetOptionString( const char name[], char string[], 00047 int len, bool *flg ) const{ 00048 PetscTruth f; 00049 int ierr = PetscOptionsGetString(PETSC_NULL,name,string,len,&f); 00050 CHKERRQ(ierr); 00051 *flg = (f == PETSC_TRUE); 00052 return 0; 00053 } 00054 int OptionsSetValue( const char iname[],const char value[] ) { 00055 int ierr = PetscOptionsSetValue( iname, value ); CHKERRQ(ierr); 00056 return 0; 00057 } 00058 // debug 00059 int print( int myproc = 0, FILE *file = stderr )const{ 00060 int ierr = PetscOptionsPrint(file); CHKERRQ(ierr); 00061 return 0; 00062 } 00063 int verbose_; 00064 bool matrix_, files_; 00065 }; 00066 #else 00067 00068 #include <iostream.h> 00069 00070 #define void_error(s) { printf(s,__FILE__,__LINE__); exit(3); } 00071 00072 class String; 00073 /* Int.h */ 00078 class Int 00079 { 00080 public: 00081 Int() : val_(0) {;} 00082 Int(int val) : val_(val) {;} 00083 int byteCount() const {return sizeof(int);} 00084 inline String toString() const ; 00085 int hashCode() const {return val_;} 00086 operator int () const {return val_;} 00087 bool operator==(const Int& other) const {return val_==other.val_;} 00088 bool operator==(const int& other) const {return val_==other;} 00089 bool operator<(const Int& other) const {return val_ < other.val_;} 00090 Int& operator+=(int i) {val_ += i; return *this;} 00091 friend Int& operator++(Int& x); 00092 private: 00093 int val_; 00094 }; 00095 00096 /* Double.h */ 00102 class Double 00103 { 00104 public: 00105 Double() : val_(0.0) {;} 00106 Double(double val) : val_(val) {;} 00107 int byteCount() const {return sizeof(double);} 00108 inline String toString(int precision=16) const ; 00109 int hashCode() const {return (int) val_;} 00110 00111 operator double () const {return val_;} 00112 private: 00113 double val_; 00114 }; 00115 00116 /********************* Array.h *********************/ 00136 //#define NOBOUNDSCHECK 00137 template<class T> 00138 class Array { 00139 public: 00143 inline Array(); 00145 inline Array(int n); 00147 inline Array(int n, const T* cArray); 00149 inline Array(int n, const T& t); 00151 // explicit copy ctor, dtor, and assign needed to prevent memory 00152 // corruption 00153 inline ~Array(); 00154 inline Array(const Array<T>& other); 00155 inline const Array<T>& operator=(const Array<T>& other); 00161 inline int length() const ; 00163 inline void resize(int newN); 00165 inline void reserve(int n); 00167 inline int reserve() const ; 00169 00174 inline Array<T>& append(const T& rhs); 00179 inline T& operator[](int i); 00184 inline const T& operator[](int i) const; 00189 inline void remove(int i); 00191 00194 inline int hashCode() const ; 00196 inline String toString() const ; 00198 inline int byteCount() const ; 00199 private: 00200 T* data_; 00201 int len_; 00202 int reserve_; 00203 00204 int indexCheckCrash(int i) const; 00205 bool indexCheckNoCrash(int i) const; 00206 }; 00207 00208 /* Array utils. 00209 template<class T> ostream& operator<<(ostream& os, const Array<T>& array); 00210 template<class T> 00211 Array<T> sliceArray(const Array<Array<T> >& array, int index); 00212 template<class T> Array<T> tuple(const T& a); 00213 template<class T> Array<T> tuple(const T& a, const T& b); 00214 template<class T> Array<T> tuple(const T& a, const T& b, const T& c); 00215 template<class T> 00216 Array<T> tuple(const T& a, const T& b, const T& c, const T& d); 00217 template<class T> 00218 Array<T> tuple(const T& a, const T& b, const T& c, const T& d, const T& e); 00219 template<class T> 00220 Array<T> tuple(const T& a, const T& b, const T& c, const T& d, const T& e, 00221 const T& f); */ 00222 00223 /* Array.inl */ 00224 // print in form (), (1), or (1,2) 00225 template<class T> inline ostream& operator<<(ostream& os,const Array<T>& item) 00226 { 00227 const Array<T>& myItem = item; 00228 T myElem; 00229 00230 os << "("; 00231 int ultimate = myItem.length()-1; 00232 00233 for (int i = 0; i < ultimate; ++i) { 00234 myElem = myItem[i]; 00235 os << myElem; 00236 os << ", "; 00237 } 00238 if (ultimate >= 0) 00239 os << myItem[ultimate]; 00240 os << ")"; 00241 return os; 00242 } 00243 00244 /*template<class T> inline int Array<T>::hashCode() const 00245 { 00246 int rtn = Int(len_).hashCode(); 00247 for (int i=0; i<a.length(); i++) 00248 { 00249 rtn += (a[i]).hashCode(); 00250 } 00251 return rtn; 00252 }*/ 00253 00254 template<class T> inline int Array<T>::byteCount() const 00255 { 00256 int data = sizeof(Array<T>); 00257 for (int i=0; i<length(); i++) 00258 { 00259 data += (data_[i]).byteCount(); 00260 } 00261 data += sizeof(T)*(reserve() - length()); 00262 return data; 00263 } 00264 00265 template<class T> inline String Array<T>::toString() const 00266 { 00267 String rtn = "{"; 00268 00269 for (int i=0; i<length(); i++) 00270 { 00271 rtn += (data_[i]).toString(); 00272 if (i<length()-1) rtn += ", "; 00273 } 00274 rtn += "}"; 00275 00276 return rtn; 00277 } 00278 00279 template<class T> inline Array<T>::Array() 00280 : data_(0), 00281 len_(0), 00282 reserve_(0) 00283 { 00284 } 00285 00286 template<class T> inline Array<T>::Array(int n) 00287 : data_(0), 00288 len_(n), 00289 reserve_(n) 00290 { 00291 if (len_ < 0) 00292 void_error("file %s line %d: Negative length passed to Array<T>::Array(int n)\n"); 00293 if (len_ > 0) 00294 { 00295 data_ = new T [len_]; 00296 if (!data_) 00297 void_error("file %s line %d: Array constructor out of memory\n"); 00298 } 00299 } 00300 00301 template<class T> inline Array<T>::Array(int n, const T* cArray) 00302 : data_(0), 00303 len_(n), 00304 reserve_(n) 00305 { 00306 if (len_ < 0) 00307 void_error("file %s line %d: Negative lenght passed to Array::Array(n, cArray)\n"); 00308 if (len_ > 0) 00309 { 00310 data_ = new T [len_]; 00311 if (!data_) 00312 void_error("file %s line %d: Array constructor out of memory\n"); 00313 } 00314 for (int i = 0; i < len_; i++) data_[i] = cArray[i]; 00315 } 00316 00317 template<class T> inline Array<T>::Array(int n, const T& t) 00318 : data_(0), 00319 len_(n), 00320 reserve_(n) 00321 { 00322 if (len_ < 0) 00323 void_error("file %s line %d: Negative length passed to Array<T>::Array(int n)\n"); 00324 if (len_ > 0) 00325 { 00326 data_ = new T [len_]; 00327 if (!data_) 00328 void_error("file %s line %d: Array constructor out of memory\n"); 00329 } 00330 for (int i = 0; i < len_; ++ i) 00331 data_[i] = t; 00332 } 00333 00334 template<class T> inline Array<T>::Array(const Array<T>& arr) 00335 : data_(0), 00336 len_(arr.len_), 00337 reserve_(arr.len_) 00338 { 00339 if (len_ > 0) 00340 { 00341 data_ = new T [reserve_]; 00342 if (!data_) 00343 void_error("file %s line %d: Array constructor out of memory\n"); 00344 for (int i = 0; i < len_; ++i) 00345 data_[i] = arr.data_[i]; 00346 } 00347 } 00348 00349 template<class T> Array<T>::~Array() 00350 { 00351 delete [] data_; 00352 } 00353 00354 template<class T> inline 00355 const Array<T>& Array<T>::operator=(const Array<T>& arr) 00356 { 00357 if (this != &arr) 00358 { // don't bother to assign if they're already identical 00359 if (reserve_ < arr.len_) 00360 { //If the reserved space is too small to hold arr 00361 delete [] data_; 00362 data_ = 0; 00363 reserve_ = arr.len_; 00364 if (reserve_ > 0) { 00365 data_ = new T[reserve_]; 00366 if (!data_) 00367 void_error("file %s line %d: Array constructor out of memory\n"); 00368 } 00369 } 00370 len_ = arr.len_; 00371 for (int i = 0; i < len_; ++i) 00372 data_[i] = arr[i]; 00373 } 00374 return *this; 00375 } 00376 00377 inline int bump(int start, int finish) 00378 { 00379 if (finish < 10000) 00380 { 00381 if (start == 0) 00382 start = 1; 00383 while (start < finish) 00384 start *= 2; 00385 return start; 00386 } 00387 else 00388 { 00389 while (start < finish) 00390 { 00391 start += 10000; 00392 } 00393 return start; 00394 } 00395 } 00396 00397 template<class T> inline 00398 void Array<T>::resize(int newN) { 00399 if (len_ != newN) { // do not do anything if new size is not different 00400 if (newN < 0) 00401 void_error("file %s line %d: Negative length passed to Array<T>::resize(int newN)\n"); 00402 if(newN > reserve_) 00403 reserve(bump(reserve_, newN)); 00404 len_ = newN; 00405 } 00406 } 00407 00408 template<class T> inline 00409 void Array<T>::reserve(int N){ 00410 if(reserve_ != N){ 00411 if(N < 0){ 00412 void_error("file %s line %d: Negative length passed to Array<T>::reserve(int N)\n"); 00413 } 00414 if(N < len_){ len_ = N;} 00415 reserve_ = N; 00416 T* oldData = data_; 00417 data_ = 0; 00418 data_ = new T [reserve_]; 00419 if (!data_) 00420 void_error("file %s line %d: Array<T>::reserve(int N) out of memory\n"); 00421 for (int i = 0; i < len_; i++) 00422 data_[i] = oldData[i]; 00423 delete [] oldData; 00424 } 00425 } 00426 00427 template<class T> inline int Array<T>::reserve() const{ 00428 return reserve_; 00429 } 00430 00431 template<class T> inline Array<T>& Array<T>::append(const T& rhs) 00432 { 00433 resize(len_+1); 00434 data_[len_-1] = rhs; 00435 return *this; 00436 } 00437 00438 template<class T> inline T& Array<T>::operator[](int i) { 00439 #ifndef NOBOUNDSCHECK 00440 indexCheckCrash(i); 00441 #endif 00442 return data_[i]; 00443 } 00444 00445 template<class T> inline const T& Array<T>::operator[](int i) const { 00446 #ifndef NOBOUNDSCHECK 00447 indexCheckCrash(i); 00448 #endif 00449 return data_[i]; 00450 } 00451 00452 template<class T> inline void Array<T>::remove(int i) 00453 { 00454 #ifndef NOBOUNDSCHECK 00455 indexCheckCrash(i); 00456 #endif 00457 for (int j=i+1; j<length(); j++) 00458 { 00459 data_[j-1] = data_[j]; 00460 } 00461 data_[len_-1] = T(); 00462 len_--; 00463 } 00464 00465 template<class T> inline int Array<T>::length() const { 00466 return len_; 00467 } 00468 00469 template<class T> inline int Array<T>::indexCheckCrash(int i) const 00470 { 00471 assert(i>=0 && i<len_); 00472 return 0; 00473 } 00474 00475 template<class T> inline bool Array<T>::indexCheckNoCrash(int i) const 00476 { 00477 if (i<0 || i>=len_) return FALSE; 00478 return TRUE; 00479 } 00480 00481 /* Array utils. */ 00482 template<class T> inline Array<T> sliceArray(const Array<Array<T> >& array, 00483 int index) 00484 { 00485 Array<T> rtn(array.length()); 00486 00487 for (int i=0; i<array.length(); i++) 00488 { 00489 rtn[i] = array[i][index]; 00490 } 00491 return rtn; 00492 } 00493 00494 // utilities for building small arrays 00495 template<class T> inline Array<T> tuple(const T& a) 00496 { 00497 Array<T> rtn(1, a); 00498 return rtn; 00499 } 00500 00501 template<class T> inline Array<T> tuple(const T& a, const T& b) 00502 { 00503 Array<T> rtn(2); 00504 rtn[0] = a; 00505 rtn[1] = b; 00506 return rtn; 00507 } 00508 00509 template<class T> inline Array<T> tuple(const T& a, const T& b, const T& c) 00510 { 00511 Array<T> rtn(3); 00512 rtn[0] = a; 00513 rtn[1] = b; 00514 rtn[2] = c; 00515 return rtn; 00516 } 00517 00518 template<class T> inline Array<T> tuple(const T& a, const T& b, const T& c, 00519 const T& d) 00520 { 00521 Array<T> rtn(4); 00522 rtn[0] = a; 00523 rtn[1] = b; 00524 rtn[2] = c; 00525 rtn[3] = d; 00526 return rtn; 00527 } 00528 00529 template<class T> inline Array<T> tuple(const T& a, const T& b, const T& c, 00530 const T& d, const T& e) 00531 { 00532 Array<T> rtn(5); 00533 rtn[0] = a; 00534 rtn[1] = b; 00535 rtn[2] = c; 00536 rtn[3] = d; 00537 rtn[4] = e; 00538 return rtn; 00539 } 00540 00541 template<class T> inline Array<T> tuple(const T& a, const T& b, const T& c, 00542 const T& d, const T& e, const T& f) 00543 { 00544 Array<T> rtn(6); 00545 rtn[0] = a; 00546 rtn[1] = b; 00547 rtn[2] = c; 00548 rtn[3] = d; 00549 rtn[4] = e; 00550 rtn[5] = f; 00551 return rtn; 00552 } 00553 00554 /********************* String.h *********************/ 00561 class String 00562 { 00563 public: 00567 inline String(); 00569 inline String(char c); 00571 inline String(const char* str); 00573 inline String(const char* str, int len); 00575 // Non-default copy ctor, assignment, and dtor must be defined. 00576 inline String(const String& other); 00577 inline ~String(); 00578 inline String& operator=(const String& other); 00579 00583 inline const char* cString() const ; 00585 inline int length() const ; 00587 00591 inline const char& operator[](int i) const ; 00593 inline char& operator[](int i) ; 00595 00599 inline bool operator==(const String& other) const ; 00601 inline bool operator!=(const String& other) const ; 00603 inline bool operator<(const String& other) const ; 00605 inline String& operator+=(const String& other); 00607 inline String operator+(const String& other) const ; 00609 inline String operator+(const int& x) const ; 00611 inline String operator+(const double& x) const ; 00613 00617 inline bool contains(char c) const ; 00618 00620 inline int find(const char* sub) const ; 00622 inline int find(const String& sub) const ; 00623 00625 inline String before(const char* sub) const ; 00627 inline String before(const String& sub) const ; 00628 00630 inline String after(const char* sub) const ; 00632 inline String after(const String& sub) const ; 00633 00636 inline String beforeToken(const String& tokens) const ; 00644 inline String between(const String& begin, const String& end, 00645 String& front, String& back) const ; 00647 inline String subString(int begin, int end) const ; 00649 // conversion to all capital characters 00650 inline String allCaps() const ; 00651 // find out if string has any non-whitespace chars 00652 inline bool isWhite() const ; 00653 inline bool hasNonWhite() const ; 00654 00655 /* 00656 * Return a String minus any initial whitespace contained in this String 00657 */ 00658 inline String trimInitialWhitespace() const ; 00659 00660 inline static String readFromStream(istream& is); 00661 00665 inline int hashCode() const ; 00667 inline String toString() const {return *this;} 00669 inline int byteCount() const ; 00671 00675 inline int atoi() const; 00677 inline double atof() const ; 00679 inline bool atob() const ; 00681 private: 00682 inline int indexcheck(int i) const ; 00683 inline int init(const char* str, int n); 00684 00685 // pointer to beginning of string 00686 char* str_; 00687 }; 00688 00689 /* String.cpp */ 00692 inline ostream& operator<<(ostream& os, const String& str) 00693 { 00694 os << str.cString(); 00695 return os; 00696 } 00697 00698 inline String operator+(const char* a, const String& b) 00699 { 00700 return String(a)+b; 00701 } 00702 00703 inline istream& operator>>(istream& is, String& str) 00704 { 00705 str = String::readFromStream(is); 00706 return is; 00707 } 00708 00709 inline int findNextNonWhitespace(const String& str, int offset) 00710 { 00711 for (int i=0; i<(str.length()-offset); i++) 00712 { 00713 if (!(str[i+offset]==' ' || str[i+offset]=='\t' || str[i+offset]=='\n')) 00714 { 00715 return i+offset; 00716 } 00717 } 00718 return str.length(); 00719 } 00720 00721 inline int atoi(const String& s) {return s.atoi();} 00722 inline bool atob(const String& s) {return s.atob();} 00723 inline double atof(const String& s) {return s.atof();} 00724 00725 /* String.h */ 00726 inline String::~String() 00727 { 00728 delete [] str_; 00729 } 00730 inline const char* String::cString() const 00731 { 00732 return str_; 00733 } 00734 00735 inline int String::length() const 00736 { 00737 return strlen(str_); 00738 } 00739 00740 inline int String::byteCount() const 00741 { 00742 return length() + 1; 00743 } 00744 00745 inline const char& String::operator[](int i) const 00746 { 00747 #ifndef NOBOUNDSCHECK 00748 indexcheck(i); 00749 #endif 00750 return str_[i]; 00751 } 00752 00753 inline char& String::operator[](int i) 00754 { 00755 #ifndef NOBOUNDSCHECK 00756 indexcheck(i); 00757 #endif 00758 return str_[i]; 00759 } 00760 00761 inline bool String::operator==(const String& other) const 00762 { 00763 return strcmp(str_, other.str_) == 0; 00764 } 00765 00766 inline bool String::operator!=(const String& other) const 00767 { 00768 return !(operator==(other)); 00769 } 00770 00771 inline bool String::operator< (const String& other) const 00772 { 00773 return (0 > strcmp(str_, other.str_)); 00774 } 00775 00776 inline String::String() 00777 : str_(0) 00778 { 00779 str_ = new char[1]; 00780 if (str_==0) void_error("%s line %d: String::String()\n"); 00781 str_[0] = '\0'; 00782 } 00783 00784 inline String::String(char c) 00785 : str_(0) 00786 { 00787 if (c=='\0') 00788 { 00789 str_ = new char[1]; 00790 if (str_==0) void_error("%s line %d: String::String(char c)\n"); 00791 str_[0] = c; 00792 } 00793 else 00794 { 00795 str_ = new char[2]; 00796 if (str_==0) void_error("%s line %d: String::String(char c)"); 00797 str_[0] = c; 00798 str_[1] = '\0'; 00799 } 00800 } 00801 00802 inline String::String(const char* str) 00803 : str_(0) 00804 { 00805 if (str==0) void_error("%s line %d: String::String(const char* str) null argument"); 00806 int len = strlen(str); 00807 init(str, len); 00808 } 00809 00810 inline String::String(const char* str, int n) 00811 : str_(0) 00812 { 00813 init(str, n); 00814 str_[n] = '\0'; 00815 } 00816 00817 inline String::String(const String& other) 00818 : str_(0) 00819 { 00820 init(other.cString(), other.length()); 00821 } 00822 00823 inline String String::readFromStream(istream& is) 00824 { 00825 String rtn; 00826 char c; 00827 00828 bool empty = TRUE; 00829 while (is.get(c)) 00830 { 00831 if (isspace(c)) 00832 { 00833 if (empty) continue; 00834 else break; 00835 } 00836 rtn += c; 00837 empty = FALSE; 00838 } 00839 00840 return rtn; 00841 } 00842 00843 inline String& String::operator=(const String& other) 00844 { 00845 if (*this != other) 00846 { 00847 delete [] str_; 00848 init(other.str_, other.length()); 00849 } 00850 return *this; 00851 } 00852 00853 inline int String::init(const char* str, int n) 00854 { 00855 str_ = new char[n+1]; 00856 if (str_==0) SETERRQ(1,"String::init"); 00857 strncpy(str_, str, n+1); 00858 return 0; 00859 } 00860 00861 inline String& String::operator+=(const String& other) 00862 { 00863 if (other.length()==0) return *this; 00864 00865 String tmp(str_); 00866 delete [] str_; 00867 str_ = new char[tmp.length() + other.length() + 1]; 00868 if (str_==0) void_error("%s line %d: String::operator+=())"); 00869 strcpy(str_, tmp.cString()); 00870 strcat(str_, other.cString()); 00871 00872 return *this; 00873 } 00874 00875 inline String String::operator+(const String& other) const 00876 { 00877 String rtn(*this); 00878 rtn += other; 00879 return rtn; 00880 } 00881 00882 inline String String::operator+(const int& x) const 00883 { 00884 String rtn(*this); 00885 rtn += Int(x).toString(); 00886 return rtn; 00887 } 00888 00889 inline String String::operator+(const double& x) const 00890 { 00891 String rtn(*this); 00892 rtn += Double(x).toString(); 00893 return rtn; 00894 } 00895 00896 inline String operator+(const int& x, const String& s) 00897 { 00898 return Int(x).toString() + s; 00899 } 00900 00901 inline String operator+(const double& x, const String& s) 00902 { 00903 return Double(x).toString() + s; 00904 } 00905 00906 inline bool String::contains(char c) const 00907 { 00908 char* p = strchr(str_, c); 00909 if (p==0) return FALSE; 00910 return TRUE; 00911 } 00912 00913 inline int String::find(const char* sub) const 00914 { 00915 char* p = strstr(str_, sub); 00916 if (p==0) return -1; 00917 return p-str_; 00918 } 00919 00920 inline int String::find(const String& sub) const 00921 { 00922 return find(sub.cString()); 00923 } 00924 00925 inline String String::subString(int begin, int end) const 00926 { 00927 return String(str_+begin, end-begin); 00928 } 00929 00930 inline String String::before(const char* sub) const 00931 { 00932 if (sub==0) void_error("%s line %d: String::before: arg is null pointer"); 00933 char* p = strstr(str_, sub); 00934 if (p==0) return *this; 00935 int subLen = p-str_; 00936 String rtn(str_, subLen); 00937 return rtn; 00938 } 00939 00940 inline String String::before(const String& sub) const 00941 { 00942 return before(sub.cString()); 00943 } 00944 00945 inline String String::after(const char* sub) const 00946 { 00947 if (sub==0) void_error("%s line %d: String::after: arg is null pointer"); 00948 // find beginning of substring 00949 char* p = strstr(str_, sub) ; 00950 // if substring not found, return empty string 00951 if (p==0) return String(); 00952 // offset to end of substring 00953 p+= strlen(sub); 00954 return String(p); 00955 } 00956 00957 inline String String::after(const String& sub) const 00958 { 00959 return after(sub.cString()); 00960 } 00961 00962 inline String String::beforeToken(const String& tokens) const 00963 { 00964 String rtn = *this; 00965 int minLen = length(); 00966 00967 for (int i=0; i<tokens.length(); i++) 00968 { 00969 String tok = tokens[i]; 00970 String test = before(tok); 00971 if (minLen > test.length()) 00972 { 00973 rtn = test; 00974 minLen = test.length(); 00975 } 00976 } 00977 00978 return rtn; 00979 } 00980 00981 inline String String::between(const String& begin, const String& end, 00982 String& front, String& back) const 00983 { 00984 front = before(begin); 00985 String middle = after(begin).before(end); 00986 back = after(end); 00987 return middle; 00988 } 00989 00990 inline int String::indexcheck(int i) const 00991 { 00992 if (i<0 || i>=(int) strlen(str_)) 00993 SETERRQ3(1,"String::indexcheck %d %d %d", i, 0, strlen(str_)); 00994 return 0; 00995 } 00996 00997 inline String String::allCaps() const 00998 { 00999 int len = length(); 01000 String newstr; 01001 01002 if (len !=0) 01003 { 01004 01005 for (int i = 0; i < len; i++) 01006 { 01007 int temp = (int) str_[i]; 01008 if ( (temp >= 'a') && ( temp <= 'z') ) 01009 temp = 'A' + (temp - 'a'); 01010 String ch((char) temp); 01011 newstr += ch; 01012 } 01013 return newstr; 01014 } 01015 else return *this; 01016 } 01017 01018 inline bool String::hasNonWhite() const 01019 { 01020 // look for non-white characters 01021 int n = (int) strcspn(str_, " \n\t\r"); 01022 if (n==0) return FALSE; 01023 return TRUE; 01024 } 01025 01026 inline bool String::isWhite() const 01027 { 01028 return !hasNonWhite(); 01029 } 01030 01031 inline String String::trimInitialWhitespace() const 01032 { 01033 int offset = 0 ; 01034 int start = findNextNonWhitespace(*this, offset); 01035 return str_ + start; 01036 } 01037 01038 inline int String::hashCode() const 01039 { 01040 int len = length(); 01041 int step = len/4 + 1; 01042 int base = 1; 01043 int rtn = 0; 01044 01045 for (int i=0; i<len/2; i+=step) 01046 { 01047 rtn += base*(int) str_[i]; 01048 base *= 128; 01049 rtn += base*(int) str_[len-i-1]; 01050 base *= 128; 01051 } 01052 01053 return rtn; 01054 } 01055 01056 inline int String::atoi() const 01057 { 01058 return ::atoi(cString()); 01059 } 01060 01061 inline double String::atof() const 01062 { 01063 return ::atof(cString()); 01064 } 01065 01066 inline bool String::atob() const 01067 { 01068 if (allCaps() == "TRUE") 01069 { 01070 return TRUE; 01071 } 01072 else return FALSE; 01073 } 01074 01075 01076 /******************** RBTreeNode.h *********************/ 01077 enum RBColor {RBRed, RBBlack}; 01078 01079 template<class Key, class Value> class RBTreeNode 01080 { 01081 public: 01082 inline RBTreeNode(const Key& key, const Value& value, 01083 RBTreeNode<Key, Value>* parent, RBColor color); 01084 inline ~RBTreeNode(); 01085 inline RBTreeNode<Key, Value>* clone() const ; 01086 01087 // printing, with variable verboseness. 01088 inline void inorderPrint(ostream& os, bool debug) const ; 01089 // verbose printing. 01090 inline void debugPrint(ostream& os) const ; 01091 // laconic printing. 01092 inline void print(ostream& os) const ; 01093 01094 // traversal functions. 01095 inline const RBTreeNode<Key, Value>* minimum() const ; 01096 inline const RBTreeNode<Key, Value>* maximum() const ; 01097 inline const RBTreeNode<Key, Value>* successor() const ; 01098 01099 // some geneological operations that will be needed in 01100 // balancing. 01101 inline bool isLeftChild() const ; 01102 inline RBTreeNode<Key, Value>* grandparent() const ; 01103 01104 // data members are public. They should be used only by RBTRee. 01105 Key key_; 01106 Value value_; 01107 RBColor color_; 01108 RBTreeNode<Key, Value>* parent_; 01109 RBTreeNode<Key, Value>* left_; 01110 RBTreeNode<Key, Value>* right_; 01111 01112 private: 01113 // copy ctor and assignment are private. 01114 // The copy ctor should be called only by clone(). 01115 // The assignment op should never be called. It is left undefined 01116 // and made private to prevent accidental use. 01117 inline RBTreeNode(const RBTreeNode<Key,Value>& other); 01118 inline const RBTreeNode<Key,Value>& 01119 operator=(const RBTreeNode<Key,Value>& other); 01120 }; 01121 01122 /* RBTreeNode.h */ 01123 // Constructor: insert (key, value), assign a color, and link to a parent. 01124 template<class Key, class Value> inline 01125 RBTreeNode<Key, Value>::RBTreeNode(const Key& key, const Value& value, 01126 RBTreeNode<Key, Value>* parent, 01127 RBColor color) 01128 : key_(key), 01129 value_(value), 01130 color_(color), 01131 parent_(parent), 01132 left_(0), 01133 right_(0) 01134 { 01135 ; 01136 } 01137 01138 // Make a copy by copying the left and right subtrees as well as the data 01139 // fields. Don't set the parent here; the calling code is responsible for 01140 // registering the new parent with this node. 01141 template<class Key, class Value> inline 01142 RBTreeNode<Key, Value>::RBTreeNode(const RBTreeNode<Key,Value>& other) 01143 : key_(other.key_), 01144 01145 value_(other.value_), 01146 color_(other.color_), 01147 parent_(0), 01148 left_(0), 01149 right_(0) 01150 { 01151 if (other.left_ != 0) 01152 { 01153 left_ = other.left_->clone(); 01154 } 01155 if (other.right_ != 0) 01156 { 01157 right_ = other.right_->clone(); 01158 } 01159 // don't clone the parent. It will have to be set later. 01160 } 01161 01162 // destructor: just delete the left and right subtrees. 01163 template<class Key, class Value> inline 01164 RBTreeNode<Key, Value>::~RBTreeNode() 01165 { 01166 delete left_; 01167 delete right_; 01168 } 01169 01170 // Make a copy of the node and its subtrees. 01171 // Register the copy node as the parent of the copy subtrees. 01172 template<class Key, class Value> inline 01173 RBTreeNode<Key,Value>* RBTreeNode<Key, Value>::clone() const 01174 { 01175 RBTreeNode<Key,Value>* result = new RBTreeNode<Key,Value>(*this); 01176 if (result == 0) 01177 void_error("RBTreeNode<Key, Value>::clone() out of memory"); 01178 if (result->left_ != 0) 01179 { 01180 result->left_->parent_ = result; 01181 } 01182 if (result->right_ != 0) 01183 { 01184 result->right_->parent_ = result; 01185 } 01186 01187 return result; 01188 } 01189 01190 // RBTreeNode* mininum() 01191 // Find the pointer to the leftmost child. This is easy: at every node, 01192 // just walk left. 01193 01194 template<class Key, class Value> inline 01195 const RBTreeNode<Key, Value>* RBTreeNode<Key, Value>::minimum() const 01196 { 01197 const RBTreeNode<Key, Value>* minPtr = this; 01198 while (minPtr->left_ != 0) 01199 { 01200 minPtr = minPtr->left_; 01201 } 01202 return minPtr; 01203 } 01204 01205 // RBTreeNode* maximum() 01206 // Find the pointer to the rightmost child. This is easy: at every node, 01207 // just walk right. 01208 01209 template<class Key, class Value> inline 01210 const RBTreeNode<Key, Value>* RBTreeNode<Key, Value>::maximum() const 01211 { 01212 const RBTreeNode<Key, Value>* maxPtr = this; 01213 while (maxPtr->right_ != 0) 01214 { 01215 maxPtr = maxPtr->right_; 01216 } 01217 return maxPtr; 01218 } 01219 01220 // RBTreeNode* successor() 01221 // Find the pointer to the next-highest-keyed node. 01222 // There are two possibilities: 01223 // (1) There is a right child tree. Then, find the minimum 01224 // of the right child subtree. 01225 // (2) There is no right child tree. In that case, walk back up the tree 01226 // until we find the node of which this branch is a left subtree. 01227 template<class Key, class Value> inline 01228 const RBTreeNode<Key, Value>* RBTreeNode<Key, Value>::successor() const 01229 { 01230 if (right_ != 0) 01231 { 01232 return right_->minimum(); 01233 } 01234 const RBTreeNode<Key, Value>* y = parent_; 01235 const RBTreeNode<Key, Value>* x = this; 01236 01237 while (y != 0 && x==y->right_) 01238 { 01239 x = y; 01240 y = y->parent_; 01241 } 01242 return y; 01243 } 01244 01245 template<class Key, class Value> inline 01246 bool RBTreeNode<Key, Value>::isLeftChild() const 01247 { 01248 if (parent_->left_ == this) return TRUE; 01249 return FALSE; 01250 } 01251 01252 template<class Key, class Value> inline 01253 RBTreeNode<Key, Value>* RBTreeNode<Key, Value>::grandparent() const 01254 { 01255 return parent_->parent_; 01256 } 01257 01258 // Print nodes in order of keys. 01259 // If debug==TRUE, do a print of everything including pointers. 01260 // If debug==FALSE, just print (key, value) pairs. 01261 template<class Key, class Value> inline 01262 void RBTreeNode<Key, Value>::inorderPrint(ostream& os, bool debug) const 01263 { 01264 if (left_) 01265 { 01266 left_->inorderPrint(os, debug); 01267 } 01268 if (debug) debugPrint(os); 01269 else print(os); 01270 01271 if (right_) 01272 { 01273 if (!debug) os << ", "; 01274 right_->inorderPrint(os, debug); 01275 } 01276 } 01277 01278 // Print everything including pointers. 01279 template<class Key, class Value> inline 01280 void RBTreeNode<Key, Value>::debugPrint(ostream& os) const 01281 { 01282 os << "P=" << parent_ 01283 << " This=" << this 01284 << " L=" << left_ 01285 << " R=" << right_ 01286 << " c=" << (int) color_ 01287 << " data=(" << key_ 01288 << ", " 01289 << value_ << ")" << endl; 01290 } 01291 01292 // Print just the key and value 01293 template<class Key, class Value> inline 01294 void RBTreeNode<Key, Value>::print(ostream& os) const 01295 { 01296 os << "(" << key_ 01297 << ", " 01298 << value_ << ")"; 01299 } 01300 01301 /* RBTree.h */ 01316 template<class Key, class Value> class RBTree 01317 { 01318 public: 01320 inline RBTree(); 01321 inline RBTree(const RBTree<Key, Value>& other); 01322 inline ~RBTree(); 01323 inline const RBTree<Key, Value>& operator=(const RBTree<Key, Value>& other); 01324 01326 int size() const {return count_;} 01328 inline const Value& get( const Key& key ) const ; 01329 inline bool get( const Key& key, Value& value ) const ; 01331 inline bool containsKey( const Key& key ) const ; 01333 inline bool put( const Key& key, const Value& value ); 01334 01335 inline ostream& print(ostream& os, bool debug=TRUE) const ; 01337 // void arrayify(Array<Key>& keys, Array<Value>& values) const ; 01338 // Array<Key> arrayifyKeys() const ; 01339 // Array<Value> arrayifyValues() const ; 01340 private: 01341 inline const RBTreeNode<Key, Value>* minimum() const ; 01342 inline const RBTreeNode<Key, Value>* maximum() const ; 01343 inline int rotateLeft(RBTreeNode<Key, Value>* pivot); 01344 inline int rotateRight(RBTreeNode<Key, Value>* pivot); 01345 inline const RBTreeNode<Key, Value>* pointerTo(const Key& key) const ; 01346 inline RBTreeNode<Key, Value>* rawInsert(const Key& key, const Value& value); 01347 01348 RBTreeNode<Key, Value>* root_; 01349 int count_; 01350 Key cacheKey_; 01351 Value cacheValue_; 01352 }; 01353 01354 /* RBTree.h */ 01355 //----------------------- implementation ----------------------------------- 01356 01357 template<class Key, class Value> inline RBTree<Key, Value>::RBTree() 01358 : root_(0), 01359 count_(0), 01360 cacheKey_(), 01361 cacheValue_() 01362 { 01363 ; 01364 } 01365 01366 template<class Key, class Value> inline 01367 RBTree<Key, Value>::RBTree(const RBTree<Key, Value>& other) : 01368 root_(0), 01369 count_(0), 01370 cacheKey_(other.cacheKey_), 01371 cacheValue_(other.cacheValue_) 01372 { 01373 if (other.root_ != 0) 01374 { 01375 root_ = other.root_->clone(); 01376 if (root_==0) void_error("file %s line %d: RBTree copy ctor\n"); 01377 count_ = other.count_; 01378 } 01379 } 01380 01381 template<class Key, class Value> inline RBTree<Key, Value>::~RBTree() 01382 { 01383 delete root_; 01384 } 01385 01386 template<class Key, class Value> inline 01387 const RBTree<Key, Value>& RBTree<Key, Value>::operator= 01388 (const RBTree<Key, Value>& other) 01389 { 01390 if (this != &other) 01391 { 01392 cacheKey_ = other.cacheKey_; 01393 cacheValue_ = other.cacheValue_; 01394 if (root_) 01395 { 01396 delete root_; 01397 root_ = 0; 01398 } 01399 if (other.root_ != 0) 01400 { 01401 root_ = other.root_->clone(); 01402 if (root_==0) void_error("file %s line %d: RBTree copy ctor\n"); 01403 count_ = other.count_; 01404 } 01405 } 01406 return *this; 01407 } 01408 01409 // ------------------------------------------------------------------------- 01410 // 01411 // Insertion: put() and rawInsert() 01412 // 01413 //-------------------------------------------------------------------------- 01414 01415 01416 // rawInsert() sticks a node into the tree without regard to red/black 01417 // coloring. put() does a raw insert, followed by recoloring and rotations 01418 // for balance. 01419 01420 template<class Key, class Value> inline 01421 RBTreeNode<Key, Value>* RBTree<Key, Value>::rawInsert(const Key& key, 01422 const Value& value) 01423 { 01424 count_++; 01425 // If this is the first entry into the tree, root_ will not exist. 01426 // In that case, create root with a null parent. 01427 if (root_==0) 01428 { 01429 root_ = new RBTreeNode<Key, Value>(key, value, 0, RBRed); 01430 return root_; 01431 } 01432 01433 // Otherwise, begin at root and do an ordered search for a place to fit 01434 // the new node. 01435 01436 RBTreeNode<Key, Value>* newParent = 0 ; 01437 RBTreeNode<Key, Value>* newPtr = root_; 01438 01439 // Compare to key at each node along path, and go left/right accordingly. 01440 // At each turn, keep track of whether the turn was left or right; that 01441 // will be needed in the final step. 01442 bool lastWasLeft = FALSE; 01443 while (newPtr != 0) 01444 { 01445 newParent = newPtr; 01446 if (key < newPtr->key_) 01447 { 01448 newPtr = newPtr->left_; 01449 lastWasLeft = TRUE; 01450 } 01451 else if (key == newPtr->key_) 01452 { 01453 count_--; 01454 newPtr->value_ = value; 01455 return newPtr; 01456 } 01457 else 01458 { 01459 newPtr = newPtr->right_; 01460 lastWasLeft = FALSE; 01461 } 01462 } 01463 01464 // OK, we've found a location for the new node. 01465 // Create a node object, and inform the parent that it has a new 01466 // left or right child. 01467 RBTreeNode<Key, Value>* newNode 01468 = new RBTreeNode<Key, Value>(key, value, newParent, RBRed); 01469 if (lastWasLeft) 01470 { 01471 newParent->left_ = newNode; 01472 } 01473 else 01474 { 01475 newParent->right_ = newNode; 01476 } 01477 01478 // all done; return a ptr to the newly created node. 01479 return newNode; 01480 } 01481 01482 // put(). Do a rawInsert(), then fix up balance. 01483 template<class Key, class Value> inline 01484 bool RBTree<Key, Value>::put(const Key& key, const Value& value) 01485 { 01486 // stick the new node in, coloring it red. 01487 RBTreeNode<Key, Value>* x = rawInsert(key, value); 01488 if (x==0) return FALSE; 01489 01490 // now fix up the RB state of the tree. 01491 01492 while (x != root_ && x->parent_ != 0 && x->parent_->color_ == RBRed) 01493 { 01494 if (x->grandparent() == 0) void_error("file %s line %d: RBTree::put() null grandparent discovered\n"); 01495 if (x->parent_->isLeftChild()) 01496 { 01497 RBTreeNode<Key, Value>* y = x->grandparent()->right_; 01498 if (y!=0 && y->color_ == RBRed) 01499 { 01500 x->parent_->color_ = RBBlack; 01501 y->color_ = RBBlack; 01502 x->grandparent()->color_ = RBRed; 01503 x = x->grandparent(); 01504 } 01505 else if (!x->isLeftChild()) 01506 { 01507 x = x->parent_; 01508 rotateLeft(x); 01509 } 01510 else 01511 { 01512 x->parent_->color_ = RBBlack; 01513 x->grandparent()->color_ = RBRed; 01514 rotateRight(x->grandparent()); 01515 } 01516 } 01517 else 01518 { 01519 RBTreeNode<Key, Value>* y = x->grandparent()->left_; 01520 if (y!=0 && y->color_ == RBRed) 01521 { 01522 x->parent_->color_ = RBBlack; 01523 y->color_ = RBBlack; 01524 x->grandparent()->color_ = RBRed; 01525 x = x->grandparent(); 01526 } 01527 else if (x->isLeftChild()) 01528 { 01529 x = x->parent_; 01530 rotateRight(x); 01531 } 01532 else 01533 { 01534 x->parent_->color_ = RBBlack; 01535 x->grandparent()->color_ = RBRed; 01536 rotateLeft(x->grandparent()); 01537 } 01538 } 01539 } 01540 01541 root_->color_ = RBBlack; 01542 return TRUE; 01543 } 01544 01545 template<class Key, class Value> inline 01546 const RBTreeNode<Key, Value>* RBTree<Key, Value>::minimum() const 01547 { 01548 if (root_==0) return 0; 01549 else return root_->minimum(); 01550 } 01551 01552 template<class Key, class Value> inline 01553 const RBTreeNode<Key, Value>* RBTree<Key, Value>::maximum() const 01554 { 01555 if (root_==0) return 0; 01556 else return root_->maximum(); 01557 } 01558 01559 template<class Key, class Value> inline 01560 const RBTreeNode<Key, Value>* RBTree<Key, Value>::pointerTo(const Key& key) const 01561 { 01562 RBTreeNode<Key, Value>* tryPtr = root_; 01563 01564 /* 01565 This code is generating a possibly uninitialized variable error at the 01566 highest optimization levels. 01567 */ 01568 while (tryPtr != 0) 01569 { 01570 if (tryPtr->key_ == key) return tryPtr; 01571 if (key < tryPtr->key_) 01572 { 01573 tryPtr = tryPtr->left_; 01574 } 01575 else 01576 { 01577 tryPtr = tryPtr->right_; 01578 } 01579 } 01580 return tryPtr; 01581 } 01582 01583 template<class Key, class Value> inline 01584 bool RBTree<Key, Value>::containsKey(const Key& key) const 01585 { 01586 const RBTreeNode<Key, Value>* ptr = pointerTo(key); 01587 if (ptr==0) return FALSE; 01588 (Key&) cacheKey_ = key; 01589 (Value&) cacheValue_ = ptr->value_; 01590 return TRUE; 01591 } 01592 01593 template<class Key, class Value> inline 01594 const Value& RBTree<Key, Value>::get(const Key& key) const 01595 { 01596 if (!containsKey(key)) void_error("file %s line %d: RBTree::get() key not found\n"); 01597 return cacheValue_; 01598 } 01599 01600 template<class Key, class Value> inline 01601 bool RBTree<Key, Value>::get(const Key& key, Value& value) const 01602 { 01603 const RBTreeNode<Key, Value>* ptr = pointerTo(key); 01604 if (ptr==0) return FALSE; 01605 value = ptr->value_; 01606 return TRUE; 01607 } 01608 01609 template<class Key, class Value> inline 01610 ostream& RBTree<Key, Value>::print(ostream& os, bool debug) const 01611 { 01612 if (root_!=0) root_->inorderPrint(os, debug); 01613 return os; 01614 } 01615 01616 template<class Key, class Value> inline 01617 ostream& operator<<(ostream& os, const RBTree<Key, Value>& t) 01618 { 01619 return t.print(os, FALSE); 01620 } 01621 01622 //------------------------------------------------------------------------- 01623 // 01624 // Rotations 01625 01626 template<class Key, class Value> inline 01627 int RBTree<Key, Value>::rotateLeft(RBTreeNode<Key, Value>* x) 01628 { 01629 // check for bad input; failure indicates a logic error in the 01630 // red-black balancing code. 01631 if (x==0) SETERRQ(1,"RBTree::rotateLeft input error: x = nil. This should never happen, and indicates a bug in the tree balancing code."); 01632 if (x->right_ == 0) SETERRQ(1,"RBTree::rotateLeft input error: x->right = nil. This should never happen, and indicates a bug in the tree balancing code."); 01633 RBTreeNode<Key, Value>* y = x->right_; 01634 01635 // attach left subtree of y to right side of x. 01636 x->right_ = y->left_; 01637 // notify the former left subtree of y that it is now a subtree of x. 01638 if (y->left_ != 0) y->left_->parent_ = x; 01639 01640 // link x's former parent to y. 01641 y->parent_ = x->parent_; 01642 01643 // if x was root, set root to y. 01644 if (x->parent_ == 0) 01645 { 01646 root_ = y; 01647 } 01648 // otherwise, tell x's former parent about y. 01649 else if (x == x->parent_->left_) 01650 { 01651 x->parent_->left_ = y; 01652 } 01653 else 01654 { 01655 x->parent_->right_ = y; 01656 } 01657 01658 // attach x to y's left 01659 y->left_ = x; 01660 // inform x that y is now its parent. 01661 x->parent_ = y; 01662 01663 return 0; 01664 } 01665 01666 template<class Key, class Value> inline 01667 int RBTree<Key, Value>::rotateRight(RBTreeNode<Key, Value>* x) 01668 { 01669 // check for bad input; failure indicates a logic error in the 01670 // red-black balancing code. 01671 if (x==0) SETERRQ(1,"RBTree::rotateRight input error: x = nil. This should never happen, and indicates a bug in the tree balancing code."); 01672 if (x->left_ == 0) SETERRQ(1,"RBTree::rotateRight input error: x->left = nil. This should never happen, and indicates a bug in the tree balancing code."); 01673 01674 RBTreeNode<Key, Value>* y = x->left_; 01675 01676 // attach right subtree of y to left side of x. 01677 x->left_ = y->right_; 01678 // notify the former right subtree of y that it is now a subtree of x. 01679 if (y->right_ != 0) y->right_->parent_ = x; 01680 01681 // link x's former parent to y. 01682 y->parent_ = x->parent_; 01683 01684 // if x was root, set root to y. 01685 if (x->parent_ == 0) 01686 { 01687 root_ = y; 01688 } 01689 // otherwise, tell x's former parent about y. 01690 else if (x == x->parent_->right_) 01691 { 01692 x->parent_->right_ = y; 01693 } 01694 else 01695 { 01696 x->parent_->left_ = y; 01697 } 01698 01699 // attach x to y's right 01700 y->right_ = x; 01701 // inform x that y is now its parent. 01702 x->parent_ = y; 01703 01704 return 0; 01705 } 01706 01707 01708 /* CommandLine.h */ 01709 /* class PromOptions ******************************************************** 01710 * BUGS/FEATURES: 01711 * 01712 * If for some strange reason a key appears twice, e.g. 01713 * myCode -pi 3.14 -pi 2.72 01714 * the second value wins. 01715 * 01716 * Everything crashes if you try to call init() twice. I'd rather have 01717 * a crash than the possibility of inconsistent results. 01718 * 01719 * If you forget to call init() and then call one of the CommandLine 01720 * functions, everything crashes. 01721 * 01722 */ 01723 class PromOptions 01724 { 01725 public: 01727 inline PromOptions() : matrix_(FALSE), verbose_(FALSE), files_(FALSE) {} 01728 // 01729 int InsertOptions( int *, char ***, char * ); 01730 int HasOptionName(const char name[], bool *flg)const { 01731 *flg = find( String(name) ); 01732 return 0; 01733 } 01734 // 01735 int GetOptionDouble(const char name[],double *dvalue,bool *flg)const{ 01736 double val; 01737 *flg = findDouble( String(name), val ); 01738 if( *flg ) *dvalue = val; 01739 return 0; 01740 } 01741 // 01742 int GetOptionInt(const char name[], int *ivalue, bool *flg) const { 01743 int val; 01744 *flg = findInt( String(name), val ); 01745 if( *flg ) *ivalue = val; 01746 return 0; 01747 } 01748 // 01749 int GetOptionString( const char name[], char string[], int len, 01750 bool *flg ) const { 01751 String val(len); 01752 *flg = findString( String(name), val ); 01753 if( strlen(val.cString()) >= len ) SETERRQ(1,"string buffer too short"); 01754 strcpy(string,val.cString()); 01755 01756 return 0; 01757 } 01758 int OptionsSetValue( const char iname[], const char value[] ) { 01759 int ntok = tokens_.length(); 01760 if( iname != NULL && iname[0] != '\0' ){ 01761 int ii = 1; 01762 if( value != NULL && value[0] != '\0' ) ii++; 01763 tokens_.resize(ntok+ii); 01764 tokens_[ntok] = String( iname ); 01765 tokenMap_.put( tokens_[ntok], ntok ); 01766 #if defined(PROM_HAVE_PETSc) 01767 if( strcmp(iname,"-log_info") == 0 || strcmp(iname,"-trmalloc") || 01768 strcmp(iname,"-trdump") ){ 01769 int ierr = PetscOptionsSetValue( iname, "" ); CHKERRQ(ierr); 01770 } 01771 #endif 01772 if( ii == 2 ) { 01773 ntok++; 01774 if( value != NULL ) tokens_[ntok] = String( value ); 01775 else tokens_[ntok] = String( "" ); 01776 tokenMap_.put( tokens_[ntok], ntok ); 01777 } 01778 } 01779 return 0; 01780 } 01781 inline int print(int myproc = 0, FILE *file=stderr)const; 01783 inline bool findString(const String& str, String& val) const; 01784 inline void debugPrint()const{ 01785 //tokens_.print(cout); 01786 tokenMap_.print(cout); 01787 } 01788 private: 01790 inline bool find(const String& str) const; 01791 inline bool find(const String& str, int& position) const; 01793 inline bool findDouble( const String& str, double& val ) const; 01795 inline bool findInt(const String& str, int& val) const; 01797 inline bool findInt(const String& str, Array<int>& val, 01798 int count) const; 01799 inline int checkInitialization()const; 01800 // data 01801 Array<String> tokens_; 01802 RBTree<String, int> tokenMap_; 01803 public: 01804 bool matrix_, files_; 01805 int verbose_; 01806 }; 01807 01808 /* Double.cpp */ 01809 inline String Double::toString( int precision ) const 01810 { 01811 int size = 40; 01812 char* str = new char[size+1]; 01813 01814 01815 int fmtSize = 10; 01816 char* fmt = new char[fmtSize+1]; 01817 int status = sprintf(fmt, "%%%d.%dle", precision+8, precision); 01818 if(status < 0) void_error("%s line %d: Double::toString() format truncated"); 01819 status = sprintf(str, fmt, val_); 01820 delete [] fmt; 01821 if (status < 0) void_error("%s line %d: Double::toString() input truncated"); 01822 01823 String rtn = str; 01824 delete [] str; 01825 return rtn; 01826 } 01827 01828 /* Int.cpp */ 01829 inline String Int::toString() const 01830 { 01831 int size = 12; 01832 char* str = new char[size+1]; 01833 01834 int status = sprintf(str, "%d", val_); 01835 if (status < 0) void_error("%s line %d: Int::toString() input truncated"); 01836 01837 String rtn = str; 01838 delete [] str; 01839 return rtn; 01840 } 01841 01842 /* CommandLine.cpp */ 01843 // set argc and argv. This should only be done once, so the class 01844 // is frozen when done. 01845 inline int PromOptions::InsertOptions( int *pargc, char ***pargv, char *fname) 01846 { 01847 int argc=*pargc,ii=0,toki=0; 01848 char **argv = *pargv; 01849 01850 // file 01851 FILE *file; 01852 if( fname != NULL && (file=fopen(fname,"r")) != NULL ) { 01853 #define BUFF_SIZE 256 01854 #define NOTISEND (jj < BUFF_SIZE && buff[jj] != '\0' && buff[jj] != '\n'&& buff[jj] != '!' && buff[jj] != '%' && buff[jj] != '/') 01855 char buff[BUFF_SIZE], word[BUFF_SIZE]; 01856 int kk = 0, ntok = argc - 1; 01857 while( kk++ < 2 ) { 01858 while( fgets( buff, BUFF_SIZE, file ) != NULL ) { 01859 if( buff[0] == '-' ) { 01860 int len, jj = 0; 01861 while( NOTISEND ) { 01862 // end of !white 01863 assert( buff[jj] != ' ' ); // have data 01864 for(len=0; buff[jj] != ' ' && NOTISEND; ) word[len++] = buff[jj++]; 01865 word[len] = '\0'; 01866 if( kk == 1 ) ntok++; 01867 else { 01868 String string( word, len ); 01869 tokens_[toki] = string; 01870 tokenMap_.put( tokens_[toki], toki ); 01871 toki++; 01872 } 01873 while(buff[jj] == ' ' && jj < BUFF_SIZE) jj++;//get to end of white 01874 } 01875 } 01876 } 01877 if( kk == 1 ) { 01878 tokens_.resize(ntok); // sets the size here: (argc-1) + |file| 01879 rewind(file); 01880 } 01881 } 01882 } 01883 else tokens_.resize(argc-1); // sets the size here: (argc-1) + |file| 01884 01885 // command line args -- enter last so as to overide file args 01886 for(ii=0; ii<(argc-1); ii++) { 01887 if (argv[ii+1]==0) continue; 01888 tokens_[toki] = String( argv[ii+1] ); 01889 tokenMap_.put( tokens_[toki], toki ); 01890 toki++; 01891 } 01892 01893 return 0; 01894 } 01895 01896 inline int PromOptions::checkInitialization() const 01897 { 01898 return 0; 01899 } 01900 01901 // check for presence of string on command line 01902 01903 inline bool PromOptions::find(const String& str) const 01904 { 01905 int ierr = checkInitialization(); CHKERRQ(ierr); 01906 return tokenMap_.containsKey(str); 01907 } 01908 01909 inline bool PromOptions::find(const String& str, int& position) const 01910 { 01911 int ierr = checkInitialization(); CHKERRQ(ierr); 01912 return tokenMap_.get(str, position); 01913 } 01914 01915 // return value via reference. Returns a bool indicating success or failure. 01916 01917 inline bool PromOptions::findDouble(const String& str, double& val) const 01918 { 01919 int position; 01920 01921 int ierr = checkInitialization(); CHKERRQ(ierr); 01922 01923 bool rtn; 01924 rtn = tokenMap_.get(str, position); 01925 if (!rtn || position >= tokens_.length()) return FALSE; 01926 val = atof(tokens_[position+1].cString()); 01927 return TRUE; 01928 } 01929 01930 inline bool PromOptions::findInt(const String& str, int& val) const 01931 { 01932 int position; 01933 01934 int ierr = checkInitialization(); CHKERRQ(ierr); 01935 01936 bool rtn; 01937 rtn = tokenMap_.get(str, position); 01938 if (!rtn || position >= tokens_.length()) return FALSE; 01939 val = atoi(tokens_[position+1].cString()); 01940 return TRUE; 01941 } 01942 01943 inline bool PromOptions::findString(const String& str, String& val) const 01944 { 01945 int position; 01946 01947 int ierr = checkInitialization(); CHKERRQ(ierr); 01948 01949 bool rtn; 01950 rtn = tokenMap_.get(str, position); 01951 if (!rtn || position >= tokens_.length()) return FALSE; 01952 val = tokens_[position+1]; 01953 return TRUE; 01954 } 01955 01956 inline int PromOptions::print( int myproc, FILE *file /*= stderr*/ ) const 01957 { 01958 const String str = tokens_.toString(); 01959 fprintf(file, "[%d] PromOptions: %s\n", myproc, str.cString()); 01960 return 0; 01961 } 01962 01963 #endif // PROM_USE_PETSC_OPTIONS 01964 01965 #endif // __PROM_OPTIONS_H__

Generated on Fri May 21 14:17:54 2004 by doxygen 1.3.7