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