gutil.h 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799
  1. ///////////////////////////////////////////////////////////////////////////////////////
  2. /// \file gutil.h
  3. /// \brief GUTIL LIBRARY (Fully portable version)
  4. ///
  5. /// This library is provided as a component of the ecosystem modelling platform
  6. /// LPJ-GUESS. It combines the functionality of the XTRING and BENUTIL libraries
  7. /// These components are documented separately by commenting in this header file
  8. /// and in the source code file gutil.cpp.
  9. ///
  10. /// FULL PORTABILITY VERSION: tested and should work in any Unix, Linux or Windows
  11. /// environment.
  12. ///
  13. /// Enquiries to: Joe Siltberg, Lund University: joe.siltberg@nateko.lu.se
  14. /// All rights reserved, copyright retained by the author.
  15. ///
  16. /// \author Ben Smith, University of Lund
  17. /// $Date: 2014-09-09 10:49:13 +0200 (mar, 09 sep 2014) $
  18. ///
  19. ///////////////////////////////////////////////////////////////////////////////////////
  20. #ifndef GUTIL_H
  21. #define GUTIL_H
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <time.h>
  25. #include <string.h>
  26. #include <stdarg.h>
  27. void fail();
  28. /// XTRING class - pointer-free manipulation of character strings in C++.
  29. /** Declare new xstring objects using one of the following forms:
  30. *
  31. * \code
  32. * xtring s; // equivalent to xtring s=""
  33. * xtring s="initial text";
  34. * xtring s='c';
  35. * xtring s(INITSIZE); // reserves space for at least INITSIZE+1 characters
  36. * \endcode
  37. *
  38. * You can also cast a string literal to an xtring the usual way:
  39. *
  40. * \code
  41. * (xtring)"Cast to a xtring"
  42. * \endcode
  43. *
  44. * In general, xtring objects can be used in place of standard C char* strings
  45. * without explicit casting, e.g.
  46. *
  47. * \code
  48. * char copy[100];
  49. * xtring original="text";
  50. * strcpy(copy,original);
  51. * \endcode
  52. *
  53. * However, xtring objects must be explicitly casted to char* when specified as
  54. * arguments in calls to functions with an ellipsis argument, e.g.
  55. *
  56. * \code
  57. * xtring name="Ben"
  58. * printf("My name is: %s",(char*)name);
  59. * \endcode
  60. *
  61. * Casting to char* is useful also if you (unwisely?) choose to write directly to
  62. * the internal string buffer of the xtring object:
  63. *
  64. * \code
  65. * xtring name(100);
  66. * char* pbuffer=(char*)name;
  67. * strcpy(pbuffer,"Ben");
  68. * \endcode
  69. *
  70. * Note that some of the member functions of xtring can cause the size and memory
  71. * position of the internal buffer to change.
  72. *
  73. * \section ops Operators
  74. *
  75. * Operator functionality is described mainly by code examples. The examples below
  76. * assume the following data types for variables:
  77. *
  78. * \code
  79. * xtring x1,x2,x3;
  80. * char* s;
  81. * char c;
  82. * unsigned long n;
  83. * \endcode
  84. *
  85. * Assignment operator:
  86. *
  87. * \code
  88. * x1=x2; x1=s; x1=c;
  89. * \endcode
  90. *
  91. * Concatenation (appends a char* string, xtring or character to the end of an
  92. * xtring string):
  93. *
  94. * \code
  95. * x1=x2+x3; x1=x2+s; x1=x2+c;
  96. * x1+=x2; x1+=s; x1+=c;
  97. * \endcode
  98. *
  99. * Concatenation of, for example, two char* strings, or a xtring to the end of
  100. * a char* string, is possible by casting one of the operands to an xtring:
  101. *
  102. * \code
  103. * x1=(xtring)"first"+"second";
  104. * x1=(xtring)"before"+x2;
  105. * \endcode
  106. *
  107. * Reference to character as array element:
  108. *
  109. * \code
  110. * c=x1[n]; x1[n]=c;
  111. * \endcode
  112. *
  113. * The size of the internal string buffer is expanded if necessary to ensure
  114. * that the specified index is valid (points to a character position within the
  115. * internal string buffer). However, the string itself is not expanded (i.e.
  116. * the position of the trailing null byte, signifying the end of the string, is
  117. * not changed.
  118. *
  119. * Comparison operators:
  120. *
  121. * \code
  122. * x1==x2 && x2!=x3 || x1<s || x1>c || x2<=x3 || x3>=x1
  123. * \endcode
  124. *
  125. * Note that the left hand operand must be a xtring (or casted to xtring)
  126. *
  127. * \author Ben Smith, University of Lund
  128. */
  129. class xtring {
  130. // MEMBER VARIABLES
  131. private:
  132. char *ptext;
  133. unsigned long nxegment;
  134. char *buf;
  135. // MEMBER FUNCTIONS
  136. private:
  137. void init();
  138. void resize(unsigned long nchar);
  139. void expand(unsigned long nchar);
  140. public:
  141. xtring(const xtring& s);
  142. xtring();
  143. xtring(char* text);
  144. xtring(const char* inittext);
  145. xtring(char c);
  146. xtring(unsigned long n);
  147. xtring(int n);
  148. xtring(long n);
  149. xtring(unsigned int n);
  150. ~xtring();
  151. operator char*();
  152. operator const char*() const;
  153. /// Adjusts memory allocation
  154. /** Expands or contracts the memory allocation to the current xtring object
  155. * to accomodate a string at least n characters in length (not including
  156. * the trailing null byte). The currently stored string may be copied to a
  157. * new location in memory but is not deleted. This function may be useful
  158. * if you intend to write directly to the internal string buffer, whose
  159. * address is returned by casting the xtring object to char*.
  160. */
  161. void reserve(unsigned long n);
  162. /// Length of string
  163. /** Returns length of current string in characters
  164. * (not including trailing null character).
  165. */
  166. unsigned long len();
  167. /// Converts to upper case
  168. /** Returns a new xtring equivalent to the current one, but with
  169. * lower-case alphabetics 'a'-'z' converted to upper case.
  170. */
  171. xtring upper();
  172. /// Converts to lower case
  173. /** Returns a new xtring equivalent to the current one, but with
  174. * upper-case alphabetics 'A'-'Z' converted to lower case.
  175. */
  176. xtring lower();
  177. /// Returns only printable characters
  178. /** Returns a new xtring equivalent to the current one, but with
  179. * non-printable characters (ASCII code 0-31) removed.
  180. */
  181. xtring printable();
  182. /// Returns a prefix of the string
  183. /** Returns a new xtring consisting of the leftmost n characters of
  184. * the current xtring. A null xtring ("") is returned if n<=0; if n>length
  185. * of the current xtring, an identical copy of the current xtring is
  186. * returned.
  187. */
  188. xtring left(unsigned long n);
  189. /// Returns a substring
  190. /** Returns a new xtring consisting of the rightmost portion of the current
  191. * xtring, starting at character number s (on 0 base). If s<0 an identical
  192. * copy of the current xtring is returned; if s>=length of the current
  193. * xtring, a null xtring is returned.
  194. */
  195. xtring mid(unsigned long s);
  196. /// Returns a substring
  197. /** Returns a new xtring consisting of up to n characters, starting at
  198. * character number s of the current xtring. If s<0, the new string starts
  199. * at character 0 of the current xtring; if s>=length of the current
  200. * xtring, a null xtring is returned.
  201. */
  202. xtring mid(unsigned long s,unsigned long n);
  203. /// Returns a postfix of the string
  204. /** Returns a new xtring consisting of the rightmost n characters of the
  205. * current xtring. A null string is returned if n<=0; if n>length of the
  206. * current xtring, an identical copy is returned.
  207. */
  208. xtring right(unsigned long n);
  209. /// Search for a substring
  210. /** Returns the position of the (first character of the) specified character
  211. * string if it occurs as a substring of the current xtring. If there are
  212. * several occurences, the position of the leftmost occurence is returned.
  213. * Returns -1 if string not found.
  214. */
  215. long find(const char* s);
  216. /// Search for a character
  217. /** Returns the position of the (first character of the) specified character
  218. * if it occurs in the current xtring. If there are several occurences, the
  219. * position of the leftmost occurence is returned.
  220. * Returns -1 if character not found.
  221. */
  222. long find(char c);
  223. /// Search for one of several characters
  224. /** Returns the position in this xtring of the first (leftmost) occurrence
  225. * any character forming part of the string pointed to by s. Returns -1 if
  226. * there are no occurrences.
  227. */
  228. long findoneof(const char* s);
  229. /// Search for character which isn't one of a given sequence of characters
  230. /** Returns the position in this xtring of the first (leftmost) character
  231. * NOT forming part of the string pointed to by s. Returns -1 if no such
  232. * character is found.
  233. */
  234. long findnotoneof(const char* s);
  235. /// Convert to a number
  236. /** Returns the numerical value of the current xtring, if it is a valid
  237. * representation of a double precision floating point number in C++. Call
  238. * function isnum() to test whether the returned value is meaningful.
  239. */
  240. double num();
  241. /// Checks if the string represents a number
  242. /** Returns 1 if the current xtring is a valid representation of a double
  243. * precision floating point number in C++, 0 otherwise.
  244. */
  245. char isnum();
  246. /// String formatting
  247. /** A printf-style function for writing formatted data to this xtring object.
  248. * Equivalent to sprintf in the standard C library (stdio.h).
  249. */
  250. void printf(const char* fmt,...);
  251. xtring& operator=(xtring& s);
  252. xtring& operator=(const char* s);
  253. xtring& operator=(char c);
  254. xtring operator+(xtring& s2);
  255. xtring operator+(const char* s2);
  256. xtring operator+(char c);
  257. xtring& operator+=(xtring& s2);
  258. xtring& operator+=(const char* s2);
  259. xtring& operator+=(char c);
  260. char& operator[](unsigned long n);
  261. char& operator[](int n);
  262. char& operator[](unsigned int n);
  263. char& operator[](long n);
  264. bool operator==(xtring& s2) const;
  265. bool operator==(char* s2) const;
  266. bool operator==(char c) const;
  267. bool operator==(const char* s2) const;
  268. bool operator!=(xtring& s2) const;
  269. bool operator!=(char* s2) const;
  270. bool operator!=(char c) const;
  271. bool operator!=(const char* s2) const;
  272. bool operator<(xtring& s2) const;
  273. bool operator<(char* s2) const;
  274. bool operator<(char c) const;
  275. bool operator<(const char* s2) const;
  276. bool operator>(xtring& s2) const;
  277. bool operator>(char* s2) const;
  278. bool operator>(char c) const;
  279. bool operator>(const char* s2) const;
  280. bool operator<=(xtring& s2) const;
  281. bool operator<=(char* s2) const;
  282. bool operator<=(char c) const;
  283. bool operator<=(const char* s2) const;
  284. bool operator>=(xtring& s2) const;
  285. bool operator>=(char* s2) const;
  286. bool operator>=(char c) const;
  287. bool operator>=(const char* s2) const;
  288. };
  289. ///////////////////////////////////////////////////////////////////////////////////////
  290. // COLLECTION CLASS TEMPLATES FROM THE BENUTIL LIBRARY
  291. const int SEGSIZE=16;
  292. /// List Array of objects
  293. /** Use this template to produce collection classes of any objects with a valid default
  294. * constructor.
  295. *
  296. * Declare a type using this template as either:
  297. *
  298. * \code
  299. * typedef ListArray<MyObjectType> MyCollectionClass;
  300. * \endcode
  301. *
  302. * or (for collection classes containing additional members)
  303. *
  304. * \code
  305. * class myclass : public ListArray<MyObjectType>
  306. * { ... };
  307. * \endcode
  308. *
  309. * Either of the above declarations will produce a class including the public functions
  310. * and member variables included in this class.
  311. *
  312. * This functionality implies that it is possible to loop sequentially through all
  313. * items in the list array using code like the following:
  314. *
  315. * \code
  316. * mycollection.firstobj();
  317. * while (mycollection.isobj) {
  318. * MyObjectType& obj=mycollection.getobj(); // NB: '&' required unless query only
  319. * // query or modify object obj here
  320. * mycollection.nextobj();
  321. * }
  322. * \endcode
  323. *
  324. * or alternatively:
  325. *
  326. * \code
  327. * for (i=0;i<mycollection.nobj;i++) {
  328. * MyObjectType& obj=mycollection[i];
  329. * // query or modify object obj here
  330. * }
  331. * \endcode
  332. */
  333. template<class tdata> class ListArray {
  334. class Item {
  335. public:
  336. Item* pnext;
  337. Item* pprev;
  338. tdata object;
  339. };
  340. private:
  341. Item** array;
  342. Item* pfirstitem;
  343. Item* plastitem;
  344. Item* pthisitem;
  345. unsigned int nseg;
  346. unsigned int thisobj;
  347. public:
  348. /// Whether the internal object pointer points to an object
  349. /** This variable (NB: not a function) is true whenever the internal object
  350. * pointer points to a MyObjectType object, false otherwise (including
  351. * when the list array is empty).
  352. */
  353. bool isobj;
  354. /// The number of objects currently stored in the list array.
  355. unsigned int nobj;
  356. public:
  357. ListArray() {
  358. pfirstitem=NULL;
  359. plastitem=NULL;
  360. pthisitem=NULL;
  361. isobj=false;
  362. nobj=0;
  363. nseg=0;
  364. }
  365. /// Clears the entire list array, releasing dynamic memory.
  366. void killall() {
  367. Item* pitem=pfirstitem;
  368. Item* pnext;
  369. while (pitem) {
  370. pnext=pitem->pnext;
  371. delete pitem;
  372. pitem=pnext;
  373. }
  374. if (nseg) delete[] array;
  375. pfirstitem=NULL;
  376. plastitem=NULL;
  377. pthisitem=NULL;
  378. isobj=false;
  379. nobj=0;
  380. nseg=0;
  381. }
  382. ~ListArray() {
  383. killall();
  384. }
  385. /// Clears list array (if not empty)
  386. /** Clears the array (if not empty) and fills it with nitem MyObjectType
  387. * objects.
  388. */
  389. void initarray(unsigned int nitem) {
  390. unsigned int i;
  391. killall();
  392. if (nitem<=0) return;
  393. nseg=nitem%SEGSIZE;
  394. if (nseg*SEGSIZE<nitem) nseg++;
  395. array=new Item*[nseg*SEGSIZE];
  396. if (!array) fail();
  397. for (i=0;i<nitem;i++) createobj();
  398. pthisitem=0;
  399. thisobj=0;
  400. }
  401. /// Creates a new object of type MyObjectType and returns a reference to it.
  402. tdata& createobj() {
  403. Item* pitem=new Item;
  404. if (!pitem) fail();
  405. pitem->pprev=plastitem;
  406. pitem->pnext=NULL;
  407. if (plastitem) plastitem->pnext=pitem;
  408. else pfirstitem=pitem;
  409. plastitem=pitem;
  410. pthisitem=pitem;
  411. isobj=true;
  412. thisobj=nobj++;
  413. if (nobj>nseg*SEGSIZE) {
  414. Item** newarray=new Item*[(nseg+1)*SEGSIZE];
  415. if (!newarray) fail();
  416. if (nseg++) {
  417. unsigned int i;
  418. for (i=0;i<nobj-1;i++)
  419. newarray[i]=array[i];
  420. delete[] array;
  421. }
  422. array=newarray;
  423. }
  424. array[nobj-1]=pitem;
  425. return pitem->object;
  426. }
  427. /// Go to the first object
  428. /** Causes the internal object pointer (pthisitem) to point to the first
  429. * MyObjectType object in the list array. Returns false if the list array
  430. * is empty.
  431. */
  432. bool firstobj() {
  433. if (pfirstitem) {
  434. pthisitem=pfirstitem;
  435. isobj=true;
  436. thisobj=0;
  437. return true;
  438. }
  439. return false;
  440. }
  441. /// Go to the next object
  442. /** Causes the internal object pointer to point to the next MyObjectType
  443. * object in the list array. Returns false if the last item has already
  444. * been reached.
  445. */
  446. bool nextobj() {
  447. if (pthisitem) {
  448. pthisitem=pthisitem->pnext;
  449. thisobj++;
  450. }
  451. if (pthisitem) return true;
  452. isobj=false;
  453. return false;
  454. }
  455. /// Returns current object
  456. /** Returns a reference to the object currently pointed to by the internal
  457. * object pointer. Do not call this function unless the pointer is
  458. * pointing to a valid object (isobj=true).
  459. */
  460. tdata& getobj() {
  461. return pthisitem->object;
  462. }
  463. /// Returns i'th object
  464. /** Overload of the array brackets operator which returns a reference to
  465. * the i'th MyObjectType item in the list array. Do not call unless the
  466. * internal object pointer is pointing to a valid object. Note that this
  467. * function does NOT affect the value of the internal pointer.
  468. */
  469. tdata& operator[](unsigned int i) {
  470. return array[i]->object;
  471. }
  472. /// Removes the object currently pointed to by the internal pointer.
  473. void killobj() {
  474. unsigned int i;
  475. if (!pthisitem) return;
  476. if (pthisitem==pfirstitem) pfirstitem=pthisitem->pnext;
  477. if (pthisitem==plastitem) plastitem=pthisitem->pprev;
  478. Item* pnextitem=pthisitem->pnext;
  479. if (pthisitem->pprev) pthisitem->pprev->pnext=pthisitem->pnext;
  480. if (pthisitem->pnext) pthisitem->pnext->pprev=pthisitem->pprev;
  481. delete pthisitem;
  482. pthisitem=pnextitem;
  483. if (!pthisitem) isobj=false;
  484. for (i=thisobj+1;i<nobj;i++)
  485. array[i-1]=array[i];
  486. nobj--;
  487. }
  488. };
  489. /// List Array of objects with id member and no reference members
  490. /** Use this template to produce collection classes for objects similar to:
  491. *
  492. * \code
  493. * class MyObjectType {
  494. * public:
  495. * unsigned int id;
  496. * // Other member data and functions
  497. * };
  498. * \endcode
  499. *
  500. * Declare a type using this template as either:
  501. *
  502. * \code
  503. * typedef ListArray_id<MyObjectType> MyCollectionClass;
  504. * \endcode
  505. *
  506. * or (for collection classes containing additional members)
  507. *
  508. * \code
  509. * class myclass : public ListArray_id<MyObjectType>
  510. * { ... };
  511. * \endcode
  512. *
  513. * Either of the above declarations will produce a class including the public functions
  514. * and member variables included in this class.
  515. *
  516. * This functionality implies that it is possible to loop sequentially through all
  517. * items in the list array using code like the following:
  518. *
  519. * \code
  520. * mycollection.firstobj();
  521. * while (mycollection.isobj) {
  522. * MyObjectType& obj=mycollection.getobj(); // NB: '&' required unless query only
  523. * // query or modify object obj here
  524. * mycollection.nextobj();
  525. * }
  526. * \endcode
  527. *
  528. * or alternatively:
  529. *
  530. * \code
  531. * for (i=0;i<mycollection.nobj;i++) {
  532. * MyObjectType& obj=mycollection[i];
  533. * // query or modify object obj here
  534. * }
  535. * \endcode
  536. */
  537. template<class tdata> class ListArray_id {
  538. class Item {
  539. public:
  540. Item* pnext;
  541. Item* pprev;
  542. tdata object;
  543. };
  544. private:
  545. Item** array;
  546. Item* pfirstitem;
  547. Item* plastitem;
  548. Item* pthisitem;
  549. unsigned int nseg;
  550. unsigned int id;
  551. unsigned int thisobj;
  552. public:
  553. /// Whether the internal object pointer points to an object
  554. /** This variable (NB: not a function) is true whenever the internal
  555. * object pointer points to a MyObjectType object, false otherwise
  556. * (including when the list array is empty).
  557. */
  558. bool isobj;
  559. /// The number of objects currently stored in the list array.
  560. unsigned int nobj;
  561. public:
  562. ListArray_id() {
  563. pfirstitem=NULL;
  564. plastitem=NULL;
  565. pthisitem=NULL;
  566. isobj=false;
  567. nobj=0;
  568. nseg=0;
  569. id=0;
  570. }
  571. /// Clears the entire list array, releasing dynamic memory.
  572. /** Resets the id counter to 0.
  573. */
  574. void killall() {
  575. Item* pitem=pfirstitem;
  576. Item* pnext;
  577. while (pitem) {
  578. pnext=pitem->pnext;
  579. delete pitem;
  580. pitem=pnext;
  581. }
  582. if (nseg) delete[] array;
  583. pfirstitem=NULL;
  584. plastitem=NULL;
  585. pthisitem=NULL;
  586. isobj=false;
  587. nobj=0;
  588. nseg=0;
  589. id=0;
  590. }
  591. ~ListArray_id() {
  592. killall();
  593. }
  594. /// Clears list array (if not empty)
  595. /** Clears list array (if not empty), resets id counter to 0 and fills list
  596. * array with nitem MyObjectType objects.
  597. */
  598. void initarray(unsigned int nitem) {
  599. unsigned int i;
  600. killall();
  601. if (nitem<=0) return;
  602. nseg=nitem%SEGSIZE;
  603. if (nseg*SEGSIZE<nitem) nseg++;
  604. array=new Item*[nseg*SEGSIZE];
  605. if (!array) fail();
  606. for (i=0;i<nitem;i++) createobj();
  607. pthisitem=0;
  608. thisobj=0;
  609. }
  610. /// Creates a new object of type MyObjectType and returns a reference to it.
  611. /** The id member of the new object is set to the value of a counter
  612. * which has initial value 0 and is incremented (by 1) on each subsequent
  613. * call to createobj.
  614. */
  615. tdata& createobj() {
  616. Item* pitem=new Item;
  617. if (!pitem) fail();
  618. pitem->object.id=id++;
  619. pitem->pprev=plastitem;
  620. pitem->pnext=NULL;
  621. if (plastitem) plastitem->pnext=pitem;
  622. else pfirstitem=pitem;
  623. plastitem=pitem;
  624. pthisitem=pitem;
  625. isobj=true;
  626. thisobj=nobj++;
  627. if (nobj>nseg*SEGSIZE) {
  628. Item** newarray=new Item*[(nseg+1)*SEGSIZE];
  629. if (!newarray) fail();
  630. if (nseg++) {
  631. unsigned int i;
  632. for (i=0;i<nobj-1;i++)
  633. newarray[i]=array[i];
  634. delete[] array;
  635. }
  636. array=newarray;
  637. }
  638. array[nobj-1]=pitem;
  639. return pitem->object;
  640. }
  641. /// Go to the first object
  642. /** Causes the internal object pointer (pthisitem) to point to the first
  643. * MyObjectType object in the list array. Returns false if the list array
  644. * is empty.
  645. */
  646. bool firstobj() {
  647. if (pfirstitem) {
  648. pthisitem=pfirstitem;
  649. isobj=true;
  650. thisobj=0;
  651. return true;
  652. }
  653. return false;
  654. }
  655. /// Go to the next object
  656. /** Causes the internal object pointer to point to the next MyObjectType
  657. * object in the list array. Returns false if the last item has already
  658. * been reached.
  659. */
  660. bool nextobj() {
  661. if (pthisitem) {
  662. pthisitem=pthisitem->pnext;
  663. thisobj++;
  664. }
  665. if (pthisitem) return true;
  666. isobj=false;
  667. return false;
  668. }
  669. /// Returns current object
  670. /** Returns a reference to the object currently pointed to by the internal
  671. * object pointer. Do not call this function unless the pointer is
  672. * pointing to a valid object (isobj=true).
  673. */
  674. tdata& getobj() {
  675. return pthisitem->object;
  676. }
  677. /// Returns i'th object
  678. /** Overload of the array brackets operator which returns a reference to
  679. * the i'th MyObjectType item in the list array. Do not call unless the
  680. * internal object pointer is pointing to a valid object. Note that this
  681. * function does NOT affect the value of the internal pointer.
  682. */
  683. tdata& operator[](unsigned int i) {
  684. return array[i]->object;
  685. }
  686. /// Removes the object currently pointed to by the internal pointer.
  687. void killobj() {
  688. unsigned int i;
  689. if (!pthisitem) return;
  690. if (pthisitem==pfirstitem) pfirstitem=pthisitem->pnext;
  691. if (pthisitem==plastitem) plastitem=pthisitem->pprev;
  692. Item* pnextitem=pthisitem->pnext;
  693. if (pthisitem->pprev) pthisitem->pprev->pnext=pthisitem->pnext;
  694. if (pthisitem->pnext) pthisitem->pnext->pprev=pthisitem->pprev;
  695. delete pthisitem;
  696. pthisitem=pnextitem;
  697. if (!pthisitem) isobj=false;
  698. for (i=thisobj+1;i<nobj;i++)
  699. array[i-1]=array[i];
  700. nobj--;
  701. }
  702. };
  703. /// List Array of objects with id member plus one extra member to initialise
  704. /** Use this template to produce collection classes for objects similar to:
  705. *
  706. * \code
  707. * class MyObjectType {
  708. * private:
  709. * unsigned int id;
  710. * MyRefType& refmember; // typically a reference member, but may be any type
  711. * public:
  712. * MyObjectType(unsigned int i,MyRefType& r):id(i),refmember(r) {}
  713. * // constructor with declaration like this MUST exist
  714. * // Other member data and functions
  715. * };
  716. * \endcode
  717. *
  718. * Declare a type using this template as either:
  719. *
  720. * \code
  721. * typedef ListArray_idin1<MyObjectType,MyRefType> MyCollectionClass;
  722. * \endcode
  723. *
  724. * or (for collection classes containing additional members)
  725. *
  726. * \code
  727. * class myclass : ListArray_idin1<MyObjectType,MyRefType>
  728. * { ... };
  729. * \endcode
  730. *
  731. * Either of the above declarations will produce a class including the public functions
  732. * and member variables included in this class.
  733. *
  734. * This functionality implies that it is possible to loop sequentially through all
  735. * items in the list array using code like the following:
  736. *
  737. * \code
  738. * mycollection.firstobj();
  739. * while (mycollection.isobj) {
  740. * MyObjectType& obj=mycollection.getobj(); // NB: '&' required unless query only
  741. * // query or modify object obj here
  742. * mycollection.nextobj();
  743. * }
  744. * \endcode
  745. *
  746. * or alternatively:
  747. *
  748. * \code
  749. * for (i=0;i<mycollection.nobj;i++) {
  750. * MyObjectType& obj=mycollection[i];
  751. * // query or modify object obj here
  752. * }
  753. * \endcode
  754. */
  755. template<class tdata,class tref> class ListArray_idin1 {
  756. class Item {
  757. public:
  758. Item* pnext;
  759. Item* pprev;
  760. tdata object;
  761. Item(unsigned int id,tref& ref) : object(id,ref) {}
  762. };
  763. private:
  764. Item** array;
  765. Item* pfirstitem;
  766. Item* plastitem;
  767. Item* pthisitem;
  768. unsigned int nseg;
  769. unsigned int id;
  770. unsigned int thisobj;
  771. public:
  772. /// Whether the internal object pointer points to an object
  773. /** This variable (NB: not a function) is true whenever the internal object
  774. * pointer points to a MyObjectType object, false otherwise (including
  775. * when the list array is empty).
  776. */
  777. bool isobj;
  778. /// The number of objects currently stored in the list array.
  779. unsigned int nobj;
  780. public:
  781. ListArray_idin1() {
  782. pfirstitem=NULL;
  783. plastitem=NULL;
  784. pthisitem=NULL;
  785. isobj=false;
  786. nobj=0;
  787. nseg=0;
  788. id=0;
  789. }
  790. /// Clears the entire list array, releases dynamic memory.
  791. /** Resets the id counter to 0.
  792. */
  793. void killall() {
  794. Item* pitem=pfirstitem;
  795. Item* pnext;
  796. while (pitem) {
  797. pnext=pitem->pnext;
  798. delete pitem;
  799. pitem=pnext;
  800. }
  801. if (nseg) delete[] array;
  802. pfirstitem=NULL;
  803. plastitem=NULL;
  804. pthisitem=NULL;
  805. isobj=false;
  806. nobj=0;
  807. nseg=0;
  808. id=0;
  809. }
  810. ~ListArray_idin1() {
  811. killall();
  812. }
  813. /// Creates a new object of type MyObjectType and returns a reference to it.
  814. /** The constructor function MyObjectType(unsigned int,MyRefType&) is
  815. * called, with the unsigned int argument set to the value of a counter
  816. * which has initial value 0 and is incremented (by 1) on each subsequent
  817. * call to createobj; ref is sent as the MyRefType& argument to the
  818. * constructor function.
  819. */
  820. tdata& createobj(tref& ref) {
  821. Item* pitem=new Item(id++,ref);
  822. if (!pitem) fail();
  823. pitem->pprev=plastitem;
  824. pitem->pnext=NULL;
  825. if (plastitem) plastitem->pnext=pitem;
  826. else pfirstitem=pitem;
  827. plastitem=pitem;
  828. pthisitem=pitem;
  829. isobj=true;
  830. thisobj=nobj++;
  831. if (nobj>nseg*SEGSIZE) {
  832. Item** newarray=new Item*[(nseg+1)*SEGSIZE];
  833. if (!newarray) fail();
  834. if (nseg++) {
  835. unsigned int i;
  836. for (i=0;i<nobj-1;i++)
  837. newarray[i]=array[i];
  838. delete[] array;
  839. }
  840. array=newarray;
  841. }
  842. array[nobj-1]=pitem;
  843. return pitem->object;
  844. }
  845. /// Go to the first object
  846. /** Causes the internal object pointer (pthisitem) to point to the first
  847. * MyObjectType object in the list array. Returns false if the list array
  848. * is empty.
  849. */
  850. bool firstobj() {
  851. if (pfirstitem) {
  852. pthisitem=pfirstitem;
  853. isobj=true;
  854. thisobj=0;
  855. return true;
  856. }
  857. return false;
  858. }
  859. /// Go to the next object
  860. /** Causes the internal object pointer to point to the next MyObjectType
  861. * object in the list array. Returns false if the last item has already
  862. * been reached.
  863. */
  864. bool nextobj() {
  865. if (pthisitem) {
  866. pthisitem=pthisitem->pnext;
  867. thisobj++;
  868. }
  869. if (pthisitem) return true;
  870. isobj=false;
  871. return false;
  872. }
  873. /// Returns current object
  874. /** Returns a reference to the object currently pointed to by the internal
  875. * object pointer. Do not call this function unless the pointer is
  876. * pointing to a valid object (isobj=true).
  877. */
  878. tdata& getobj() {
  879. return pthisitem->object;
  880. }
  881. /// Returns i'th object
  882. /** Overload of the array brackets operator which returns a reference to
  883. * the i'th MyObjectType item in the list array. Do not call unless the
  884. * internal object pointer is pointing to a valid object. Note that this
  885. * function does NOT affect the value of the internal pointer.
  886. */
  887. tdata& operator[](unsigned int i) {
  888. return array[i]->object;
  889. }
  890. /// Removes the object currently pointed to by the internal pointer.
  891. void killobj() {
  892. unsigned int i;
  893. if (!pthisitem) return;
  894. if (pthisitem==pfirstitem) pfirstitem=pthisitem->pnext;
  895. if (pthisitem==plastitem) plastitem=pthisitem->pprev;
  896. Item* pnextitem=pthisitem->pnext;
  897. if (pthisitem->pprev) pthisitem->pprev->pnext=pthisitem->pnext;
  898. if (pthisitem->pnext) pthisitem->pnext->pprev=pthisitem->pprev;
  899. delete pthisitem;
  900. pthisitem=pnextitem;
  901. if (!pthisitem) isobj=false;
  902. for (i=thisobj+1;i<nobj;i++)
  903. array[i-1]=array[i];
  904. nobj--;
  905. }
  906. };
  907. /// List Array of objects with id member plus two extra members to initialise
  908. /** Use this template to produce collection classes for objects similar to:
  909. *
  910. * \code
  911. * class MyObjectType {
  912. * private:
  913. * unsigned int id;
  914. * MyRefType1& refmember1; // typically reference members,
  915. * MyRefType2& refmember2; // but may be any type
  916. * public:
  917. * MyObjectType(unsigned int i,MyRefType1& r1,MyRefType2& r2):id(i),
  918. * refmember1(r1),refmember2(r2) {}
  919. * // constructor with declaration like this MUST exist
  920. * // Other member data and functions
  921. * };
  922. * \endcode
  923. *
  924. * Declare a type using this template as either:
  925. *
  926. * \code
  927. * typedef ListArray_idin2<MyObjectType,MyRefType1,MyRefType2>
  928. * MyCollectionClass;
  929. * \endcode
  930. *
  931. * or (for collection classes containing additional members)
  932. *
  933. * \code
  934. * class myclass :
  935. * public ListArray_idin2<MyObjectType,MyRefType1,MyRefType2>
  936. * { ... };
  937. * \endcode
  938. *
  939. * Either of the above declarations will produce a class including the public functions
  940. * and member variables included in this class.
  941. *
  942. * This functionality implies that it is possible to loop sequentially through all
  943. * items in the list array using code like the following:
  944. *
  945. * \code
  946. * mycollection.firstobj();
  947. * while (mycollection.isobj) {
  948. * MyObjectType& obj=mycollection.getobj(); // NB: '&' required unless query only
  949. * // query or modify object obj here
  950. * mycollection.nextobj();
  951. * }
  952. * \endcode
  953. *
  954. * or alternatively:
  955. *
  956. * \code
  957. * for (i=0;i<mycollection.nobj;i++) {
  958. * MyObjectType& obj=mycollection[i];
  959. * // query or modify object obj here
  960. * }
  961. * \endcode
  962. */
  963. template<class tdata,class tref1,class tref2> class ListArray_idin2 {
  964. class Item {
  965. public:
  966. Item* pnext;
  967. Item* pprev;
  968. tdata object;
  969. Item(unsigned int id,tref1& ref1,tref2& ref2) :
  970. object(id,ref1,ref2) {}
  971. };
  972. private:
  973. Item** array;
  974. Item* pfirstitem;
  975. Item* plastitem;
  976. Item* pthisitem;
  977. unsigned int nseg;
  978. unsigned int id;
  979. unsigned int thisobj;
  980. public:
  981. /// Whether the internal object pointer points to an object
  982. /** This variable (NB: not a function) is true whenever the internal object
  983. * pointer points to a MyObjectType object, false otherwise (including
  984. * when the list array is empty).
  985. */
  986. bool isobj;
  987. /// The number of objects currently stored in the list array.
  988. unsigned int nobj;
  989. public:
  990. ListArray_idin2() {
  991. pfirstitem=NULL;
  992. plastitem=NULL;
  993. pthisitem=NULL;
  994. isobj=false;
  995. nobj=0;
  996. nseg=0;
  997. id=0;
  998. }
  999. /// Clears the entire list array, releases dynamic memory.
  1000. /** Resets the id counter to 0.
  1001. */
  1002. void killall() {
  1003. Item* pitem=pfirstitem;
  1004. Item* pnext;
  1005. while (pitem) {
  1006. pnext=pitem->pnext;
  1007. delete pitem;
  1008. pitem=pnext;
  1009. }
  1010. if (nseg) delete[] array;
  1011. pfirstitem=NULL;
  1012. plastitem=NULL;
  1013. pthisitem=NULL;
  1014. isobj=false;
  1015. nobj=0;
  1016. nseg=0;
  1017. id=0;
  1018. }
  1019. ~ListArray_idin2() {
  1020. killall();
  1021. }
  1022. /// Creates a new object of type MyObjectType and returns a reference to it.
  1023. /** The constructor function MyObjectType(unsigned int,MyRefType1&,MyRefType2&)
  1024. * is called, with the unsigned int argument set to the value of a counter
  1025. * which has initial value 0 and is incremented (by 1) on each subsequent
  1026. * call to createobj; ref1 and ref2 are sent as the MyRefType& arguments
  1027. * to the constructor function.
  1028. */
  1029. tdata& createobj(tref1& ref1,tref2& ref2) {
  1030. Item* pitem=new Item(id++,ref1,ref2);
  1031. if (!pitem) fail();
  1032. pitem->pprev=plastitem;
  1033. pitem->pnext=NULL;
  1034. if (plastitem) plastitem->pnext=pitem;
  1035. else pfirstitem=pitem;
  1036. plastitem=pitem;
  1037. pthisitem=pitem;
  1038. isobj=true;
  1039. thisobj=nobj++;
  1040. if (nobj>nseg*SEGSIZE) {
  1041. Item** newarray=new Item*[(nseg+1)*SEGSIZE];
  1042. if (!newarray) fail();
  1043. if (nseg++) {
  1044. unsigned int i;
  1045. for (i=0;i<nobj-1;i++)
  1046. newarray[i]=array[i];
  1047. delete[] array;
  1048. }
  1049. array=newarray;
  1050. }
  1051. array[nobj-1]=pitem;
  1052. return pitem->object;
  1053. }
  1054. /// Returns the first object
  1055. /** Causes the internal object pointer (pthisitem) to point to the first
  1056. * MyObjectType object in the list array. Returns false if the list array
  1057. * is empty.
  1058. */
  1059. bool firstobj() {
  1060. if (pfirstitem) {
  1061. pthisitem=pfirstitem;
  1062. isobj=true;
  1063. thisobj=0;
  1064. return true;
  1065. }
  1066. return false;
  1067. }
  1068. /// Returns the next object
  1069. /** Causes the internal object pointer to point to the next MyObjectType
  1070. * object in the list array. Returns false if the last item has already
  1071. * been reached.
  1072. */
  1073. bool nextobj() {
  1074. if (pthisitem) {
  1075. pthisitem=pthisitem->pnext;
  1076. thisobj++;
  1077. }
  1078. if (pthisitem) return true;
  1079. isobj=false;
  1080. return false;
  1081. }
  1082. /// Returns current object
  1083. /** Returns a reference to the object currently pointed to by the internal
  1084. * object pointer. Do not call this function unless the pointer is
  1085. * pointing to a valid object (isobj=true).
  1086. */
  1087. tdata& getobj() {
  1088. return pthisitem->object;
  1089. }
  1090. /// Returns i'th object
  1091. /** Overload of the array brackets operator which returns a reference to
  1092. * the i'th MyObjectType item in the list array. Do not call unless the
  1093. * internal object pointer is pointing to a valid object. Note that this
  1094. * function does NOT affect the value of the internal pointer.
  1095. */
  1096. tdata& operator[](unsigned int i) {
  1097. return array[i]->object;
  1098. }
  1099. /// Removes the object currently pointed to by the internal pointer.
  1100. void killobj() {
  1101. unsigned int i;
  1102. if (!pthisitem) return;
  1103. if (pthisitem==pfirstitem) pfirstitem=pthisitem->pnext;
  1104. if (pthisitem==plastitem) plastitem=pthisitem->pprev;
  1105. Item* pnextitem=pthisitem->pnext;
  1106. if (pthisitem->pprev) pthisitem->pprev->pnext=pthisitem->pnext;
  1107. if (pthisitem->pnext) pthisitem->pnext->pprev=pthisitem->pprev;
  1108. delete pthisitem;
  1109. pthisitem=pnextitem;
  1110. if (!pthisitem) isobj=false;
  1111. for (i=thisobj+1;i<nobj;i++)
  1112. array[i-1]=array[i];
  1113. nobj--;
  1114. }
  1115. };
  1116. /// List Array of objects with id member plus three extra members to initialise
  1117. /** Use this template to produce collection classes for objects similar to:
  1118. *
  1119. * \code
  1120. * class MyObjectType {
  1121. * private:
  1122. * unsigned int id;
  1123. * MyRefType1& refmember1; // typically reference members,
  1124. * MyRefType2& refmember2; // but may be any type
  1125. * MyRefType3& refmember3;
  1126. * public:
  1127. * MyObjectType(unsigned int i,MyRefType1& r1,MyRefType2& r2):id(i),
  1128. * refmember1(r1),refmember2(r2),refmember3(r3) {}
  1129. * // constructor with declaration like this MUST exist
  1130. * // Other member data and functions
  1131. * };
  1132. * \endcode
  1133. *
  1134. * Declare a type using this template as either:
  1135. *
  1136. * \code
  1137. * typedef ListArray_idin3<MyObjectType,MyRefType1,MyRefType2,MyRefType3>
  1138. * MyCollectionClass;
  1139. * \endcode
  1140. *
  1141. * or (for collection classes containing additional members)
  1142. *
  1143. * \code
  1144. * class myclass :
  1145. * public ListArray_idin3<MyObjectType,MyRefType1,MyRefType2,MyRefType3>
  1146. * { ... };
  1147. * \endcode
  1148. *
  1149. * Either of the above declarations will produce a class including the public functions
  1150. * and member variables included in this class.
  1151. *
  1152. * This functionality implies that it is possible to loop sequentially through all
  1153. * items in the list array using code like the following:
  1154. *
  1155. * \code
  1156. * mycollection.firstobj();
  1157. * while (mycollection.isobj) {
  1158. * MyObjectType& obj=mycollection.getobj(); // NB: '&' required unless query only
  1159. * // query or modify object obj here
  1160. * mycollection.nextobj();
  1161. * }
  1162. * \endcode
  1163. *
  1164. * or alternatively:
  1165. *
  1166. * \code
  1167. * for (i=0;i<mycollection.nobj;i++) {
  1168. * MyObjectType& obj=mycollection[i];
  1169. * // query or modify object obj here
  1170. * }
  1171. * \endcode
  1172. */
  1173. template<class tdata,class tref1,class tref2,class tref3> class ListArray_idin3 {
  1174. class Item {
  1175. public:
  1176. Item* pnext;
  1177. Item* pprev;
  1178. tdata object;
  1179. Item(unsigned int id,tref1& ref1,tref2& ref2,tref3& ref3) :
  1180. object(id,ref1,ref2,ref3) {}
  1181. };
  1182. private:
  1183. Item** array;
  1184. Item* pfirstitem;
  1185. Item* plastitem;
  1186. Item* pthisitem;
  1187. unsigned int nseg;
  1188. unsigned int id;
  1189. unsigned int thisobj;
  1190. public:
  1191. /// Whether the internal object pointer points to an object
  1192. /** This variable (NB: not a function) is true whenever the internal object
  1193. * pointer points to a MyObjectType object, false otherwise (including
  1194. * when the list array is empty).
  1195. */
  1196. bool isobj;
  1197. /// The number of objects currently stored in the list array.
  1198. unsigned int nobj;
  1199. public:
  1200. ListArray_idin3() {
  1201. pfirstitem=NULL;
  1202. plastitem=NULL;
  1203. pthisitem=NULL;
  1204. isobj=false;
  1205. nobj=0;
  1206. nseg=0;
  1207. id=0;
  1208. }
  1209. /// Clears the entire list array, releases dynamic memory.
  1210. /** Resets the id counter to 0.
  1211. */
  1212. void killall() {
  1213. Item* pitem=pfirstitem;
  1214. Item* pnext;
  1215. while (pitem) {
  1216. pnext=pitem->pnext;
  1217. delete pitem;
  1218. pitem=pnext;
  1219. }
  1220. if (nseg) delete[] array;
  1221. pfirstitem=NULL;
  1222. plastitem=NULL;
  1223. pthisitem=NULL;
  1224. isobj=false;
  1225. nobj=0;
  1226. nseg=0;
  1227. id=0;
  1228. }
  1229. ~ListArray_idin3() {
  1230. killall();
  1231. }
  1232. /// Creates a new object of type MyObjectType and returns a reference to it.
  1233. /** The constructor function MyObjectType(unsigned int,MyRefType1&,MyRefType2&, MyRefType3&)
  1234. * is called, with the unsigned int argument set to the value of a counter
  1235. * which has initial value 0 and is incremented (by 1) on each subsequent
  1236. * call to createobj; ref1, ref2 and ref3 are sent as the MyRefType&
  1237. * arguments to the constructor function.
  1238. */
  1239. tdata& createobj(tref1& ref1,tref2& ref2,tref3& ref3) {
  1240. Item* pitem=new Item(id++,ref1,ref2,ref3);
  1241. if (!pitem) fail();
  1242. pitem->pprev=plastitem;
  1243. pitem->pnext=NULL;
  1244. if (plastitem) plastitem->pnext=pitem;
  1245. else pfirstitem=pitem;
  1246. plastitem=pitem;
  1247. pthisitem=pitem;
  1248. isobj=true;
  1249. thisobj=nobj++;
  1250. if (nobj>nseg*SEGSIZE) {
  1251. Item** newarray=new Item*[(nseg+1)*SEGSIZE];
  1252. if (!newarray) fail();
  1253. if (nseg++) {
  1254. unsigned int i;
  1255. for (i=0;i<nobj-1;i++)
  1256. newarray[i]=array[i];
  1257. delete[] array;
  1258. }
  1259. array=newarray;
  1260. }
  1261. array[nobj-1]=pitem;
  1262. return pitem->object;
  1263. }
  1264. /// Go to the first object
  1265. /** Causes the internal object pointer (pthisitem) to point to the first
  1266. * MyObjectType object in the list array. Returns false if the list array
  1267. * is empty.
  1268. */
  1269. bool firstobj() {
  1270. if (pfirstitem) {
  1271. pthisitem=pfirstitem;
  1272. isobj=true;
  1273. thisobj=0;
  1274. return true;
  1275. }
  1276. return false;
  1277. }
  1278. /// Go to the next object
  1279. /** Causes the internal object pointer to point to the next MyObjectType
  1280. * object in the list array. Returns false if the last item has already
  1281. * been reached.
  1282. */
  1283. bool nextobj() {
  1284. if (pthisitem) {
  1285. pthisitem=pthisitem->pnext;
  1286. thisobj++;
  1287. }
  1288. if (pthisitem) return true;
  1289. isobj=false;
  1290. return false;
  1291. }
  1292. /// Returns current object
  1293. /** Returns a reference to the object currently pointed to by the internal
  1294. * object pointer. Do not call this function unless the pointer is
  1295. * pointing to a valid object (isobj=true).
  1296. */
  1297. tdata& getobj() {
  1298. return pthisitem->object;
  1299. }
  1300. /// Returns i'th object
  1301. /** Overload of the array brackets operator which returns a reference to
  1302. * the i'th MyObjectType item in the list array. Do not call unless the
  1303. * internal object pointer is pointing to a valid object. Note that this
  1304. * function does NOT affect the value of the internal pointer.
  1305. */
  1306. tdata& operator[](unsigned int i) {
  1307. return array[i]->object;
  1308. }
  1309. /// Removes the object currently pointed to by the internal pointer.
  1310. void killobj() {
  1311. unsigned int i;
  1312. if (!pthisitem) return;
  1313. if (pthisitem==pfirstitem) pfirstitem=pthisitem->pnext;
  1314. if (pthisitem==plastitem) plastitem=pthisitem->pprev;
  1315. Item* pnextitem=pthisitem->pnext;
  1316. if (pthisitem->pprev) pthisitem->pprev->pnext=pthisitem->pnext;
  1317. if (pthisitem->pnext) pthisitem->pnext->pprev=pthisitem->pprev;
  1318. delete pthisitem;
  1319. pthisitem=pnextitem;
  1320. if (!pthisitem) isobj=false;
  1321. for (i=thisobj+1;i<nobj;i++)
  1322. array[i-1]=array[i];
  1323. nobj--;
  1324. }
  1325. };
  1326. /// Functionality for relating runtime "progress" to real time
  1327. /** The computer model for which gutil was developed can sometimes take many
  1328. * hours to complete a simulation. It is desirable for users to obtain an
  1329. * ongoing estimate of progress and remaining simulation time. This class
  1330. * provides the necessary functionality.
  1331. *
  1332. * Sample program:
  1333. *
  1334. * \code
  1335. * void slow(int i) {
  1336. * // Do some number crunching
  1337. * }
  1338. *
  1339. * int main() {
  1340. * const int STEPS=1e10;
  1341. * const int REPORT=1e9;
  1342. * int i;
  1343. *
  1344. * Timer t;
  1345. * t.init();
  1346. *
  1347. * t.settimer();
  1348. *
  1349. * for (i=0;i<STEPS;i++) {
  1350. * t.setprogress(double(i)/double(STEPS));
  1351. *
  1352. * if (!(i%REPORT)) {
  1353. * printf("Elapsed time: %s\n",t.elapsed.str);
  1354. * printf("Remaining time: %s\n",t.remaining.str);
  1355. * }
  1356. *
  1357. * slow(i);
  1358. * }
  1359. *
  1360. * return 0;
  1361. * }
  1362. * \endcode
  1363. */
  1364. class Timer {
  1365. private:
  1366. long m_clock;
  1367. long lastclock;
  1368. double start_t;
  1369. double finish_t;
  1370. unsigned long timebase;
  1371. double progress;
  1372. public:
  1373. struct {
  1374. int hours; ///< elapsed full hours since timer set
  1375. int minutes; ///< elapsed full minutes past the hour since timer set
  1376. int seconds; ///< elapsed full seconds past the minute since timer set
  1377. int milliseconds; ///< elapsed milliseconds past the second since timer set
  1378. double time;
  1379. char str[12]; ///< elapsed time in the form "hh:mm:ss"
  1380. } elapsed;
  1381. struct {
  1382. int hours; ///< full hours remaining to "finished" status
  1383. int minutes; ///< full minutes past the hour remaining
  1384. int seconds; ///< full seconds past the minute remaining
  1385. int milliseconds; ///< milliseconds past the second remaining
  1386. double time;
  1387. char str[12]; ///< remaining time in the form "hh:mm:ss"
  1388. } remaining;
  1389. private:
  1390. void print() {
  1391. if (elapsed.minutes>59 || elapsed.seconds>59 || elapsed.hours>9999) strcpy(elapsed.str,"#time_err#");
  1392. else sprintf(elapsed.str,"%d%d:%d%d:%d%d",
  1393. elapsed.hours/10,elapsed.hours%10,elapsed.minutes/10,
  1394. elapsed.minutes%10,elapsed.seconds/10,elapsed.seconds%10);
  1395. if (remaining.minutes>59 || remaining.seconds>59 || remaining.hours>9999) strcpy(remaining.str,"#time_err#");
  1396. sprintf(remaining.str,"%d%d:%d%d:%d%d",
  1397. remaining.hours/10,remaining.hours%10,remaining.minutes/10,
  1398. remaining.minutes%10,remaining.seconds/10,remaining.seconds%10);
  1399. }
  1400. public:
  1401. /// Returns time since start of process in milliseconds
  1402. long timemilli() {
  1403. long newclock=(long)((double)clock()/(double)CLOCKS_PER_SEC*1000.0);
  1404. if (newclock>=lastclock) m_clock+=newclock-lastclock;
  1405. lastclock=newclock;
  1406. return m_clock;
  1407. }
  1408. /// Initialises the timer, called by the constructor
  1409. void init() {
  1410. m_clock=0;
  1411. lastclock=(long)((double)clock()/(double)CLOCKS_PER_SEC*1000.0);
  1412. timebase=timemilli();
  1413. settimer(3600.0);
  1414. }
  1415. Timer() {
  1416. init();
  1417. }
  1418. void update() {
  1419. unsigned long time=timemilli();
  1420. elapsed.time=(double)(time-timebase-start_t)/1000.0;
  1421. elapsed.hours=(int)(elapsed.time/3600.0);
  1422. elapsed.minutes=(int)(elapsed.time-elapsed.hours*3600)/60;
  1423. elapsed.seconds=(int)(elapsed.time-elapsed.hours*3600-
  1424. elapsed.minutes*60);
  1425. elapsed.milliseconds=(int)(elapsed.time-elapsed.hours*3600-elapsed.minutes*60-
  1426. elapsed.seconds);
  1427. remaining.time=(double)(finish_t-time+timebase)/1000.0;
  1428. if (remaining.time<0.0) remaining.time=0.0;
  1429. remaining.hours=(int)(remaining.time/3600.0);
  1430. remaining.minutes=(int)(remaining.time-remaining.hours*3600)/60;
  1431. remaining.seconds=(int)(remaining.time-remaining.hours*3600-
  1432. remaining.minutes*60);
  1433. remaining.milliseconds=(int)(remaining.time-remaining.hours*3600-
  1434. remaining.minutes*60-remaining.seconds);
  1435. progress=elapsed.time*1000.0/(finish_t-start_t);
  1436. print();
  1437. }
  1438. /// Commences timing
  1439. /**
  1440. * \param duration gives number of seconds to "finished" status
  1441. */
  1442. void settimer(double duration) {
  1443. unsigned long time=timemilli();
  1444. start_t=time-timebase;
  1445. finish_t=start_t+duration*1000.0;
  1446. update();
  1447. }
  1448. /// Sets one hour to "finished" status
  1449. void settimer() {
  1450. settimer(3600.0);
  1451. }
  1452. /// Specifies fractional progress (in range 0-1) towards "finished" status
  1453. /** Modifies time remaining to "finished"
  1454. */
  1455. void setprogress(double p) {
  1456. if (p>1.0) p=1.0;
  1457. update();
  1458. if (p>1.0e-10) finish_t=start_t+elapsed.time*1000.0/p;
  1459. update();
  1460. }
  1461. /// Returns fractional progress (in range 0-1) towards "finished" status
  1462. double getprogress() {
  1463. update();
  1464. return progress;
  1465. }
  1466. };
  1467. /// Writes date and time in standard Unix format to an xtring argument
  1468. /** e.g. "Tue Nov 06 10:17:47 2001"
  1469. */
  1470. void unixtime(xtring& result);
  1471. /// Reads text according to FORTRAN-style format specification
  1472. /** Function synopsis: bool readfor(FILE* strm, xtring format, ...)
  1473. *
  1474. * Reads in ASCII text data from input stream strm, according to a FORTRAN-style
  1475. * format specification given in the string format. Addresses of the variables to be
  1476. * assigned to are listed, in order of assignment, in the ellipsis (...) argument list
  1477. * of the function. By default, any characters remaining on the current line are
  1478. * discarded when the statement terminates (this behaviour can be overridden by a $
  1479. * specifier in the format string - see below). The function returns true if all
  1480. * specified values could be read in and assigned, or false if an end-of-file
  1481. * condition prevented some values from being read in and assigned.
  1482. *
  1483. * Version modified 2005-09-13
  1484. * The only change is that "a" format now reads only as far as next white space
  1485. * character (or comma, or separator specified in format string), instead of end of
  1486. * line as previously. The read to end of line specify "a#" in format string.
  1487. *
  1488. * Example: The following code opens for reading a text file called "climate.txt",
  1489. * reads in two values of type double, one integer, and 12 further values of type
  1490. * double, and assigns these values, respectively, to variables lon, lat, elev, and
  1491. * the 12 elements of array mdata. Note that the arguments following the format
  1492. * string are addresses of the variables to be assigned to - use the '&' prefix for
  1493. * simple variables; omit the '&' if specifying an array name (a pointer).
  1494. *
  1495. * \code
  1496. * #include <stdio.h>
  1497. * #include <gutil.h>
  1498. *
  1499. * FILE* in;
  1500. * double lon,lat;
  1501. * int elev;
  1502. * double mdata[12];
  1503. *
  1504. * in=fopen("climate.txt","rt");
  1505. * if (!readfor(in,"f6.1,f5.1,i4,12f5.1",&lon,&lat,&elev,mdata))
  1506. * printf("Warning: not all values could be read in\n");
  1507. * \endcode
  1508. *
  1509. * \section format Format specifiers
  1510. *
  1511. * A subset of the format specifiers defined for input in the FORTRAN-77 language are
  1512. * supported by function readfor. Note that there are some differences in the way
  1513. * these are implemented compared to FORTRAN. Specifier fields in the format string
  1514. * are normally separated by commas. Each instance of an F, I or A specifier is
  1515. * assumedto correspond to one argument in the ellipsis argument list. Specifier
  1516. * syntax is case-insensitive and spaces and tabs in the format string are ignored.
  1517. *
  1518. * Important: a value (other than 1) for n (number of items), if specified as part of
  1519. * an F, I or A specification, assumes the values read are to be assigned to
  1520. * consecutive elements of an array, whose starting address is given by a single
  1521. * argument in the argument list. Do not use this feature to assign multiple values
  1522. * with the same input format to multiple consective arguments.
  1523. *
  1524. * \subsection float Floating point specifier: nFw.dEe
  1525. *
  1526. * Reads one or more floating point numbers, assigning each value to a variable of
  1527. * type double.
  1528. *
  1529. * - n - the number of items to read in; if n is not specified, one value is assumed.
  1530. * See cautionary note above.
  1531. * - w - the number of characters to read in for each item; if not specified,
  1532. * characters are read up to the next space, tab, end-of-line, or the next
  1533. * instance on the current line of a separator character appearing immediately
  1534. * after the specifier in the format string (see below).
  1535. * - d - the number of digits in the fractional part of the number; if a decimal point
  1536. * is encountered, this overrides the specified value. If d is omitted and no
  1537. * decimal point is encountered, the input string is interpreted as a whole
  1538. * number.
  1539. * - e - the number of digits in the exponent part of the number; if the character 'E'
  1540. * or 'e' is encountered, this overrides the specified value. If e is omitted,
  1541. * the exponent 0 (i.e., 10^0 = 1) is assumed.
  1542. *
  1543. * Examples:
  1544. *
  1545. * \verbatim
  1546. Input stream: 1234 5.67
  1547. Format spec Strings read Values assigned
  1548. F "1234" 1234.0
  1549. F3 "123" 123.0
  1550. F3.1 "123" 12.3
  1551. F4.2E1 "1234" 1.23E+04
  1552. 2F4.2 "1234", " 5.6" 12.34, 5.6
  1553. \endverbatim
  1554. *
  1555. * \subsection integer Integer specifier: nIw
  1556. *
  1557. * Reads one or more integers, assigning each value to a variable of type int.
  1558. *
  1559. * - n - the number of items to read in; if n is not specified, one value is assumed.
  1560. * See cautionary note above.
  1561. * - w - the number of characters to read in for each item; if not specified,
  1562. * characters are read up to the next space, tab, end-of-line, or the next
  1563. * instance on the current line of a separator character appearing immediately
  1564. * after the specifier in the format string (see below).
  1565. *
  1566. * Examples:
  1567. *
  1568. * \verbatim
  1569. Input stream: 123 4567
  1570. Format spec Strings read Values assigned
  1571. I "123" 123
  1572. I2 "12" 12
  1573. 2I4 "123 ", "4567" 123, 4567
  1574. \endverbatim
  1575. * \subsection char Character string specifier: nAw
  1576. *
  1577. * Reads one or more character strings, assigning each to a variable of type xtring.
  1578. *
  1579. * - n - the number of items to read in; if n is not specified, one value is assumed.
  1580. *
  1581. * - w - the number of characters to read for each item; if not specified, characters
  1582. * are read up to the next white space character, comma, or the next instance of
  1583. * a separator character appearing immediately after the specifier in the format
  1584. * string (see below).
  1585. *
  1586. * Specify # after specified to read to end of line (see below)
  1587. *
  1588. * Examples:
  1589. *
  1590. * \verbatim
  1591. Input stream: BERT HIGGINS
  1592. Format spec Strings read and assigned
  1593. A "BERT"
  1594. A# "BERT HIGGINS"
  1595. A2 "BE"
  1596. 2A6 "BERT H", "IGGINS"
  1597. \endverbatim
  1598. *
  1599. * \subsection pos Position specifier: nX
  1600. *
  1601. * Advances one or more characters on the input stream.
  1602. *
  1603. * - n - The number of characters to read and discard; if n is omitted, a single
  1604. * character is read in and discarded.
  1605. *
  1606. * \subsection eol End-of-line specifier: /
  1607. *
  1608. * Advances to the end of the current line on the input stream. Input continues from
  1609. * the start of the next line.
  1610. *
  1611. * \subsection suppress Suppress line feed specifier: $
  1612. *
  1613. * If given as the last significant character in the format string, suppresses
  1614. * reading and discarding of the remainder of the current line on the input stream.
  1615. *
  1616. * \subsection readeol Read to end of line specifier: #
  1617. *
  1618. * Continues reading to end of line (intended for use with character string (A)
  1619. * specifier).
  1620. *
  1621. * \subsection sep Separator character specifier:
  1622. *
  1623. * Any character other than a space, tab or comma, that cannot be interpreted as part
  1624. * of one of the specifiers above, is interpreted as a separator character, and
  1625. * causes input up to and including the first instance of the specified separator
  1626. * character on the current line. If given immediately following a variable-width F,
  1627. * I or A specification, input continues, for each item, until an instance of the
  1628. * specified separator character is encountered, or the end of the current line is
  1629. * reached (otherwise input continues until a space, tab or the end of the line is
  1630. * reached). If the separator character follows a fixed-width F, I or A specification,
  1631. * or forms a separate specification field, the characters read are discarded.
  1632. *
  1633. * Examples:
  1634. *
  1635. * \verbatim
  1636. Input stream: 123; Hello World!; 3.142
  1637. Format spec Strings read Values assigned
  1638. I;A;F "123", " Hello World!", "3.142" 123, " Hello World!", 3.142
  1639. F2.1;;I2,A "12", " 3", ".142" 1.2, 3, ".142"
  1640. \endverbatim
  1641. *
  1642. */
  1643. bool readfor(FILE* in, const char* fmt, ...);
  1644. /// Used by functions with variable number of arguments to print to a string
  1645. /** Function synopsis: void formatf(xtring& output, xtring& format, void* parglist)
  1646. *
  1647. * Translates a printf-style format string (format) and a set of "ellipsis" arguments
  1648. * whose starting address is given by parglist to an output xtring (output)
  1649. */
  1650. void formatf(xtring& output,char* format,va_list& v);
  1651. /// Checks if a file exists
  1652. /**
  1653. * \returns true if the specified filename exists and can be opened for
  1654. * reading, otherwise false
  1655. */
  1656. bool fileexists(const xtring& filename);
  1657. #endif // GUTIL_H