1 #include "GBase.h"
2 #include <stdarg.h>
3 #include <ctype.h>
4
5 #ifndef S_ISDIR
6 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
7 #endif
8
9 #ifndef S_ISREG
10 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
11 #endif
12
13 /*
14 #ifdef _DEFINE_WIN32_FSEEKO
15 int fseeko(FILE *stream, off_t offset, int whence) {
16
17 }
18 #endif
19
20 #ifdef _DEFINE_WIN32_FTELLO
21 off_t ftello(FILE *stream) {
22
23 }
24 #endif
25 */
26
27 /*
28 int saprintf(char **retp, const char *fmt, ...) {
29 va_list argp;
30 int len;
31 char *buf;
32
33 va_start(argp, fmt);
34 len = vsnprintf(NULL, 0, fmt, argp);
35 va_end(argp);
36 GMALLOC(buf, (len + 1));
37 if(buf == NULL)
38 {
39 *retp = NULL;
40 return -1;
41 }
42
43 va_start(argp, fmt);
44 vsnprintf(buf, len+1, fmt, argp);
45 va_end(argp);
46
47 *retp = buf;
48 return len;
49 }
50 */
51
52 //************************* Debug helpers **************************
53 // Assert failed routine
GAssert(const char * expression,const char * filename,unsigned int lineno)54 void GAssert(const char* expression, const char* filename, unsigned int lineno){
55 char msg[4096];
56 sprintf(msg,"%s(%d): ASSERT(%s) failed.\n",filename,lineno,expression);
57 fprintf(stderr,"%s",msg);
58 #ifdef DEBUG
59 // modify here if you [don't] want a core dump
60 abort();
61 #endif
62 exit(1);
63 }
64
65 // Error routine (prints error message and exits!)
GError(const char * format,...)66 void GError(const char* format,...){
67 #ifdef __WIN32__
68 char msg[4096];
69 va_list arguments;
70 va_start(arguments,format);
71 _vsnprintf(msg, 4095, format, arguments);
72 vfprintf(stderr, format, arguments); // if a console is available
73 msg[4095]=0;
74 va_end(arguments);
75 OutputDebugString(msg);
76 MessageBox(NULL,msg,NULL,MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL);
77 #else
78 va_list arguments;
79 va_start(arguments,format);
80 vfprintf(stderr,format,arguments);
81 va_end(arguments);
82 #ifdef DEBUG
83 // modify here if you [don't] want a core dump
84 abort();
85 #endif
86 #endif
87 exit(1);
88 }
89
90 // Warning routine (just print message without exiting)
GMessage(const char * format,...)91 void GMessage(const char* format,...){
92 #ifdef __WIN32__
93 char msg[4096];
94 va_list arguments;
95 va_start(arguments,format);
96 vfprintf(stderr, format , arguments); // if a console is available
97 _vsnprintf(msg, 4095, format, arguments);
98 msg[4095]=0;
99 va_end(arguments);
100 OutputDebugString(msg);
101 #else
102 va_list arguments;
103 va_start(arguments,format);
104 vfprintf(stderr,format,arguments);
105 va_end(arguments);
106 #endif
107 }
108
109 /*************** Memory management routines *****************/
110 // Allocate memory
GMalloc(pointer * ptr,unsigned long size)111 bool GMalloc(pointer* ptr,unsigned long size){
112 //GASSERT(ptr);
113 if (size!=0) *ptr=malloc(size);
114 return *ptr!=NULL;
115 }
116
117 // Allocate cleaned memory (0 filled)
GCalloc(pointer * ptr,unsigned long size)118 bool GCalloc(pointer* ptr,unsigned long size){
119 GASSERT(ptr);
120 *ptr=calloc(size,1);
121 return *ptr!=NULL;
122 }
123
124 // Resize memory
GRealloc(pointer * ptr,unsigned long size)125 bool GRealloc(pointer* ptr,unsigned long size){
126 //GASSERT(ptr);
127 if (size==0) {
128 GFree(ptr);
129 return true;
130 }
131 if (*ptr==NULL) {//simple malloc
132 void *p=malloc(size);
133 if (p != NULL) {
134 *ptr=p;
135 return true;
136 }
137 else return false;
138 }//malloc
139 else {//realloc
140 void *p=realloc(*ptr,size);
141 if (p) {
142 *ptr=p;
143 return true;
144 }
145 return false;
146 }
147 }
148 // Free memory, resets ptr to NULL afterward
GFree(pointer * ptr)149 void GFree(pointer* ptr){
150 GASSERT(ptr);
151 if (*ptr) free(*ptr);
152 *ptr=NULL;
153 }
154
Gstrdup(const char * str)155 char* Gstrdup(const char* str) {
156 if (str==NULL) return NULL;
157 char *copy=NULL;
158 GMALLOC(copy, strlen(str)+1);
159 strcpy(copy,str);
160 return copy;
161 }
162
newEmptyStr()163 char* newEmptyStr() {
164 char* zs=NULL;
165 GMALLOC(zs,1);
166 zs[0]=0;
167 return zs;
168 }
169
Gstrdup(const char * sfrom,const char * sto)170 char* Gstrdup(const char* sfrom, const char* sto) {
171 if (sfrom==NULL || sto==NULL) return NULL;
172 char *copy=NULL;
173 if (sfrom[0]==0 || sto<sfrom) return newEmptyStr();
174 GMALLOC(copy, sto-sfrom+2);
175 strncpy(copy, sfrom, sto-sfrom+1);
176 copy[sto-sfrom+1]=0;
177 return copy;
178 }
179
Gstrcmp(const char * a,const char * b,int n)180 int Gstrcmp(const char* a, const char* b, int n) {
181 if (a==NULL || b==NULL) {
182 return a==NULL ? -1 : 1;
183 }
184 else {
185 if (n<0) return strcmp(a,b);
186 else return strncmp(a,b,n);
187 }
188
189 }
190
G_mkdir(const char * path,int perms=0775)191 int G_mkdir(const char* path, int perms=0775) {
192 #ifdef __WIN32__
193 return _mkdir(path);
194 #else
195 //#if _POSIX_C_SOURCE
196 // return ::mkdir(path);
197 //#else
198 return mkdir(path, perms); // not sure if this works on mac
199 //#endif
200 #endif
201 }
202
203
Gmkdir(const char * path,bool recursive,int perms)204 int Gmkdir(const char *path, bool recursive, int perms) {
205 if (path==NULL || path[0]==0) return -1;
206 if (!recursive) return G_mkdir(path, perms);
207 int plen=strlen(path);
208 char* gpath=NULL;
209 //make sure gpath ends with /
210 if (path[plen-1]=='/') {
211 gpath=Gstrdup(path);
212 }
213 else {
214 GMALLOC(gpath, plen+2);
215 strcpy(gpath,path);
216 gpath[plen]='/';
217 gpath[plen+1]=0;
218 }
219 char* ss=gpath;
220 char* psep = NULL;
221 while (*ss!=0 && (psep=strchr(ss, '/'))!=NULL) {
222 *psep=0; //now gpath is the path up to this /
223 ss=psep; ++ss; //ss repositioned just after the /
224 // create current level
225 if (fileExists(gpath)!=1 && G_mkdir(gpath, perms)!=0) {
226 GFREE(gpath);
227 return -1;
228 }
229 *psep='/';
230 }
231 GFREE(gpath);
232 return 0;
233 }
234
GstrEq(const char * a,const char * b)235 bool GstrEq(const char* a, const char* b) {
236 if (a==NULL || b==NULL) return false;
237 register int i=0;
238 while (a[i]==b[i]) {
239 if (a[i]==0) return true;
240 ++i;
241 }
242 return false;
243 }
244
GstriEq(const char * a,const char * b)245 bool GstriEq(const char* a, const char* b) {
246 if (a==NULL || b==NULL) return false;
247 register int i=0;
248 while (tolower((unsigned char)a[i])==tolower((unsigned char)b[i])) {
249 if (a[i]==0) return true;
250 }
251 return false;
252 }
253
Gstricmp(const char * a,const char * b,int n)254 int Gstricmp(const char* a, const char* b, int n) {
255 if (a==NULL || b==NULL) return a==NULL ? -1 : 1;
256 register int ua, ub;
257 if (n<0) {
258 while ((*a!=0) && (*b!=0)) {
259 ua=tolower((unsigned char)*a);
260 ub=tolower((unsigned char)*b);
261 a++;b++;
262 if (ua!=ub) return ua < ub ? -1 : 1;
263 }
264 return (*a == 0) ? ( (*b == 0) ? 0 : -1 ) : 1 ;
265 }
266 else {
267 while (n && (*a!=0) && (*b!=0)) {
268 ua=tolower((unsigned char)*a);
269 ub=tolower((unsigned char)*b);
270 a++;b++;n--;
271 if (ua!=ub) return ua < ub ? -1 : 1;
272 }
273 //return (*a == 0) ? ( (*b == 0) ? 0 : -1 ) : 1 ;
274 if (n==0) return 0;
275 else { return (*a == 0) ? ( (*b == 0) ? 0 : -1 ) : 1 ; }
276 }
277 }
278
strsplit(char * str,char ** fields,int maxfields,const char * delim)279 int strsplit(char* str, char** fields, int maxfields, const char* delim) {
280 //splits by placing 0 where delim chars are found, setting fields[] to the beginning
281 //of each field (stopping after maxfields); returns number of fields parsed
282 int tidx=0;
283 bool afterdelim=true;
284 int i=0;
285 while (str[i]!=0 && tidx<maxfields) {
286 if (afterdelim) {
287 fields[tidx]=str+i;
288 tidx++;
289 }
290 afterdelim=false;
291 if (chrInStr(str[i],(char*)delim)) {
292 str[i]=0;
293 i++;
294 while (str[i]!=0 && chrInStr(str[i], (char*)delim)) i++;
295 afterdelim=true;
296 continue;
297 }
298 i++;
299 }
300 return tidx;
301 }
302
strsplit(char * str,char ** fields,int maxfields,const char delim)303 int strsplit(char* str, char** fields, int maxfields, const char delim) {
304 //splits by placing 0 where delim is found, setting fields[] to the beginning
305 //of each field (stopping after maxfields); returns number of fields parsed
306 int tidx=0;
307 bool afterdelim=true;
308 int i=0;
309 while (str[i]!=0 && tidx<maxfields) {
310 if (afterdelim) {
311 fields[tidx]=str+i;
312 tidx++;
313 }
314 afterdelim=false;
315 if (str[i]==delim) {
316 str[i]=0;
317 i++;
318 while (str[i]!=0 && str[i]==delim) i++;
319 afterdelim=true;
320 continue;
321 }
322 i++;
323 }
324 return tidx;
325 }
326
strsplit(char * str,char ** fields,int maxfields)327 int strsplit(char* str, char** fields, int maxfields) {
328 //splits by placing 0 where delim is found, setting fields[] to the beginning
329 //of each field (stopping after maxfields); returns number of fields parsed
330 int tidx=0;
331 bool afterdelim=true;
332 int i=0;
333 while (str[i]!=0 && tidx<maxfields) {
334 if (afterdelim) {
335 fields[tidx]=str+i;
336 tidx++;
337 }
338 afterdelim=false;
339 if (str[i]==' ' || str[i]=='\t') {
340 str[i]=0;
341 i++;
342 while (str[i]!=0 && (str[i]=='\t' || str[i]==' ')) i++;
343 afterdelim=true;
344 continue;
345 }
346 i++;
347 }
348 return tidx;
349 }
350
351
Gsubstr(const char * str,char * from,char * to)352 char* Gsubstr(const char* str, char* from, char* to) {
353 //extract (and allocate) a substring, including boundaries (from/to)
354 if (str==NULL || from==NULL) return NULL;
355 if (from[0]==0 || str[0]==0) return newEmptyStr();
356 if (from<str) return NULL;
357 if (to==NULL) {
358 to=from;
359 while (to[1]) to++;
360 }
361 if (to<from) return newEmptyStr();
362 int newlen=to-from+1;
363 char* subs=NULL;
364 GMALLOC(subs, newlen);
365 memcpy(subs, str, newlen-1);
366 subs[newlen]='\0';
367 return subs;
368 }
369
replaceStr(char * & str,char * newvalue)370 char* replaceStr(char* &str, char* newvalue) {
371 if (str!=NULL) GFREE(str);
372 if (newvalue==NULL) { return NULL; }
373 GMALLOC(str, strlen(newvalue)+1);
374 strcpy(str,newvalue);
375 return str;
376 }
377
Gmemscan(void * mem,unsigned int len,void * part,unsigned int partlen)378 void* Gmemscan(void *mem, unsigned int len,
379 void *part, unsigned int partlen) {
380 char* p;
381 unsigned int restlen=len-partlen+1;
382 void* oldp=mem;
383 while ( (p=(char*)memchr(oldp, ((char*)part)[0], restlen))!=NULL) {
384 //located first char, try to match the rest:
385 p++;
386 if (memcmp(p, &((char*)part)[1], partlen-1)==0) return p-1;
387 //no string match, prepare next iteration
388 restlen-=(p-(char*)oldp);
389 oldp=p;
390 }//while
391 return NULL;
392 }
393
394 //rindex function is missing on some platforms ?
rstrchr(char * str,char ch)395 char* rstrchr(char* str, char ch) { /* returns a pointer to the rightmost
396 occurence of ch in str */
397 char *p;
398 if (str==NULL) return NULL;
399 p=str+strlen(str)-1;
400 while (p>=str) {
401 if (*p==ch) return p;
402 p--;
403 }
404 return NULL;
405 }
406
407
408 /* DOS/UNIX safer fgets : reads a text line from a (binary) file and
409 update the file position accordingly and the buffer capacity accordingly.
410 The given buf is resized to read the entire line in memory
411 -- even when it's abnormally long
412 */
fgetline(char * & buf,int & buf_cap,FILE * stream,off_t * f_pos,int * linelen)413 char* fgetline(char* & buf, int& buf_cap, FILE *stream, off_t* f_pos, int* linelen) {
414 //reads a char at a time until \n and/or \r are encountered
415 int i=0;
416 int c=0;
417 off_t fpos=(f_pos!=NULL) ? *f_pos : 0;
418 while ((c=getc(stream))!=EOF) {
419 if (i>=buf_cap-1) {
420 buf_cap+=1024;
421 GREALLOC(buf, buf_cap);
422 }
423 if (c=='\n' || c=='\r') {
424 if (c=='\r') {
425 if ((c=getc(stream))!='\n') ungetc(c,stream);
426 else fpos++;
427 }
428 fpos++;
429 break;
430 }
431 fpos++;
432 buf[i]=(char)c;
433 i++;
434 } //while i<buf_cap-1
435 if (linelen!=NULL) *linelen=i;
436 if (f_pos!=NULL) *f_pos=fpos;
437 if (c==EOF && i==0) return NULL;
438 buf[i]='\0';
439 return buf;
440 }
441
getLine(FILE * stream,off_t & f_pos)442 char* GLineReader::getLine(FILE* stream, off_t& f_pos) {
443 if (pushed) { pushed=false; return buf; }
444 //reads a char at a time until \n and/or \r are encountered
445 len=0;
446 int c=0;
447 while ((c=getc(stream))!=EOF) {
448 if (len>=allocated-1) {
449 allocated+=1024;
450 GREALLOC(buf, allocated);
451 }
452 if (c=='\n' || c=='\r') {
453 buf[len]='\0';
454 if (c=='\r') { //DOS file -- special case
455 if ((c=getc(stream))!='\n') ungetc(c,stream);
456 else f_pos++;
457 }
458 f_pos++;
459 lcount++;
460 return buf;
461 }
462 f_pos++;
463 buf[len]=(char)c;
464 len++;
465 } //while i<buf_cap-1
466 if (c==EOF) {
467 isEOF=true;
468 if (len==0) return NULL;
469 }
470 buf[len]='\0';
471 lcount++;
472 return buf;
473 }
474
475
476 //strchr but with a set of chars instead of only one
strchrs(const char * s,const char * chrs)477 char* strchrs(const char* s, const char* chrs) {
478 if (s==NULL || chrs==NULL || *chrs=='\0' || *s=='\0')
479 return NULL;
480 unsigned int l=strlen(s);
481 unsigned int r=strcspn(s, chrs);
482 if (r==l) return NULL;
483 return ((char*)s+r);
484 }
485
upCase(const char * str)486 char* upCase(const char* str) {
487 if (str==NULL) return NULL;
488 int len=strlen(str);
489 char* upstr=NULL;
490 GMALLOC(upstr, len+1);
491 upstr[len]='\0';
492 for (int i=0;i<len;i++) upstr[i]=toupper(str[i]);
493 return upstr;
494 }
495
loCase(const char * str)496 char* loCase(const char* str) {
497 if (str==NULL) return NULL;
498 int len=strlen(str);
499 char* lostr=NULL;
500 GMALLOC(lostr, len+1);
501 lostr[len]='\0';
502 for (int i=0;i<len;i++) lostr[i]=tolower(str[i]);
503 return lostr;
504 }
505
strlower(char * str)506 char* strlower(char * str) {//changes string in place
507 if (str==NULL) return NULL;
508 int i=0;
509 while (str[i]!=0) { str[i]=tolower(str[i]); i++; }
510 return str;
511 }
512
strupper(char * str)513 char* strupper(char * str) {//changes string in place
514 if (str==NULL) return NULL;
515 int i=0;
516 while (str[i]!=0) { str[i]=toupper(str[i]); i++; }
517 return str;
518 }
519
520
521
522 //test if a char is in a given string (set)
chrInStr(char c,const char * str)523 bool chrInStr(char c, const char* str) {
524 if (str==NULL || *str=='\0') return false;
525 for (const char* p=str; (*p)!='\0'; p++) {
526 if ((*p)==c) return true;
527 }
528 return false;
529 }
530
531
532
rstrfind(const char * str,const char * substr)533 char* rstrfind(const char* str, const char* substr) {
534 /* like rindex() for a string */
535 int l,i;
536 if (str==NULL || *str=='\0') return NULL;
537 if (substr==NULL || *substr=='\0') return NULL;
538 l=strlen(substr);
539 char* p=(char*)str+strlen(str)-l;
540 //rightmost position that could match
541
542 while (p>=str) {
543 for (i=0; i<l && *(p+i) == *(substr+i); i++) ;
544 if (i==l) return p; //found!
545 p--;
546 }
547 return NULL;
548 }
549
550
strifind(const char * str,const char * substr)551 char* strifind(const char* str, const char* substr) {
552 // case insensitive version of strstr -- finding a string within another
553 int l,i;
554 if (str==NULL || *str==0) return NULL;
555 if (substr==NULL || *substr==0) return NULL;
556 l=strlen(substr);
557 char* smax=(char*)str+strlen(str)-l;
558 //rightmost position that could match
559 char* p=(char*)str;
560 while (p<=smax) {
561 for (i=0; i<l && tolower(*(p+i))==tolower(*(substr+i)); i++) ;
562 if (i==l) return p;
563 p++;
564 }
565 return NULL;
566 }
567
568
569
570 // tests if string s has the given prefix
startsWith(const char * s,const char * prefix)571 bool startsWith(const char* s, const char* prefix) {
572 if (prefix==NULL || s==NULL) return false;
573 int i=0;
574 while (prefix[i]!='\0' && prefix[i]==s[i]) i++;
575 return (prefix[i]=='\0');
576 }
577
startsiWith(const char * s,const char * prefix)578 bool startsiWith(const char* s, const char* prefix) {
579 if (prefix==NULL || s==NULL) return false;
580 int i=0;
581 while (prefix[i]!='\0' && tolower(prefix[i])==tolower(s[i])) i++;
582 return (prefix[i]=='\0');
583 }
584
585
586 // tests if string s ends with given suffix
endsWith(const char * s,const char * suffix)587 bool endsWith(const char* s, const char* suffix) {
588 if (suffix==NULL || s==NULL) return false;
589 if (suffix[0]==0) return true; //special case: empty suffix
590 int j=strlen(suffix)-1;
591 int i=strlen(s)-1;
592 if (i<j) return false;
593 while (j>=0 && s[i]==suffix[j]) { i--; j--; }
594 return (j==-1);
595 }
596
597
reverseChars(char * str,int slen)598 char* reverseChars(char* str, int slen) {
599 if (slen==0) slen=strlen(str);
600 int l=0;
601 int r=slen-1;
602 char c;
603 while (l<r) {
604 c=str[l];str[l]=str[r];
605 str[r]=c;
606 l++;r--;
607 }
608 return str;
609 }
610
611
rstrstr(const char * rstart,const char * lend,const char * substr)612 char* rstrstr(const char* rstart, const char *lend, const char* substr) { /*like strstr, but starts searching
613 from right end, going up to lend and returns a pointer to the last (right)
614 matching character in str */
615 char *p;
616 int l,i;
617 l=strlen(substr);
618 p=(char*)rstart-l+1;
619 while (p>=lend) {
620 for (i=0;i<l;i++) if (*(p+i) != *(substr+i)) break;
621 if (i==l) return p+l-1;
622 p--;
623 }
624 return NULL;
625 }
626
627
628 //hash function used for strings in GHash
strhash(const char * str)629 int strhash(const char* str){
630 register int h=0;
631 register int g;
632 while (*str) {
633 h=(h<<4)+*str++;
634 g=h&0xF0000000;
635 if(g) h^=g>>24;
636 h&=0x0fffffff;
637 }
638 GASSERT(h<=0x0fffffff);
639 return h;
640 }
641
642 // removes the last part (file or directory name) of a full path
643 // this is a destructive operation for the given string!!!
644 // the trailing '/' is guaranteed to be there
delFileName(char * filepath)645 void delFileName(char* filepath) {
646 char *p, *sep;
647 if (filepath==NULL) return;
648 for (p=filepath, sep=filepath;*p!='\0';p++)
649 if (*p=='/' || *p=='\\') sep=p+1;
650 *sep='\0'; // truncate filepath
651 }
652
653 // returns a pointer to the last file or directory name in a full path
getFileName(const char * filepath)654 const char* getFileName(const char* filepath) {
655 const char *p, *sep;
656 if (filepath==NULL) return NULL;
657 for (p=filepath, sep=filepath;*p!='\0';p++)
658 if (*p=='/' || *p=='\\') sep=p+1;
659 return sep;
660 }
661
662 // returns a pointer to the file "extension" part in a filename
getFileExt(const char * filepath)663 const char* getFileExt(const char* filepath) {
664 const char *p, *dp, *sep;
665 if (filepath==NULL) return NULL;
666 for (p=filepath, dp=filepath, sep=filepath;*p!='\0';p++) {
667 if (*p=='.') dp=p+1;
668 else if (*p=='/' || *p=='\\')
669 sep=p+1;
670 }
671 return (dp>sep) ? dp : NULL ;
672 }
673
fileExists(const char * fname)674 int fileExists(const char* fname) {
675 struct stat stFileInfo;
676 int r=0;
677 // Attempt to get the file attributes
678 int fs = stat(fname,&stFileInfo);
679 if (fs == 0) {
680 r=3;
681 // We were able to get the file attributes
682 // so the file obviously exists.
683 if (S_ISREG (stFileInfo.st_mode)) {
684 r=2;
685 }
686 if (S_ISDIR (stFileInfo.st_mode)) {
687 r=1;
688 }
689 }
690 return r;
691 }
692
693 /*bool fileExists(const char* filepath) {
694 if (filepath==NULL) return false;
695 FILE* ft=fopen(filepath, "rb");
696 if (ft==NULL) return false;
697 fclose(ft);
698 return true;
699 }
700 */
fileSize(const char * fpath)701 int64 fileSize(const char* fpath) {
702 struct stat results;
703 if (stat(fpath, &results) == 0)
704 // The size of the file in bytes is in
705 return (int64)results.st_size;
706 else
707 // An error occurred
708 //GMessage("Error at stat(%s)!\n", fpath);
709 return 0;
710 }
711
parseNumber(char * & p,double & v)712 bool parseNumber(char* &p, double& v) {
713 //skip any spaces..
714 while (*p==' ' || *p=='\t') p++;
715 char* start=p;
716 /*if (*p=='-') p++;
717 else if (*p=='+') { p++;start++; }*/
718
719 /* while ((*p>='1' && *p<='9') || *p=='0' ||
720 *p=='.' || *p=='-' || tolower(*p)=='e') p++; */
721 int numlen=strspn(start, "0123456789eE.-+");
722 p=start+numlen;
723 //now p is on a non-digit;
724 if (*start=='-' && p==start+1) return false;
725 char saved=*p;
726 *p='\0';
727 char* endptr=p;
728 v=strtod(start,&endptr);
729 *p=saved;
730 if (endptr!=p) return false;
731 return true;
732 }
733
734
parseDouble(char * & p,double & v)735 bool parseDouble(char* &p, double& v) {
736 return parseNumber(p,v);
737 }
738
parseInt(char * & p,int & i)739 bool parseInt(char* &p, int& i) {
740 while (*p==' ' || *p=='\t') p++;
741 char* start=p;
742 if (*p=='-') p++;
743 else if (*p=='+') { p++;start++; }
744 while ((*p>='1' && *p<='9') || *p=='0') p++;
745 //now p is on a non-digit;
746 if (*start=='-' && p==start+1) return false;
747 char saved=*p;
748 *p='\0';
749 char* endptr=p;
750 long l=strtol(start,&endptr,10);
751 i=(int)l;
752 *p=saved;
753 if (endptr!=p || i!=l) return false;
754 return true;
755 }
756
parseUInt(char * & p,uint & i)757 bool parseUInt(char* &p, uint& i) {
758 while (*p==' ' || *p=='\t') p++;
759 char* start=p;
760 if (*p=='-') return false;
761 else if (*p=='+') { p++;start++; }
762 while ((*p>='1' && *p<='9') || *p=='0') p++;
763 //now p is on a non-digit;
764 if (*start=='-' && p==start+1) return false;
765 char saved=*p;
766 *p='\0';
767 char* endptr=p;
768 unsigned long l=strtoul(start,&endptr,10);
769 i=(uint) l;
770 *p=saved;
771 if (endptr!=p || i!=l) return false;
772 return true;
773 }
774
parseHex(char * & p,uint & i)775 bool parseHex(char* &p, uint& i) {
776 //skip initial spaces/prefix
777 while (*p==' ' || *p=='\t' || *p=='0' || *p=='x') p++;
778 char* start=p;
779 if (*p=='-') return false;
780 else if (*p=='+') { p++;start++; }
781 while (isxdigit(*p)) p++;
782 //now p is on a non-hexdigit;
783 if (p==start+1) return false;
784 char saved=*p;
785 *p='\0';
786 char* endptr=p;
787 unsigned long l=strtoul(start,&endptr,16);
788 i=(uint) l;
789 *p=saved;
790 if (endptr!=p || i!=l) return false;
791 return true;
792 }
793
794 //write a formatted fasta record, fasta formatted
writeFasta(FILE * fw,const char * seqid,const char * descr,const char * seq,int linelen,int seqlen)795 void writeFasta(FILE *fw, const char* seqid, const char* descr,
796 const char* seq, int linelen, int seqlen) {
797 fflush(fw);
798 // write header line only if given!
799 if (seqid!=NULL) {
800 if (descr==NULL || descr[0]==0)
801 fprintf(fw,">%s\n",seqid);
802 else fprintf(fw,">%s %s\n",seqid, descr);
803 }
804 fflush(fw);
805 if (seq==NULL || *seq==0) return; //nothing to print
806 if (linelen==0) { //unlimited line length: write the whole sequence on a line
807 if (seqlen>0)
808 fwrite((const void*)seq, 1, seqlen,fw);
809 else fprintf(fw,"%s",seq);
810 fprintf(fw,"\n");
811 fflush(fw);
812 return;
813 }
814 int ilen=0;
815 if (seqlen>0) { //seq length given, so we know when to stop
816 for (int i=0; i < seqlen; i++, ilen++) {
817 if (ilen == linelen) {
818 fputc('\n', fw);
819 ilen = 0;
820 }
821 fputc(seq[i], fw);
822 }
823 fputc('\n', fw);
824 }
825 else { //seq length not given, stop when 0 encountered
826 for (int i=0; seq[i]!=0; i++, ilen++) {
827 if (ilen == linelen) {
828 fputc('\n', fw);
829 ilen = 0;
830 }
831 fputc(seq[i], fw);
832 } //for
833 fputc('\n', fw);
834 }
835 fflush(fw);
836 }
837
commaprintnum(uint64 n)838 char* commaprintnum(uint64 n) {
839 int comma = ',';
840 char retbuf[48];
841 char *p = &retbuf[sizeof(retbuf)-1];
842 int i = 0;
843 *p = '\0';
844 do {
845 if(i%3 == 0 && i != 0)
846 *--p = comma;
847 *--p = '0' + n % 10;
848 n /= 10;
849 i++;
850 } while(n != 0);
851 return Gstrdup(p);
852 }
853