ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/gclib/gclib/GBase.cpp
Revision: 198
Committed: Sun Feb 26 18:03:46 2012 UTC (7 years, 2 months ago) by gpertea
File size: 18713 byte(s)
Log Message:
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    
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 gpertea 2 //************************* 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 gpertea 16
83 gpertea 2 // 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 gpertea 16 char *copy=NULL;
144 gpertea 2 GMALLOC(copy, strlen(str)+1);
145     strcpy(copy,str);
146     return copy;
147     }
148    
149     char* newEmptyStr() {
150 gpertea 16 char* zs=NULL;
151 gpertea 2 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 gpertea 16 char *copy=NULL;
159 gpertea 2 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 gpertea 150 int Gstrcmp(const char* a, const char* b, int n) {
167 gpertea 2 if (a==NULL || b==NULL) {
168     return a==NULL ? -1 : 1;
169     }
170 gpertea 150 else {
171     if (n<0) return strcmp(a,b);
172     else return strncmp(a,b,n);
173     }
174    
175 gpertea 2 }
176    
177 gpertea 150 int Gstricmp(const char* a, const char* b, int n) {
178 gpertea 2 if (a==NULL || b==NULL) return a==NULL ? -1 : 1;
179     register int ua, ub;
180 gpertea 150 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 gpertea 2 }
189 gpertea 150 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 gpertea 2 }
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 gpertea 16 char* strchrs(const char* s, const char* chrs) {
401 gpertea 2 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 gpertea 16 return ((char*)s+r);
407 gpertea 2 }
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 gpertea 16 bool chrInStr(char c, const char* str) {
447 gpertea 2 if (str==NULL || *str=='\0') return false;
448 gpertea 16 for (const char* p=str; (*p)!='\0'; p++) {
449 gpertea 2 if ((*p)==c) return true;
450     }
451     return false;
452     }
453    
454    
455    
456 gpertea 16 char* rstrfind(const char* str, const char* substr) {
457 gpertea 2 /* 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 gpertea 16 char* p=(char*)str+strlen(str)-l;
463 gpertea 2 //rightmost position that could match
464    
465     while (p>=str) {
466 gpertea 16 for (i=0; i<l && *(p+i) == *(substr+i); i++) ;
467 gpertea 2 if (i==l) return p; //found!
468     p--;
469     }
470     return NULL;
471     }
472    
473    
474 gpertea 16 char* strifind(const char* str, const char* substr) {
475 gpertea 2 // 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 gpertea 16 char* smax=(char*)str+strlen(str)-l;
481 gpertea 2 //rightmost position that could match
482 gpertea 16 char* p=(char*)str;
483 gpertea 2 while (p<=smax) {
484 gpertea 16 for (i=0; i<l && tolower(*(p+i))==tolower(*(substr+i)); i++) ;
485 gpertea 2 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 gpertea 16 bool startsWith(const char* s, const char* prefix) {
495 gpertea 2 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 gpertea 16 // 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 gpertea 2
512 gpertea 16
513 gpertea 2 char* reverseChars(char* str, int slen) {
514     if (slen==0) slen=strlen(str);
515     int l=0;
516     int r=slen-1;
517 gpertea 90 char c;
518 gpertea 2 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 gpertea 16 char* rstrstr(const char* rstart, const char *lend, const char* substr) { /*like strstr, but starts searching
528 gpertea 2 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 gpertea 16 p=(char*)rstart-l+1;
534 gpertea 2 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 gpertea 16 // removes the last part (file or directory name) of a full path
558 gpertea 2 // 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 gpertea 16 if (*p=='/' || *p=='\\') sep=p+1;
565 gpertea 2 *sep='\0'; // truncate filepath
566     }
567    
568 gpertea 16 // 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 gpertea 2 if (filepath==NULL) return NULL;
572     for (p=filepath, sep=filepath;*p!='\0';p++)
573 gpertea 16 if (*p=='/' || *p=='\\') sep=p+1;
574 gpertea 2 return sep;
575     }
576    
577 gpertea 16 // 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 gpertea 2 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 gpertea 16 int64 fileSize(const char* fpath) {
617 gpertea 2 struct stat results;
618     if (stat(fpath, &results) == 0)
619     // The size of the file in bytes is in
620 gpertea 16 return (int64)results.st_size;
621 gpertea 2 else
622     // An error occurred
623 gpertea 16 //GMessage("Error at stat(%s)!\n", fpath);
624 gpertea 2 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 gpertea 16 //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     }