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