1 #ifndef G_BASE_DEFINED
2 #define G_BASE_DEFINED
3 #define GCLIB_VERSION "0.11.9"
4 
5 #ifdef HAVE_CONFIG_H
6 #include "config.h"
7 #endif
8 
9 #if defined(__WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_WIN64) || defined(__MINGW64__) || defined(__WINDOWS__)
10   #ifndef _WIN32
11     #define _WIN32
12   #endif
13   #ifndef _WIN64
14     #define _WIN64
15   #endif
16   #define __USE_MINGW_ANSI_STDIO 1
17   //#define __ISO_C_VISIBLE 1999
18 #endif
19 
20 #include <string.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <limits.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <stdint.h>
28 #include <stdarg.h>
29 
30 #ifdef _WIN32
31   #include <windows.h>
32   #include <io.h>
33   #define CHPATHSEP '\\'
34   #undef off_t
35   #define off_t int64_t
36   #ifndef popen
37    #define popen _popen
38   #endif
39   #ifndef fseeko
40 		#ifdef _fseeki64
41 			#define fseeko(stream, offset, origin) _fseeki64(stream, offset, origin)
42 		#else
43 			#define fseeko fseek
44 		#endif
45   #endif
46  #ifndef ftello
47   #ifdef _ftelli64
48     #define ftello(stream) _ftelli64(stream)
49   #else
50     #define ftello ftell
51   #endif
52  #endif
53  #else
54   #define CHPATHSEP '/'
55   #include <unistd.h>
56 #endif
57 
58 #ifndef fseeko
59  #define fseeko fseek
60 #endif
61 #ifndef ftello
62  #define ftello ftell
63 #endif
64 
65 #ifdef DEBUG
66 #undef NDEBUG
67 #define _DEBUG 1
68 #define _DEBUG_ 1
69 #endif
70 
71 typedef int32_t int32;
72 typedef uint32_t uint32;
73 typedef int16_t int16;
74 typedef uint16_t uint16;
75 
76 typedef unsigned char uchar;
77 typedef unsigned char byte;
78 
79 #ifndef MAXUINT
80 #define MAXUINT ((unsigned int)-1)
81 #endif
82 
83 #ifndef MAXINT
84 #define MAXINT INT_MAX
85 #endif
86 
87 #ifndef MAX_UINT
88 #define MAX_UINT ((unsigned int)-1)
89 #endif
90 
91 #ifndef MAX_INT
92 #define MAX_INT INT_MAX
93 #endif
94 
95 typedef int64_t int64;
96 typedef uint64_t uint64;
97 
98 /****************************************************************************/
99 
100 #ifndef EXIT_FAILURE
101 #define EXIT_FAILURE 1
102 #endif
103 
104 #ifndef EXIT_SUCCESS
105 #define EXIT_SUCCESS 0
106 #endif
107 
108 /****************************************************************************/
109 #define ERR_ALLOC "Error allocating memory.\n"
110 
111 //-------------------
112 
113 #define GEXIT(a) { \
114 fprintf(stderr, "Error: "); fprintf(stderr, a); \
115 GError("Exiting from line %i in file %s\n",__LINE__,__FILE__); \
116 }
117 
118 // Debug helpers
119 #ifndef NDEBUG
120  #define GASSERT(exp) ((exp)?((void)0):(void)GAssert(#exp,__FILE__,__LINE__))
121  #define GVERIFY(condition) \
122 if (!(condition)) { \
123 fprintf(stderr, "Assumption \"%s\"\nFailed in file %s: at line:%i\n", \
124 #condition,__FILE__,__LINE__); \
125 GEXIT(#condition);}
126  #ifdef TRACE
127   #define GTRACE(exp)  (GMessage(exp))
128  #else
129   #define GTRACE(exp)
130  #endif
131 #else
132  #define GASSERT(exp)
133  #define GTRACE(exp)
134  #define GVERIFY(condition)
135 #endif
136 
137 #define GERROR(exp) (GError(exp))
138 
139 // Abolute value
140 #define GABS(val) (((val)>=0)?(val):-(val))
141 
142 // Min and Max
143 #define GMAX(a,b) (((a)>(b))?(a):(b))
144 #define GMIN(a,b) (((a)>(b))?(b):(a))
145 
146 // Min of three
147 #define GMIN3(x,y,z) ((x)<(y)?GMIN(x,z):GMIN(y,z))
148 
149 // Max of three
150 #define GMAX3(x,y,z) ((x)>(y)?GMAX(x,z):GMAX(y,z))
151 
152 // Return minimum and maximum of a, b
153 #define GMINMAX(lo,hi,a,b) ((a)<(b)?((lo)=(a),(hi)=(b)):((lo)=(b),(hi)=(a)))
154 
155 // Clamp value x to range [lo..hi]
156 #define GCLAMP(lo,x,hi) ((x)<(lo)?(lo):((x)>(hi)?(hi):(x)))
157 
158 typedef void* pointer;
159 typedef unsigned int uint;
160 
161 typedef int GCompareProc(const pointer item1, const pointer item2);
162 typedef long GFStoreProc(const pointer item1, FILE* fstorage); //for serialization
163 typedef pointer GFLoadProc(FILE* fstorage); //for deserialization
164 
165 typedef void GFreeProc(pointer item); //usually just delete,
166       //but may also support structures with embedded dynamic members
167 
168 #define GMALLOC(ptr,size)  if (!GMalloc((pointer*)(&ptr),size)) \
169                                      GError(ERR_ALLOC)
170 #define GCALLOC(ptr,size)  if (!GCalloc((pointer*)(&ptr),size)) \
171                                      GError(ERR_ALLOC)
172 #define GREALLOC(ptr,size) if (!GRealloc((pointer*)(&ptr),size)) \
173                                      GError(ERR_ALLOC)
174 #define GFREE(ptr)       GFree((pointer*)(&ptr))
175 
strMin(char * arg1,char * arg2)176 inline char* strMin(char *arg1, char *arg2) {
177     return (strcmp(arg1, arg2) < 0)? arg1 : arg2;
178 }
179 
strMax(char * arg1,char * arg2)180 inline char* strMax(char *arg1, char *arg2) {
181     return (strcmp(arg2, arg1) < 0)? arg1 : arg2;
182 }
183 
iround(double x)184 inline int iround(double x) {
185    return (int)floor(x + 0.5);
186 }
187 
188 int Gmkdir(const char *path, bool recursive=true, int perms = (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH));
189 void Gmktempdir(char* templ);
190 
191 /****************************************************************************/
192 
Gintcmp(int a,int b)193 inline int Gintcmp(int a, int b) {
194  //return (a>b)? 1 : ((a==b)?0:-1);
195   return a-b;
196 }
197 
198 int Gstrcmp(const char* a, const char* b, int n=-1);
199 //same as strcmp but doesn't crash on NULL pointers
200 
201 int Gstricmp(const char* a, const char* b, int n=-1);
202 bool GstrEq(const char* a, const char* b);
203 bool GstriEq(const char* a, const char* b);
204 
205 //basic swap template function
Gswap(T & lhs,T & rhs)206 template<class T> void Gswap(T& lhs, T& rhs) {
207  T tmp=lhs; //requires copy operator
208  lhs=rhs;
209  rhs=tmp;
210 }
211 
212 
213 /**************** Memory management ***************************/
214 
215 bool GMalloc(pointer* ptr, unsigned long size); // Allocate memory
216 bool GCalloc(pointer* ptr, unsigned long size); // Allocate and initialize memory
217 bool GRealloc(pointer* ptr,unsigned long size); // Resize memory
218 void GFree(pointer* ptr); // Free memory, resets ptr to NULL
219 
220 //int saprintf(char **retp, const char *fmt, ...);
221 
222 void GError(const char* format,...); // Error routine (aborts program)
223 void GMessage(const char* format,...);// Log message to stderr
224 // Assert failed routine:- usually not called directly but through GASSERT
225 void GAssert(const char* expression, const char* filename, unsigned int lineno);
226 
227 // ****************** basic string manipulation *************************
228 char *Gstrdup(const char* str, int xtracap=0); //string duplication with extra capacity added
229 //duplicate a string by allocating a copy for it (+xtracap heap room) and returning the new pointer
230 //caller is responsible for deallocating the returned pointer!
231 
232 char* Gstrdup(const char* sfrom, const char* sto);
233 //same as GStrdup, but with an early termination (e.g. on delimiter)
234 
235 char* Gsubstr(const char* str, char* from, char* to=NULL);
236 //extracts a substring, allocating it, including boundaries (from/to)
237 
238 char* replaceStr(char* &str, char* newvalue);
239 
240 //conversion: to Lower/Upper case
241 // creating a new string:
242 char* upCase(const char* str);
243 char* loCase(const char* str);
244 // changing string in place:
245 char* strlower(char * str);
246 char* strupper(char * str);
247 
248 
249 //strstr but for memory zones: scans a memory region
250 //for a substring:
251 void* Gmemscan(void *mem, unsigned int len,
252                   void *part, unsigned int partlen);
253 
254 
255 FILE* Gfopen(const char *path, char *mode=NULL);
256 
257 // test if a char is in a string:
258 bool chrInStr(char c, const char* str);
259 
260 char* rstrchr(char* str, char ch);
261 /* returns a pointer to the rightmost
262   occurence of ch in str - like rindex for platforms missing it*/
263 
264 char* strchrs(const char* s, const char* chrs);
265 //strchr but with a set of chars instead of only one
266 
267 char* rstrfind(const char* str, const char *substr);
268 // like rindex() but for strings;  right side version of strstr()
269 
270 char* reverseChars(char* str, int slen=0); //in place reversal of string
271 
272 char* rstrstr(const char* rstart, const char *lend, const char* substr);
273 /*the reversed, rightside equivalent of strstr: starts searching
274  from right end (rstart), going back to left end (lend) and returns
275  a pointer to the last (right) matching character in str */
276 
277 char* strifind(const char* str,  const char* substr);
278 // case insensitive version of strstr -- finding a string within another string
279 // returns NULL if not found
280 
281 //Determines if a string begins with a given prefix
282 //(returns false when any of the params is NULL,
283 // but true when prefix is '' (empty string)!)
284 bool startsWith(const char* s, const char* prefix);
285 
286 bool startsiWith(const char* s, const char* prefix); //case insensitive
287 
288 
289 bool endsWith(const char* s, const char* suffix);
290 //Note: returns true if suffix is empty string, but false if it's NULL
291 bool endsiWith(const char* s, const char* suffix); //case insensitive version
292 
293 //like endsWith but also remove the suffix if found
294 //returns true if the given suffix was found and removed
295 bool trimSuffix(char* s, const char* suffix);
296 //case insensitive version:
297 bool trimiSuffix(char* s, const char* suffix);
298 
299 // ELF hash function for strings
300 int strhash(const char* str);
301 
302 //alternate hash functions:
303 int fnv1a_hash(const char* cp);
304 int djb_hash(const char* cp);
305 
306 //---- generic base GSeg : genomic segment (interval) --
307 // coordinates are considered 1-based (so 0 is invalid)
308 class GSeg {
309  public:
310   uint start; //start<end always!
311   uint end;
312   GSeg(uint s=0,uint e=0) {
313     if (s>e) { start=e;end=s; }
314         else { start=s;end=e; }
315   }
316   //check for overlap with other segment
len()317   uint len() { return end-start+1; }
overlap(GSeg * d)318   bool overlap(GSeg* d) {
319      //return start<d->start ? (d->start<=end) : (start<=d->end);
320      return (start<=d->end && end>=d->start);
321   }
322 
overlap(GSeg & d)323   bool overlap(GSeg& d) {
324      //return start<d.start ? (d.start<=end) : (start<=d.end);
325      return (start<=d.end && end>=d.start);
326   }
327 
overlap(GSeg & d,int fuzz)328   bool overlap(GSeg& d, int fuzz) {
329      //return start<d.start ? (d.start<=end+fuzz) : (start<=d.end+fuzz);
330      return (start<=d.end+fuzz && end+fuzz>=d.start);
331   }
332 
overlap(uint x)333   bool overlap(uint x) {
334 	return (start<=x && x<=end);
335   }
336 
overlap(uint s,uint e)337   bool overlap(uint s, uint e) {
338      if (s>e) { Gswap(s,e); }
339      return (start<=e && end>=s);
340   }
341 
342   //return the length of overlap between two segments
overlapLen(GSeg * r)343   int overlapLen(GSeg* r) {
344      if (start<r->start) {
345         if (r->start>end) return 0;
346         return (r->end>end) ? end-r->start+1 : r->end-r->start+1;
347         }
348        else { //r->start<=start
349         if (start>r->end) return 0;
350         return (r->end<end)? r->end-start+1 : end-start+1;
351         }
352      }
overlapLen(uint rstart,uint rend)353   int overlapLen(uint rstart, uint rend) {
354      if (rstart>rend) { Gswap(rstart,rend); }
355      if (start<rstart) {
356         if (rstart>end) return 0;
357         return (rend>end) ? end-rstart+1 : rend-rstart+1;
358         }
359        else { //rstart<=start
360         if (start>rend) return 0;
361         return (rend<end)? rend-start+1 : end-start+1;
362         }
363   }
364 
contains(GSeg * s)365   bool contains(GSeg* s) {
366 	  return (start<=s->start && end>=s->end);
367   }
contained(GSeg * s)368   bool contained(GSeg* s) {
369 	  return (s->start<=start && s->end>=end);
370   }
371 
equals(GSeg & d)372   bool equals(GSeg& d){
373       return (start==d.start && end==d.end);
374   }
equals(GSeg * d)375   bool equals(GSeg* d){
376       return (start==d->start && end==d->end);
377   }
378 
379   //fuzzy coordinate matching:
380   bool coordMatch(GSeg* s, uint fuzz=0) { //caller must check for s!=NULL
381     if (fuzz==0) return (start==s->start && end==s->end);
382     uint sd = (start>s->start) ? start-s->start : s->start-start;
383     uint ed = (end>s->end) ? end-s->end : s->end-end;
384     return (sd<=fuzz && ed<=fuzz);
385   }
expand(int by)386   void expand(int by) { //expand in both directions
387 	  start-=by;
388 	  end+=by;
389   }
expandInclude(uint rstart,uint rend)390   void expandInclude(uint rstart, uint rend) { //expand to include given coordinates
391 	 if (rstart>rend) { Gswap(rstart,rend); }
392 	 if (rstart<start) start=rstart;
393 	 if (rend>end) end=rend;
394   }
395   //comparison operators required for sorting
396   bool operator==(GSeg& d){
397       return (start==d.start && end==d.end);
398       }
399   bool operator<(GSeg& d){
400      return (start==d.start)?(end<d.end):(start<d.start);
401      }
402 };
403 
404 //basic dynamic array template for primitive types
405 //which can only grow (reallocate) as needed
406 
407 //optimize index test
408 #define GDynArray_INDEX_ERR "Error: use of index (%d) in GDynArray of size %d!\n"
409  #if defined(NDEBUG) || defined(NODEBUG) || defined(_NDEBUG) || defined(NO_DEBUG)
410  #define GDynArray_TEST_INDEX(x)
411 #else
412  #define GDynArray_TEST_INDEX(x) \
413  if (fCount==0 || x>=fCount) GError(GDynArray_INDEX_ERR, x, fCount)
414 #endif
415 
416 #define GDynArray_MAXCOUNT UINT_MAX-1
417 #define GDynArray_NOIDX UINT_MAX
418 
419 //basic dynamic array (vector) template for simple/primitive types or structs
420 //Warning: uses malloc so it will never call the item's default constructor when growing
421 
422 template<class OBJ> class GDynArray {
423  protected:
424 	bool byptr; //in-place copy (pointer) takeover of existing OBJ[]
425     OBJ *fArray;
426     uint fCount;
427     uint fCapacity; // size of allocated memory
428 	const static uint dyn_array_defcap = 16; // initial capacity (in elements)
429  public:
byptr(false)430     GDynArray(int initcap=dyn_array_defcap):byptr(false), fArray(NULL), fCount(0),
431 	     fCapacity(initcap) { // constructor
432     	  GMALLOC(fArray, fCapacity*sizeof(OBJ));
433     }
434 
GDynArray(const GDynArray & a)435     GDynArray(const GDynArray &a):byptr(false), fArray(NULL),
436     		fCount(a.fCount), fCapacity(a.fCapacity) { // copy constructor
437         GMALLOC(fArray, sizeof(OBJ)*a.fCapacity);
438         memcpy(fArray, a.fArray, sizeof(OBJ)* a.fCapacity);
439     }
GDynArray(OBJ * ptr,uint pcap)440     GDynArray(OBJ* ptr, uint pcap):byptr(true), fArray(ptr), fCount(0), fCapacity(pcap) {
441     	//this will never deallocate the passed pointer
442     }
443 
~GDynArray()444     virtual ~GDynArray() { if (!byptr) { GFREE(fArray); } }
445 
446     GDynArray& operator = (const GDynArray &a) { // assignment operator
447         if (this == &a) return *this;
448     	if (a.fCount == 0) {
449     		Clear();
450     		return *this;
451     	}
452     	growTo(a.fCapacity); //set size
453         memcpy(fArray, a.fArray, sizeof(OBJ)*a.fCount);
454         return *this;
455     }
456 
457     OBJ& operator[] (uint idx) {// get array item
458     	GDynArray_TEST_INDEX(idx);
459     	return fArray[idx];
460     }
461 
Grow()462     void Grow() {
463     	int delta = (fCapacity>16) ? (fCapacity>>2) : 2;
464     	if (GDynArray_MAXCOUNT-delta<=fCapacity)
465     		delta=GDynArray_MAXCOUNT-fCapacity;
466     	if (delta<=1) GError("Error at GDynArray::Grow(): max capacity reached!\n");
467     	growTo(fCapacity + delta);
468     }
469 #define GDynArray_ADD(item) \
470     	if (fCount==MAX_UINT-1) GError("Error at GDynArray: cannot add item, maximum count reached!\n"); \
471     	if ((++fCount) > fCapacity) Grow(); \
472     	fArray[fCount-1] = item;
473 
Add(OBJ * item)474     uint Add(OBJ* item) { // Add item to the end of array
475       //element given by pointer
476       if (item==NULL) return GDynArray_NOIDX;
477   	  GDynArray_ADD( (*item) );
478   	  return (fCount-1);
479     }
480 
Add(OBJ item)481     uint Add(OBJ item) { // Add OBJ copy to the end of array
482 	  GDynArray_ADD(item);
483 	  return (fCount-1);
484     }
485 
Push(OBJ item)486     uint Push(OBJ item) { //same as Add
487     	GDynArray_ADD(item);
488     	return (fCount-1);
489     }
490 
Pop()491     OBJ Pop() { //shoddy.. Do NOT call this for an empty array!
492     	if (fCount==0) return (OBJ)NULL; //a NULL cast operator is required
493     	--fCount;
494     	return fArray[fCount];
495     }
496 
Count()497     uint Count() { return fCount; } // get size of array (elements)
Capacity()498     uint Capacity() { return fCapacity; }
growTo(uint newcap)499     void growTo(uint newcap) {
500     	if (newcap==0) { Clear(); return; }
501     	if (newcap <= fCapacity) return; //never shrink! (use Pack() for shrinking)
502     	GREALLOC(fArray, newcap*sizeof(OBJ));
503     	fCapacity=newcap;
504     }
505 
append(OBJ * arr,uint count)506     void append(OBJ* arr, uint count) {
507     	//fast adding of a series of objects
508     	growTo(fCount+count);
509     	memcpy(fArray+fCount, arr, count*sizeof(OBJ));
510     	fCount+=count;
511     }
512 
append(GDynArray<OBJ> arr)513     void append(GDynArray<OBJ> arr) {
514     	//fast adding of a series of objects
515     	growTo(fCount+arr.fCount);
516     	memcpy(fArray+fCount, arr.fArray, arr.fCount*sizeof(OBJ));
517     	fCount+=arr.fCount;
518     }
519 
520     void Trim(int tcount=1) {
521     	//simply cut (discard) the last tcount items
522     	//new Count is now fCount-tcount
523     	//does NOT shrink capacity accordingly!
524     	if (fCount>=tcount) fCount-=tcount;
525     }
526 
Pack()527     void Pack() { //shrink capacity to fCount+dyn_array_defcap
528     	if (fCapacity-fCount<=dyn_array_defcap) return;
529     	int newcap=fCount+dyn_array_defcap;
530     	GREALLOC(fArray, newcap*sizeof(OBJ));
531     	fCapacity=newcap;
532     }
533 
zPack(OBJ z)534     void zPack(OBJ z) { //shrink capacity to fCount+1 and adds a z terminator
535     	if (fCapacity-fCount<=1) { fArray[fCount]=z; return; }
536     	int newcap=fCount+1;
537     	GREALLOC(fArray, newcap*sizeof(OBJ));
538     	fCapacity=newcap;
539     	fArray[fCount]=z;
540     }
541 
542 
Shrink()543     inline void Shrink() { Pack(); }
544 
Delete(uint idx)545     void Delete(uint idx) {
546 	  GDynArray_TEST_INDEX(idx);
547 	  --fCount;
548 	  if (idx<fCount)
549 		  memmove(&fArray[idx], &fArray[idx+1], (fCount-idx)*sizeof(OBJ));
550     }
551 
Remove(uint idx)552     inline void Remove(uint idx) { Delete(idx); }
553 
Clear()554     void Clear() { // clear array, shrinking its allocated memory
555     	fCount = 0;
556     	GREALLOC(fArray, sizeof(OBJ)*dyn_array_defcap);
557     	// set initial memory size again
558     	fCapacity = dyn_array_defcap;
559     }
560 
Reset()561     void Reset() {// fast clear array WITHOUT deallocating it
562     	fCount = 0;
563     }
564 
operator()565     OBJ* operator()() { return fArray; }
566 
567     //use methods below in order to prevent deallocation of fArray pointer on destruct
568     //could be handy for adopting stack objects (e.g. cheap dynamic strings)
ForgetPtr()569     void ForgetPtr() { byptr=true;  }
DetachPtr()570     void DetachPtr() { byptr=true;  }
571 
572 };
573 
574 
575 int strsplit(char* str, GDynArray<char*>& fields, const char* delim, int maxfields=MAX_INT);
576 //splits a string by placing 0 where any of the delim chars are found, setting fields[] to the beginning
577 //of each field (stopping after maxfields); returns number of fields parsed
578 
579 int strsplit(char* str, GDynArray<char*>& fields, const char delim, int maxfields=MAX_INT);
580 //splits a string by placing 0 where the delim char is found, setting fields[] to the beginning
581 //of each field (stopping after maxfields); returns number of fields parsed
582 
583 int strsplit(char* str, GDynArray<char*>& fields, int maxfields=MAX_INT); //splits by tab or space
584 //splits a string by placing 0 where tab or space is found, setting fields[] to the beginning
585 //of each field (stopping after maxfields); returns number of fields parsed
586 
587 // ************** simple line reading class for text files
588 //GLineReader -- text line reading/buffering class
589 class GLineReader {
590    bool closeFile;
591    //int len;
592    //int allocated;
593    GDynArray<char> buf;
594    int textlen; //length of actual text, without newline character(s)
595    bool isEOF;
596    FILE* file;
597    off_t filepos; //current position
598    bool pushed; //pushed back
599    int lcount; //line counter (read lines)
600  public:
chars()601    char* chars() { return buf(); }
line()602    char* line() { return buf(); }
readcount()603    int readcount() { return lcount; } //number of lines read
setFile(FILE * stream)604    void setFile(FILE* stream) { file=stream; }
blength()605    int blength() { return buf.Count(); } //binary/buffer length, including newline character(s)
charcount()606    int charcount() { return buf.Count(); } //line length, including newline character(s)
tlength()607    int tlength() { return textlen; } //text length excluding newline character(s)
linelen()608    int linelen() { return textlen; } //line length, excluding newline character(s)
609    //int size() { return buf.Count(); } //same as size();
isEof()610    bool isEof() {return isEOF; }
eof()611    bool eof() { return isEOF; }
getfpos()612    off_t getfpos() { return filepos; }
getFpos()613    off_t getFpos() { return filepos; }
nextLine()614    char* nextLine() { return getLine(); }
getLine()615    char* getLine() { if (pushed) { pushed=false; return buf(); }
616                             else return getLine(file);  }
getLine(FILE * stream)617    char* getLine(FILE* stream) {
618                  if (pushed) { pushed=false; return buf(); }
619                           else return getLine(stream, filepos); }
620    char* getLine(FILE* stream, off_t& f_pos); //read a line from a stream and update
621                            // the given file position
pushBack()622    void pushBack() { if (lcount>0) pushed=true; } // "undo" the last getLine request
623             // so the next call will in fact return the same line
GLineReader(const char * fname)624    GLineReader(const char* fname):closeFile(false),buf(1024), textlen(0),
625 		   isEOF(false),file(NULL),filepos(0), pushed(false), lcount(0) {
626       FILE* f=fopen(fname, "rb");
627       if (f==NULL) GError("Error opening file '%s'!\n",fname);
628       closeFile=true;
629       file=f;
630       }
closeFile(false)631    GLineReader(FILE* stream=NULL, off_t fpos=0):closeFile(false),buf(1024),
632 		   textlen(0), isEOF(false),file(stream),
633 		   filepos(fpos), pushed(false), lcount(0) {
634      }
~GLineReader()635    ~GLineReader() {
636      if (closeFile) fclose(file);
637      }
638 };
639 
640 
641 /* extended fgets() -  to read one full line from a file and
642   update the file position correctly !
643   buf will be reallocated as necessary, to fit the whole line
644   */
645 char* fgetline(char* & buf, int& buflen, FILE* stream, off_t* f_pos=NULL, int* linelen=NULL);
646 
647 
648 //print int/values nicely formatted in 3-digit groups
649 char* commaprintnum(uint64 n);
650 
651 /*********************** File management functions *********************/
652 
653 // removes the last part (file or directory name) of a full path
654 // WARNING: this is a destructive operation for the given string!
655 void delFileName(char* filepath);
656 
657 // returns a pointer to the last file or directory name in a full path
658 const char* getFileName(const char* filepath);
659 // returns a pointer to the file "extension" part in a filename
660 const char* getFileExt(const char* filepath);
661 
662 
663 int fileExists(const char* fname);
664 //returns 0 if path doesn't exist
665 //        1 if it's a directory
666 //        2 if it's a regular file
667 //        3 something else (but entry exists)
668 
669 int64 fileSize(const char* fpath);
670 
671 //write a formatted fasta record, fasta formatted
672 void writeFasta(FILE *fw, const char* seqid, const char* descr,
673         const char* seq, int linelen=60, int seqlen=0);
674 
675 //parses the next number found in a string at the current position
676 //until a non-digit (and not a '.', 'e','E','-','+') is encountered;
677 //updates the char* pointer to be after the last digit parsed
678 bool parseNumber(char* &p, double& v);
679 bool parseDouble(char* &p, double& v); //just an alias for parseNumber
680 bool parseFloat(char* &p, float& v);
681 
682 bool strToInt(char* p, int& i);
683 bool strToUInt(char* p, uint& i);
684 bool parseInt(char* &p, int& i); //advance pointer p after the number
685 bool parseUInt(char* &p, uint& i); //advance pointer p after the number
686 bool parseHex(char* &p,  uint& i);
687 
688 #endif /* G_BASE_DEFINED */
689