00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include <stdio.h>
00054 #include <stdlib.h>
00055 #include <ctype.h>
00056 #include <string.h>
00057
00058 #include "hlrmisc.h"
00059 #include "log.h"
00060 #include "format.h"
00061
00062
00063
00064
00065
00081 Array stringCreate(int initialSize)
00082 {
00083 Array a = arrayCreate(initialSize, char) ;
00084 array(a, 0, char) = '\0' ;
00085 return a ;
00086 }
00087
00088
00089
00096 void stringTerminate(Array s )
00097 {
00098 if (!s || !arrayMax(s))
00099 die("stringTerminate: not a Stringa") ;
00100 if (!arru(s, arrayMax(s)-1, char))
00101 die("stringTerminate: already terminated") ;
00102 array(s, arrayMax(s), char) = '\0' ;
00103 }
00104
00105
00106
00114 void stringTerminateP(Array s , char *cp)
00115 {
00116 stringTerminateI(s, cp-string(s)) ;
00117 }
00118
00119
00120
00128 void stringTerminateI(Array s , int i)
00129 {
00130 if (i<0 || i>stringLen(s))
00131 die("stringTerminateI: s='%s', i=%d", string(s), i) ;
00132 arru(s, i, char) = '\0' ;
00133 arraySetMax(s, i+1) ;
00134 }
00135
00136
00137
00138 void stringAdjust(Array s1) {
00139
00140
00141
00142
00143
00144
00145
00146
00147 int l ;
00148 if (!s1) die("stringAdjust: null") ;
00149 if (!arrayMax(s1)) {
00150 stringClear(s1) ;
00151 return ;
00152 }
00153 l = strlen(string(s1)) ;
00154 if (l >= arrayMax(s1))
00155 die("stringAdjust: memory allocation error? actual string length is %d, but array knows only about %d chars", l, arrayMax(s1)-1) ;
00156 arraySetMax(s1, l+1) ;
00157 }
00158
00159
00160
00168 void stringChop(Stringa s, int n)
00169 {
00170 int l = arrayMax(s) ;
00171 if (n >= l) {
00172 stringClear(s) ;
00173 return ;
00174 }
00175 arru(s, l-n-1, char) = '\0' ;
00176 arraySetMax(s, l-n) ;
00177 return ;
00178 }
00179
00180
00181
00197 char *stringCut(Array s, int pos, int len)
00198 {
00199 static Array r = NULL ;
00200 int l = arrayMax(s) - 1 ;
00201 char *from ;
00202 char *to ;
00203 char c ;
00204
00205 if (l < 0 || arru(s, l, char))
00206 die("stringCut: not a proper string") ;
00207
00208 if (pos >= l)
00209 return NULL ;
00210 if (len < 0 || len > l - pos)
00211 len = l - pos ;
00212
00213 stringCreateClear(r, len+1) ;
00214
00215 if (len > 0) {
00216 stringNCpy(r, arrp(s,pos,char), len) ;
00217 to = arrp(s,pos,char) ;
00218 from = to + len - 1 ;
00219 while (c = *++from)
00220 *to++ = c ;
00221 *to = '\0' ;
00222 arraySetMax(s, to - string(s) + 1) ;
00223 }
00224
00225 return string(r) ;
00226 }
00227
00228
00229
00238 void stringInsert(Stringa s, int p, char *i)
00239 {
00240 int il = strlen(i) ;
00241 int k = arrayMax(s) - p ;
00242 int oldlen = arrayMax(s)-1 ;
00243 int maxnew = oldlen+il ;
00244 char *to ;
00245 char *from ;
00246 if (!il)
00247 return ;
00248 array(s, maxnew, char) = '\0' ;
00249 to = arrp(s, maxnew, char) ;
00250 from = arrp(s, oldlen, char) ;
00251 if (k < 0)
00252 die("stringInsert: k=%d", k) ;
00253 while (k--)
00254 *to-- = *from-- ;
00255 memcpy(arrp(s,p,char), i, il) ;
00256
00257 }
00258
00259
00260
00267 void stringCat(Array s1, char *s2)
00268 {
00269 int i = arrayMax(s1) - 1 ;
00270 int l = strlen(s2) ;
00271 if (arru(s1, i, char))
00272 die("stringCat: s1 is not null-terminated (i=%d)", i) ;
00273 array(s1, i + l, char) = '\0' ;
00274 memcpy(arrp(s1, i, char), s2, l) ;
00275 }
00276
00277
00278
00282 void stringCatInt(Array s, int i) {
00283 char c[30] ;
00284 hlr_itoa(c, i) ;
00285 stringCat(s, c) ;
00286 }
00287
00288
00289
00293 void stringCatChar (Stringa s,char c)
00294 {
00295 arru(s, arrayMax(s)-1, char) = c ;
00296 array(s, arrayMax(s), char) = '\0';
00297 }
00298
00299
00300
00305 void stringNCpy(Stringa s1, char *s2, int n)
00306 {
00307 stringClear(s1) ;
00308 stringNCat(s1, s2, n) ;
00309 }
00310
00311
00312
00321 void stringNCat(Stringa s1, char *s2, int n)
00322 {
00323 int i ;
00324 int l = 0 ;
00325 char *cp = s2 - 1 ;
00326 if (n <= 0)
00327 return ;
00328 while (*++cp)
00329 if (++l >= n) break ;
00330
00331 i = arrayMax(s1) - 1 ;
00332 if (arru(s1, i, char))
00333 die("stringNCat: s1 is not null-terminated (i=%d)", i) ;
00334 array(s1, i + l, char) = '\0' ;
00335 memcpy(arrp(s1, i, char), s2, l) ;
00336
00337
00338 }
00339
00340
00341
00348 void stringCpy(Array s1, char *s2)
00349 {
00350 arraySetMax (s1,0) ;
00351 array(s1, strlen(s2), char) = '\0' ;
00352 strcpy(arrp(s1, 0, char), s2) ;
00353 }
00354
00355
00356
00360 void stringClear(Array s1)
00361 {
00362 arraySetMax (s1,0) ;
00363 array(s1, 0, char) = '\0' ;
00364 }
00365
00366
00367
00372 int stringTrim(Array s , char *left, char *right)
00373 {
00374 int len = strTrim(string(s), left, right) ;
00375 arraySetMax(s, len+1) ;
00376 return len ;
00377 }
00378
00379
00380
00381 static int strTranslate_resultLen = 0 ;
00382
00383
00384
00389 int stringTranslate(Array s, char *fromChars, char *toChars)
00390 {
00391 int cnt = strTranslate(string(s), fromChars, toChars) ;
00392 arraySetMax(s, strTranslate_resultLen+1) ;
00393 return cnt ;
00394 }
00395
00396
00397
00398 static int computeResultLength(char *format, va_list args)
00399 {
00400
00401
00402
00403
00404
00405 int deflength = 18;
00406 int maxlength = 0;
00407 char *cp = format;
00408 int isPercent = 0;
00409
00410
00411 while (*cp) {
00412
00413 if (*cp == '%')
00414 isPercent = (isPercent) ? 0 : 1;
00415 else if (isPercent) {
00416
00417 int width = 0;
00418 int prec = 0;
00419 int dot = 0;
00420 int asteriskCnt = 0;
00421 long int intConv = 0;
00422 char *intConvEnd = NULL;
00423 char *arg = NULL;
00424 int arglength = 0;
00425
00426 for (;;) {
00427
00428 intConv = strtol(cp, &intConvEnd, 10);
00429
00430
00431 if (intConvEnd != cp) {
00432
00433 cp = intConvEnd;
00434
00435
00436 if (dot)
00437 prec = intConv;
00438 else
00439 width = intConv;
00440 }
00441
00442 else if (*cp == '*')
00443 asteriskCnt ++;
00444
00445
00446 if (strchr("lLh", *cp))
00447 cp ++;
00448
00449 if (*cp == 'l')
00450 cp ++;
00451
00452
00453 if (strchr("pdinouxXeEfgGcCsS", *cp)) {
00454
00455 isPercent = 0;
00456 if (strchr("eEfgG", *cp)) {
00457
00458
00459
00460
00461
00462
00463
00464
00465 va_arg(args, double);
00466 arg = NULL ;
00467 }
00468 else
00469 arg = va_arg(args, char *);
00470
00471 if (asteriskCnt) {
00472 if (asteriskCnt == 2) {
00473 width = (int) arg;
00474 arg = va_arg(args, char *);
00475 prec = (int) arg;
00476 arg = va_arg(args, char *);
00477 }
00478 else if (asteriskCnt == 1) {
00479 if (dot)
00480 prec = (int) arg;
00481 else
00482 width = (int) arg;
00483
00484 arg = va_arg(args, char *);
00485 }
00486 else
00487 die("stringPrintf(): cannot handle format string %s", format);
00488 }
00489
00490 if (*cp == 's') {
00491
00492 if (prec)
00493 arglength = prec;
00494 else
00495 arglength = arg ? strlen(arg) : 6 ;
00496
00497 maxlength += MAX(arglength, width);
00498 }
00499 else if (*cp == 'S') {
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 die("stringPrintf()/Appendf(): wide character strings not handled");
00510 }
00511 else if (*cp == 'c') {
00512 maxlength ++;
00513 }
00514 else if (*cp == 'C') {
00515
00516
00517
00518
00519 die("stringPrintf(): wide characters not handled");
00520 }
00521 else {
00522
00523 maxlength += (deflength + MAX(width, prec));
00524 }
00525
00526
00527 break;
00528 }
00529 else {
00530
00531 if (*cp == '.')
00532 dot = 1;
00533
00534
00535 if (*cp == '$')
00536 warn("stringPrintf(): argument position manipulation not supported");
00537
00538 cp ++;
00539 }
00540 }
00541 }
00542
00543 maxlength ++;
00544 cp ++;
00545 }
00546 return maxlength ;
00547 }
00548
00549
00550
00563 int stringPrintf(Stringa str, char *format, ...)
00564 {
00565 va_list args ;
00566 int maxlength ;
00567 int resultLen ;
00568
00569 va_start(args, format) ;
00570 maxlength = computeResultLength(format, args) ;
00571 va_end(args);
00572
00573 array(str, maxlength + 1, char) ;
00574
00575 va_start(args, format);
00576 resultLen = vsprintf(string(str), format, args);
00577 va_end(args);
00578
00579 if (resultLen > maxlength || resultLen < 0)
00580 die("stringPrintf(): oops") ;
00581
00582 arraySetMax(str, resultLen+1) ;
00583
00584 return resultLen ;
00585 }
00586
00587
00588
00593 int stringAppendf(Stringa str, char *format, ...)
00594 {
00595 va_list args ;
00596 int maxlength ;
00597 int len = stringLen(str) ;
00598 int resultLen ;
00599
00600 va_start(args, format) ;
00601 maxlength = computeResultLength(format, args) ;
00602 va_end(args);
00603
00604 array(str, len + maxlength + 1, char) ;
00605
00606 va_start(args, format);
00607 resultLen = vsprintf(string(str)+len, format, args);
00608 va_end(args);
00609 if (resultLen > maxlength || resultLen < 0)
00610 die("stringAppend(): oops") ;
00611
00612 arraySetMax(str, len+resultLen+1) ;
00613 return resultLen ;
00614 }
00615
00616
00617
00625 char *stringPrintBuf(char *format, ...)
00626 {
00627 static Stringa str = NULL ;
00628 va_list args ;
00629 int maxlength ;
00630 int resultLen ;
00631 stringCreateOnce(str, 100) ;
00632
00633 va_start(args, format) ;
00634 maxlength = computeResultLength(format, args) ;
00635 va_end(args);
00636
00637 array(str, maxlength + 1, char) ;
00638
00639 va_start(args, format);
00640 resultLen = vsprintf(string(str), format, args);
00641 va_end(args);
00642
00643 if (resultLen > maxlength || resultLen < 0)
00644 die("stringPrintBuf(): oops") ;
00645
00646 arraySetMax(str, resultLen+1) ;
00647 return string(str) ;
00648 }
00649
00650
00651
00652
00653
00654
00658 void toupperStr(char *s)
00659 {
00660 register char *cp = s - 1 ;
00661 while (*++cp)
00662 *cp = toupper(*cp) ;
00663 }
00664
00665
00666
00670 void tolowerStr(char *s)
00671 {
00672 register char *cp = s - 1 ;
00673 while (*++cp)
00674 *cp = tolower(*cp) ;
00675 }
00676
00677
00678
00686 char *strCaseStr (char *s, char *t)
00687 {
00688 char *p , *r ;
00689 if (*t == '\0')
00690 return s ;
00691 for ( ; *s != '\0'; s++) {
00692 for (p = s, r = t; *r != '\0' && tolower(*p) == tolower(*r); p++, r++) ;
00693 if (r > t && *r == '\0')
00694 return s ;
00695 }
00696 return NULL ;
00697 }
00698
00699
00708 void strReplace(char **s1, char *s2)
00709 {
00710 if (!s1)
00711 die("strReplace: NULL") ;
00712 hlr_free(*s1) ;
00713 if (s2)
00714 *s1 = hlr_strdup(s2) ;
00715 }
00716
00717
00718
00729 char *strCopySubstr(char *string, char begin, char end,
00730 Array substr )
00731 {
00732 char *pbegin = NULL ;
00733 char *pend = NULL ;
00734 char *nextPos = NULL ;
00735 stringClear(substr) ;
00736
00737 if(pbegin = strchr(string, begin)) {
00738 pbegin ++;
00739
00740 if(pend = strchr(pbegin, end)) {
00741 nextPos = pend + 1;
00742 pend --;
00743 stringNCpy(substr, pbegin, pend - pbegin + 1) ;
00744 }
00745 }
00746 return nextPos ;
00747 }
00748
00749
00750
00767 int strTranslate(char *s, char *fromChars, char *toChars)
00768 {
00769 char *from = s - 1 ;
00770 char *to = s ;
00771 char c ;
00772 int toLen = strlen(toChars) ;
00773 char *hit ;
00774 int cnt = 0 ;
00775
00776 while (c = *++from) {
00777 if (hit = strchr(fromChars, c)) {
00778 ++cnt ;
00779 if (hit - fromChars < toLen)
00780 *to++ = toChars[hit - fromChars] ;
00781 }
00782 else
00783 *to++ = c ;
00784 }
00785 *to = '\0' ;
00786 strTranslate_resultLen = to - s ;
00787 return cnt ;
00788 }
00789
00790
00791
00804 int strTrim(char *s, char *left, char *right)
00805 {
00806
00807
00808
00809
00810
00811 int len ;
00812 char *cp ;
00813 if (!s)
00814 return 0 ;
00815 len = strlen(s) ;
00816
00817 if (len && right) {
00818
00819
00820
00821 cp = s + len - 1 ;
00822 while( cp >= s && strchr(right, *cp))
00823 *cp-- = '\0' ;
00824 len = cp - s + 1 ;
00825 }
00826
00827 if (len && left) {
00828
00829
00830
00831 cp = s ;
00832 while (*cp && strchr(left, *cp))
00833 ++cp ;
00834 len = len - (cp - s) ;
00835 while (*cp)
00836 *s++ = *cp++ ;
00837 *s = '\0' ;
00838 }
00839 return len ;
00840 }
00841
00842
00843
00849 void strScramble(char *s)
00850 {
00851 char *cp = s - 1 ;
00852 while (*++cp) {
00853 if ((unsigned char)*cp == 255)
00854 die("clsv_scramble: cannot scramble 0xFF") ;
00855 *cp = *cp ^ 255 ;
00856 }
00857 }
00858
00859
00860
00864 void strUnscramble(char *s)
00865 {
00866 strScramble(s) ;
00867 }
00868
00869
00870
00875 int isBlankStr(char *s) {
00876
00877 char *cp = s-1 ;
00878 while (*++cp && isspace(*cp)) ;
00879 return *cp == '\0' ;
00880 }
00881
00882
00883
00884 int isEmptyString(Array s) {
00885 if (!s || arrayMax(s)<1)
00886 die("isEmptyString: NULL or corrupt string") ;
00887 return !arru(s,0,char) ;
00888 }
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00906 void textClear(Texta a )
00907 {
00908 int i = arrayMax(a) ;
00909 while (i--)
00910 hlr_free(arru(a, i ,char*)) ;
00911 arrayClear(a) ;
00912 }
00913
00914
00915
00916
00922 void textDestroyFunc(Texta a)
00923 {
00924 if (!a)
00925 return ;
00926 textClear(a) ;
00927 arrayDestroy(a) ;
00928 }
00929
00930
00931
00938 Texta textClone(Array a )
00939 {
00940 int i ;
00941 Texta b ;
00942 char *s ;
00943 if (!a)
00944 return NULL ;
00945 i = arrayMax(a) ;
00946 b = textCreate(i) ;
00947 if (i == 0)
00948 return b ;
00949 array(b, i-1, char*) = NULL ;
00950 while (i--) {
00951 s = arru(a,i,char*) ;
00952 arru(b,i,char*) = (s ? hlr_strdup(s) : NULL) ;
00953 }
00954 return b ;
00955 }
00956
00957
00958
00968 Texta textStrtok(char *s, char *sep)
00969 {
00970 WordIter wi=wordIterCreate(s,sep,1) ;
00971 char *pos ;
00972 Texta a=textCreate(10) ;
00973 while (pos=wordNext(wi))
00974 array(a,arrayMax(a),char*)=hlr_strdup(pos) ;
00975 wordIterDestroy(wi) ;
00976 return a ;
00977 }
00978
00979
00980
00985 Texta textStrtokP(char *s, char *sep)
00986 {
00987 char *cp = hlr_strdup(s) ;
00988 Texta t = textStrtok(cp, sep) ;
00989 hlr_free(cp) ;
00990 return t ;
00991 }
00992
00993
00994
01003 Texta textFieldtok(char *s, char *sep)
01004 {
01005 WordIter wi=wordIterCreate(s,sep,0) ;
01006 char *pos ;
01007 Texta a=textCreate(10) ;
01008 while (pos=wordNext(wi))
01009 array(a,arrayMax(a),char*)=hlr_strdup(pos) ;
01010 wordIterDestroy(wi) ;
01011 return a ;
01012 }
01013
01014
01015
01020 Texta textFieldtokP(char *s, char *sep)
01021 {
01022 char *cp = hlr_strdup(s) ;
01023 Texta t = textFieldtok(cp, sep) ;
01024 hlr_free(cp) ;
01025 return t ;
01026 }
01027
01028
01029
01045 void textJoin(Stringa s, char *sep, Array a )
01046 {
01047 int i ;
01048 stringClear(s) ;
01049 if (! arrayMax(a))
01050 return ;
01051 stringCpy(s, arru(a,0,char*)) ;
01052 for (i=1; i<arrayMax(a); ++i) {
01053 stringCat(s, sep) ;
01054 stringCat(s, arru(a,i,char*)) ;
01055 }
01056 }
01057
01058
01059
01082 void textUniqKeepOrder(Texta t)
01083 {
01084 Texta b = textCreate(arrayMax(t)) ;
01085 int from = -1 ;
01086 int to = -1 ;
01087 char *cp ;
01088 while (++from < arrayMax(t)) {
01089 cp = arru(t, from, char*) ;
01090 if (arrayFindInsert(b, &cp, NULL, (ARRAYORDERF) arrayStrcmp)) {
01091 ++to ;
01092 arru(t, to, char*) = cp ;
01093 }
01094 else
01095 hlr_free(cp) ;
01096 }
01097 arraySetMax(t, to + 1) ;
01098 arrayDestroy(b) ;
01099 }
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116 #define GETLINE_MIN 80
01117 #define GETLINE_INC 1024
01118
01119
01139 int getLine(FILE *stream, char **buffer, int *buflen)
01140 {
01141 int buffree ;
01142 char *startp ;
01143 char *bufp ;
01144 int c ;
01145
01146 if (!buffer) die("getLine() without buffer");
01147 if (! *buffer) {
01148 *buflen = GETLINE_MIN ;
01149 *buffer = hlr_malloc(*buflen) ;
01150 }
01151 buffree = (*buflen) -1 ;
01152 bufp = *buffer ;
01153 startp = bufp ;
01154
01155 while ((c = getc(stream)) != EOF) {
01156
01157 if (! --buffree) {
01158 *buflen = *buflen + GETLINE_INC ;
01159 buffree += GETLINE_INC ;
01160 *buffer = realloc(*buffer, *buflen) ;
01161 if (! *buffer) die("getLine: realloc") ;
01162 bufp = *buffer + (bufp - startp) ;
01163 startp = *buffer ;
01164 }
01165
01166 if (!c) warn("getLine: read a NULL character") ;
01167 *(bufp++) = c ;
01168 if (c == '\n') break ;
01169 }
01170
01171 *bufp = '\0' ;
01172 return bufp - startp ;
01173 }
01174
01175
01176
01177
01185 int stripNlGetLength(char *line)
01186 {
01187
01188
01189
01190
01191
01192
01193
01194 int len = strlen(line) ;
01195 if (!len)
01196 return 0 ;
01197 --len ;
01198 if (line[len] == '\n')
01199 line[len] = '\0' ;
01200 else
01201 ++len ;
01202 return len ;
01203 }
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01232 void wordIterDestroy_func(WordIter this1)
01233 {
01234 if (!this1)
01235 die("wordIterDestroy: null") ;
01236 hlr_free(this1) ;
01237 }
01238
01239
01252 WordIter wordIterCreate(char *s, char *seps, int manySepsAreOne)
01253 {
01254 WordIter this1 ;
01255 if (!s || !seps || !*seps)
01256 die("wordIterCreate: some null/empty input") ;
01257 this1 = (WordIter) hlr_malloc(sizeof(struct wordIterStruct)) ;
01258 this1->seps = seps ;
01259 this1->cp = s ;
01260 this1->manySepsAreOne = manySepsAreOne ;
01261 this1->atEnd = 0 ;
01262 return this1 ;
01263 }
01264
01265
01266
01267
01268
01269
01270
01271
01272
01280 char *wordNextG(WordIter this1, int *lenP)
01281 {
01282 char *cp ;
01283 char *word ;
01284 if (!this1)
01285 die("wordNext: null") ;
01286 if (lenP)
01287 *lenP = 0 ;
01288 if (this1->atEnd)
01289 return NULL ;
01290 cp = this1->cp ;
01291 if (this1->manySepsAreOne) {
01292 --cp ;
01293 while (*++cp && strchr(this1->seps, *cp)) ;
01294 }
01295 else {
01296 if (! *cp) {
01297 this1->atEnd = 1 ;
01298 return cp ;
01299 }
01300 if (strchr(this1->seps, *cp)) {
01301 ++this1->cp ;
01302 *cp = '\0' ;
01303 return cp ;
01304 }
01305 }
01306 if (! *cp) {
01307 this1->atEnd = 1 ;
01308 return NULL ;
01309 }
01310
01311
01312
01313 word = cp ;
01314 --cp ;
01315 while (*++cp && !strchr(this1->seps, *cp)) ;
01316 if (lenP)
01317 *lenP = cp - word ;
01318
01319 if (! *cp )
01320 this1->atEnd = 1 ;
01321 else {
01322 *cp = '\0' ;
01323 this1->cp = cp + 1 ;
01324 }
01325 return word ;
01326 }
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01346 int strEndsWith(char *s, char *suffix)
01347 {
01348 int len = strlen(s) ;
01349 int slen = strlen(suffix) ;
01350 if (slen > len)
01351 return 0 ;
01352 return strEqual(s + len - slen, suffix) ;
01353 }
01354