diff --git a/bstest.c b/bstest.c index ec2e2969892422c1e4856310b98f9ae939eb3500_YnN0ZXN0LmM=..ca4a485f8d8477316f90e04acfccdb1d07c1a0b9_YnN0ZXN0LmM= 100644 --- a/bstest.c +++ b/bstest.c @@ -63,6 +63,36 @@ return (char *) dumpOut[rot]->data; } +static char* dumpCstring (const char* s) { + rot = (rot + 1) % (unsigned)16; + if (dumpOut[rot] == NULL) { + dumpOut[rot] = bfromcstr (""); + if (dumpOut[rot] == NULL) return "FATAL INTERNAL ERROR"; + } + dumpOut[rot]->slen = 0; + if (s == NULL) { + bcatcstr (dumpOut[rot], "NULL"); + } else { + static char msg[64]; + int i; + + sprintf (msg, "cstr[%p] -> ", (void *)s); + bcatcstr (dumpOut[rot], msg); + + bcatStatic (dumpOut[rot], "\""); + for (i = 0; s[i]; i++) { + if (i > 1024) { + bcatStatic (dumpOut[rot], " ..."); + break; + } + bconchar (dumpOut[rot], s[i]); + } + bcatStatic (dumpOut[rot], "\""); + } + + return (char *) dumpOut[rot]->data; +} + static int test0_0 (const char * s, const char * res) { bstring b0 = bfromcstr (s); int ret = 0; @@ -107,6 +137,51 @@ #define EIGHT_CHAR_STRING "Waterloo" #define LONG_STRING "This is a bogus but reasonably long string. Just long enough to cause some mallocing." +static int test0_2 (char* s) { +int l = s?strlen(s):2; +int i, j, k; +int ret = 0; + + for (i = 0; i < l*2; i++) { + for (j = 0; j < l*2; j++) { + for (k = 0; k <= l; k++) { + char* t = s ? (s + k) : NULL; + bstring b = bfromcstrrangealloc (i, j, t); + if (NULL == b) { + if (i < j && t != NULL) { + printf ("[%d] i = %d, j = %d, l = %d, k = %d\n", __LINE__, i, j, l, k); + } + ret += (i < j && t != NULL); + continue; + } + if (NULL == t) { + printf ("[%d] i = %d, j = %d, l = %d, k = %d\n", __LINE__, i, j, l, k); + ret++; + bdestroy (b); + continue; + } + if (b->data == NULL) { + printf ("[%d] i = %d, j = %d, l = %d, k = %d\n", __LINE__, i, j, l, k); + ret++; + continue; + } + if (b->slen != l-k || b->data[l-k] != '\0' || b->mlen <= b->slen) { + printf ("[%d] i = %d, j = %d, l = %d, k = %d, b->slen = %d\n", __LINE__, i, j, l, k, b->slen); + ret++; + } else if (0 != memcmp (t, b->data, l-k+1)) { + printf ("[%d] \"%s\" != \"%s\"\n", b->data, t); + ret++; + } + bdestroy (b); + continue; + } + } + } + + printf (".\tbfromcstrrangealloc (*,*,%s) correct\n", dumpCstring(s)); + return ret; +} + static int test0 (void) { int ret = 0; @@ -134,6 +209,13 @@ ret += test0_1 (SHORT_STRING, 30, SHORT_STRING); ret += test0_1 ( LONG_STRING, 0, LONG_STRING); ret += test0_1 ( LONG_STRING, 30, LONG_STRING); + + printf ("TEST: bstring bfromcstrrangealloc (int minl, int maxl, const char * str);\n"); + + ret += test0_2 (NULL); + ret += test0_2 (EMPTY_STRING); + ret += test0_2 ( LONG_STRING); + printf ("\t# failures: %d\n", ret); return ret; diff --git a/bstraux.c b/bstraux.c index ec2e2969892422c1e4856310b98f9ae939eb3500_YnN0cmF1eC5j..ca4a485f8d8477316f90e04acfccdb1d07c1a0b9_YnN0cmF1eC5j 100644 --- a/bstraux.c +++ b/bstraux.c @@ -950,10 +950,9 @@ if ((c = UCHAR_MAX + 1) == termchar) c++; for (i=0; ; i++) { - if (termchar == c || (maxlen > 0 && i >= maxlen)) c = EOF; - else c = vgetchar (vgcCtx); - + if (termchar == c || (maxlen > 0 && i >= maxlen)) break; + c = vgetchar (vgcCtx); if (EOF == c) break; if (i+1 >= b->mlen) { @@ -956,11 +955,10 @@ if (EOF == c) break; if (i+1 >= b->mlen) { - /* Double size, but deal with unusual case of numeric - overflows */ + /* Double size, and deal with numeric overflows */ if (b->mlen <= INT_MAX / 2) m = b->mlen << 1; else if (b->mlen <= INT_MAX - 1024) m = b->mlen + 1024; else if (b->mlen <= INT_MAX - 16) m = b->mlen + 16; else if (b->mlen <= INT_MAX - 1) m = b->mlen + 1; @@ -962,8 +960,10 @@ if (b->mlen <= INT_MAX / 2) m = b->mlen << 1; else if (b->mlen <= INT_MAX - 1024) m = b->mlen + 1024; else if (b->mlen <= INT_MAX - 16) m = b->mlen + 16; else if (b->mlen <= INT_MAX - 1) m = b->mlen + 1; - else return NULL; - t = bfromcstralloc (m, ""); + else { + bSecureDestroy (b); /* Cleanse partial buffer */ + return NULL; + } @@ -969,2 +969,3 @@ + t = bfromcstrrangealloc (b->mlen + 1, m, ""); if (t) memcpy (t->data, b->data, i); @@ -970,5 +971,5 @@ if (t) memcpy (t->data, b->data, i); - bSecureDestroy (b); /* Cleanse previous buffer */ + bSecureDestroy (b); /* Cleanse previous buffer */ b = t; if (!b) return b; } diff --git a/bstraux.h b/bstraux.h index ec2e2969892422c1e4856310b98f9ae939eb3500_YnN0cmF1eC5o..ca4a485f8d8477316f90e04acfccdb1d07c1a0b9_YnN0cmF1eC5o 100644 --- a/bstraux.h +++ b/bstraux.h @@ -28,9 +28,10 @@ #define bstrFree(b) {if ((b) != NULL && (b)->slen >= 0 && (b)->mlen >= (b)->slen) { bdestroy (b); (b) = NULL; }} /* Backward compatibilty with previous versions of Bstrlib */ +#if !defined(BSTRLIB_REDUCE_NAMESPACE_POLLUTION) #define bAssign(a,b) ((bassign)((a), (b))) #define bSubs(b,pos,len,a,c) ((breplace)((b),(pos),(len),(a),(unsigned char)(c))) #define bStrchr(b,c) ((bstrchr)((b), (c))) #define bStrchrFast(b,c) ((bstrchr)((b), (c))) #define bCatCstr(b,s) ((bcatcstr)((b), (s))) #define bCatBlk(b,s,len) ((bcatblk)((b),(s),(len))) @@ -31,10 +32,10 @@ #define bAssign(a,b) ((bassign)((a), (b))) #define bSubs(b,pos,len,a,c) ((breplace)((b),(pos),(len),(a),(unsigned char)(c))) #define bStrchr(b,c) ((bstrchr)((b), (c))) #define bStrchrFast(b,c) ((bstrchr)((b), (c))) #define bCatCstr(b,s) ((bcatcstr)((b), (s))) #define bCatBlk(b,s,len) ((bcatblk)((b),(s),(len))) -#define bCatStatic(b,s) bCatBlk ((b), ("" s ""), sizeof (s) - 1) +#define bCatStatic(b,s) bcatStatic(b,s) #define bTrunc(b,n) ((btrunc)((b), (n))) #define bReplaceAll(b,find,repl,pos) ((bfindreplace)((b),(find),(repl),(pos))) #define bUppercase(b) ((btoupper)(b)) @@ -43,6 +44,7 @@ #define bCaselessNCmp(a,b,n) ((bstrnicmp)((a), (b), (n))) #define bBase64Decode(b) (bBase64DecodeEx ((b), NULL)) #define bUuDecode(b) (bUuDecodeEx ((b), NULL)) +#endif /* Unusual functions */ extern struct bStream * bsFromBstr (const_bstring b); diff --git a/bstrlib.c b/bstrlib.c index ec2e2969892422c1e4856310b98f9ae939eb3500_YnN0cmxpYi5j..ca4a485f8d8477316f90e04acfccdb1d07c1a0b9_YnN0cmxpYi5j 100644 --- a/bstrlib.c +++ b/bstrlib.c @@ -211,5 +211,5 @@ return b; } -/* bstring bfromcstralloc (int mlen, const char * str) +/* bstring bfromcstrrangealloc (int minl, int maxl, const char* str) * @@ -215,5 +215,6 @@ * - * Create a bstring which contains the contents of the '\0' terminated char * - * buffer str. The memory buffer backing the string is at least len - * characters in length. + * Create a bstring which contains the contents of the '\0' terminated + * char* buffer str. The memory buffer backing the string is at least + * minl characters in length, but an attempt is made to allocate up to + * maxl characters. */ @@ -219,6 +220,6 @@ */ -bstring bfromcstralloc (int mlen, const char * str) { +bstring bfromcstrrangealloc (int minl, int maxl, const char* str) { bstring b; int i; size_t j; @@ -221,5 +222,6 @@ bstring b; int i; size_t j; + /* Bad parameters? */ if (str == NULL) return NULL; @@ -225,2 +227,5 @@ if (str == NULL) return NULL; + if (maxl < minl || minl < 0) return NULL; + + /* Adjust lengths */ j = (strlen) (str); @@ -226,7 +231,8 @@ j = (strlen) (str); - i = snapUpSize ((int) (j + (2 - (j != 0)))); - if (i <= (int) j) return NULL; + if ((size_t) minl < (j+1)) minl = (int) (j+1); + if (maxl < minl) maxl = minl; + i = maxl; b = (bstring) bstr__alloc (sizeof (struct tagbstring)); if (b == NULL) return NULL; b->slen = (int) j; @@ -229,15 +235,18 @@ b = (bstring) bstr__alloc (sizeof (struct tagbstring)); if (b == NULL) return NULL; b->slen = (int) j; - if (i < mlen) i = mlen; - - if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { - bstr__free (b); - return NULL; + + while (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { + int k = (i >> 1) + (minl >> 1); + if (i == k || i < minl) { + bstr__free (b); + return NULL; + } + i = k; } bstr__memcpy (b->data, str, j+1); return b; } @@ -238,9 +247,19 @@ } bstr__memcpy (b->data, str, j+1); return b; } +/* bstring bfromcstralloc (int mlen, const char * str) + * + * Create a bstring which contains the contents of the '\0' terminated + * char* buffer str. The memory buffer backing the string is at least + * mlen characters in length. + */ +bstring bfromcstralloc (int mlen, const char * str) { + return bfromcstrrangealloc (mlen, mlen, str); +} + /* bstring blk2bstr (const void * blk, int len) * * Create a bstring which contains the content of the block blk of length @@ -1566,8 +1585,8 @@ if (b == NULL || b->data == NULL || find == NULL || find->data == NULL || repl == NULL || repl->data == NULL || - pos < 0 || find->slen <= 0 || b->mlen < 0 || b->slen > b->mlen || - b->mlen <= 0 || b->slen < 0 || repl->slen < 0) return BSTR_ERR; + pos < 0 || find->slen <= 0 || b->mlen <= 0 || b->slen > b->mlen || + b->slen < 0 || repl->slen < 0) return BSTR_ERR; if (pos > b->slen - find->slen) return BSTR_OK; /* Alias with find string */ diff --git a/bstrlib.h b/bstrlib.h index ec2e2969892422c1e4856310b98f9ae939eb3500_YnN0cmxpYi5o..ca4a485f8d8477316f90e04acfccdb1d07c1a0b9_YnN0cmxpYi5o 100644 --- a/bstrlib.h +++ b/bstrlib.h @@ -40,6 +40,7 @@ #define cstr2bstr bfromcstr extern bstring bfromcstr (const char * str); extern bstring bfromcstralloc (int mlen, const char * str); +extern bstring bfromcstrrangealloc (int minl, int maxl, const char* str); extern bstring blk2bstr (const void * blk, int len); extern char * bstr2cstr (const_bstring s, char z); extern int bcstrfree (char * s); @@ -212,6 +213,11 @@ /* Static constant block parameter pair */ #define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1) +#define bcatStatic(b,s) ((bcatblk)((b), bsStaticBlkParms(s))) +#define bfromStatic(s) ((blk2bstr)(bsStaticBlkParms(s))) +#define bassignStatic(b,s) ((bassignblk)((b), bsStaticBlkParms(s))) +#define bisstemeqcaselessStatic(b,s) ((bisstemeqcaselessblk)((b), bsStaticBlkParms(s))) + /* Reference building macros */ #define cstr2tbstr btfromcstr #define btfromcstr(t,s) { \ diff --git a/bstrlib.txt b/bstrlib.txt index ec2e2969892422c1e4856310b98f9ae939eb3500_YnN0cmxpYi50eHQ=..ca4a485f8d8477316f90e04acfccdb1d07c1a0b9_YnN0cmxpYi50eHQ= 100644 --- a/bstrlib.txt +++ b/bstrlib.txt @@ -574,5 +574,6 @@ Files ----- +Core C files (required for C and C++): bstrlib.c - C implementaion of bstring functions. bstrlib.h - C header file for bstring functions. @@ -577,8 +578,6 @@ bstrlib.c - C implementaion of bstring functions. bstrlib.h - C header file for bstring functions. -bstraux.c - C example that implements trivial additional functions. -bstraux.h - C header for bstraux.c -bstest.c - C unit/regression test for bstrlib.c - + +Core C++ files (required for C++): bstrwrap.cpp - C++ implementation of CBString. bstrwrap.h - C++ header file for CBString. @@ -583,12 +582,9 @@ bstrwrap.cpp - C++ implementation of CBString. bstrwrap.h - C++ header file for CBString. -test.cpp - C++ unit/regression test for bstrwrap.cpp - -bsafe.c - C runtime stubs to abort usage of unsafe C functions. -bsafe.h - C header file for bsafe.c functions. - + +Base Unicode support: utf8util.c - C implemention of generic utf8 parsing functions. utf8util.h - C head file for generic utf8 parsing functions. buniutil.c - C implemention utf8 bstring packing and unpacking functions. buniutil.c - C header file for utf8 bstring functions. @@ -590,8 +586,18 @@ utf8util.c - C implemention of generic utf8 parsing functions. utf8util.h - C head file for generic utf8 parsing functions. buniutil.c - C implemention utf8 bstring packing and unpacking functions. buniutil.c - C header file for utf8 bstring functions. +Extra utility functions: +bstraux.c - C example that implements trivial additional functions. +bstraux.h - C header for bstraux.c + +Miscellaneous: +bstest.c - C unit/regression test for bstrlib.c +test.cpp - C++ unit/regression test for bstrwrap.cpp +bsafe.c - C runtime stubs to abort usage of unsafe C functions. +bsafe.h - C header file for bsafe.c functions. + C modules need only include bstrlib.h and compile/link bstrlib.c to use the basic bstring library. C++ projects need to additionally include bstrwrap.h and compile/link bstrwrap.cpp. For both, there may be a need to make choices @@ -632,7 +638,9 @@ Create a bstring which contains the contents of the '\0' terminated char * buffer str. The memory buffer backing the bstring is at least - mlen characters in length. If an error occurs NULL is returned. + mlen characters in length. The buffer is also at least size required + to hold the string with the '\0' terminator. If an error occurs NULL + is returned. So for example: @@ -646,6 +654,27 @@ .......................................................................... + extern bstring bfromcstrrangealloc (int minl, int maxl, const char* str); + + Create a bstring which contains the contents of the '\0' terminated + char * buffer str. The memory buffer backing the string is at least + minl characters in length, but an attempt is made to allocate up to + maxl characters. The buffer is also at least size required to hold + the string with the '\0' terminator. If an error occurs NULL is + returned. + + So for example: + + bstring b = bfromcstrrangealloc (0, 128, "Hello."); + if (b) b->data[5] = '!'; + + The idea is that this will set the 6th character of b to '!' if it was + allocated otherwise do nothing. And we know this is well defined so + long as b was successfully created, since it will have been allocated + with at least 7 (strlen("Hello.")) characters. + + .......................................................................... + extern bstring blk2bstr (const void * blk, int len); Create a bstring whose contents are described by the contiguous buffer @@ -1922,6 +1951,40 @@ .......................................................................... + bstring bfromStatic("..."); + + Allocate a bstring with the contents of a string literal. Returns + NULL if an error has occurred (ran out of memory). The string literal + parameter is enforced as literal at compile time. + + .......................................................................... + + int bcatStatic (bstring b, "..."); + + Append a string literal to bstring b. Returns 0 if successful, or + BSTR_ERR if some error has occurred. The string literal parameter is + enforced as literal at compile time. + + .......................................................................... + + int bassignStatic (bstring b, " ... "); + + Assign the contents of a string literal to the bstring b. The string + literal parameter is enforced as literal at compile time. + + .......................................................................... + + int bisstemeqcaselessStatic (bstring b, " ... "); + + Compare beginning of bstring b with a string literal without + differentiating between case for equality. If the beginning of b differs + from the memory block other than in case (or if b0 is too short), 0 is + returned, if the bstrings are the same, 1 is returned, if there is an + error, -1 is returned. The string literal parameter is enforced as + literal at compile time. + + .......................................................................... + void bvformata (int& ret, bstring b, const char * format, lastarg); Append the bstring b with printf like formatting with the format control @@ -3256,6 +3319,23 @@ it seems marginal (i.e., to want a string that cannot be resized, yet can be modified and yet where a fixed sized buffer is undesirable.) +Libsrt +------ + +This is a length based string library based on a slightly different strategy. +The string contents are appended to the end of the header directly so strings +only require a single allocation. However, whenever a reallocation occurs, +the header is replicated and the base pointer for the string is changed. +That means references to the string are only valid so long as they are not +resized after any such reference is cached. The internal structure maintains +a lot some state used to accelerate unicode manipulation. This makes +sustainable usage of the library essentially opaque. This also creates a +bottleneck for whatever extensions to the library one desires (write all +extensions on top of the base library, put in a request to the author, or +dedicate an expert to learn the internals of the library). The library is +committed to Unicode representation of its string data, and therefore cannot +be used as a generic buffer library. + =============================================================================== Examples diff --git a/test.cpp b/test.cpp index ec2e2969892422c1e4856310b98f9ae939eb3500_dGVzdC5jcHA=..ca4a485f8d8477316f90e04acfccdb1d07c1a0b9_dGVzdC5jcHA= 100644 --- a/test.cpp +++ b/test.cpp @@ -1347,6 +1347,8 @@ return ret; } +#if !defined(BSTRLIB_CANNOT_USE_STL) + int test28 (void) { int ret = 0; @@ -1456,6 +1458,8 @@ return ret; } +#endif + int test29 (void) { int ret = 0; @@ -1559,5 +1563,5 @@ return ret; } -/* int bMultiCountConcat (bstring dst, int n, ...) +/* int bMultiConcatNeedNULLAsLastArgument (bstring dst, ...) * @@ -1563,3 +1567,3 @@ * - * Concatenate a sequence of exactly n bstring arguments to dst. + * Concatenate a sequence of exactly n char * arguments to dst. */ @@ -1565,3 +1569,3 @@ */ -int bMultiCountConcat (bstring dst, int n, ...) { +int bMultiConcatNeedNULLAsLastArgument (bstring dst, ...) { va_list arglist; @@ -1567,11 +1571,17 @@ va_list arglist; -int i, ret = 0; - va_start (arglist, n); - for (i = 0; i < n; i++) { - ret = bconcat (dst, va_arg (arglist, bstring)); - if (0 > ret) break; - } +int ret = 0; + va_start (arglist, dst); + do { + bstring parm = va_arg (arglist, bstring); + if (NULL == parm) break; + if (NULL == parm->data || parm->slen > parm->mlen || + parm->mlen < 0 || parm->slen < 0) { + ret = BSTR_ERR; + break; + } + ret = bconcat (dst, parm); + } while (0 <= ret); va_end (arglist); return ret; } @@ -1574,8 +1584,8 @@ va_end (arglist); return ret; } -/* int bMultiCountCatCstr (bstring dst, int n, ...) +/* int bMultiCatCstrNeedNULLAsLastArgument (bstring dst, ...) * * Concatenate a sequence of exactly n char * arguments to dst. */ @@ -1579,5 +1589,5 @@ * * Concatenate a sequence of exactly n char * arguments to dst. */ -int bMultiCountCatCstr (bstring dst, int n, ...) { +int bMultiCatCstrNeedNULLAsLastArgument (bstring dst, ...) { va_list arglist; @@ -1583,12 +1593,13 @@ va_list arglist; -int i, ret = 0; - va_start (arglist, n); - for (i = 0; i < n; i++) { - ret = bcatcstr (dst, va_arg (arglist, char *)); - if (0 > ret) break; - } +int ret = 0; + va_start (arglist, dst); + do { + char* parm = va_arg (arglist, char *); + if (NULL == parm) break; + ret = bcatcstr (dst, parm); + } while (0 <= ret); va_end (arglist); return ret; } /* @@ -1590,9 +1601,11 @@ va_end (arglist); return ret; } /* - * These can be dangerous because there is no compiler time type checking - * on the arguments. + * The following macros are only available on more recent compilers that + * support variable length macro arguments and __VA_ARGS__. These can also + * be dangerous because there is no compiler time type checking on the + * arguments. */ @@ -1597,5 +1610,3 @@ */ -extern int bMultiCountConcat (bstring dst, int n, ...); -extern int bMultiCountCatCstr (bstring dst, int n, ...); @@ -1601,26 +1612,6 @@ -#if defined(__GNUC__) -# define COUNT_ARGS(...) COUNT_ARGS_(,##__VA_ARGS__,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0) -# define COUNT_ARGS_(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66,_67,_68,_69,_70,_71,_72,_73,_74,_75,_76,_77,_78,_79,_80,_81,_82,_83,_84,_85,_86,_87,_88,_89,_90,_91,_92,_93,_94,_95,_96,_97,_98,_99,cnt,...) cnt -#else -# if defined(__WATCOMC__) || defined(_MSC_VER) -# define COUNT_ARGS(...) ARGCNT_ARGINDEX100((ARGCNT_0_LENGTH_ ## __VA_ARGS__ ## _SPECIAL_CASE,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1)) -# define ARGCNT_ARGINDEX100(__args) ARGCNT_ARGINDEX100_RAW __args -# define ARGCNT_0_LENGTH__SPECIAL_CASE ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0 -# define ARGCNT_ARGINDEX100_RAW(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,_33,_34,_35,_36,_37,_38,_39,_40,_41,_42,_43,_44,_45,_46,_47,_48,_49,_50,_51,_52,_53,_54,_55,_56,_57,_58,_59,_60,_61,_62,_63,_64,_65,_66,_67,_68,_69,_70,_71,_72,_73,_74,_75,_76,_77,_78,_79,_80,_81,_82,_83,_84,_85,_86,_87,_88,_89,_90,_91,_92,_93,_94,_95,_96,_97,_98,_99,n,...) n -# endif -#endif - -/* - * The following macros are only available on more recent compilers. - * Can process up to 100 arguments. These can also be dangerous because - * there is no compiler time type checking on the arguments. - */ - -#if defined(COUNT_ARGS) -# define bMultiConcat(dst,...) bMultiCountConcat((dst),COUNT_ARGS(__VA_ARGS__),##__VA_ARGS__) -# define bMultiCatCstr(dst,...) bMultiCountCatCstr((dst),COUNT_ARGS(__VA_ARGS__),##__VA_ARGS__) -#endif +#define bMultiConcat(dst,...) bMultiConcatNeedNULLAsLastArgument((dst),##__VA_ARGS__,NULL) +#define bMultiCatCstr(dst,...) bMultiCatCstrNeedNULLAsLastArgument((dst),##__VA_ARGS__,NULL) int main () { int ret = 0; @@ -1655,4 +1646,5 @@ ret += test25 (); ret += test26 (); ret += test27 (); +#if !defined(BSTRLIB_CANNOT_USE_STL) ret += test28 (); @@ -1658,4 +1650,5 @@ ret += test28 (); +#endif ret += test29 (); ret += test30 (); ret += test31 (); diff --git a/testaux.c b/testaux.c index ec2e2969892422c1e4856310b98f9ae939eb3500_dGVzdGF1eC5j..ca4a485f8d8477316f90e04acfccdb1d07c1a0b9_dGVzdGF1eC5j 100644 --- a/testaux.c +++ b/testaux.c @@ -349,7 +349,7 @@ } int test13 (void) { -struct tagbstring t0 = bsStatic ("Random String"); +struct tagbstring t0 = bsStatic ("Random String, long enough to cause to reallocing"); struct vfgetc vctx; bstring b; int ret = 0; @@ -368,7 +368,7 @@ h = b->data; bSecureDestroy (b); - /* WARNING! Technically unsound code follows: */ + /* WARNING! Technically undefined code follows (h has been freed): */ ret += (0 == memcmp (h, t0.data, t0.slen)); if (ret) break;