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(char* a, char* b) { |
167 |
if (a==NULL || b==NULL) { |
168 |
return a==NULL ? -1 : 1; |
169 |
} |
170 |
else return strcmp(a,b); |
171 |
} |
172 |
|
173 |
int Gstricmp(const char* a, const char* b) { |
174 |
if (a==NULL || b==NULL) return a==NULL ? -1 : 1; |
175 |
register int ua, ub; |
176 |
while ((*a!=0) && (*b!=0)) { |
177 |
ua=tolower((unsigned char)*a); |
178 |
ub=tolower((unsigned char)*b); |
179 |
a++;b++; |
180 |
if (ua!=ub) return ua < ub ? -1 : 1; |
181 |
} |
182 |
return (*a == 0) ? ( (*b == 0) ? 0 : -1 ) : 1 ; |
183 |
} |
184 |
|
185 |
int strsplit(char* str, char** fields, int maxfields, const char* delim) { |
186 |
//splits by placing 0 where delim chars are found, setting fields[] to the beginning |
187 |
//of each field (stopping after maxfields); returns number of fields parsed |
188 |
int tidx=0; |
189 |
bool afterdelim=true; |
190 |
int i=0; |
191 |
while (str[i]!=0 && tidx<maxfields) { |
192 |
if (afterdelim) { |
193 |
fields[tidx]=str+i; |
194 |
tidx++; |
195 |
} |
196 |
afterdelim=false; |
197 |
if (chrInStr(str[i],(char*)delim)) { |
198 |
str[i]=0; |
199 |
i++; |
200 |
while (str[i]!=0 && chrInStr(str[i], (char*)delim)) i++; |
201 |
afterdelim=true; |
202 |
continue; |
203 |
} |
204 |
i++; |
205 |
} |
206 |
return tidx; |
207 |
} |
208 |
|
209 |
int strsplit(char* str, char** fields, int maxfields, const char delim) { |
210 |
//splits by placing 0 where delim is found, setting fields[] to the beginning |
211 |
//of each field (stopping after maxfields); returns number of fields parsed |
212 |
int tidx=0; |
213 |
bool afterdelim=true; |
214 |
int i=0; |
215 |
while (str[i]!=0 && tidx<maxfields) { |
216 |
if (afterdelim) { |
217 |
fields[tidx]=str+i; |
218 |
tidx++; |
219 |
} |
220 |
afterdelim=false; |
221 |
if (str[i]==delim) { |
222 |
str[i]=0; |
223 |
i++; |
224 |
while (str[i]!=0 && str[i]==delim) i++; |
225 |
afterdelim=true; |
226 |
continue; |
227 |
} |
228 |
i++; |
229 |
} |
230 |
return tidx; |
231 |
} |
232 |
|
233 |
int strsplit(char* str, char** fields, int maxfields) { |
234 |
//splits by placing 0 where delim is found, setting fields[] to the beginning |
235 |
//of each field (stopping after maxfields); returns number of fields parsed |
236 |
int tidx=0; |
237 |
bool afterdelim=true; |
238 |
int i=0; |
239 |
while (str[i]!=0 && tidx<maxfields) { |
240 |
if (afterdelim) { |
241 |
fields[tidx]=str+i; |
242 |
tidx++; |
243 |
} |
244 |
afterdelim=false; |
245 |
if (str[i]==' ' || str[i]=='\t') { |
246 |
str[i]=0; |
247 |
i++; |
248 |
while (str[i]!=0 && (str[i]=='\t' || str[i]==' ')) i++; |
249 |
afterdelim=true; |
250 |
continue; |
251 |
} |
252 |
i++; |
253 |
} |
254 |
return tidx; |
255 |
} |
256 |
|
257 |
|
258 |
char* Gsubstr(const char* str, char* from, char* to) { |
259 |
//extract (and allocate) a substring, including boundaries (from/to) |
260 |
if (str==NULL || from==NULL) return NULL; |
261 |
if (from[0]==0 || str[0]==0) return newEmptyStr(); |
262 |
if (from<str) return NULL; |
263 |
if (to==NULL) { |
264 |
to=from; |
265 |
while (to[1]) to++; |
266 |
} |
267 |
if (to<from) return newEmptyStr(); |
268 |
int newlen=to-from+1; |
269 |
char* subs; |
270 |
GMALLOC(subs, newlen); |
271 |
memcpy(subs, str, newlen-1); |
272 |
subs[newlen]='\0'; |
273 |
return subs; |
274 |
} |
275 |
|
276 |
char* replaceStr(char* &str, char* newvalue) { |
277 |
if (str!=NULL) GFREE(str); |
278 |
if (newvalue==NULL) { return NULL; } |
279 |
GMALLOC(str, strlen(newvalue)+1); |
280 |
strcpy(str,newvalue); |
281 |
return str; |
282 |
} |
283 |
|
284 |
void* Gmemscan(void *mem, unsigned int len, |
285 |
void *part, unsigned int partlen) { |
286 |
char* p; |
287 |
unsigned int restlen=len-partlen+1; |
288 |
void* oldp=mem; |
289 |
while ( (p=(char*)memchr(oldp, ((char*)part)[0], restlen))!=NULL) { |
290 |
//located first char, try to match the rest: |
291 |
p++; |
292 |
if (memcmp(p, &((char*)part)[1], partlen-1)==0) return p-1; |
293 |
//no string match, prepare next iteration |
294 |
restlen-=(p-(char*)oldp); |
295 |
oldp=p; |
296 |
}//while |
297 |
return NULL; |
298 |
} |
299 |
|
300 |
//rindex function is missing on some platforms ? |
301 |
char* rstrchr(char* str, char ch) { /* returns a pointer to the rightmost |
302 |
occurence of ch in str */ |
303 |
char *p; |
304 |
if (str==NULL) return NULL; |
305 |
p=str+strlen(str)-1; |
306 |
while (p>=str) { |
307 |
if (*p==ch) return p; |
308 |
p--; |
309 |
} |
310 |
return NULL; |
311 |
} |
312 |
|
313 |
|
314 |
/* DOS/UNIX safer fgets : reads a text line from a (binary) file and |
315 |
update the file position accordingly and the buffer capacity accordingly. |
316 |
The given buf is resized to read the entire line in memory |
317 |
-- even when it's abnormally long |
318 |
*/ |
319 |
char* fgetline(char* & buf, int& buf_cap, FILE *stream, off_t* f_pos, int* linelen) { |
320 |
//reads a char at a time until \n and/or \r are encountered |
321 |
int i=0; |
322 |
int c=0; |
323 |
off_t fpos=(f_pos!=NULL) ? *f_pos : 0; |
324 |
while ((c=getc(stream))!=EOF) { |
325 |
if (i>=buf_cap-1) { |
326 |
buf_cap+=1024; |
327 |
GREALLOC(buf, buf_cap); |
328 |
} |
329 |
if (c=='\n' || c=='\r') { |
330 |
if (c=='\r') { |
331 |
if ((c=getc(stream))!='\n') ungetc(c,stream); |
332 |
else fpos++; |
333 |
} |
334 |
fpos++; |
335 |
break; |
336 |
} |
337 |
fpos++; |
338 |
buf[i]=(char)c; |
339 |
i++; |
340 |
} //while i<buf_cap-1 |
341 |
if (linelen!=NULL) *linelen=i; |
342 |
if (f_pos!=NULL) *f_pos=fpos; |
343 |
if (c==EOF && i==0) return NULL; |
344 |
buf[i]='\0'; |
345 |
return buf; |
346 |
} |
347 |
|
348 |
char* GLineReader::getLine(FILE* stream, off_t& f_pos) { |
349 |
if (pushed) { pushed=false; return buf; } |
350 |
//reads a char at a time until \n and/or \r are encountered |
351 |
len=0; |
352 |
int c=0; |
353 |
while ((c=getc(stream))!=EOF) { |
354 |
if (len>=allocated-1) { |
355 |
allocated+=1024; |
356 |
GREALLOC(buf, allocated); |
357 |
} |
358 |
if (c=='\n' || c=='\r') { |
359 |
buf[len]='\0'; |
360 |
if (c=='\r') { //DOS file -- special case |
361 |
if ((c=getc(stream))!='\n') ungetc(c,stream); |
362 |
else f_pos++; |
363 |
} |
364 |
f_pos++; |
365 |
lcount++; |
366 |
return buf; |
367 |
} |
368 |
f_pos++; |
369 |
buf[len]=(char)c; |
370 |
len++; |
371 |
} //while i<buf_cap-1 |
372 |
if (c==EOF) { |
373 |
isEOF=true; |
374 |
if (len==0) return NULL; |
375 |
} |
376 |
buf[len]='\0'; |
377 |
lcount++; |
378 |
return buf; |
379 |
} |
380 |
|
381 |
|
382 |
//strchr but with a set of chars instead of only one |
383 |
char* strchrs(const char* s, const char* chrs) { |
384 |
if (s==NULL || chrs==NULL || *chrs=='\0' || *s=='\0') |
385 |
return NULL; |
386 |
unsigned int l=strlen(s); |
387 |
unsigned int r=strcspn(s, chrs); |
388 |
if (r==l) return NULL; |
389 |
return ((char*)s+r); |
390 |
} |
391 |
|
392 |
char* upCase(const char* str) { |
393 |
if (str==NULL) return NULL; |
394 |
int len=strlen(str); |
395 |
char* upstr; |
396 |
GMALLOC(upstr, len+1); |
397 |
upstr[len]='\0'; |
398 |
for (int i=0;i<len;i++) upstr[i]=toupper(str[i]); |
399 |
return upstr; |
400 |
} |
401 |
|
402 |
char* loCase(const char* str) { |
403 |
if (str==NULL) return NULL; |
404 |
int len=strlen(str); |
405 |
char* lostr; |
406 |
GMALLOC(lostr, len+1); |
407 |
lostr[len]='\0'; |
408 |
for (int i=0;i<len;i++) lostr[i]=tolower(str[i]); |
409 |
return lostr; |
410 |
} |
411 |
|
412 |
char* strlower(char * str) {//changes string in place |
413 |
if (str==NULL) return NULL; |
414 |
int i=0; |
415 |
while (str[i]!=0) { str[i]=tolower(str[i]); i++; } |
416 |
return str; |
417 |
} |
418 |
|
419 |
char* strupper(char * str) {//changes string in place |
420 |
if (str==NULL) return NULL; |
421 |
int i=0; |
422 |
while (str[i]!=0) { str[i]=toupper(str[i]); i++; } |
423 |
return str; |
424 |
} |
425 |
|
426 |
|
427 |
|
428 |
//test if a char is in a given string (set) |
429 |
bool chrInStr(char c, const char* str) { |
430 |
if (str==NULL || *str=='\0') return false; |
431 |
for (const char* p=str; (*p)!='\0'; p++) { |
432 |
if ((*p)==c) return true; |
433 |
} |
434 |
return false; |
435 |
} |
436 |
|
437 |
|
438 |
|
439 |
char* rstrfind(const char* str, const char* substr) { |
440 |
/* like rindex() for a string */ |
441 |
int l,i; |
442 |
if (str==NULL || *str=='\0') return NULL; |
443 |
if (substr==NULL || *substr=='\0') return NULL; |
444 |
l=strlen(substr); |
445 |
char* p=(char*)str+strlen(str)-l; |
446 |
//rightmost position that could match |
447 |
|
448 |
while (p>=str) { |
449 |
for (i=0; i<l && *(p+i) == *(substr+i); i++) ; |
450 |
if (i==l) return p; //found! |
451 |
p--; |
452 |
} |
453 |
return NULL; |
454 |
} |
455 |
|
456 |
|
457 |
char* strifind(const char* str, const char* substr) { |
458 |
// the case insensitive version of strstr -- finding a string within a strin |
459 |
int l,i; |
460 |
if (str==NULL || *str==0) return NULL; |
461 |
if (substr==NULL || *substr==0) return NULL; |
462 |
l=strlen(substr); |
463 |
char* smax=(char*)str+strlen(str)-l; |
464 |
//rightmost position that could match |
465 |
char* p=(char*)str; |
466 |
while (p<=smax) { |
467 |
for (i=0; i<l && tolower(*(p+i))==tolower(*(substr+i)); i++) ; |
468 |
if (i==l) return p; //found! |
469 |
p++; |
470 |
} |
471 |
return NULL; |
472 |
} |
473 |
|
474 |
|
475 |
|
476 |
// tests if string s has the given prefix |
477 |
bool startsWith(const char* s, const char* prefix) { |
478 |
if (prefix==NULL || s==NULL) return false; |
479 |
int i=0; |
480 |
while (prefix[i]!='\0' && prefix[i]==s[i]) i++; |
481 |
return (prefix[i]=='\0'); |
482 |
} |
483 |
|
484 |
// tests if string s ends with given suffix |
485 |
bool endsWith(const char* s, const char* suffix) { |
486 |
if (suffix==NULL || s==NULL) return false; |
487 |
if (suffix[0]==0) return true; //special case: empty suffix |
488 |
int j=strlen(suffix)-1; |
489 |
int i=strlen(s)-1; |
490 |
if (i<j) return false; |
491 |
while (j>=0 && s[i]==suffix[j]) { i--; j--; } |
492 |
return (j==-1); |
493 |
} |
494 |
|
495 |
|
496 |
char* reverseChars(char* str, int slen) { |
497 |
if (slen==0) slen=strlen(str); |
498 |
int l=0; |
499 |
int r=slen-1; |
500 |
char c; |
501 |
while (l<r) { |
502 |
c=str[l];str[l]=str[r]; |
503 |
str[r]=c; |
504 |
l++;r--; |
505 |
} |
506 |
return str; |
507 |
} |
508 |
|
509 |
|
510 |
char* rstrstr(const char* rstart, const char *lend, const char* substr) { /*like strstr, but starts searching |
511 |
from right end, going up to lend and returns a pointer to the last (right) |
512 |
matching character in str */ |
513 |
char *p; |
514 |
int l,i; |
515 |
l=strlen(substr); |
516 |
p=(char*)rstart-l+1; |
517 |
while (p>=lend) { |
518 |
for (i=0;i<l;i++) if (*(p+i) != *(substr+i)) break; |
519 |
if (i==l) return p+l-1; |
520 |
p--; |
521 |
} |
522 |
return NULL; |
523 |
} |
524 |
|
525 |
|
526 |
//hash function used for strings in GHash |
527 |
int strhash(const char* str){ |
528 |
register int h=0; |
529 |
register int g; |
530 |
while (*str) { |
531 |
h=(h<<4)+*str++; |
532 |
g=h&0xF0000000; |
533 |
if(g) h^=g>>24; |
534 |
h&=0x0fffffff; |
535 |
} |
536 |
GASSERT(h<=0x0fffffff); |
537 |
return h; |
538 |
} |
539 |
|
540 |
// removes the last part (file or directory name) of a full path |
541 |
// this is a destructive operation for the given string!!! |
542 |
// the trailing '/' is guaranteed to be there |
543 |
void delFileName(char* filepath) { |
544 |
char *p, *sep; |
545 |
if (filepath==NULL) return; |
546 |
for (p=filepath, sep=filepath;*p!='\0';p++) |
547 |
if (*p=='/' || *p=='\\') sep=p+1; |
548 |
*sep='\0'; // truncate filepath |
549 |
} |
550 |
|
551 |
// returns a pointer to the last file or directory name in a full path |
552 |
const char* getFileName(const char* filepath) { |
553 |
const char *p, *sep; |
554 |
if (filepath==NULL) return NULL; |
555 |
for (p=filepath, sep=filepath;*p!='\0';p++) |
556 |
if (*p=='/' || *p=='\\') sep=p+1; |
557 |
return sep; |
558 |
} |
559 |
|
560 |
// returns a pointer to the file "extension" part in a filename |
561 |
const char* getFileExt(const char* filepath) { |
562 |
const char *p, *dp, *sep; |
563 |
if (filepath==NULL) return NULL; |
564 |
for (p=filepath, dp=filepath, sep=filepath;*p!='\0';p++) { |
565 |
if (*p=='.') dp=p+1; |
566 |
else if (*p=='/' || *p=='\\') |
567 |
sep=p+1; |
568 |
} |
569 |
return (dp>sep) ? dp : NULL ; |
570 |
} |
571 |
|
572 |
int fileExists(const char* fname) { |
573 |
struct stat stFileInfo; |
574 |
int r=0; |
575 |
// Attempt to get the file attributes |
576 |
int fs = stat(fname,&stFileInfo); |
577 |
if (fs == 0) { |
578 |
r=3; |
579 |
// We were able to get the file attributes |
580 |
// so the file obviously exists. |
581 |
if (S_ISREG (stFileInfo.st_mode)) { |
582 |
r=2; |
583 |
} |
584 |
if (S_ISDIR (stFileInfo.st_mode)) { |
585 |
r=1; |
586 |
} |
587 |
} |
588 |
return r; |
589 |
} |
590 |
|
591 |
/*bool fileExists(const char* filepath) { |
592 |
if (filepath==NULL) return false; |
593 |
FILE* ft=fopen(filepath, "rb"); |
594 |
if (ft==NULL) return false; |
595 |
fclose(ft); |
596 |
return true; |
597 |
} |
598 |
*/ |
599 |
int64 fileSize(const char* fpath) { |
600 |
struct stat results; |
601 |
if (stat(fpath, &results) == 0) |
602 |
// The size of the file in bytes is in |
603 |
return (int64)results.st_size; |
604 |
else |
605 |
// An error occurred |
606 |
//GMessage("Error at stat(%s)!\n", fpath); |
607 |
return 0; |
608 |
} |
609 |
|
610 |
bool parseNumber(char* &p, double& v) { |
611 |
//skip any spaces.. |
612 |
while (*p==' ' || *p=='\t') p++; |
613 |
char* start=p; |
614 |
/*if (*p=='-') p++; |
615 |
else if (*p=='+') { p++;start++; }*/ |
616 |
|
617 |
/* while ((*p>='1' && *p<='9') || *p=='0' || |
618 |
*p=='.' || *p=='-' || tolower(*p)=='e') p++; */ |
619 |
int numlen=strspn(start, "0123456789eE.-+"); |
620 |
p=start+numlen; |
621 |
//now p is on a non-digit; |
622 |
if (*start=='-' && p==start+1) return false; |
623 |
char saved=*p; |
624 |
*p='\0'; |
625 |
char* endptr=p; |
626 |
v=strtod(start,&endptr); |
627 |
*p=saved; |
628 |
if (endptr!=p) return false; |
629 |
return true; |
630 |
} |
631 |
|
632 |
|
633 |
bool parseDouble(char* &p, double& v) { |
634 |
return parseNumber(p,v); |
635 |
} |
636 |
|
637 |
bool parseInt(char* &p, int& i) { |
638 |
while (*p==' ' || *p=='\t') p++; |
639 |
char* start=p; |
640 |
if (*p=='-') p++; |
641 |
else if (*p=='+') { p++;start++; } |
642 |
while ((*p>='1' && *p<='9') || *p=='0') p++; |
643 |
//now p is on a non-digit; |
644 |
if (*start=='-' && p==start+1) return false; |
645 |
char saved=*p; |
646 |
*p='\0'; |
647 |
char* endptr=p; |
648 |
long l=strtol(start,&endptr,10); |
649 |
i=(int)l; |
650 |
*p=saved; |
651 |
if (endptr!=p || i!=l) return false; |
652 |
return true; |
653 |
} |
654 |
|
655 |
bool parseUInt(char* &p, uint& i) { |
656 |
while (*p==' ' || *p=='\t') p++; |
657 |
char* start=p; |
658 |
if (*p=='-') return false; |
659 |
else if (*p=='+') { p++;start++; } |
660 |
while ((*p>='1' && *p<='9') || *p=='0') p++; |
661 |
//now p is on a non-digit; |
662 |
if (*start=='-' && p==start+1) return false; |
663 |
char saved=*p; |
664 |
*p='\0'; |
665 |
char* endptr=p; |
666 |
unsigned long l=strtoul(start,&endptr,10); |
667 |
i=(uint) l; |
668 |
*p=saved; |
669 |
if (endptr!=p || i!=l) return false; |
670 |
return true; |
671 |
} |
672 |
|
673 |
bool parseHex(char* &p, uint& i) { |
674 |
//skip initial spaces/prefix |
675 |
while (*p==' ' || *p=='\t' || *p=='0' || *p=='x') p++; |
676 |
char* start=p; |
677 |
if (*p=='-') return false; |
678 |
else if (*p=='+') { p++;start++; } |
679 |
while (isxdigit(*p)) p++; |
680 |
//now p is on a non-hexdigit; |
681 |
if (p==start+1) return false; |
682 |
char saved=*p; |
683 |
*p='\0'; |
684 |
char* endptr=p; |
685 |
unsigned long l=strtoul(start,&endptr,16); |
686 |
i=(uint) l; |
687 |
*p=saved; |
688 |
if (endptr!=p || i!=l) return false; |
689 |
return true; |
690 |
} |
691 |
|
692 |
//write a formatted fasta record, fasta formatted |
693 |
void writeFasta(FILE *fw, const char* seqid, const char* descr, |
694 |
const char* seq, int linelen, int seqlen) { |
695 |
fflush(fw); |
696 |
// write header line only if given! |
697 |
if (seqid!=NULL) { |
698 |
if (descr==NULL || descr[0]==0) |
699 |
fprintf(fw,">%s\n",seqid); |
700 |
else fprintf(fw,">%s %s\n",seqid, descr); |
701 |
} |
702 |
fflush(fw); |
703 |
if (seq==NULL || *seq==0) return; //nothing to print |
704 |
if (linelen==0) { //unlimited line length: write the whole sequence on a line |
705 |
if (seqlen>0) |
706 |
fwrite((const void*)seq, 1, seqlen,fw); |
707 |
else fprintf(fw,"%s",seq); |
708 |
fprintf(fw,"\n"); |
709 |
fflush(fw); |
710 |
return; |
711 |
} |
712 |
int ilen=0; |
713 |
if (seqlen>0) { //seq length given, so we know when to stop |
714 |
for (int i=0; i < seqlen; i++, ilen++) { |
715 |
if (ilen == linelen) { |
716 |
fputc('\n', fw); |
717 |
ilen = 0; |
718 |
} |
719 |
fputc(seq[i], fw); |
720 |
} |
721 |
fputc('\n', fw); |
722 |
} |
723 |
else { //seq length not given, stop when 0 encountered |
724 |
for (int i=0; seq[i]!=0; i++, ilen++) { |
725 |
if (ilen == linelen) { |
726 |
fputc('\n', fw); |
727 |
ilen = 0; |
728 |
} |
729 |
fputc(seq[i], fw); |
730 |
} //for |
731 |
fputc('\n', fw); |
732 |
} |
733 |
fflush(fw); |
734 |
} |
735 |
|
736 |
char* commaprint(uint64 n) { |
737 |
static int comma = '\0'; |
738 |
static char retbuf[48]; |
739 |
char *p = &retbuf[sizeof(retbuf)-1]; |
740 |
int i = 0; |
741 |
if(comma == '\0') { |
742 |
/* struct lconv *lcp = localeconv(); |
743 |
if(lcp != NULL) { |
744 |
if(lcp->thousands_sep != NULL && |
745 |
*lcp->thousands_sep != '\0') |
746 |
comma = *lcp->thousands_sep; |
747 |
else */ |
748 |
comma = ','; |
749 |
// } |
750 |
} |
751 |
*p = '\0'; |
752 |
do { |
753 |
if(i%3 == 0 && i != 0) |
754 |
*--p = comma; |
755 |
*--p = '0' + n % 10; |
756 |
n /= 10; |
757 |
i++; |
758 |
} while(n != 0); |
759 |
return p; |
760 |
} |