ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/gclib/gclib/GBase.cpp
Revision: 258
Committed: Tue Jun 26 22:29:50 2012 UTC (7 years, 3 months ago) by gpertea
File size: 18718 byte(s)
Log Message:
commented out saprintf(), not used

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