12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799 |
- ///////////////////////////////////////////////////////////////////////////////////////
- /// \file gutil.h
- /// \brief GUTIL LIBRARY (Fully portable version)
- ///
- /// This library is provided as a component of the ecosystem modelling platform
- /// LPJ-GUESS. It combines the functionality of the XTRING and BENUTIL libraries
- /// These components are documented separately by commenting in this header file
- /// and in the source code file gutil.cpp.
- ///
- /// FULL PORTABILITY VERSION: tested and should work in any Unix, Linux or Windows
- /// environment.
- ///
- /// Enquiries to: Joe Siltberg, Lund University: joe.siltberg@nateko.lu.se
- /// All rights reserved, copyright retained by the author.
- ///
- /// \author Ben Smith, University of Lund
- /// $Date: 2014-09-09 10:49:13 +0200 (mar, 09 sep 2014) $
- ///
- ///////////////////////////////////////////////////////////////////////////////////////
- #ifndef GUTIL_H
- #define GUTIL_H
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <string.h>
- #include <stdarg.h>
- void fail();
- /// XTRING class - pointer-free manipulation of character strings in C++.
- /** Declare new xstring objects using one of the following forms:
- *
- * \code
- * xtring s; // equivalent to xtring s=""
- * xtring s="initial text";
- * xtring s='c';
- * xtring s(INITSIZE); // reserves space for at least INITSIZE+1 characters
- * \endcode
- *
- * You can also cast a string literal to an xtring the usual way:
- *
- * \code
- * (xtring)"Cast to a xtring"
- * \endcode
- *
- * In general, xtring objects can be used in place of standard C char* strings
- * without explicit casting, e.g.
- *
- * \code
- * char copy[100];
- * xtring original="text";
- * strcpy(copy,original);
- * \endcode
- *
- * However, xtring objects must be explicitly casted to char* when specified as
- * arguments in calls to functions with an ellipsis argument, e.g.
- *
- * \code
- * xtring name="Ben"
- * printf("My name is: %s",(char*)name);
- * \endcode
- *
- * Casting to char* is useful also if you (unwisely?) choose to write directly to
- * the internal string buffer of the xtring object:
- *
- * \code
- * xtring name(100);
- * char* pbuffer=(char*)name;
- * strcpy(pbuffer,"Ben");
- * \endcode
- *
- * Note that some of the member functions of xtring can cause the size and memory
- * position of the internal buffer to change.
- *
- * \section ops Operators
- *
- * Operator functionality is described mainly by code examples. The examples below
- * assume the following data types for variables:
- *
- * \code
- * xtring x1,x2,x3;
- * char* s;
- * char c;
- * unsigned long n;
- * \endcode
- *
- * Assignment operator:
- *
- * \code
- * x1=x2; x1=s; x1=c;
- * \endcode
- *
- * Concatenation (appends a char* string, xtring or character to the end of an
- * xtring string):
- *
- * \code
- * x1=x2+x3; x1=x2+s; x1=x2+c;
- * x1+=x2; x1+=s; x1+=c;
- * \endcode
- *
- * Concatenation of, for example, two char* strings, or a xtring to the end of
- * a char* string, is possible by casting one of the operands to an xtring:
- *
- * \code
- * x1=(xtring)"first"+"second";
- * x1=(xtring)"before"+x2;
- * \endcode
- *
- * Reference to character as array element:
- *
- * \code
- * c=x1[n]; x1[n]=c;
- * \endcode
- *
- * The size of the internal string buffer is expanded if necessary to ensure
- * that the specified index is valid (points to a character position within the
- * internal string buffer). However, the string itself is not expanded (i.e.
- * the position of the trailing null byte, signifying the end of the string, is
- * not changed.
- *
- * Comparison operators:
- *
- * \code
- * x1==x2 && x2!=x3 || x1<s || x1>c || x2<=x3 || x3>=x1
- * \endcode
- *
- * Note that the left hand operand must be a xtring (or casted to xtring)
- *
- * \author Ben Smith, University of Lund
- */
- class xtring {
- // MEMBER VARIABLES
- private:
- char *ptext;
- unsigned long nxegment;
- char *buf;
- // MEMBER FUNCTIONS
- private:
- void init();
- void resize(unsigned long nchar);
- void expand(unsigned long nchar);
- public:
- xtring(const xtring& s);
- xtring();
- xtring(char* text);
- xtring(const char* inittext);
- xtring(char c);
- xtring(unsigned long n);
- xtring(int n);
- xtring(long n);
- xtring(unsigned int n);
- ~xtring();
- operator char*();
- operator const char*() const;
- /// Adjusts memory allocation
- /** Expands or contracts the memory allocation to the current xtring object
- * to accomodate a string at least n characters in length (not including
- * the trailing null byte). The currently stored string may be copied to a
- * new location in memory but is not deleted. This function may be useful
- * if you intend to write directly to the internal string buffer, whose
- * address is returned by casting the xtring object to char*.
- */
- void reserve(unsigned long n);
- /// Length of string
- /** Returns length of current string in characters
- * (not including trailing null character).
- */
- unsigned long len();
- /// Converts to upper case
- /** Returns a new xtring equivalent to the current one, but with
- * lower-case alphabetics 'a'-'z' converted to upper case.
- */
- xtring upper();
- /// Converts to lower case
- /** Returns a new xtring equivalent to the current one, but with
- * upper-case alphabetics 'A'-'Z' converted to lower case.
- */
- xtring lower();
- /// Returns only printable characters
- /** Returns a new xtring equivalent to the current one, but with
- * non-printable characters (ASCII code 0-31) removed.
- */
- xtring printable();
- /// Returns a prefix of the string
- /** Returns a new xtring consisting of the leftmost n characters of
- * the current xtring. A null xtring ("") is returned if n<=0; if n>length
- * of the current xtring, an identical copy of the current xtring is
- * returned.
- */
- xtring left(unsigned long n);
- /// Returns a substring
- /** Returns a new xtring consisting of the rightmost portion of the current
- * xtring, starting at character number s (on 0 base). If s<0 an identical
- * copy of the current xtring is returned; if s>=length of the current
- * xtring, a null xtring is returned.
- */
- xtring mid(unsigned long s);
- /// Returns a substring
- /** Returns a new xtring consisting of up to n characters, starting at
- * character number s of the current xtring. If s<0, the new string starts
- * at character 0 of the current xtring; if s>=length of the current
- * xtring, a null xtring is returned.
- */
- xtring mid(unsigned long s,unsigned long n);
- /// Returns a postfix of the string
- /** Returns a new xtring consisting of the rightmost n characters of the
- * current xtring. A null string is returned if n<=0; if n>length of the
- * current xtring, an identical copy is returned.
- */
- xtring right(unsigned long n);
- /// Search for a substring
- /** Returns the position of the (first character of the) specified character
- * string if it occurs as a substring of the current xtring. If there are
- * several occurences, the position of the leftmost occurence is returned.
- * Returns -1 if string not found.
- */
- long find(const char* s);
- /// Search for a character
- /** Returns the position of the (first character of the) specified character
- * if it occurs in the current xtring. If there are several occurences, the
- * position of the leftmost occurence is returned.
- * Returns -1 if character not found.
- */
- long find(char c);
- /// Search for one of several characters
- /** Returns the position in this xtring of the first (leftmost) occurrence
- * any character forming part of the string pointed to by s. Returns -1 if
- * there are no occurrences.
- */
- long findoneof(const char* s);
- /// Search for character which isn't one of a given sequence of characters
- /** Returns the position in this xtring of the first (leftmost) character
- * NOT forming part of the string pointed to by s. Returns -1 if no such
- * character is found.
- */
- long findnotoneof(const char* s);
- /// Convert to a number
- /** Returns the numerical value of the current xtring, if it is a valid
- * representation of a double precision floating point number in C++. Call
- * function isnum() to test whether the returned value is meaningful.
- */
- double num();
- /// Checks if the string represents a number
- /** Returns 1 if the current xtring is a valid representation of a double
- * precision floating point number in C++, 0 otherwise.
- */
- char isnum();
- /// String formatting
- /** A printf-style function for writing formatted data to this xtring object.
- * Equivalent to sprintf in the standard C library (stdio.h).
- */
- void printf(const char* fmt,...);
- xtring& operator=(xtring& s);
- xtring& operator=(const char* s);
- xtring& operator=(char c);
- xtring operator+(xtring& s2);
- xtring operator+(const char* s2);
- xtring operator+(char c);
- xtring& operator+=(xtring& s2);
- xtring& operator+=(const char* s2);
- xtring& operator+=(char c);
- char& operator[](unsigned long n);
- char& operator[](int n);
- char& operator[](unsigned int n);
- char& operator[](long n);
- bool operator==(xtring& s2) const;
- bool operator==(char* s2) const;
- bool operator==(char c) const;
- bool operator==(const char* s2) const;
- bool operator!=(xtring& s2) const;
- bool operator!=(char* s2) const;
- bool operator!=(char c) const;
- bool operator!=(const char* s2) const;
- bool operator<(xtring& s2) const;
- bool operator<(char* s2) const;
- bool operator<(char c) const;
- bool operator<(const char* s2) const;
- bool operator>(xtring& s2) const;
- bool operator>(char* s2) const;
- bool operator>(char c) const;
- bool operator>(const char* s2) const;
- bool operator<=(xtring& s2) const;
- bool operator<=(char* s2) const;
- bool operator<=(char c) const;
- bool operator<=(const char* s2) const;
- bool operator>=(xtring& s2) const;
- bool operator>=(char* s2) const;
- bool operator>=(char c) const;
- bool operator>=(const char* s2) const;
- };
- ///////////////////////////////////////////////////////////////////////////////////////
- // COLLECTION CLASS TEMPLATES FROM THE BENUTIL LIBRARY
- const int SEGSIZE=16;
- /// List Array of objects
- /** Use this template to produce collection classes of any objects with a valid default
- * constructor.
- *
- * Declare a type using this template as either:
- *
- * \code
- * typedef ListArray<MyObjectType> MyCollectionClass;
- * \endcode
- *
- * or (for collection classes containing additional members)
- *
- * \code
- * class myclass : public ListArray<MyObjectType>
- * { ... };
- * \endcode
- *
- * Either of the above declarations will produce a class including the public functions
- * and member variables included in this class.
- *
- * This functionality implies that it is possible to loop sequentially through all
- * items in the list array using code like the following:
- *
- * \code
- * mycollection.firstobj();
- * while (mycollection.isobj) {
- * MyObjectType& obj=mycollection.getobj(); // NB: '&' required unless query only
- * // query or modify object obj here
- * mycollection.nextobj();
- * }
- * \endcode
- *
- * or alternatively:
- *
- * \code
- * for (i=0;i<mycollection.nobj;i++) {
- * MyObjectType& obj=mycollection[i];
- * // query or modify object obj here
- * }
- * \endcode
- */
- template<class tdata> class ListArray {
- class Item {
- public:
- Item* pnext;
- Item* pprev;
- tdata object;
- };
- private:
- Item** array;
- Item* pfirstitem;
- Item* plastitem;
- Item* pthisitem;
- unsigned int nseg;
- unsigned int thisobj;
- public:
- /// Whether the internal object pointer points to an object
- /** This variable (NB: not a function) is true whenever the internal object
- * pointer points to a MyObjectType object, false otherwise (including
- * when the list array is empty).
- */
- bool isobj;
- /// The number of objects currently stored in the list array.
- unsigned int nobj;
- public:
- ListArray() {
- pfirstitem=NULL;
- plastitem=NULL;
- pthisitem=NULL;
- isobj=false;
- nobj=0;
- nseg=0;
- }
- /// Clears the entire list array, releasing dynamic memory.
- void killall() {
- Item* pitem=pfirstitem;
- Item* pnext;
- while (pitem) {
- pnext=pitem->pnext;
- delete pitem;
- pitem=pnext;
- }
- if (nseg) delete[] array;
- pfirstitem=NULL;
- plastitem=NULL;
- pthisitem=NULL;
- isobj=false;
- nobj=0;
- nseg=0;
- }
- ~ListArray() {
- killall();
- }
- /// Clears list array (if not empty)
- /** Clears the array (if not empty) and fills it with nitem MyObjectType
- * objects.
- */
- void initarray(unsigned int nitem) {
- unsigned int i;
- killall();
- if (nitem<=0) return;
- nseg=nitem%SEGSIZE;
- if (nseg*SEGSIZE<nitem) nseg++;
- array=new Item*[nseg*SEGSIZE];
- if (!array) fail();
- for (i=0;i<nitem;i++) createobj();
- pthisitem=0;
- thisobj=0;
- }
- /// Creates a new object of type MyObjectType and returns a reference to it.
- tdata& createobj() {
- Item* pitem=new Item;
- if (!pitem) fail();
- pitem->pprev=plastitem;
- pitem->pnext=NULL;
- if (plastitem) plastitem->pnext=pitem;
- else pfirstitem=pitem;
- plastitem=pitem;
- pthisitem=pitem;
- isobj=true;
- thisobj=nobj++;
- if (nobj>nseg*SEGSIZE) {
- Item** newarray=new Item*[(nseg+1)*SEGSIZE];
- if (!newarray) fail();
- if (nseg++) {
- unsigned int i;
- for (i=0;i<nobj-1;i++)
- newarray[i]=array[i];
- delete[] array;
- }
- array=newarray;
- }
- array[nobj-1]=pitem;
- return pitem->object;
- }
- /// Go to the first object
- /** Causes the internal object pointer (pthisitem) to point to the first
- * MyObjectType object in the list array. Returns false if the list array
- * is empty.
- */
- bool firstobj() {
- if (pfirstitem) {
- pthisitem=pfirstitem;
- isobj=true;
- thisobj=0;
- return true;
- }
- return false;
- }
- /// Go to the next object
- /** Causes the internal object pointer to point to the next MyObjectType
- * object in the list array. Returns false if the last item has already
- * been reached.
- */
- bool nextobj() {
- if (pthisitem) {
- pthisitem=pthisitem->pnext;
- thisobj++;
- }
- if (pthisitem) return true;
- isobj=false;
- return false;
- }
- /// Returns current object
- /** Returns a reference to the object currently pointed to by the internal
- * object pointer. Do not call this function unless the pointer is
- * pointing to a valid object (isobj=true).
- */
- tdata& getobj() {
- return pthisitem->object;
- }
- /// Returns i'th object
- /** Overload of the array brackets operator which returns a reference to
- * the i'th MyObjectType item in the list array. Do not call unless the
- * internal object pointer is pointing to a valid object. Note that this
- * function does NOT affect the value of the internal pointer.
- */
- tdata& operator[](unsigned int i) {
- return array[i]->object;
- }
- /// Removes the object currently pointed to by the internal pointer.
- void killobj() {
- unsigned int i;
- if (!pthisitem) return;
- if (pthisitem==pfirstitem) pfirstitem=pthisitem->pnext;
- if (pthisitem==plastitem) plastitem=pthisitem->pprev;
- Item* pnextitem=pthisitem->pnext;
- if (pthisitem->pprev) pthisitem->pprev->pnext=pthisitem->pnext;
- if (pthisitem->pnext) pthisitem->pnext->pprev=pthisitem->pprev;
- delete pthisitem;
- pthisitem=pnextitem;
- if (!pthisitem) isobj=false;
- for (i=thisobj+1;i<nobj;i++)
- array[i-1]=array[i];
- nobj--;
- }
- };
- /// List Array of objects with id member and no reference members
- /** Use this template to produce collection classes for objects similar to:
- *
- * \code
- * class MyObjectType {
- * public:
- * unsigned int id;
- * // Other member data and functions
- * };
- * \endcode
- *
- * Declare a type using this template as either:
- *
- * \code
- * typedef ListArray_id<MyObjectType> MyCollectionClass;
- * \endcode
- *
- * or (for collection classes containing additional members)
- *
- * \code
- * class myclass : public ListArray_id<MyObjectType>
- * { ... };
- * \endcode
- *
- * Either of the above declarations will produce a class including the public functions
- * and member variables included in this class.
- *
- * This functionality implies that it is possible to loop sequentially through all
- * items in the list array using code like the following:
- *
- * \code
- * mycollection.firstobj();
- * while (mycollection.isobj) {
- * MyObjectType& obj=mycollection.getobj(); // NB: '&' required unless query only
- * // query or modify object obj here
- * mycollection.nextobj();
- * }
- * \endcode
- *
- * or alternatively:
- *
- * \code
- * for (i=0;i<mycollection.nobj;i++) {
- * MyObjectType& obj=mycollection[i];
- * // query or modify object obj here
- * }
- * \endcode
- */
- template<class tdata> class ListArray_id {
- class Item {
- public:
- Item* pnext;
- Item* pprev;
- tdata object;
- };
- private:
- Item** array;
- Item* pfirstitem;
- Item* plastitem;
- Item* pthisitem;
- unsigned int nseg;
- unsigned int id;
- unsigned int thisobj;
- public:
- /// Whether the internal object pointer points to an object
- /** This variable (NB: not a function) is true whenever the internal
- * object pointer points to a MyObjectType object, false otherwise
- * (including when the list array is empty).
- */
- bool isobj;
- /// The number of objects currently stored in the list array.
- unsigned int nobj;
- public:
- ListArray_id() {
- pfirstitem=NULL;
- plastitem=NULL;
- pthisitem=NULL;
- isobj=false;
- nobj=0;
- nseg=0;
- id=0;
- }
- /// Clears the entire list array, releasing dynamic memory.
- /** Resets the id counter to 0.
- */
- void killall() {
- Item* pitem=pfirstitem;
- Item* pnext;
- while (pitem) {
- pnext=pitem->pnext;
- delete pitem;
- pitem=pnext;
- }
- if (nseg) delete[] array;
- pfirstitem=NULL;
- plastitem=NULL;
- pthisitem=NULL;
- isobj=false;
- nobj=0;
- nseg=0;
- id=0;
- }
- ~ListArray_id() {
- killall();
- }
- /// Clears list array (if not empty)
- /** Clears list array (if not empty), resets id counter to 0 and fills list
- * array with nitem MyObjectType objects.
- */
- void initarray(unsigned int nitem) {
- unsigned int i;
- killall();
- if (nitem<=0) return;
- nseg=nitem%SEGSIZE;
- if (nseg*SEGSIZE<nitem) nseg++;
- array=new Item*[nseg*SEGSIZE];
- if (!array) fail();
- for (i=0;i<nitem;i++) createobj();
- pthisitem=0;
- thisobj=0;
- }
- /// Creates a new object of type MyObjectType and returns a reference to it.
- /** The id member of the new object is set to the value of a counter
- * which has initial value 0 and is incremented (by 1) on each subsequent
- * call to createobj.
- */
- tdata& createobj() {
- Item* pitem=new Item;
- if (!pitem) fail();
- pitem->object.id=id++;
- pitem->pprev=plastitem;
- pitem->pnext=NULL;
- if (plastitem) plastitem->pnext=pitem;
- else pfirstitem=pitem;
- plastitem=pitem;
- pthisitem=pitem;
- isobj=true;
- thisobj=nobj++;
- if (nobj>nseg*SEGSIZE) {
- Item** newarray=new Item*[(nseg+1)*SEGSIZE];
- if (!newarray) fail();
- if (nseg++) {
- unsigned int i;
- for (i=0;i<nobj-1;i++)
- newarray[i]=array[i];
- delete[] array;
- }
- array=newarray;
- }
- array[nobj-1]=pitem;
- return pitem->object;
- }
- /// Go to the first object
- /** Causes the internal object pointer (pthisitem) to point to the first
- * MyObjectType object in the list array. Returns false if the list array
- * is empty.
- */
- bool firstobj() {
- if (pfirstitem) {
- pthisitem=pfirstitem;
- isobj=true;
- thisobj=0;
- return true;
- }
- return false;
- }
- /// Go to the next object
- /** Causes the internal object pointer to point to the next MyObjectType
- * object in the list array. Returns false if the last item has already
- * been reached.
- */
- bool nextobj() {
- if (pthisitem) {
- pthisitem=pthisitem->pnext;
- thisobj++;
- }
- if (pthisitem) return true;
- isobj=false;
- return false;
- }
- /// Returns current object
- /** Returns a reference to the object currently pointed to by the internal
- * object pointer. Do not call this function unless the pointer is
- * pointing to a valid object (isobj=true).
- */
- tdata& getobj() {
- return pthisitem->object;
- }
- /// Returns i'th object
- /** Overload of the array brackets operator which returns a reference to
- * the i'th MyObjectType item in the list array. Do not call unless the
- * internal object pointer is pointing to a valid object. Note that this
- * function does NOT affect the value of the internal pointer.
- */
- tdata& operator[](unsigned int i) {
- return array[i]->object;
- }
- /// Removes the object currently pointed to by the internal pointer.
- void killobj() {
- unsigned int i;
- if (!pthisitem) return;
- if (pthisitem==pfirstitem) pfirstitem=pthisitem->pnext;
- if (pthisitem==plastitem) plastitem=pthisitem->pprev;
- Item* pnextitem=pthisitem->pnext;
- if (pthisitem->pprev) pthisitem->pprev->pnext=pthisitem->pnext;
- if (pthisitem->pnext) pthisitem->pnext->pprev=pthisitem->pprev;
- delete pthisitem;
- pthisitem=pnextitem;
- if (!pthisitem) isobj=false;
- for (i=thisobj+1;i<nobj;i++)
- array[i-1]=array[i];
- nobj--;
- }
- };
- /// List Array of objects with id member plus one extra member to initialise
- /** Use this template to produce collection classes for objects similar to:
- *
- * \code
- * class MyObjectType {
- * private:
- * unsigned int id;
- * MyRefType& refmember; // typically a reference member, but may be any type
- * public:
- * MyObjectType(unsigned int i,MyRefType& r):id(i),refmember(r) {}
- * // constructor with declaration like this MUST exist
- * // Other member data and functions
- * };
- * \endcode
- *
- * Declare a type using this template as either:
- *
- * \code
- * typedef ListArray_idin1<MyObjectType,MyRefType> MyCollectionClass;
- * \endcode
- *
- * or (for collection classes containing additional members)
- *
- * \code
- * class myclass : ListArray_idin1<MyObjectType,MyRefType>
- * { ... };
- * \endcode
- *
- * Either of the above declarations will produce a class including the public functions
- * and member variables included in this class.
- *
- * This functionality implies that it is possible to loop sequentially through all
- * items in the list array using code like the following:
- *
- * \code
- * mycollection.firstobj();
- * while (mycollection.isobj) {
- * MyObjectType& obj=mycollection.getobj(); // NB: '&' required unless query only
- * // query or modify object obj here
- * mycollection.nextobj();
- * }
- * \endcode
- *
- * or alternatively:
- *
- * \code
- * for (i=0;i<mycollection.nobj;i++) {
- * MyObjectType& obj=mycollection[i];
- * // query or modify object obj here
- * }
- * \endcode
- */
- template<class tdata,class tref> class ListArray_idin1 {
- class Item {
- public:
- Item* pnext;
- Item* pprev;
- tdata object;
- Item(unsigned int id,tref& ref) : object(id,ref) {}
- };
- private:
- Item** array;
- Item* pfirstitem;
- Item* plastitem;
- Item* pthisitem;
- unsigned int nseg;
- unsigned int id;
- unsigned int thisobj;
- public:
- /// Whether the internal object pointer points to an object
- /** This variable (NB: not a function) is true whenever the internal object
- * pointer points to a MyObjectType object, false otherwise (including
- * when the list array is empty).
- */
- bool isobj;
- /// The number of objects currently stored in the list array.
- unsigned int nobj;
- public:
- ListArray_idin1() {
- pfirstitem=NULL;
- plastitem=NULL;
- pthisitem=NULL;
- isobj=false;
- nobj=0;
- nseg=0;
- id=0;
- }
- /// Clears the entire list array, releases dynamic memory.
- /** Resets the id counter to 0.
- */
- void killall() {
- Item* pitem=pfirstitem;
- Item* pnext;
- while (pitem) {
- pnext=pitem->pnext;
- delete pitem;
- pitem=pnext;
- }
- if (nseg) delete[] array;
- pfirstitem=NULL;
- plastitem=NULL;
- pthisitem=NULL;
- isobj=false;
- nobj=0;
- nseg=0;
- id=0;
- }
- ~ListArray_idin1() {
- killall();
- }
- /// Creates a new object of type MyObjectType and returns a reference to it.
- /** The constructor function MyObjectType(unsigned int,MyRefType&) is
- * called, with the unsigned int argument set to the value of a counter
- * which has initial value 0 and is incremented (by 1) on each subsequent
- * call to createobj; ref is sent as the MyRefType& argument to the
- * constructor function.
- */
- tdata& createobj(tref& ref) {
- Item* pitem=new Item(id++,ref);
- if (!pitem) fail();
- pitem->pprev=plastitem;
- pitem->pnext=NULL;
- if (plastitem) plastitem->pnext=pitem;
- else pfirstitem=pitem;
- plastitem=pitem;
- pthisitem=pitem;
- isobj=true;
- thisobj=nobj++;
- if (nobj>nseg*SEGSIZE) {
- Item** newarray=new Item*[(nseg+1)*SEGSIZE];
- if (!newarray) fail();
- if (nseg++) {
- unsigned int i;
- for (i=0;i<nobj-1;i++)
- newarray[i]=array[i];
- delete[] array;
- }
- array=newarray;
- }
- array[nobj-1]=pitem;
- return pitem->object;
- }
- /// Go to the first object
- /** Causes the internal object pointer (pthisitem) to point to the first
- * MyObjectType object in the list array. Returns false if the list array
- * is empty.
- */
- bool firstobj() {
- if (pfirstitem) {
- pthisitem=pfirstitem;
- isobj=true;
- thisobj=0;
- return true;
- }
- return false;
- }
- /// Go to the next object
- /** Causes the internal object pointer to point to the next MyObjectType
- * object in the list array. Returns false if the last item has already
- * been reached.
- */
- bool nextobj() {
- if (pthisitem) {
- pthisitem=pthisitem->pnext;
- thisobj++;
- }
- if (pthisitem) return true;
- isobj=false;
- return false;
- }
- /// Returns current object
- /** Returns a reference to the object currently pointed to by the internal
- * object pointer. Do not call this function unless the pointer is
- * pointing to a valid object (isobj=true).
- */
- tdata& getobj() {
- return pthisitem->object;
- }
- /// Returns i'th object
- /** Overload of the array brackets operator which returns a reference to
- * the i'th MyObjectType item in the list array. Do not call unless the
- * internal object pointer is pointing to a valid object. Note that this
- * function does NOT affect the value of the internal pointer.
- */
- tdata& operator[](unsigned int i) {
- return array[i]->object;
- }
- /// Removes the object currently pointed to by the internal pointer.
- void killobj() {
- unsigned int i;
- if (!pthisitem) return;
- if (pthisitem==pfirstitem) pfirstitem=pthisitem->pnext;
- if (pthisitem==plastitem) plastitem=pthisitem->pprev;
- Item* pnextitem=pthisitem->pnext;
- if (pthisitem->pprev) pthisitem->pprev->pnext=pthisitem->pnext;
- if (pthisitem->pnext) pthisitem->pnext->pprev=pthisitem->pprev;
- delete pthisitem;
- pthisitem=pnextitem;
- if (!pthisitem) isobj=false;
- for (i=thisobj+1;i<nobj;i++)
- array[i-1]=array[i];
- nobj--;
- }
- };
- /// List Array of objects with id member plus two extra members to initialise
- /** Use this template to produce collection classes for objects similar to:
- *
- * \code
- * class MyObjectType {
- * private:
- * unsigned int id;
- * MyRefType1& refmember1; // typically reference members,
- * MyRefType2& refmember2; // but may be any type
- * public:
- * MyObjectType(unsigned int i,MyRefType1& r1,MyRefType2& r2):id(i),
- * refmember1(r1),refmember2(r2) {}
- * // constructor with declaration like this MUST exist
- * // Other member data and functions
- * };
- * \endcode
- *
- * Declare a type using this template as either:
- *
- * \code
- * typedef ListArray_idin2<MyObjectType,MyRefType1,MyRefType2>
- * MyCollectionClass;
- * \endcode
- *
- * or (for collection classes containing additional members)
- *
- * \code
- * class myclass :
- * public ListArray_idin2<MyObjectType,MyRefType1,MyRefType2>
- * { ... };
- * \endcode
- *
- * Either of the above declarations will produce a class including the public functions
- * and member variables included in this class.
- *
- * This functionality implies that it is possible to loop sequentially through all
- * items in the list array using code like the following:
- *
- * \code
- * mycollection.firstobj();
- * while (mycollection.isobj) {
- * MyObjectType& obj=mycollection.getobj(); // NB: '&' required unless query only
- * // query or modify object obj here
- * mycollection.nextobj();
- * }
- * \endcode
- *
- * or alternatively:
- *
- * \code
- * for (i=0;i<mycollection.nobj;i++) {
- * MyObjectType& obj=mycollection[i];
- * // query or modify object obj here
- * }
- * \endcode
- */
- template<class tdata,class tref1,class tref2> class ListArray_idin2 {
- class Item {
- public:
- Item* pnext;
- Item* pprev;
- tdata object;
- Item(unsigned int id,tref1& ref1,tref2& ref2) :
- object(id,ref1,ref2) {}
- };
- private:
- Item** array;
- Item* pfirstitem;
- Item* plastitem;
- Item* pthisitem;
- unsigned int nseg;
- unsigned int id;
- unsigned int thisobj;
- public:
- /// Whether the internal object pointer points to an object
- /** This variable (NB: not a function) is true whenever the internal object
- * pointer points to a MyObjectType object, false otherwise (including
- * when the list array is empty).
- */
- bool isobj;
- /// The number of objects currently stored in the list array.
- unsigned int nobj;
- public:
- ListArray_idin2() {
- pfirstitem=NULL;
- plastitem=NULL;
- pthisitem=NULL;
- isobj=false;
- nobj=0;
- nseg=0;
- id=0;
- }
- /// Clears the entire list array, releases dynamic memory.
- /** Resets the id counter to 0.
- */
- void killall() {
- Item* pitem=pfirstitem;
- Item* pnext;
- while (pitem) {
- pnext=pitem->pnext;
- delete pitem;
- pitem=pnext;
- }
- if (nseg) delete[] array;
- pfirstitem=NULL;
- plastitem=NULL;
- pthisitem=NULL;
- isobj=false;
- nobj=0;
- nseg=0;
- id=0;
- }
- ~ListArray_idin2() {
- killall();
- }
- /// Creates a new object of type MyObjectType and returns a reference to it.
- /** The constructor function MyObjectType(unsigned int,MyRefType1&,MyRefType2&)
- * is called, with the unsigned int argument set to the value of a counter
- * which has initial value 0 and is incremented (by 1) on each subsequent
- * call to createobj; ref1 and ref2 are sent as the MyRefType& arguments
- * to the constructor function.
- */
- tdata& createobj(tref1& ref1,tref2& ref2) {
- Item* pitem=new Item(id++,ref1,ref2);
- if (!pitem) fail();
- pitem->pprev=plastitem;
- pitem->pnext=NULL;
- if (plastitem) plastitem->pnext=pitem;
- else pfirstitem=pitem;
- plastitem=pitem;
- pthisitem=pitem;
- isobj=true;
- thisobj=nobj++;
- if (nobj>nseg*SEGSIZE) {
- Item** newarray=new Item*[(nseg+1)*SEGSIZE];
- if (!newarray) fail();
- if (nseg++) {
- unsigned int i;
- for (i=0;i<nobj-1;i++)
- newarray[i]=array[i];
- delete[] array;
- }
- array=newarray;
- }
- array[nobj-1]=pitem;
- return pitem->object;
- }
- /// Returns the first object
- /** Causes the internal object pointer (pthisitem) to point to the first
- * MyObjectType object in the list array. Returns false if the list array
- * is empty.
- */
- bool firstobj() {
- if (pfirstitem) {
- pthisitem=pfirstitem;
- isobj=true;
- thisobj=0;
- return true;
- }
- return false;
- }
- /// Returns the next object
- /** Causes the internal object pointer to point to the next MyObjectType
- * object in the list array. Returns false if the last item has already
- * been reached.
- */
- bool nextobj() {
- if (pthisitem) {
- pthisitem=pthisitem->pnext;
- thisobj++;
- }
- if (pthisitem) return true;
- isobj=false;
- return false;
- }
- /// Returns current object
- /** Returns a reference to the object currently pointed to by the internal
- * object pointer. Do not call this function unless the pointer is
- * pointing to a valid object (isobj=true).
- */
- tdata& getobj() {
- return pthisitem->object;
- }
- /// Returns i'th object
- /** Overload of the array brackets operator which returns a reference to
- * the i'th MyObjectType item in the list array. Do not call unless the
- * internal object pointer is pointing to a valid object. Note that this
- * function does NOT affect the value of the internal pointer.
- */
- tdata& operator[](unsigned int i) {
- return array[i]->object;
- }
- /// Removes the object currently pointed to by the internal pointer.
- void killobj() {
- unsigned int i;
- if (!pthisitem) return;
- if (pthisitem==pfirstitem) pfirstitem=pthisitem->pnext;
- if (pthisitem==plastitem) plastitem=pthisitem->pprev;
- Item* pnextitem=pthisitem->pnext;
- if (pthisitem->pprev) pthisitem->pprev->pnext=pthisitem->pnext;
- if (pthisitem->pnext) pthisitem->pnext->pprev=pthisitem->pprev;
- delete pthisitem;
- pthisitem=pnextitem;
- if (!pthisitem) isobj=false;
- for (i=thisobj+1;i<nobj;i++)
- array[i-1]=array[i];
- nobj--;
- }
- };
- /// List Array of objects with id member plus three extra members to initialise
- /** Use this template to produce collection classes for objects similar to:
- *
- * \code
- * class MyObjectType {
- * private:
- * unsigned int id;
- * MyRefType1& refmember1; // typically reference members,
- * MyRefType2& refmember2; // but may be any type
- * MyRefType3& refmember3;
- * public:
- * MyObjectType(unsigned int i,MyRefType1& r1,MyRefType2& r2):id(i),
- * refmember1(r1),refmember2(r2),refmember3(r3) {}
- * // constructor with declaration like this MUST exist
- * // Other member data and functions
- * };
- * \endcode
- *
- * Declare a type using this template as either:
- *
- * \code
- * typedef ListArray_idin3<MyObjectType,MyRefType1,MyRefType2,MyRefType3>
- * MyCollectionClass;
- * \endcode
- *
- * or (for collection classes containing additional members)
- *
- * \code
- * class myclass :
- * public ListArray_idin3<MyObjectType,MyRefType1,MyRefType2,MyRefType3>
- * { ... };
- * \endcode
- *
- * Either of the above declarations will produce a class including the public functions
- * and member variables included in this class.
- *
- * This functionality implies that it is possible to loop sequentially through all
- * items in the list array using code like the following:
- *
- * \code
- * mycollection.firstobj();
- * while (mycollection.isobj) {
- * MyObjectType& obj=mycollection.getobj(); // NB: '&' required unless query only
- * // query or modify object obj here
- * mycollection.nextobj();
- * }
- * \endcode
- *
- * or alternatively:
- *
- * \code
- * for (i=0;i<mycollection.nobj;i++) {
- * MyObjectType& obj=mycollection[i];
- * // query or modify object obj here
- * }
- * \endcode
- */
- template<class tdata,class tref1,class tref2,class tref3> class ListArray_idin3 {
- class Item {
- public:
- Item* pnext;
- Item* pprev;
- tdata object;
- Item(unsigned int id,tref1& ref1,tref2& ref2,tref3& ref3) :
- object(id,ref1,ref2,ref3) {}
- };
- private:
- Item** array;
- Item* pfirstitem;
- Item* plastitem;
- Item* pthisitem;
- unsigned int nseg;
- unsigned int id;
- unsigned int thisobj;
- public:
- /// Whether the internal object pointer points to an object
- /** This variable (NB: not a function) is true whenever the internal object
- * pointer points to a MyObjectType object, false otherwise (including
- * when the list array is empty).
- */
- bool isobj;
- /// The number of objects currently stored in the list array.
- unsigned int nobj;
- public:
- ListArray_idin3() {
- pfirstitem=NULL;
- plastitem=NULL;
- pthisitem=NULL;
- isobj=false;
- nobj=0;
- nseg=0;
- id=0;
- }
- /// Clears the entire list array, releases dynamic memory.
- /** Resets the id counter to 0.
- */
- void killall() {
- Item* pitem=pfirstitem;
- Item* pnext;
- while (pitem) {
- pnext=pitem->pnext;
- delete pitem;
- pitem=pnext;
- }
- if (nseg) delete[] array;
- pfirstitem=NULL;
- plastitem=NULL;
- pthisitem=NULL;
- isobj=false;
- nobj=0;
- nseg=0;
- id=0;
- }
- ~ListArray_idin3() {
- killall();
- }
- /// Creates a new object of type MyObjectType and returns a reference to it.
- /** The constructor function MyObjectType(unsigned int,MyRefType1&,MyRefType2&, MyRefType3&)
- * is called, with the unsigned int argument set to the value of a counter
- * which has initial value 0 and is incremented (by 1) on each subsequent
- * call to createobj; ref1, ref2 and ref3 are sent as the MyRefType&
- * arguments to the constructor function.
- */
- tdata& createobj(tref1& ref1,tref2& ref2,tref3& ref3) {
- Item* pitem=new Item(id++,ref1,ref2,ref3);
- if (!pitem) fail();
- pitem->pprev=plastitem;
- pitem->pnext=NULL;
- if (plastitem) plastitem->pnext=pitem;
- else pfirstitem=pitem;
- plastitem=pitem;
- pthisitem=pitem;
- isobj=true;
- thisobj=nobj++;
- if (nobj>nseg*SEGSIZE) {
- Item** newarray=new Item*[(nseg+1)*SEGSIZE];
- if (!newarray) fail();
- if (nseg++) {
- unsigned int i;
- for (i=0;i<nobj-1;i++)
- newarray[i]=array[i];
- delete[] array;
- }
- array=newarray;
- }
- array[nobj-1]=pitem;
- return pitem->object;
- }
- /// Go to the first object
- /** Causes the internal object pointer (pthisitem) to point to the first
- * MyObjectType object in the list array. Returns false if the list array
- * is empty.
- */
- bool firstobj() {
- if (pfirstitem) {
- pthisitem=pfirstitem;
- isobj=true;
- thisobj=0;
- return true;
- }
- return false;
- }
- /// Go to the next object
- /** Causes the internal object pointer to point to the next MyObjectType
- * object in the list array. Returns false if the last item has already
- * been reached.
- */
- bool nextobj() {
- if (pthisitem) {
- pthisitem=pthisitem->pnext;
- thisobj++;
- }
- if (pthisitem) return true;
- isobj=false;
- return false;
- }
- /// Returns current object
- /** Returns a reference to the object currently pointed to by the internal
- * object pointer. Do not call this function unless the pointer is
- * pointing to a valid object (isobj=true).
- */
- tdata& getobj() {
- return pthisitem->object;
- }
- /// Returns i'th object
- /** Overload of the array brackets operator which returns a reference to
- * the i'th MyObjectType item in the list array. Do not call unless the
- * internal object pointer is pointing to a valid object. Note that this
- * function does NOT affect the value of the internal pointer.
- */
- tdata& operator[](unsigned int i) {
- return array[i]->object;
- }
- /// Removes the object currently pointed to by the internal pointer.
- void killobj() {
- unsigned int i;
- if (!pthisitem) return;
- if (pthisitem==pfirstitem) pfirstitem=pthisitem->pnext;
- if (pthisitem==plastitem) plastitem=pthisitem->pprev;
- Item* pnextitem=pthisitem->pnext;
- if (pthisitem->pprev) pthisitem->pprev->pnext=pthisitem->pnext;
- if (pthisitem->pnext) pthisitem->pnext->pprev=pthisitem->pprev;
- delete pthisitem;
- pthisitem=pnextitem;
- if (!pthisitem) isobj=false;
- for (i=thisobj+1;i<nobj;i++)
- array[i-1]=array[i];
- nobj--;
- }
- };
- /// Functionality for relating runtime "progress" to real time
- /** The computer model for which gutil was developed can sometimes take many
- * hours to complete a simulation. It is desirable for users to obtain an
- * ongoing estimate of progress and remaining simulation time. This class
- * provides the necessary functionality.
- *
- * Sample program:
- *
- * \code
- * void slow(int i) {
- * // Do some number crunching
- * }
- *
- * int main() {
- * const int STEPS=1e10;
- * const int REPORT=1e9;
- * int i;
- *
- * Timer t;
- * t.init();
- *
- * t.settimer();
- *
- * for (i=0;i<STEPS;i++) {
- * t.setprogress(double(i)/double(STEPS));
- *
- * if (!(i%REPORT)) {
- * printf("Elapsed time: %s\n",t.elapsed.str);
- * printf("Remaining time: %s\n",t.remaining.str);
- * }
- *
- * slow(i);
- * }
- *
- * return 0;
- * }
- * \endcode
- */
- class Timer {
- private:
- long m_clock;
- long lastclock;
- double start_t;
- double finish_t;
- unsigned long timebase;
- double progress;
- public:
- struct {
- int hours; ///< elapsed full hours since timer set
- int minutes; ///< elapsed full minutes past the hour since timer set
- int seconds; ///< elapsed full seconds past the minute since timer set
- int milliseconds; ///< elapsed milliseconds past the second since timer set
- double time;
- char str[12]; ///< elapsed time in the form "hh:mm:ss"
- } elapsed;
- struct {
- int hours; ///< full hours remaining to "finished" status
- int minutes; ///< full minutes past the hour remaining
- int seconds; ///< full seconds past the minute remaining
- int milliseconds; ///< milliseconds past the second remaining
- double time;
- char str[12]; ///< remaining time in the form "hh:mm:ss"
- } remaining;
- private:
- void print() {
- if (elapsed.minutes>59 || elapsed.seconds>59 || elapsed.hours>9999) strcpy(elapsed.str,"#time_err#");
- else sprintf(elapsed.str,"%d%d:%d%d:%d%d",
- elapsed.hours/10,elapsed.hours%10,elapsed.minutes/10,
- elapsed.minutes%10,elapsed.seconds/10,elapsed.seconds%10);
- if (remaining.minutes>59 || remaining.seconds>59 || remaining.hours>9999) strcpy(remaining.str,"#time_err#");
- sprintf(remaining.str,"%d%d:%d%d:%d%d",
- remaining.hours/10,remaining.hours%10,remaining.minutes/10,
- remaining.minutes%10,remaining.seconds/10,remaining.seconds%10);
- }
- public:
- /// Returns time since start of process in milliseconds
- long timemilli() {
- long newclock=(long)((double)clock()/(double)CLOCKS_PER_SEC*1000.0);
- if (newclock>=lastclock) m_clock+=newclock-lastclock;
- lastclock=newclock;
- return m_clock;
- }
- /// Initialises the timer, called by the constructor
- void init() {
- m_clock=0;
- lastclock=(long)((double)clock()/(double)CLOCKS_PER_SEC*1000.0);
- timebase=timemilli();
- settimer(3600.0);
- }
- Timer() {
- init();
- }
- void update() {
- unsigned long time=timemilli();
- elapsed.time=(double)(time-timebase-start_t)/1000.0;
- elapsed.hours=(int)(elapsed.time/3600.0);
- elapsed.minutes=(int)(elapsed.time-elapsed.hours*3600)/60;
- elapsed.seconds=(int)(elapsed.time-elapsed.hours*3600-
- elapsed.minutes*60);
- elapsed.milliseconds=(int)(elapsed.time-elapsed.hours*3600-elapsed.minutes*60-
- elapsed.seconds);
- remaining.time=(double)(finish_t-time+timebase)/1000.0;
- if (remaining.time<0.0) remaining.time=0.0;
- remaining.hours=(int)(remaining.time/3600.0);
- remaining.minutes=(int)(remaining.time-remaining.hours*3600)/60;
- remaining.seconds=(int)(remaining.time-remaining.hours*3600-
- remaining.minutes*60);
- remaining.milliseconds=(int)(remaining.time-remaining.hours*3600-
- remaining.minutes*60-remaining.seconds);
- progress=elapsed.time*1000.0/(finish_t-start_t);
- print();
- }
- /// Commences timing
- /**
- * \param duration gives number of seconds to "finished" status
- */
- void settimer(double duration) {
- unsigned long time=timemilli();
- start_t=time-timebase;
- finish_t=start_t+duration*1000.0;
- update();
- }
- /// Sets one hour to "finished" status
- void settimer() {
- settimer(3600.0);
- }
- /// Specifies fractional progress (in range 0-1) towards "finished" status
- /** Modifies time remaining to "finished"
- */
- void setprogress(double p) {
- if (p>1.0) p=1.0;
- update();
- if (p>1.0e-10) finish_t=start_t+elapsed.time*1000.0/p;
- update();
- }
- /// Returns fractional progress (in range 0-1) towards "finished" status
- double getprogress() {
- update();
- return progress;
- }
- };
- /// Writes date and time in standard Unix format to an xtring argument
- /** e.g. "Tue Nov 06 10:17:47 2001"
- */
- void unixtime(xtring& result);
- /// Reads text according to FORTRAN-style format specification
- /** Function synopsis: bool readfor(FILE* strm, xtring format, ...)
- *
- * Reads in ASCII text data from input stream strm, according to a FORTRAN-style
- * format specification given in the string format. Addresses of the variables to be
- * assigned to are listed, in order of assignment, in the ellipsis (...) argument list
- * of the function. By default, any characters remaining on the current line are
- * discarded when the statement terminates (this behaviour can be overridden by a $
- * specifier in the format string - see below). The function returns true if all
- * specified values could be read in and assigned, or false if an end-of-file
- * condition prevented some values from being read in and assigned.
- *
- * Version modified 2005-09-13
- * The only change is that "a" format now reads only as far as next white space
- * character (or comma, or separator specified in format string), instead of end of
- * line as previously. The read to end of line specify "a#" in format string.
- *
- * Example: The following code opens for reading a text file called "climate.txt",
- * reads in two values of type double, one integer, and 12 further values of type
- * double, and assigns these values, respectively, to variables lon, lat, elev, and
- * the 12 elements of array mdata. Note that the arguments following the format
- * string are addresses of the variables to be assigned to - use the '&' prefix for
- * simple variables; omit the '&' if specifying an array name (a pointer).
- *
- * \code
- * #include <stdio.h>
- * #include <gutil.h>
- *
- * FILE* in;
- * double lon,lat;
- * int elev;
- * double mdata[12];
- *
- * in=fopen("climate.txt","rt");
- * if (!readfor(in,"f6.1,f5.1,i4,12f5.1",&lon,&lat,&elev,mdata))
- * printf("Warning: not all values could be read in\n");
- * \endcode
- *
- * \section format Format specifiers
- *
- * A subset of the format specifiers defined for input in the FORTRAN-77 language are
- * supported by function readfor. Note that there are some differences in the way
- * these are implemented compared to FORTRAN. Specifier fields in the format string
- * are normally separated by commas. Each instance of an F, I or A specifier is
- * assumedto correspond to one argument in the ellipsis argument list. Specifier
- * syntax is case-insensitive and spaces and tabs in the format string are ignored.
- *
- * Important: a value (other than 1) for n (number of items), if specified as part of
- * an F, I or A specification, assumes the values read are to be assigned to
- * consecutive elements of an array, whose starting address is given by a single
- * argument in the argument list. Do not use this feature to assign multiple values
- * with the same input format to multiple consective arguments.
- *
- * \subsection float Floating point specifier: nFw.dEe
- *
- * Reads one or more floating point numbers, assigning each value to a variable of
- * type double.
- *
- * - n - the number of items to read in; if n is not specified, one value is assumed.
- * See cautionary note above.
- * - w - the number of characters to read in for each item; if not specified,
- * characters are read up to the next space, tab, end-of-line, or the next
- * instance on the current line of a separator character appearing immediately
- * after the specifier in the format string (see below).
- * - d - the number of digits in the fractional part of the number; if a decimal point
- * is encountered, this overrides the specified value. If d is omitted and no
- * decimal point is encountered, the input string is interpreted as a whole
- * number.
- * - e - the number of digits in the exponent part of the number; if the character 'E'
- * or 'e' is encountered, this overrides the specified value. If e is omitted,
- * the exponent 0 (i.e., 10^0 = 1) is assumed.
- *
- * Examples:
- *
- * \verbatim
- Input stream: 1234 5.67
- Format spec Strings read Values assigned
- F "1234" 1234.0
- F3 "123" 123.0
- F3.1 "123" 12.3
- F4.2E1 "1234" 1.23E+04
- 2F4.2 "1234", " 5.6" 12.34, 5.6
- \endverbatim
- *
- * \subsection integer Integer specifier: nIw
- *
- * Reads one or more integers, assigning each value to a variable of type int.
- *
- * - n - the number of items to read in; if n is not specified, one value is assumed.
- * See cautionary note above.
- * - w - the number of characters to read in for each item; if not specified,
- * characters are read up to the next space, tab, end-of-line, or the next
- * instance on the current line of a separator character appearing immediately
- * after the specifier in the format string (see below).
- *
- * Examples:
- *
- * \verbatim
- Input stream: 123 4567
- Format spec Strings read Values assigned
- I "123" 123
- I2 "12" 12
- 2I4 "123 ", "4567" 123, 4567
- \endverbatim
- * \subsection char Character string specifier: nAw
- *
- * Reads one or more character strings, assigning each to a variable of type xtring.
- *
- * - n - the number of items to read in; if n is not specified, one value is assumed.
- *
- * - w - the number of characters to read for each item; if not specified, characters
- * are read up to the next white space character, comma, or the next instance of
- * a separator character appearing immediately after the specifier in the format
- * string (see below).
- *
- * Specify # after specified to read to end of line (see below)
- *
- * Examples:
- *
- * \verbatim
- Input stream: BERT HIGGINS
- Format spec Strings read and assigned
- A "BERT"
- A# "BERT HIGGINS"
- A2 "BE"
- 2A6 "BERT H", "IGGINS"
- \endverbatim
- *
- * \subsection pos Position specifier: nX
- *
- * Advances one or more characters on the input stream.
- *
- * - n - The number of characters to read and discard; if n is omitted, a single
- * character is read in and discarded.
- *
- * \subsection eol End-of-line specifier: /
- *
- * Advances to the end of the current line on the input stream. Input continues from
- * the start of the next line.
- *
- * \subsection suppress Suppress line feed specifier: $
- *
- * If given as the last significant character in the format string, suppresses
- * reading and discarding of the remainder of the current line on the input stream.
- *
- * \subsection readeol Read to end of line specifier: #
- *
- * Continues reading to end of line (intended for use with character string (A)
- * specifier).
- *
- * \subsection sep Separator character specifier:
- *
- * Any character other than a space, tab or comma, that cannot be interpreted as part
- * of one of the specifiers above, is interpreted as a separator character, and
- * causes input up to and including the first instance of the specified separator
- * character on the current line. If given immediately following a variable-width F,
- * I or A specification, input continues, for each item, until an instance of the
- * specified separator character is encountered, or the end of the current line is
- * reached (otherwise input continues until a space, tab or the end of the line is
- * reached). If the separator character follows a fixed-width F, I or A specification,
- * or forms a separate specification field, the characters read are discarded.
- *
- * Examples:
- *
- * \verbatim
- Input stream: 123; Hello World!; 3.142
- Format spec Strings read Values assigned
- I;A;F "123", " Hello World!", "3.142" 123, " Hello World!", 3.142
- F2.1;;I2,A "12", " 3", ".142" 1.2, 3, ".142"
- \endverbatim
- *
- */
- bool readfor(FILE* in, const char* fmt, ...);
- /// Used by functions with variable number of arguments to print to a string
- /** Function synopsis: void formatf(xtring& output, xtring& format, void* parglist)
- *
- * Translates a printf-style format string (format) and a set of "ellipsis" arguments
- * whose starting address is given by parglist to an output xtring (output)
- */
- void formatf(xtring& output,char* format,va_list& v);
- /// Checks if a file exists
- /**
- * \returns true if the specified filename exists and can be opened for
- * reading, otherwise false
- */
- bool fileexists(const xtring& filename);
- #endif // GUTIL_H
|