00001
00002
00003
00004
00005
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
00016 {
00017 void *newPt = needLargeMem(size);
00018 memcpy(newPt, pt, size);
00019 return newPt;
00020 }
00021
00022 char *cloneStringZ(char *s, int size)
00023
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
00033 {
00034 if (s == NULL)
00035 return NULL;
00036 else
00037 return cloneStringZ(s, strlen(s));
00038 }
00039
00040 char *cloneLongString(char *s)
00041
00042 {
00043 size_t size = strlen(s);
00044 return cloneMem(s, size+1);
00045 }
00046
00047
00048
00049 void zeroBytes(void *vpt, int count)
00050 {
00051 char *pt = (char*)vpt;
00052 while (--count>=0)
00053 *pt++=0;
00054 }
00055
00056
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
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
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
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
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
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
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
00159
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
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
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
00195
00196
00197
00198
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
00214
00215
00216
00217
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
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
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
00267
00268
00269
00270
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
00286
00287
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
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
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
00351
00352
00353
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
00373
00374
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
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
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
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
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
00437 {
00438 if (count > 1)
00439 qsort(array, count, sizeof(array[0]), doubleCmp);
00440 }
00441
00442 double doubleMedian(int count, double *array)
00443
00444
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
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
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
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
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
00513 {
00514 if (count > 1)
00515 qsort(array, count, sizeof(array[0]), intCmp);
00516 }
00517
00518 int intMedian(int count, int *array)
00519
00520
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
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
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
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
00571 {
00572 slSort(pList, slNameCmpCase);
00573 }
00574
00575 int slNameCmp(const void *va, const void *vb)
00576
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
00585 {
00586 slSort(pList, slNameCmp);
00587 }
00588
00589 boolean slNameInList(struct slName *list, char *string)
00590
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
00601
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
00612
00613
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
00625
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
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
00648
00649 {
00650 struct slName *el = slNameNew(name);
00651 slAddTail(pList, el);
00652 return el;
00653 }
00654
00655 struct slName *slNameCloneList(struct slName *list)
00656
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
00670
00671
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
00694
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
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
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
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
00736 {
00737 if (refOnList(*pRefList, val) == NULL)
00738 {
00739 refAdd(pRefList, val);
00740 }
00741 }
00742
00743 struct slRef *refListFromSlList(void *list)
00744
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
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
00770 {
00771 struct slPair *el = slPairNew(name, val);
00772 slAddHead(pList, el);
00773 }
00774
00775 void slPairFree(struct slPair **pEl)
00776
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
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
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
00809 {
00810 slPairFreeVals(*pList);
00811 slPairFreeList(pList);
00812 }
00813
00814 struct slPair *slPairFind(struct slPair *list, char *name)
00815
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
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
00841
00842
00843 {
00844 char c1, c2;
00845 for (;;)
00846 {
00847 c1 = toupper(*s1++);
00848 c2 = toupper(*s2++);
00849 if (c1 != c2)
00850 return c2-c1;
00851 if (c1 == 0)
00852 return 0;
00853 }
00854 }
00855
00856 int differentStringNullOk(char *a, char *b)
00857
00858
00859
00860
00861
00862
00863
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
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
00892
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
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
00918
00919
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
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
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
00959
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
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
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
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
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
01021
01022
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
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
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
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
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
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
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
01151 {
01152 int count = 0;
01153 while (*s++ == c)
01154 ++count;
01155 return count;
01156 }
01157
01158 int countSame(char *a, char *b)
01159
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
01178
01179
01180
01181
01182
01183
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
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
01211 {
01212 int recordCount = 0;
01213 char c;
01214 for (;;)
01215 {
01216 if (outArray != NULL && recordCount >= outSize)
01217 break;
01218
01219
01220 while (isspace(*in)) ++in;
01221 if (*in == 0)
01222 break;
01223
01224
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
01240 if (outArray != NULL)
01241 *in = 0;
01242
01243 in += 1;
01244 }
01245 return recordCount;
01246 }
01247
01248 int chopByChar(char *in, char chopper, char *outArray[], int outSize)
01249
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
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
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
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
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
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
01359 {
01360 while (--count >= 0)
01361 fputc(' ', f);
01362 }
01363
01364 void starOut(FILE *f, int count)
01365
01366 {
01367 while (--count >= 0)
01368 fputc('*', f);
01369 }
01370
01371 boolean hasWhiteSpace(char *s)
01372
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
01383
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
01394
01395
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
01416
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
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
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
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
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
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
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
01527
01528
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
01545
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
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
01572
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
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
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
01615
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
01626 {
01627 char *e = strrchr(s, '.');
01628 if (e != NULL)
01629 *e = 0;
01630 }
01631
01632 void chopSuffixAt(char *s, char c)
01633
01634
01635 {
01636 char *e = strrchr(s, c);
01637 if (e != NULL)
01638 *e = 0;
01639 }
01640
01641 char *chopPrefixAt(char *s, char c)
01642
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
01652
01653
01654
01655 {
01656 return chopPrefixAt(s, '.');
01657 }
01658
01659
01660
01661 boolean carefulCloseWarn(FILE **pFile)
01662
01663
01664
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
01685
01686 {
01687 if (!carefulCloseWarn(pFile))
01688 noWarnAbort();
01689 }
01690
01691 char *firstWordInFile(char *fileName, char *wordBuf, int wordBufSize)
01692
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
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
01716 {
01717 return (a >= 0 ? a : -a);
01718 }
01719
01720 int rangeIntersection(int start1, int end1, int start2, int end2)
01721
01722
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
01731
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
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
01753
01754
01755 {
01756 int i = 0;
01757 int j = 0;
01758
01759
01760 for (;;)
01761 {
01762
01763 while(src[j] == '\r')
01764 j++;
01765
01766
01767 dest[i] = src[j];
01768
01769
01770 if(src[j] == '\0')
01771 break;
01772
01773
01774 i++;
01775 j++;
01776 }
01777 }
01778
01779 char* readLine(FILE* fh)
01780
01781 {
01782 int bufCapacity = 256;
01783 int bufSize = 0;
01784 char* buf = needMem(bufCapacity);
01785 int ch;
01786
01787
01788 while (((ch = getc(fh)) != EOF) && (ch != '\n'))
01789 {
01790
01791
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
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
01816
01817 {
01818
01819 if (sameString(fileName, "stdin")) return TRUE;
01820 if (sameString(fileName, "stdout")) return TRUE;
01821
01822 return fileSize(fileName) != -1;
01823 }
01824
01825
01826
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
01836
01837
01838
01839
01840
01841
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;
01867
01868 for(index = 0; index < needleLen; index++)
01869 {
01870 needleCopy[index] = tolower(needle[index]);
01871 }
01872 needleCopy[needleLen] = 0;
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
01887
01888 {
01889 int sz = vsnprintf(buffer, bufSize, format, args);
01890
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
01898
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
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
01919
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
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
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
01959 {
01960 if (s == NULL)
01961 s = naStr;
01962 return s;
01963 }
01964
01965 char *naForEmpty(char *s)
01966
01967 {
01968 if (s == NULL || s[0] == 0)
01969 s = naStr;
01970 return s;
01971 }
01972
01973 char *emptyForNull(char *s)
01974
01975 {
01976 if (s == NULL)
01977 s = emptyStr;
01978 return s;
01979 }
01980
01981 char *nullIfAllSpace(char *s)
01982
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
01993 {
01994 return (b ? "true" : "false");
01995 }
01996
01997 void uglyTime(char *label, ...)
01998
01999
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
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
02037 {
02038 while (isdigit(*s))
02039 ++s;
02040 return s;
02041 }
02042
02043 char *skipToNumeric(char *s)
02044
02045 {
02046 while (*s != 0 && !isdigit(*s))
02047 ++s;
02048 return s;
02049 }
02050
02051 char *splitOffNonNumeric(char *s)
02052
02053 {
02054 return cloneStringZ(s,skipToNumeric(s)-s);
02055 }
02056
02057 char *splitOffNumber(char *db)
02058
02059 {
02060 return cloneString(skipToNumeric(db));
02061 }