lib/common.c

Go to the documentation of this file.
00001 /* Commonly used routines in a wide range of applications.
00002  * Strings, singly-linked lists, and a little file i/o.  
00003  *
00004  * This file is copyright 2002 Jim Kent, but license is hereby
00005  * granted for all use - public, private or commercial. */
00006 
00007 #include "common.h"
00008 #include "errabort.h"
00009 #include "portable.h"
00010 #include "linefile.h"
00011 
00012 static char const rcsid[] = "$Id: common.c,v 1.108 2007/03/30 00:12:11 markd Exp $";
00013 
00014 void *cloneMem(void *pt, size_t size)
00015 /* Allocate a new buffer of given size, and copy pt to it. */
00016 {
00017 void *newPt = needLargeMem(size);
00018 memcpy(newPt, pt, size);
00019 return newPt;
00020 }
00021 
00022 char *cloneStringZ(char *s, int size)
00023 /* Make a zero terminated copy of string in memory */
00024 {
00025 char *d = needMem(size+1);
00026 memcpy(d, s, size);
00027 d[size] = 0;
00028 return d;
00029 }
00030 
00031 char *cloneString(char *s)
00032 /* Make copy of string in dynamic memory */
00033 {
00034 if (s == NULL)
00035     return NULL;
00036 else
00037     return cloneStringZ(s, strlen(s));
00038 }
00039 
00040 char *cloneLongString(char *s)
00041 /* Make clone of long string. */
00042 {
00043 size_t size = strlen(s);
00044 return cloneMem(s, size+1);
00045 }
00046 
00047 
00048 /* fill a specified area of memory with zeroes */
00049 void zeroBytes(void *vpt, int count)
00050 {
00051 char *pt = (char*)vpt;
00052 while (--count>=0)
00053     *pt++=0;
00054 }
00055 
00056 /* Reverse the order of the bytes. */
00057 void reverseBytes(char *bytes, long length)
00058 {
00059 long halfLen = (length>>1);
00060 char *end = bytes+length;
00061 char c;
00062 while (--halfLen >= 0)
00063     {
00064     c = *bytes;
00065     *bytes++ = *--end;
00066     *end = c;
00067     }
00068 }
00069 
00070 void reverseInts(int *a, int length)
00071 /* Reverse the order of the integer array. */
00072 {
00073 int halfLen = (length>>1);
00074 int *end = a+length;
00075 int c;
00076 while (--halfLen >= 0)
00077     {
00078     c = *a;
00079     *a++ = *--end;
00080     *end = c;
00081     }
00082 }
00083 
00084 void reverseUnsigned(unsigned *a, int length)
00085 /* Reverse the order of the unsigned array. */
00086 {
00087 int halfLen = (length>>1);
00088 unsigned *end = a+length;
00089 unsigned c;
00090 while (--halfLen >= 0)
00091     {
00092     c = *a;
00093     *a++ = *--end;
00094     *end = c;
00095     }
00096 }
00097 
00098 void reverseDoubles(double *a, int length)
00099 /* Reverse the order of the double array. */
00100 {
00101 int halfLen = (length>>1);
00102 double *end = a+length;
00103 double c;
00104 while (--halfLen >= 0)
00105     {
00106     c = *a;
00107     *a++ = *--end;
00108     *end = c;
00109     }
00110 }
00111 
00112 void reverseStrings(char **a, int length)
00113 /* Reverse the order of the char* array. */
00114 {
00115 int halfLen = (length>>1);
00116 char **end = a+length;
00117 char *c;
00118 while (--halfLen >= 0)
00119     {
00120     c = *a;
00121     *a++ = *--end;
00122     *end = c;
00123     }
00124 }
00125 
00126 /* Swap buffers a and b. */
00127 void swapBytes(char *a, char *b, int length)
00128 {
00129 char c;
00130 int i;
00131 
00132 for (i=0; i<length; ++i)
00133     {
00134     c = a[i];
00135     a[i] = b[i];
00136     b[i] = c;
00137     }
00138 }
00139 
00140 
00143 /* Count up elements in list. */
00144 int slCount(void *list)
00145 {
00146 struct slList *pt = (struct slList *)list;
00147 int len = 0;
00148 
00149 while (pt != NULL)
00150     {
00151     len += 1;
00152     pt = pt->next;
00153     }
00154 return len;
00155 }
00156 
00157 void *slElementFromIx(void *list, int ix)
00158 /* Return the ix'th element in list.  Returns NULL
00159  * if no such element. */
00160 {
00161 struct slList *pt = (struct slList *)list;
00162 int i;
00163 for (i=0;i<ix;i++)
00164     {
00165     if (pt == NULL) return NULL;
00166     pt = pt->next;
00167     }
00168 return pt;
00169 }
00170 
00171 int slIxFromElement(void *list, void *el)
00172 /* Return index of el in list.  Returns -1 if not on list. */
00173 {
00174 struct slList *pt;
00175 int ix = 0;
00176 
00177 for (pt = list, ix=0; pt != NULL; pt = pt->next, ++ix)
00178     if (el == (void*)pt)
00179         return ix;
00180 return -1;
00181 }
00182 
00183 void *slLastEl(void *list)
00184 /* Returns last element in list or NULL if none. */
00185 {
00186 struct slList *next, *el;
00187 if ((el = list) == NULL)
00188     return NULL;
00189 while ((next = el->next) != NULL)
00190     el = next;
00191 return el;
00192 }
00193 
00194 /* Add new node to tail of list.
00195  * Usage:
00196  *    slAddTail(&list, node);
00197  * where list and nodes are both pointers to structure
00198  * that begin with a next pointer. 
00199  */
00200 void slAddTail(void *listPt, void *node)
00201 {
00202 struct slList **ppt = (struct slList **)listPt;
00203 struct slList *n = (struct slList *)node;
00204 
00205 while (*ppt != NULL)
00206     {
00207     ppt = &((*ppt)->next);
00208     }
00209 n->next = NULL; 
00210 *ppt = n;
00211 }
00212 
00213 /* Add new node to start of list.
00214  * Usage:
00215  *    slAddHead(&list, node);
00216  * where list and nodes are both pointers to structure
00217  * that begin with a next pointer. 
00218  */
00219 void slSafeAddHead(void *listPt, void *node)
00220 {
00221 struct slList **ppt = (struct slList **)listPt;
00222 struct slList *n = (struct slList *)node;
00223 
00224 n->next = *ppt; 
00225 *ppt = n; 
00226 }
00227 
00228 
00229 void *slPopHead(void *vListPt)
00230 /* Return head of list and remove it from list. (Fast) */
00231 {
00232 struct slList **listPt = (struct slList **)vListPt;
00233 struct slList *el = *listPt;
00234 if (el != NULL)
00235     {
00236     *listPt = el->next;
00237     el->next = NULL;
00238     }
00239 return el;
00240 }
00241 
00242 void *slPopTail(void *vListPt)
00243 /* Return tail of list and remove it from list. (Not so fast) */
00244 {
00245 struct slList **listPt = (struct slList **)vListPt;
00246 struct slList *el = *listPt;
00247 if (el != NULL)
00248     {
00249     for (;;)
00250         {
00251         if (el->next == NULL)
00252             {
00253             *listPt = NULL;
00254             break;
00255             }
00256         listPt = &el->next;
00257         el = el->next;
00258         }
00259     }
00260 return el;
00261 }
00262 
00263 
00264 
00265 void *slCat(void *va, void *vb)
00266 /* Return concatenation of lists a and b.
00267  * Example Usage:
00268  *   struct slName *a = getNames("a");
00269  *   struct slName *b = getNames("b");
00270  *   struct slName *ab = slCat(a,b)
00271  */
00272 {
00273 struct slList *a = va;
00274 struct slList *b = vb;
00275 struct slList *end;
00276 if (a == NULL)
00277     return b;
00278 for (end = a; end->next != NULL; end = end->next)
00279     ;
00280 end->next = b;
00281 return a;
00282 }
00283 
00284 void slReverse(void *listPt)
00285 /* Reverse order of a list.
00286  * Usage:
00287  *    slReverse(&list);
00288  */
00289 {
00290 struct slList **ppt = (struct slList **)listPt;
00291 struct slList *newList = NULL;
00292 struct slList *el, *next;
00293 
00294 next = *ppt;
00295 while (next != NULL)
00296     {
00297     el = next;
00298     next = el->next;
00299     el->next = newList;
00300     newList = el;
00301     }
00302 *ppt = newList;
00303 }
00304 
00305 void slFreeList(void *listPt)
00306 /* Free list */
00307 {
00308 struct slList **ppt = (struct slList**)listPt;
00309 struct slList *next = *ppt;
00310 struct slList *el;
00311 
00312 while (next != NULL)
00313     {
00314     el = next;
00315     next = el->next;
00316     freeMem((char*)el);
00317     }
00318 *ppt = NULL;
00319 }
00320 
00321 void slSort(void *pList, int (*compare )(const void *elem1,  const void *elem2))
00322 /* Sort a singly linked list with Qsort and a temporary array. */
00323 {
00324 struct slList **pL = (struct slList **)pList;
00325 struct slList *list = *pL;
00326 int count;
00327 count = slCount(list);
00328 if (count > 1)
00329     {
00330     struct slList *el;
00331     struct slList **array;
00332     int i;
00333     array = needLargeMem(count * sizeof(*array));
00334     for (el = list, i=0; el != NULL; el = el->next, i++)
00335         array[i] = el;
00336     qsort(array, count, sizeof(array[0]), compare);
00337     list = NULL;
00338     for (i=0; i<count; ++i)
00339         {
00340         array[i]->next = list;
00341         list = array[i];
00342         }
00343     freeMem(array);
00344     slReverse(&list);
00345     *pL = list;       
00346     }
00347 }
00348 
00349 void slUniqify(void *pList, int (*compare )(const void *elem1,  const void *elem2), void (*free)())
00350 /* Return sorted list with duplicates removed. 
00351  * Compare should be same type of function as slSort's compare (taking
00352  * pointers to pointers to elements.  Free should take a simple
00353  * pointer to dispose of duplicate element, and can be NULL. */
00354 {
00355 struct slList **pSlList = (struct slList **)pList;
00356 struct slList *oldList = *pSlList;
00357 struct slList *newList = NULL, *el;
00358 
00359 slSort(&oldList, compare);
00360 while ((el = slPopHead(&oldList)) != NULL)
00361     {
00362     if ((newList == NULL) || (compare(&newList, &el) != 0))
00363         slAddHead(&newList, el);
00364     else if (free != NULL)
00365         free(el);
00366     }
00367 slReverse(&newList);
00368 *pSlList = newList;
00369 }
00370 
00371 boolean slRemoveEl(void *vpList, void *vToRemove)
00372 /* Remove element from doubly linked list.  Usage:
00373  *    slRemove(&list, el);  
00374  * Returns TRUE if element in list.  */
00375 {
00376 struct slList **pList = vpList;
00377 struct slList *toRemove = vToRemove;
00378 struct slList *el, *next, *newList = NULL;
00379 boolean didRemove = FALSE;
00380 
00381 for (el = *pList; el != NULL; el = next)
00382     {
00383     next = el->next;
00384     if (el != toRemove)
00385         {
00386         slAddHead(&newList, el);
00387         }
00388     else
00389         didRemove = TRUE;
00390     }
00391 slReverse(&newList);
00392 *pList = newList;
00393 return didRemove;
00394 }
00395 
00396 struct slInt *slIntNew(int x)
00397 /* Return a new int. */
00398 {
00399 struct slInt *a;
00400 AllocVar(a);
00401 a->val = x;
00402 return a;
00403 }
00404 
00405 int slIntCmp(const void *va, const void *vb)
00406 /* Compare two slInts. */
00407 {
00408 const struct slInt *a = *((struct slInt **)va);
00409 const struct slInt *b = *((struct slInt **)vb);
00410 return a->val - b->val;
00411 }
00412 
00413 int slIntCmpRev(const void *va, const void *vb)
00414 /* Compare two slInts in reverse direction. */
00415 {
00416 const struct slInt *a = *((struct slInt **)va);
00417 const struct slInt *b = *((struct slInt **)vb);
00418 return b->val - a->val;
00419 }
00420 
00421 static int doubleCmp(const void *va, const void *vb)
00422 /* Compare function to sort array of doubles. */
00423 {
00424 const double *a = va;
00425 const double *b = vb;
00426 double diff = *a - *b;
00427 if (diff < 0)
00428     return -1;
00429 else if (diff > 0)
00430     return 1;
00431 else
00432     return 0;
00433 }
00434 
00435 void doubleSort(int count, double *array)
00436 /* Sort an array of doubles. */
00437 {
00438 if (count > 1)
00439 qsort(array, count, sizeof(array[0]), doubleCmp);
00440 }
00441 
00442 double doubleMedian(int count, double *array)
00443 /* Return median value in array.  This will sort
00444  * the array as a side effect. */
00445 {
00446 double median;
00447 doubleSort(count, array);
00448 if ((count&1) == 1)
00449     median = array[count>>1];
00450 else
00451     {
00452     count >>= 1;
00453     median = (array[count] + array[count-1]) * 0.5;
00454     }
00455 return median;
00456 }
00457 
00458 struct slDouble *slDoubleNew(double x)
00459 /* Return a new double. */
00460 {
00461 struct slDouble *a;
00462 AllocVar(a);
00463 a->val = x;
00464 return a;
00465 }
00466 
00467 int slDoubleCmp(const void *va, const void *vb)
00468 /* Compare two slDoubles. */
00469 {
00470 const struct slDouble *a = *((struct slDouble **)va);
00471 const struct slDouble *b = *((struct slDouble **)vb);
00472 double diff = a->val - b->val;
00473 if (diff < 0)
00474     return -1;
00475 else if (diff > 0)
00476     return 1;
00477 else
00478     return 0;
00479 }
00480 
00481 double slDoubleMedian(struct slDouble *list)
00482 /* Return median value on list. */
00483 {
00484 int i,count = slCount(list);
00485 struct slDouble *el;
00486 double *array, median;
00487 if (count == 0)
00488     errAbort("Can't take median of empty list");
00489 AllocArray(array,count);
00490 for (i=0, el=list; i<count; ++i, el=el->next)
00491     array[i] = el->val;
00492 median = doubleMedian(count, array);
00493 freeMem(array);
00494 return median;
00495 }
00496 
00497 static int intCmp(const void *va, const void *vb)
00498 /* Compare function to sort array of ints. */
00499 {
00500 const int *a = va;
00501 const int *b = vb;
00502 int diff = *a - *b;
00503 if (diff < 0)
00504     return -1;
00505 else if (diff > 0)
00506     return 1;
00507 else
00508     return 0;
00509 }
00510 
00511 void intSort(int count, int *array)
00512 /* Sort an array of ints. */
00513 {
00514 if (count > 1)
00515 qsort(array, count, sizeof(array[0]), intCmp);
00516 }
00517 
00518 int intMedian(int count, int *array)
00519 /* Return median value in array.  This will sort
00520  * the array as a side effect. */
00521 {
00522 int median;
00523 intSort(count, array);
00524 if ((count&1) == 1)
00525     median = array[count>>1];
00526 else
00527     {
00528     count >>= 1;
00529     median = (array[count] + array[count-1]) * 0.5;
00530     }
00531 return median;
00532 }
00533 
00534 
00535 struct slName *newSlName(char *name)
00536 /* Return a new name. */
00537 {
00538 struct slName *sn;
00539 if (name != NULL)
00540     {
00541     int len = strlen(name);
00542     sn = needMem(sizeof(*sn)+len);
00543     strcpy(sn->name, name);
00544     return sn;
00545     }
00546 else
00547     {
00548     AllocVar(sn);
00549     }
00550 return sn;
00551 }
00552 
00553 struct slName *slNameNewN(char *name, int size)
00554 /* Return new slName of given size. */
00555 {
00556 struct slName *sn = needMem(sizeof(*sn) + size);
00557 memcpy(sn->name, name, size);
00558 return sn;
00559 }
00560 
00561 int slNameCmpCase(const void *va, const void *vb)
00562 /* Compare two slNames, ignore case. */
00563 {
00564 const struct slName *a = *((struct slName **)va);
00565 const struct slName *b = *((struct slName **)vb);
00566 return strcasecmp(a->name, b->name);
00567 }
00568 
00569 void slNameSortCase(struct slName **pList)
00570 /* Sort slName list, ignore case. */
00571 {
00572 slSort(pList, slNameCmpCase);
00573 }
00574 
00575 int slNameCmp(const void *va, const void *vb)
00576 /* Compare two slNames. */
00577 {
00578 const struct slName *a = *((struct slName **)va);
00579 const struct slName *b = *((struct slName **)vb);
00580 return strcmp(a->name, b->name);
00581 }
00582 
00583 void slNameSort(struct slName **pList)
00584 /* Sort slName list. */
00585 {
00586 slSort(pList, slNameCmp);
00587 }
00588 
00589 boolean slNameInList(struct slName *list, char *string)
00590 /* Return true if string is in name list */
00591 {
00592 struct slName *el;
00593 for (el = list; el != NULL; el = el->next)
00594     if (sameWord(string, el->name))
00595         return TRUE;
00596 return FALSE;
00597 }
00598 
00599 void *slNameFind(void *list, char *string)
00600 /* Return first element of slName list (or any other list starting
00601  * with next/name fields) that matches string. */
00602 {
00603 struct slName *el;
00604 for (el = list; el != NULL; el = el->next)
00605     if (sameWord(string, el->name))
00606         return el;
00607 return NULL;
00608 }
00609 
00610 int slNameFindIx(struct slName *list, char *string)
00611 /* Return index of first element of slName list (or any other 
00612  * list starting with next/name fields) that matches string.
00613  * Return -1 if not found. */
00614 {
00615 struct slName *el;
00616 int ix = 0;
00617 for (el = list; el != NULL; el = el->next, ix++)
00618     if (sameString(string, el->name))
00619         return ix;
00620 return -1;
00621 }
00622 
00623 char *slNameStore(struct slName **pList, char *string)
00624 /* Put string into list if it's not there already.  
00625  * Return the version of string stored in list. */
00626 {
00627 struct slName *el;
00628 for (el = *pList; el != NULL; el = el->next)
00629     {
00630     if (sameString(string, el->name))
00631         return el->name;
00632     }
00633 el = newSlName(string);
00634 slAddHead(pList, el);
00635 return el->name;
00636 }
00637 
00638 struct slName *slNameAddHead(struct slName **pList, char *name)
00639 /* Add name to start of list and return it. */
00640 {
00641 struct slName *el = slNameNew(name);
00642 slAddHead(pList, el);
00643 return el;
00644 }
00645 
00646 struct slName *slNameAddTail(struct slName **pList, char *name)
00647 /* Add name to end of list (not efficient for long lists),
00648  * and return it. */
00649 {
00650 struct slName *el = slNameNew(name);
00651 slAddTail(pList, el);
00652 return el;
00653 }
00654 
00655 struct slName *slNameCloneList(struct slName *list)
00656 /* Return clone of list. */
00657 {
00658 struct slName *el, *newEl, *newList = NULL;
00659 for (el = list; el != NULL; el = el->next)
00660     {
00661     newEl = slNameNew(el->name);
00662     slAddHead(&newList, newEl);
00663     }
00664 slReverse(&newList);
00665 return newList;
00666 }
00667 
00668 struct slName *slNameListFromString(char *s, char delimiter)
00669 /* Return list of slNames gotten from parsing delimited string.
00670  * The final delimiter is optional. a,b,c  and a,b,c, are equivalent
00671  * for comma-delimited lists. */
00672 {
00673 char *e;
00674 struct slName *list = NULL, *el;
00675 while (s != NULL && s[0] != 0)
00676     {
00677     e = strchr(s, delimiter);
00678     if (e == NULL)
00679         el = slNameNew(s);
00680     else
00681         {
00682         el = slNameNewN(s, e-s);
00683         e += 1;
00684         }
00685     slAddHead(&list, el);
00686     s = e;
00687     }
00688 slReverse(&list);
00689 return list;
00690 }
00691 
00692 struct slName *slNameLoadReal(char *fileName)
00693 /* load file lines that are not blank or start with a '#' into a slName
00694  * list */
00695 {
00696 struct slName *lines = NULL;
00697 char *line;
00698 struct lineFile *lf = lineFileOpen(fileName, TRUE);
00699 while (lineFileNextReal(lf, &line))
00700     slSafeAddHead(&lines, slNameNew(line));
00701 lineFileClose(&lf);
00702 slReverse(&lines);
00703 return lines;
00704 }
00705 
00706 struct slRef *refOnList(struct slRef *refList, void *val)
00707 /* Return ref if val is already on list, otherwise NULL. */
00708 {
00709 struct slRef *ref;
00710 for (ref = refList; ref != NULL; ref = ref->next)
00711     if (ref->val == val)
00712         return ref;
00713 return NULL;
00714 }
00715 
00716 struct slRef *slRefNew(void *val)
00717 /* Create new slRef element. */
00718 {
00719 struct slRef *ref;
00720 AllocVar(ref);
00721 ref->val = val;
00722 return ref;
00723 }
00724 
00725 void refAdd(struct slRef **pRefList, void *val)
00726 /* Add reference to list. */
00727 {
00728 struct slRef *ref;
00729 AllocVar(ref);
00730 ref->val = val;
00731 slAddHead(pRefList, ref);
00732 }
00733 
00734 void refAddUnique(struct slRef **pRefList, void *val)
00735 /* Add reference to list if not already on list. */
00736 {
00737 if (refOnList(*pRefList, val) == NULL)
00738     {
00739     refAdd(pRefList, val);
00740     }
00741 }
00742 
00743 struct slRef *refListFromSlList(void *list)
00744 /* Make a reference list that mirrors a singly-linked list. */
00745 {
00746 struct slList *el;
00747 struct slRef *refList = NULL, *ref;
00748 for (el= list; el != NULL; el = el->next)
00749     {
00750     ref = slRefNew(el);
00751     slAddHead(&refList, ref);
00752     }
00753 slReverse(&refList);
00754 return refList;
00755 }
00756 
00757 
00758 struct slPair *slPairNew(char *name, void *val)
00759 /* Allocate new name/value pair. */
00760 {
00761 struct slPair *el;
00762 AllocVar(el);
00763 el->name = cloneString(name);
00764 el->val = val;
00765 return el;
00766 }
00767 
00768 void slPairAdd(struct slPair **pList, char *name, void *val)
00769 /* Add new slPair to head of list. */
00770 {
00771 struct slPair *el = slPairNew(name, val);
00772 slAddHead(pList, el);
00773 }
00774 
00775 void slPairFree(struct slPair **pEl)
00776 /* Free up struct and name.  (Don't free up values.) */
00777 {
00778 struct slPair *el = *pEl;
00779 if (el != NULL)
00780     {
00781     freeMem(el->name);
00782     freez(pEl);
00783     }
00784 }
00785 
00786 void slPairFreeList(struct slPair **pList)
00787 /* Free up list.  (Don't free up values.) */
00788 {
00789 struct slPair *el, *next;
00790 
00791 for (el = *pList; el != NULL; el = next)
00792     {
00793     next = el->next;
00794     slPairFree(&el);
00795     }
00796 *pList = NULL;
00797 }
00798 
00799 void slPairFreeVals(struct slPair *list)
00800 /* Free up all values on list. */
00801 {
00802 struct slPair *el;
00803 for (el = list; el != NULL; el = el->next)
00804     freez(&el->val);
00805 }
00806 
00807 void slPairFreeValsAndList(struct slPair **pList)
00808 /* Free up all values on list and list itself */
00809 {
00810 slPairFreeVals(*pList);
00811 slPairFreeList(pList);
00812 }
00813 
00814 struct slPair *slPairFind(struct slPair *list, char *name)
00815 /* Return list element of given name, or NULL if not found. */
00816 {
00817 struct slPair *el;
00818 for (el = list; el != NULL; el = el->next)
00819     if (sameString(name, el->name))
00820         break;
00821 return el;
00822 }
00823 
00824 void *slPairFindVal(struct slPair *list, char *name)
00825 /* Return value associated with name in list, or NULL if not found. */
00826 {
00827 struct slPair *el = slPairFind(list, name);
00828 if (el == NULL)
00829     return NULL;
00830 return el->val;
00831 }
00832 
00833 
00834 void gentleFree(void *pt)
00835 {
00836 if (pt != NULL) freeMem((char*)pt);
00837 }
00838 
00839 int differentWord(char *s1, char *s2)
00840 /* strcmp ignoring case - returns zero if strings are
00841  * the same (ignoring case) otherwise returns difference
00842  * between first non-matching characters. */
00843 {
00844 char c1, c2;
00845 for (;;)
00846     {
00847     c1 = toupper(*s1++);
00848     c2 = toupper(*s2++);
00849     if (c1 != c2) /* Takes care of end of string in one but not the other too */
00850         return c2-c1;
00851     if (c1 == 0)  /* Take care of end of string in both. */
00852         return 0;
00853     }
00854 }
00855 
00856 int differentStringNullOk(char *a, char *b)
00857 /* Returns 0 if two strings (either of which may be NULL)
00858  * are the same.  Otherwise it returns a positive or negative
00859  * number depending on the alphabetical order of the two
00860  * strings.
00861  * This is basically a strcmp that can handle NULLs in
00862  * the input.  If used in a sort the NULLs will end
00863  * up before any of the cases with data.   */
00864 {
00865 if (a == b)
00866     return FALSE;
00867 else if (a == NULL)
00868     return -1;
00869 else if (b == NULL)
00870     return 1;
00871 else
00872     return strcmp(a,b) != 0;
00873 }
00874 
00875 boolean startsWith(char *start,char *string)
00876 /* Returns TRUE if string begins with start. */
00877 {
00878 char c;
00879 int i;
00880 
00881 for (i=0; ;i += 1)
00882     {
00883     if ((c = start[i]) == 0)
00884         return TRUE;
00885     if (string[i] != c)
00886         return FALSE;
00887     }
00888 }
00889 
00890 boolean startsWithWord(char *firstWord, char *line)
00891 /* Return TRUE if first white-space-delimited word in line
00892  * is same as firstWord.  Comparison is case sensitive. */
00893 {
00894 int len = strlen(firstWord);
00895 int i;
00896 for (i=0; i<len; ++i)
00897    if (firstWord[i] != line[i])
00898        return FALSE;
00899 char c = line[len];
00900 return c == 0 || isspace(c);
00901 }
00902 
00903 char *rStringIn(char *needle, char *haystack)
00904 /* Return last position of needle in haystack, or NULL if it's not there. */
00905 {
00906 int nSize = strlen(needle);
00907 char *pos;
00908 for (pos = haystack + strlen(haystack) - nSize; pos >= haystack; pos -= 1)
00909     {
00910     if (memcmp(needle, pos, nSize) == 0)
00911         return pos;
00912     }
00913 return NULL;
00914 }
00915 
00916 char *stringBetween(char *start, char *end, char *haystack)
00917 /* Return string between start and end strings, or NULL if
00918  * none found.  The first such instance is returned. 
00919  * String must be freed by caller. */
00920 {
00921 char *pos, *p;
00922 int len;
00923 if ((p = stringIn(start, haystack)) != NULL)
00924     {
00925     pos = p + strlen(start);
00926     if ((p = stringIn(end, pos)) != NULL)
00927         {
00928         len = p - pos;
00929         pos = cloneMem(pos, len + 1);
00930         pos[len] = 0;
00931         return pos;
00932         }
00933     }
00934 return NULL;
00935 }
00936 
00937 boolean endsWith(char *string, char *end)
00938 /* Returns TRUE if string ends with end. */
00939 {
00940 int sLen, eLen, offset;
00941 sLen = strlen(string);
00942 eLen = strlen(end);
00943 offset = sLen - eLen;
00944 if (offset < 0)
00945     return FALSE;
00946 return sameString(string+offset, end);
00947 }
00948 
00949 char lastChar(char *s)
00950 /* Return last character in string. */
00951 {
00952 if (s == NULL || s[0] == 0)
00953     return 0;
00954 return s[strlen(s)-1];
00955 }
00956 
00957 char *memMatch(char *needle, int nLen, char *haystack, int hLen)
00958 /* Returns first place where needle (of nLen chars) matches
00959  * haystack (of hLen chars) */
00960 {
00961 char c = *needle++;
00962 nLen -= 1;
00963 hLen -= nLen;
00964 while (--hLen >= 0)
00965     {   
00966     if (*haystack++ == c && memcmp(needle, haystack, nLen) == 0)
00967         {
00968         return haystack-1;
00969         }
00970     }
00971 return NULL;
00972 }
00973 
00974 void toUpperN(char *s, int n)
00975 /* Convert a section of memory to upper case. */
00976 {
00977 int i;
00978 for (i=0; i<n; ++i)
00979     s[i] = toupper(s[i]);
00980 }
00981 
00982 void toLowerN(char *s, int n)
00983 /* Convert a section of memory to upper case. */
00984 {
00985 int i;
00986 for (i=0; i<n; ++i)
00987     s[i] = tolower(s[i]);
00988 }
00989 
00990 void toggleCase(char *s, int size)
00991 /* toggle upper and lower case chars in string. */
00992 {
00993 char c;
00994 int i;
00995 for (i=0; i<size; ++i)
00996     {
00997     c = s[i];
00998     if (isupper(c))
00999         c = tolower(c);
01000     else if (islower(c))
01001         c = toupper(c);
01002     s[i] = c;
01003     }
01004 }
01005 
01006 
01007 void touppers(char *s)
01008 /* Convert entire string to upper case. */
01009 {
01010 char c;
01011 for (;;)
01012     {
01013     if ((c = *s) == 0) break;
01014     *s++ = toupper(c);
01015     }
01016 }
01017 
01018 char *replaceChars(char *string, char *old, char *new)
01019 /*
01020   Replaces the old with the new. The old and new string need not be of equal size
01021  Can take any length string.
01022  Return value needs to be freeMem'd.
01023 */
01024 {
01025 int numTimes = 0;
01026 int oldLen = strlen(old);
01027 int newLen = strlen(new);
01028 int strLen = 0;
01029 char *result = NULL;
01030 char *ptr = strstr(string, old);
01031 char *resultPtr = NULL;
01032 
01033 while(NULL != ptr)
01034     {
01035     numTimes++;
01036     ptr += oldLen;
01037     ptr = strstr(ptr, old);
01038     }
01039 strLen = max(strlen(string) + (numTimes * (newLen - oldLen)), strlen(string));
01040 result = needMem(strLen + 1);
01041 
01042 ptr = strstr(string, old);
01043 resultPtr = result;
01044 while(NULL != ptr)
01045     {
01046     strLen = ptr - string;
01047     strcpy(resultPtr, string);
01048     string = ptr + oldLen;
01049 
01050     resultPtr += strLen;
01051     strcpy(resultPtr, new);
01052     resultPtr += newLen;
01053     ptr = strstr(string, old);
01054     }
01055 
01056 strcpy(resultPtr, string);
01057 return result;
01058 }
01059 
01060 void tolowers(char *s)
01061 /* Convert entire string to lower case */
01062 {
01063 char c;
01064 for (;;)
01065     {
01066     if ((c = *s) == 0) break;
01067     *s++ = tolower(c);
01068     }
01069 }
01070 
01071 void subChar(char *s, char oldChar, char newChar)
01072 /* Substitute newChar for oldChar throughout string s. */
01073 {
01074 char c;
01075 for (;;)
01076     {
01077     c = *s;
01078     if (c == 0)
01079         break;
01080     if (c == oldChar)
01081         *s = newChar;
01082     ++s;
01083     }
01084 }
01085 
01086 void stripChar(char *s, char c)
01087 /* Remove all occurences of c from s. */
01088 {
01089 char *in = s, *out = s;
01090 char b;
01091 
01092 for (;;)
01093     {
01094     b = *out = *in++;
01095     if (b == 0)
01096        break;
01097     if (b != c)
01098        ++out;
01099     }
01100 }
01101 
01102 void stripString(char *s, char *strip)
01103 /* Remove all occurences of strip from s. */
01104 {
01105 char c, *in = s, *out = s;
01106 int stripSize = strlen(strip);
01107 char stripFirst = strip[0];
01108 
01109 while ((c = *in) != 0)
01110     {
01111     c = *in;
01112     if (c == stripFirst)
01113         {
01114         if (startsWith(strip, in))
01115             {
01116             in += stripSize;
01117             continue;
01118             }
01119         }
01120     *out = c;
01121     ++out;
01122     ++in;
01123     }
01124 *out = 0;
01125 }
01126 
01127 int countChars(char *s, char c)
01128 /* Return number of characters c in string s. */
01129 {
01130 char a;
01131 int count = 0;
01132 while ((a = *s++) != 0)
01133     if (a == c)
01134         ++count;
01135 return count;
01136 }
01137 
01138 int countCharsN(char *s, char c, int size)
01139 /* Return number of characters c in string s of given size. */
01140 {
01141 int i;
01142 int count = 0;
01143 for (i=0; i<size; ++i)
01144     if (s[i] == c)
01145         ++count;
01146 return count;
01147 }
01148 
01149 int countLeadingChars(char *s, char c)
01150 /* Count number of characters c at start of string. */
01151 {
01152 int count = 0;
01153 while (*s++ == c)
01154    ++count;
01155 return count;
01156 }
01157 
01158 int countSame(char *a, char *b)
01159 /* Count number of characters that from start in a,b that are same. */
01160 {
01161 char c;
01162 int i;
01163 int count = 0;
01164 for (i=0; ; ++i)
01165    {
01166    c = a[i];
01167    if (b[i] != c)
01168        break;
01169    if (c == 0)
01170        break;
01171    ++count;
01172    }
01173 return count;
01174 }
01175 
01176 
01177 /* int chopString(in, sep, outArray, outSize); */
01178 /* This chops up the input string (cannabilizing it)
01179  * into an array of zero terminated strings in
01180  * outArray.  It returns the number of strings. 
01181  * If you pass in NULL for outArray, it will just
01182  * return the number of strings that it *would*
01183  * chop. */
01184 int chopString(char *in, char *sep, char *outArray[], int outSize)
01185 {
01186 int recordCount = 0;
01187 
01188 for (;;)
01189     {
01190     if (outArray != NULL && recordCount >= outSize)
01191         break;
01192     /* Skip initial separators. */
01193     in += strspn(in, sep);
01194     if (*in == 0)
01195         break;
01196     if (outArray != NULL)
01197         outArray[recordCount] = in;
01198     recordCount += 1;
01199     in += strcspn(in, sep);
01200     if (*in == 0)
01201         break;
01202     if (outArray != NULL)
01203         *in = 0;
01204     in += 1;
01205     }
01206 return recordCount;
01207 }
01208 
01209 int chopByWhite(char *in, char *outArray[], int outSize)
01210 /* Like chopString, but specialized for white space separators. */
01211 {
01212 int recordCount = 0;
01213 char c;
01214 for (;;)
01215     {
01216     if (outArray != NULL && recordCount >= outSize)
01217         break;
01218 
01219     /* Skip initial separators. */
01220     while (isspace(*in)) ++in;
01221     if (*in == 0)
01222         break;
01223     
01224     /* Store start of word and look for end of word. */    
01225     if (outArray != NULL)
01226         outArray[recordCount] = in;
01227     recordCount += 1;
01228     for (;;)
01229         {
01230         if ((c = *in) == 0)
01231             break;
01232         if (isspace(c))
01233             break;
01234         ++in;
01235         }
01236     if (*in == 0)
01237         break;
01238  
01239     /* Tag end of word with zero. */
01240     if (outArray != NULL)
01241         *in = 0;
01242     /* And skip over the zero. */
01243     in += 1;
01244     }
01245 return recordCount;
01246 }
01247 
01248 int chopByChar(char *in, char chopper, char *outArray[], int outSize)
01249 /* Chop based on a single character. */
01250 {
01251 int i;
01252 char c;
01253 if (*in == 0)
01254     return 0;
01255 for (i=0; (i<outSize) || (outArray==NULL); ++i)
01256     {
01257     if (outArray != NULL)
01258         outArray[i] = in;
01259     for (;;)
01260         {
01261         if ((c = *in++) == 0)
01262             return i+1;
01263         else if (c == chopper)
01264             {
01265             if (outArray != NULL)
01266                 in[-1] = 0;
01267             break;
01268             }
01269         }
01270     }
01271 return i;
01272 }
01273 
01274 char crLfChopper[] = "\n\r";
01275 char whiteSpaceChopper[] = " \t\n\r";
01276 
01277 
01278 char *skipLeadingSpaces(char *s)
01279 /* Return first non-white space. */
01280 {
01281 char c;
01282 if (s == NULL) return NULL;
01283 for (;;)
01284     {
01285     c = *s;
01286     if (!isspace(c))
01287         return s;
01288     ++s;
01289     }
01290 }
01291 
01292 /* Return first white space or NULL if none.. */
01293 char *skipToSpaces(char *s)
01294 {
01295 char c;
01296 if (s == NULL)
01297     return NULL;
01298 for (;;)
01299     {
01300     c = *s;
01301     if (c == 0)
01302         return NULL;
01303     if (isspace(c))
01304         return s;
01305     ++s;
01306     }
01307 }
01308 
01309 
01310 
01311 void eraseTrailingSpaces(char *s)
01312 /* Replace trailing white space with zeroes. */
01313 {
01314 int len = strlen(s);
01315 int i;
01316 char c;
01317 
01318 for (i=len-1; i>=0; --i)
01319     {
01320     c = s[i];
01321     if (isspace(c))
01322         s[i] = 0;
01323     else
01324         break;
01325     }
01326 }
01327 
01328 /* Remove white space from a string */
01329 void eraseWhiteSpace(char *s)
01330 {
01331 char *in, *out;
01332 char c;
01333 
01334 in = out = s;
01335 for (;;)
01336     {
01337     c = *in++;
01338     if (c == 0) 
01339         break;
01340     if (!isspace(c))
01341         *out++ = c;
01342     }
01343 *out++ = 0;
01344 }
01345 
01346 char *trimSpaces(char *s)
01347 /* Remove leading and trailing white space. */
01348 {
01349 if (s != NULL)
01350     {
01351     s = skipLeadingSpaces(s);
01352     eraseTrailingSpaces(s);
01353     }
01354 return s;
01355 }
01356 
01357 void spaceOut(FILE *f, int count)
01358 /* Put out some spaces to file. */
01359 {
01360 while (--count >= 0)
01361     fputc(' ', f);
01362 }
01363 
01364 void starOut(FILE *f, int count)
01365 /* Put out some asterisks to file. */
01366 {
01367 while (--count >= 0)
01368     fputc('*', f);
01369 }
01370 
01371 boolean hasWhiteSpace(char *s)
01372 /* Return TRUE if there is white space in string. */
01373 {
01374 char c;
01375 while ((c = *s++) != 0)
01376     if (isspace(c))
01377         return TRUE;
01378 return FALSE;
01379 }
01380 
01381 char *firstWordInLine(char *line)
01382 /* Returns first word in line if any (white space separated).
01383  * Puts 0 in place of white space after word. */
01384 {
01385 char *e;
01386 line = skipLeadingSpaces(line);
01387 if ((e = skipToSpaces(line)) != NULL)
01388     *e = 0;
01389 return line;
01390 }
01391 
01392 char *lastWordInLine(char *line)
01393 /* Returns last word in line if any (white space separated).
01394  * Returns NULL if string is empty.  Removes any terminating white space
01395  * from line. */
01396 {
01397 char *s = line;
01398 char *word = NULL, *wordEnd = NULL;
01399 for (;;)
01400     {
01401     s = skipLeadingSpaces(s);
01402     if (s == NULL || s[0] == 0)
01403         break;
01404     word = s;
01405     s = wordEnd = skipToSpaces(s);
01406     if (s == NULL)
01407         break;
01408     }
01409 if (wordEnd != NULL)
01410     *wordEnd = 0;
01411 return word;
01412 }
01413 
01414 char *nextWord(char **pLine)
01415 /* Return next word in *pLine and advance *pLine to next
01416  * word. */
01417 {
01418 char *s = *pLine, *e;
01419 if (s == NULL || s[0] == 0)
01420     return NULL;
01421 s = skipLeadingSpaces(s);
01422 if (s[0] == 0)
01423     return NULL;
01424 e = skipToSpaces(s);
01425 if (e != NULL)
01426     *e++ = 0;
01427 *pLine = e;
01428 return s;
01429 }
01430 
01431 char *nextTabWord(char **pLine)
01432 /* Return next tab-separated word. */
01433 {
01434 char *s = *pLine;
01435 char *e;
01436 if (s == NULL || *s == '\n' || *s == 0)
01437     {
01438     *pLine = NULL;
01439     return NULL;
01440     }
01441 e = strchr(s, '\t');
01442 if (e == NULL)
01443     {
01444     e = strchr(s, '\n');
01445     if (e != NULL)
01446         *e = 0;
01447     *pLine = NULL;
01448     }
01449 else
01450     {
01451     *e++ = 0;
01452     *pLine = e;
01453     }
01454 return s;
01455 }
01456 
01457 int stringArrayIx(char *string, char *array[], int arraySize)
01458 /* Return index of string in array or -1 if not there. */
01459 {
01460 int i;
01461 for (i=0; i<arraySize; ++i)
01462     if (!differentWord(array[i], string))
01463         return i;
01464 return -1;
01465 }
01466 
01467 int ptArrayIx(void *pt, void *array, int arraySize)
01468 /* Return index of pt in array or -1 if not there. */
01469 {
01470 int i;
01471 void **a = array;
01472 for (i=0; i<arraySize; ++i)
01473     {
01474     if (pt == a[i])
01475         return i;
01476     }
01477 return -1;
01478 }
01479 
01480 
01481 
01482 FILE *mustOpen(char *fileName, char *mode)
01483 /* Open a file - or squawk and die. */
01484 {
01485 FILE *f;
01486 
01487 if (sameString(fileName, "stdin"))
01488     return stdin;
01489 if (sameString(fileName, "stdout"))
01490     return stdout;
01491 if ((f = fopen(fileName, mode)) == NULL)
01492     {
01493     char *modeName = "";
01494     if (mode)
01495         {
01496         if (mode[0] == 'r')
01497             modeName = " to read";
01498         else if (mode[0] == 'w')
01499             modeName = " to write";
01500         else if (mode[0] == 'a')
01501             modeName = " to append";
01502         }
01503     errAbort("Can't open %s%s: %s", fileName, modeName, strerror(errno));
01504     }
01505 return f;
01506 }
01507 
01508 void mustWrite(FILE *file, void *buf, size_t size)
01509 /* Write to a file or squawk and die. */
01510 {
01511 if (size != 0 && fwrite(buf, size, 1, file) != 1)
01512     {
01513     errAbort("Error writing %lld bytes: %s\n", (long long)size, strerror(ferror(file)));
01514     }
01515 }
01516 
01517 
01518 void mustRead(FILE *file, void *buf, size_t size)
01519 /* Read from a file or squawk and die. */
01520 {
01521 if (size != 0 && fread(buf, size, 1, file) != 1)
01522     errAbort("Error reading %lld bytes: %s", (long long)size, strerror(ferror(file)));
01523 }
01524 
01525 void writeString(FILE *f, char *s)
01526 /* Write a 255 or less character string to a file.
01527  * This will write the length of the string in the first
01528  * byte then the string itself. */
01529 {
01530 UBYTE bLen;
01531 int len = strlen(s);
01532 
01533 if (len > 255)
01534     {
01535     warn("String too long in writeString (%d chars):\n%s", len, s);
01536     len = 255;
01537     }
01538 bLen = len;
01539 writeOne(f, bLen);
01540 mustWrite(f, s, len);
01541 }
01542 
01543 char *readString(FILE *f)
01544 /* Read a string (written with writeString) into
01545  * memory.  freeMem the result when done. */
01546 {
01547 UBYTE bLen;
01548 int len;
01549 char *s;
01550 
01551 if (!readOne(f, bLen))
01552     return NULL;
01553 len = bLen;
01554 s = needMem(len+1);
01555 if (len > 0)
01556     mustRead(f, s, len);
01557 return s;
01558 }
01559 
01560 char *mustReadString(FILE *f)
01561 /* Read a string.  Squawk and die at EOF or if any problem. */
01562 {
01563 char *s = readString(f);
01564 if (s == NULL)
01565     errAbort("Couldn't read string");
01566 return s;
01567 }
01568 
01569  
01570 boolean fastReadString(FILE *f, char buf[256])
01571 /* Read a string into buffer, which must be long enough
01572  * to hold it.  String is in 'writeString' format. */
01573 {
01574 UBYTE bLen;
01575 int len;
01576 if (!readOne(f, bLen))
01577     return FALSE;
01578 if ((len = bLen)> 0)
01579     mustRead(f, buf, len);
01580 buf[len] = 0;
01581 return TRUE;
01582 } 
01583 
01584 void writeBits64(FILE *f, bits64 x)
01585 /* Write out 64 bit number in manner that is portable across architectures */
01586 {
01587 int i;
01588 UBYTE buf[8];
01589 for (i=7; i>=0; --i)
01590     {
01591     buf[i] = (UBYTE)(x&0xff);
01592     x >>= 8;
01593     }
01594 mustWrite(f, buf, 8);
01595 }
01596 
01597 bits64 readBits64(FILE *f)
01598 /* Write out 64 bit number in manner that is portable across architectures */
01599 {
01600 int i;
01601 UBYTE buf[8];
01602 bits64 x = 0;
01603 mustRead(f, buf, 8);
01604 for (i=0; i<8; ++i)
01605     {
01606     x <<= 8;
01607     x |= buf[i];
01608     }
01609 return x;
01610 }
01611 
01612 
01613 char *addSuffix(char *head, char *suffix)
01614 /* Return a needMem'd string containing "headsuffix". Should be free'd
01615  when finished. */
01616 {
01617 char *ret = NULL;
01618 int size = strlen(head) + strlen(suffix) +1;
01619 ret = needMem(sizeof(char)*size);
01620 snprintf(ret, size, "%s%s", head, suffix);
01621 return ret;
01622 }
01623 
01624 void chopSuffix(char *s)
01625 /* Remove suffix (last . in string and beyond) if any. */
01626 {
01627 char *e = strrchr(s, '.');
01628 if (e != NULL)
01629     *e = 0;
01630 }
01631     
01632 void chopSuffixAt(char *s, char c)
01633 /* Remove end of string from first occurrence of char c. 
01634  * chopSuffixAt(s, '.') is equivalent to regular chopSuffix. */
01635 {
01636 char *e = strrchr(s, c);
01637 if (e != NULL)
01638     *e = 0;
01639 }
01640 
01641 char *chopPrefixAt(char *s, char c)
01642 /* Like chopPrefix, but can chop on any character, not just '.' */
01643 {
01644 char *e = strchr(s, c);
01645 if (e == NULL) return s;
01646 *e++ = 0;
01647 return e;
01648 }
01649 
01650 char *chopPrefix(char *s)
01651 /* This will replace the first '.' in a string with
01652  * 0, and return the character after this.  If there
01653  * is no '.' in the string this will just return the
01654  * unchanged s passed in. */
01655 {
01656 return chopPrefixAt(s, '.');
01657 }
01658 
01659 
01660     
01661 boolean carefulCloseWarn(FILE **pFile)
01662 /* Close file if open and null out handle to it. 
01663  * Return FALSE and print a warning message if there
01664  * is a problem.*/
01665 {
01666 FILE *f;
01667 boolean ok = TRUE;
01668 if ((pFile != NULL) && ((f = *pFile) != NULL))
01669     {
01670     if (f != stdin && f != stdout)
01671         {
01672         if (fclose(f) != 0)
01673             {
01674             errnoWarn("fclose failed");
01675             ok = FALSE;
01676             }
01677         }
01678     *pFile = NULL;
01679     }
01680 return ok;
01681 }
01682 
01683 void carefulClose(FILE **pFile)
01684 /* Close file if open and null out handle to it. 
01685  * Warn and abort if there's a problem. */
01686 {
01687 if (!carefulCloseWarn(pFile))
01688     noWarnAbort();
01689 }
01690         
01691 char *firstWordInFile(char *fileName, char *wordBuf, int wordBufSize)
01692 /* Read the first word in file into wordBuf. */
01693 {
01694 FILE *f = mustOpen(fileName, "r");
01695 fgets(wordBuf, wordBufSize, f);
01696 fclose(f);
01697 return trimSpaces(wordBuf);
01698 }
01699 
01700 int roundingScale(int a, int p, int q)
01701 /* returns rounded a*p/q */
01702 {
01703 if (a > 100000 || p > 100000)
01704     {
01705     double x = a;
01706     x *= p;
01707     x /= q;
01708     return round(x);
01709     }
01710 else
01711     return (a*p + q/2)/q;
01712 }
01713 
01714 int intAbs(int a)
01715 /* Return integer absolute value */
01716 {
01717 return (a >= 0 ? a : -a);
01718 }
01719 
01720 int  rangeIntersection(int start1, int end1, int start2, int end2)
01721 /* Return amount of bases two ranges intersect over, 0 or negative if no
01722  * intersection. */
01723 {
01724 int s = max(start1,start2);
01725 int e = min(end1,end2);
01726 return e-s;
01727 }
01728 
01729 int positiveRangeIntersection(int start1, int end1, int start2, int end2)
01730 /* Return number of bases in intersection of two ranges, or
01731  * zero if they don't intersect. */
01732 {
01733 int ret = rangeIntersection(start1,end1,start2,end2);
01734 if (ret < 0)
01735     ret = 0;
01736 return ret;
01737 }
01738 
01739 bits32 byteSwap32(bits32 a)
01740 /* Return byte-swapped version of a */
01741 {
01742 union {bits32 whole; UBYTE bytes[4];} u,v;
01743 u.whole = a;
01744 v.bytes[0] = u.bytes[3];
01745 v.bytes[1] = u.bytes[2];
01746 v.bytes[2] = u.bytes[1];
01747 v.bytes[3] = u.bytes[0];
01748 return v.whole;
01749 }
01750 
01751 void removeReturns(char *dest, char *src) 
01752 /* Removes the '\r' character from a string.
01753  * The source and destination strings can be the same, if there are 
01754  * no other threads */
01755 {
01756 int i = 0;
01757 int j = 0;
01758 
01759 /* until the end of the string */
01760 for (;;)
01761     {
01762     /* skip the returns */
01763     while(src[j] == '\r')
01764         j++;
01765 
01766     /* copy the characters */
01767     dest[i] = src[j];
01768 
01769     /* check to see if done */
01770     if(src[j] == '\0')
01771         break;
01772 
01773     /* advance the counters */
01774     i++;
01775     j++;
01776     }
01777 }
01778 
01779 char* readLine(FILE* fh)
01780 /* Read a line of any size into dynamic memory, return null on EOF */
01781 {
01782 int bufCapacity = 256;
01783 int bufSize = 0;
01784 char* buf = needMem(bufCapacity);
01785 int ch;
01786 
01787 /* loop until EOF of EOLN */
01788 while (((ch = getc(fh)) != EOF) && (ch != '\n'))
01789     {
01790     /* expand if almost full, always keep one extra char for
01791      * zero termination */
01792     if (bufSize >= bufCapacity-2)
01793         {
01794         bufCapacity *= 2;
01795         buf = realloc(buf, bufCapacity);
01796         if (buf == NULL)
01797             {
01798             errAbort("Out of memory in readline - request size %d bytes", bufCapacity);
01799             }
01800         }
01801     buf[bufSize++] = ch;
01802     }
01803 
01804 /* only return EOF if no data was read */
01805 if ((ch == EOF) && (bufSize == 0))
01806     {
01807     freeMem(buf);
01808     return NULL;
01809     }
01810 buf[bufSize] = '\0';
01811 return buf;
01812 }
01813 
01814 boolean fileExists(char *fileName)
01815 /* Return TRUE if file exists (may replace this with non-
01816  * portable faster way some day). */
01817 {
01818 /* To make piping easier stdin and stdout always exist. */
01819 if (sameString(fileName, "stdin")) return TRUE;
01820 if (sameString(fileName, "stdout")) return TRUE;
01821 
01822 return fileSize(fileName) != -1;
01823 }
01824 
01825 /*
01826  Friendly name for strstrNoCase
01827 */
01828 char *containsStringNoCase(char *haystack, char *needle)
01829 {
01830 return strstrNoCase(haystack, needle);
01831 }
01832 
01833 char *strstrNoCase(char *haystack, char *needle)
01834 /*
01835   A case-insensitive strstr function
01836 Will also robustly handle null strings
01837 param haystack - The string to be searched
01838 param needle - The string to look for in the haystack string
01839 
01840 return - The position of the first occurence of the desired substring
01841 or -1 if it is not found
01842  */
01843 {
01844 char *haystackCopy = NULL;
01845 char *needleCopy = NULL;
01846 int index = 0;
01847 int haystackLen = 0;
01848 int needleLen = 0;
01849 char *p, *q;
01850 
01851 if (NULL == haystack || NULL == needle) 
01852     {
01853     return NULL;
01854     }
01855 
01856 haystackLen = strlen(haystack);
01857 needleLen = strlen(needle);
01858 
01859 haystackCopy = (char*) needMem(haystackLen + 1);
01860 needleCopy = (char*) needMem(needleLen + 1);
01861 
01862 for(index = 0; index < haystackLen;  index++)
01863     {
01864     haystackCopy[index] = tolower(haystack[index]);
01865     }
01866 haystackCopy[haystackLen] = 0; /* Null terminate */
01867 
01868 for(index = 0; index < needleLen;  index++)
01869     {
01870     needleCopy[index] = tolower(needle[index]);
01871     }
01872 needleCopy[needleLen] = 0; /* Null terminate */
01873 
01874 p=strstr(haystackCopy, needleCopy);
01875 q=haystackCopy;
01876  
01877 freeMem(haystackCopy);
01878 freeMem(needleCopy);
01879 
01880 if(p==NULL) return NULL;
01881 
01882 return p-q+haystack;
01883 }
01884 
01885 int vasafef(char* buffer, int bufSize, char *format, va_list args)
01886 /* Format string to buffer, vsprintf style, only with buffer overflow
01887  * checking.  The resulting string is always terminated with zero byte. */
01888 {
01889 int sz = vsnprintf(buffer, bufSize, format, args);
01890 /* note that some version return -1 if too small */
01891 if ((sz < 0) || (sz >= bufSize))
01892     errAbort("buffer overflow, size %d, format: %s", bufSize, format);
01893 return sz;
01894 }
01895 
01896 int safef(char* buffer, int bufSize, char *format, ...)
01897 /* Format string to buffer, vsprintf style, only with buffer overflow
01898  * checking.  The resulting string is always terminated with zero byte. */
01899 {
01900 int sz;
01901 va_list args;
01902 va_start(args, format);
01903 sz = vasafef(buffer, bufSize, format, args);
01904 va_end(args);
01905 return sz;
01906 }
01907 
01908 void safecpy(char *buf, size_t bufSize, const char *src)
01909 /* copy a string to a buffer, with bounds checking.*/
01910 {
01911 size_t slen = strlen(src);
01912 if (slen > bufSize-1)
01913     errAbort("buffer overflow, size %lld, string size: %lld", (long long)bufSize, (long long)slen);
01914 strcpy(buf, src);
01915 }
01916 
01917 void safencpy(char *buf, size_t bufSize, const char *src, size_t n)
01918 /* copy n characters from a string to a buffer, with bounds checking.
01919  * Unlike strncpy, always null terminates the result */
01920 {
01921 if (n > bufSize-1)
01922     errAbort("buffer overflow, size %lld, substring size: %lld", (long long)bufSize, (long long)n);
01923 size_t slen = strlen(src);
01924 if (slen > n)
01925     slen = n;
01926 strncpy(buf, src, n);
01927 buf[slen] = '\0';
01928 }
01929 
01930 void safecat(char *buf, size_t bufSize, const char *src)
01931 /* Append  a string to a buffer, with bounds checking.*/
01932 {
01933 size_t blen = strlen(buf);
01934 size_t slen = strlen(src);
01935 if (blen+slen > bufSize-1)
01936     errAbort("buffer overflow, size %lld, new string size: %lld", (long long)bufSize, (long long)(blen+slen));
01937 strcat(buf, src);
01938 }
01939 
01940 void safencat(char *buf, size_t bufSize, const char *src, size_t n)
01941 /* append n characters from a string to a buffer, with bounds checking. */
01942 {
01943 size_t blen = strlen(buf);
01944 if (blen+n > bufSize-1)
01945     errAbort("buffer overflow, size %lld, new string size: %lld", (long long)bufSize, (long long)(blen+n));
01946 size_t slen = strlen(src);
01947 if (slen > n)
01948     slen = n;
01949 strncat(buf, src, n);
01950 buf[blen+slen] = '\0';
01951 }
01952 
01953 
01954 static char *naStr = "n/a";
01955 static char *emptyStr = "";
01956 
01957 char *naForNull(char *s)
01958 /* Return 'n/a' if s is NULL, otherwise s. */
01959 {
01960 if (s == NULL) 
01961    s = naStr;
01962 return s;
01963 }
01964 
01965 char *naForEmpty(char *s)
01966 /* Return n/a if s is "" or NULL, otherwise s. */
01967 {
01968 if (s == NULL || s[0] == 0)
01969     s = naStr;
01970 return s;
01971 }
01972 
01973 char *emptyForNull(char *s)
01974 /* Return "" if s is NULL, otherwise s. */
01975 {
01976 if (s == NULL)
01977    s = emptyStr;
01978 return s;
01979 }
01980 
01981 char *nullIfAllSpace(char *s)
01982 /* Return NULL if s is all spaces, otherwise s. */
01983 {
01984 s = skipLeadingSpaces(s);
01985 if (s != NULL)
01986     if (s[0] == 0)
01987         s = NULL;
01988 return s;
01989 }
01990 
01991 char *trueFalseString(boolean b)
01992 /* Return "true" or "false" */
01993 {
01994 return (b ? "true" : "false");
01995 }
01996 
01997 void uglyTime(char *label, ...)
01998 /* Print label and how long it's been since last call.  Call with 
01999  * a NULL label to initialize. */
02000 {
02001 static long lastTime = 0;
02002 long time = clock1000();
02003 va_list args;
02004 va_start(args, label);
02005 if (label != NULL)
02006     {
02007     vfprintf(stdout, label, args);
02008     fprintf(stdout, ": %ld millis<BR>\n", time - lastTime);
02009     }
02010 lastTime = time;
02011 va_end(args);
02012 }
02013 
02014 void makeDirs(char* path)
02015 /* make a directory, including parent directories */
02016 {
02017 char pathBuf[PATH_LEN];
02018 char* next = pathBuf;
02019 
02020 strcpy(pathBuf, path);
02021 if (*next == '/')
02022     next++;
02023 
02024 while((*next != '\0')
02025       && (next = strchr(next, '/')) != NULL)
02026     {
02027     *next = '\0';
02028     makeDir(pathBuf);
02029     *next = '/';
02030     next++;
02031     }
02032 makeDir(pathBuf);
02033 }
02034 
02035 char *skipNumeric(char *s)
02036 /* Return first char of s that's not a digit */
02037 {
02038 while (isdigit(*s))
02039    ++s;
02040 return s;
02041 }
02042 
02043 char *skipToNumeric(char *s)
02044 /* skip up to where numeric digits appear */
02045 {
02046 while (*s != 0 && !isdigit(*s))
02047     ++s;
02048 return s;
02049 }
02050 
02051 char *splitOffNonNumeric(char *s)
02052 /* Split off non-numeric part, e.g. mm of mm8. Result should be freed when done */
02053 {
02054 return cloneStringZ(s,skipToNumeric(s)-s);
02055 }
02056 
02057 char *splitOffNumber(char *db)
02058 /* Split off number part, e.g. 8 of mm8. Result should be freed when done */
02059 {
02060 return cloneString(skipToNumeric(db));
02061 }

Generated on Tue Dec 25 18:39:30 2007 for blat by  doxygen 1.5.2