6 The bstring library is an attempt to provide improved string processing
7 functionality to the C and C++ language. At the heart of the bstring library
8 (Bstrlib for short) is the management of "bstring"s which are a significant
9 improvement over '\0' terminated char buffers.
11 ===============================================================================
16 The standard C string library has serious problems:
18 1) Its use of '\0' to denote the end of the string means knowing a
19 string's length is O(n) when it could be O(1).
20 2) It imposes an interpretation for the character value '\0'.
21 3) gets() always exposes the application to a buffer overflow.
22 4) strtok() modifies the string its parsing and thus may not be usable in
23 programs which are re-entrant or multithreaded.
24 5) fgets has the unusual semantic of ignoring '\0's that occur before
26 6) There is no memory management, and actions performed such as strcpy,
27 strcat and sprintf are common places for buffer overflows.
28 7) strncpy() doesn't '\0' terminate the destination in some cases.
29 8) Passing NULL to C library string functions causes an undefined NULL
31 9) Parameter aliasing (overlapping, or self-referencing parameters)
32 within most C library functions has undefined behavior.
33 10) Many C library string function calls take integer parameters with
34 restricted legal ranges. Parameters passed outside these ranges are
35 not typically detected and cause undefined behavior.
37 So the desire is to create an alternative string library that does not suffer
38 from the above problems and adds in the following functionality:
40 1) Incorporate string functionality seen from other languages.
41 a) MID$() - from BASIC
42 b) split()/join() - from Python
43 c) string/char x n - from Perl
44 2) Implement analogs to functions that combine stream IO and char buffers
45 without creating a dependency on stream IO functionality.
46 3) Implement the basic text editor-style functions insert, delete, find,
48 4) Implement reference based sub-string access (as a generalization of
50 5) Implement runtime write protection for strings.
52 There is also a desire to avoid "API-bloat". So functionality that can be
53 implemented trivially in other functionality is omitted. So there is no
54 left$() or right$() or reverse() or anything like that as part of the core
60 A bstring is basically a header which wraps a pointer to a char buffer. Lets
61 start with the declaration of a struct tagbstring:
69 This definition is considered exposed, not opaque (though it is neither
70 necessary nor recommended that low level maintenance of bstrings be performed
71 whenever the abstract interfaces are sufficient). The mlen field (usually)
72 describes a lower bound for the memory allocated for the data field. The
73 slen field describes the exact length for the bstring. The data field is a
74 single contiguous buffer of unsigned chars. Note that the existence of a '\0'
75 character in the unsigned char buffer pointed to by the data field does not
76 necessarily denote the end of the bstring.
78 To be a well formed modifiable bstring the mlen field must be at least the
79 length of the slen field, and slen must be non-negative. Furthermore, the
80 data field must point to a valid buffer in which access to the first mlen
81 characters has been acquired. So the minimal check for correctness is:
83 (slen >= 0 && mlen >= slen && data != NULL)
85 bstrings returned by bstring functions can be assumed to be either NULL or
86 satisfy the above property. (When bstrings are only readable, the mlen >=
87 slen restriction is not required; this is discussed later in this section.)
88 A bstring itself is just a pointer to a struct tagbstring:
90 typedef struct tagbstring * bstring;
92 Note that use of the prefix "tag" in struct tagbstring is required to work
93 around the inconsistency between C and C++'s struct namespace usage. This
94 definition is also considered exposed.
96 Bstrlib basically manages bstrings allocated as a header and an associated
97 data-buffer. Since the implementation is exposed, they can also be
98 constructed manually. Functions which mutate bstrings assume that the header
99 and data buffer have been malloced; the bstring library may perform free() or
100 realloc() on both the header and data buffer of any bstring parameter.
101 Functions which return bstring's create new bstrings. The string memory is
102 freed by a bdestroy() call (or using the bstrFree macro).
104 The following related typedef is also provided:
106 typedef const struct tagbstring * const_bstring;
108 which is also considered exposed. These are directly bstring compatible (no
109 casting required) but are just used for parameters which are meant to be
110 non-mutable. So in general, bstring parameters which are read as input but
111 not meant to be modified will be declared as const_bstring, and bstring
112 parameters which may be modified will be declared as bstring. This convention
113 is recommended for user written functions as well.
115 Since bstrings maintain interoperability with C library char-buffer style
116 strings, all functions which modify, update or create bstrings also append a
117 '\0' character into the position slen + 1. This trailing '\0' character is
118 not required for bstrings input to the bstring functions; this is provided
119 solely as a convenience for interoperability with standard C char-buffer
122 Analogs for the ANSI C string library functions have been created when they
123 are necessary, but have also been left out when they are not. In particular
124 there are no functions analogous to fwrite, or puts just for the purposes of
125 bstring. The ->data member of any string is exposed, and therefore can be
126 used just as easily as char buffers for C functions which read strings.
128 For those that wish to hand construct bstrings, the following should be kept
131 1) While bstrlib can accept constructed bstrings without terminating
132 '\0' characters, the rest of the C language string library will not
133 function properly on such non-terminated strings. This is obvious
134 but must be kept in mind.
135 2) If it is intended that a constructed bstring be written to by the
136 bstring library functions then the data portion should be allocated
137 by the malloc function and the slen and mlen fields should be entered
138 properly. The struct tagbstring header is not reallocated, and only
140 3) Writing arbitrary '\0' characters at various places in the string
141 will not modify its length as perceived by the bstring library
142 functions. In fact, '\0' is a legitimate non-terminating character
143 for a bstring to contain.
144 4) For read only parameters, bstring functions do not check the mlen.
145 I.e., the minimal correctness requirements are reduced to:
147 (slen >= 0 && data != NULL)
149 Better pointer arithmetic
150 -------------------------
152 One built-in feature of '\0' terminated char * strings, is that its very easy
153 and fast to obtain a reference to the tail of any string using pointer
154 arithmetic. Bstrlib does one better by providing a way to get a reference to
155 any substring of a bstring (or any other length delimited block of memory.)
156 So rather than just having pointer arithmetic, with bstrlib one essentially
157 has segment arithmetic. This is achieved using the macro blk2tbstr() which
158 builds a reference to a block of memory and the macro bmid2tbstr() which
159 builds a reference to a segment of a bstring. Bstrlib also includes
160 functions for direct consumption of memory blocks into bstrings, namely
161 bcatblk () and blk2bstr ().
163 One scenario where this can be extremely useful is when string contains many
164 substrings which one would like to pass as read-only reference parameters to
165 some string consuming function without the need to allocate entire new
166 containers for the string data. More concretely, imagine parsing a command
167 line string whose parameters are space delimited. This can only be done for
168 tails of the string with '\0' terminated char * strings.
170 Improved NULL semantics and error handling
171 ------------------------------------------
173 Unless otherwise noted, if a NULL pointer is passed as a bstring or any other
174 detectably illegal parameter, the called function will return with an error
175 indicator (either NULL or BSTR_ERR) rather than simply performing a NULL
176 pointer access, or having undefined behavior.
178 To illustrate the value of this, consider the following example:
180 strcpy (p = malloc (13 * sizeof (char)), "Hello,");
181 strcat (p, " World");
183 This is not correct because malloc may return NULL (due to an out of memory
184 condition), and the behaviour of strcpy is undefined if either of its
185 parameters are NULL. However:
187 bstrcat (p = bfromcstr ("Hello,"), q = bfromcstr (" World"));
190 is well defined, because if either p or q are assigned NULL (indicating a
191 failure to allocate memory) both bstrcat and bdestroy will recognize it and
192 perform no detrimental action.
194 Note that it is not necessary to check any of the members of a returned
195 bstring for internal correctness (in particular the data member does not need
196 to be checked against NULL when the header is non-NULL), since this is
197 assured by the bstring library itself.
202 In addition to the bgets and bread functions, bstrlib can abstract streams
203 with a high performance read only stream called a bStream. In general, the
204 idea is to open a core stream (with something like fopen) then pass its
205 handle as well as a bNread function pointer (like fread) to the bsopen
206 function which will return a handle to an open bStream. Then the functions
207 bsread, bsreadln or bsreadlns can be called to read portions of the stream.
208 Finally, the bsclose function is called to close the bStream -- it will
209 return a handle to the original (core) stream. So bStreams, essentially,
212 The bStreams have two main advantages over the bgets and bread (as well as
213 fgets/ungetc) paradigms:
215 1) Improved functionality via the bunread function which allows a stream to
216 unread characters, giving the bStream stack-like functionality if so
218 2) A very high performance bsreadln function. The C library function fgets()
219 (and the bgets function) can typically be written as a loop on top of
220 fgetc(), thus paying all of the overhead costs of calling fgetc on a per
221 character basis. bsreadln will read blocks at a time, thus amortizing the
222 overhead of fread calls over many characters at once.
224 However, clearly bStreams are suboptimal or unusable for certain kinds of
225 streams (stdin) or certain usage patterns (a few spotty, or non-sequential
226 reads from a slow stream.) For those situations, using bgets will be more
229 The semantics of bStreams allows practical construction of layerable data
230 streams. What this means is that by writing a bNread compatible function on
231 top of a bStream, one can construct a new bStream on top of it. This can be
232 useful for writing multi-pass parsers that don't actually read the entire
233 input more than once and don't require the use of intermediate storage.
238 Aliasing occurs when a function is given two parameters which point to data
239 structures which overlap in the memory they occupy. While this does not
240 disturb read only functions, for many libraries this can make functions that
241 write to these memory locations malfunction. This is a common problem of the
242 C standard library and especially the string functions in the C standard
245 The C standard string library is entirely char by char oriented (as is
246 bstring) which makes conforming implementations alias safe for some
247 scenarios. However no actual detection of aliasing is typically performed,
248 so it is easy to find cases where the aliasing will cause anomolous or
249 undesirable behaviour (consider: strcat (p, p).) The C99 standard includes
250 the "restrict" pointer modifier which allows the compiler to document and
251 assume a no-alias condition on usage. However, only the most trivial cases
252 can be caught (if at all) by the compiler at compile time, and thus there is
253 no actual enforcement of non-aliasing.
255 Bstrlib, by contrast, permits aliasing and is completely aliasing safe, in
256 the C99 sense of aliasing. That is to say, under the assumption that
257 pointers of incompatible types from distinct objects can never alias, bstrlib
258 is completely aliasing safe. (In practice this means that the data buffer
259 portion of any bstring and header of any bstring are assumed to never alias.)
260 With the exception of the reference building macros, the library behaves as
261 if all read-only parameters are first copied and replaced by temporary
262 non-aliased parameters before any writing to any output bstring is performed
263 (though actual copying is extremely rarely ever done.)
265 Besides being a useful safety feature, bstring searching/comparison
266 functions can improve to O(1) execution when aliasing is detected.
268 Note that aliasing detection and handling code in Bstrlib is generally
269 extremely cheap. There is almost never any appreciable performance penalty
270 for using aliased parameters.
275 Nearly every function in Bstrlib is a leaf function, and is completely
276 reenterable with the exception of writing to common bstrings. The split
277 functions which use a callback mechanism requires only that the source string
278 not be destroyed by the callback function unless the callback function returns
279 with an error status (note that Bstrlib functions which return an error do
280 not modify the string in any way.) The string can in fact be modified by the
281 callback and the behaviour is deterministic. See the documentation of the
282 various split functions for more details.
287 One of the basic important premises for Bstrlib is to not to increase the
288 propogation of undefined situations from parameters that are otherwise legal
289 in of themselves. In particular, except for extremely marginal cases, usages
290 of bstrings that use the bstring library functions alone cannot lead to any
291 undefined action. But due to C/C++ language and library limitations, there
292 is no way to define a non-trivial library that is completely without
293 undefined operations. All such possible undefined operations are described
296 1) bstrings or struct tagbstrings that are not explicitely initialized cannot
297 be passed as a parameter to any bstring function.
298 2) The members of the NULL bstring cannot be accessed directly. (Though all
299 APIs and macros detect the NULL bstring.)
300 3) A bstring whose data member has not been obtained from a malloc or
301 compatible call and which is write accessible passed as a writable
302 parameter will lead to undefined results. (i.e., do not writeAllow any
303 constructed bstrings unless the data portion has been obtained from the
305 4) If the headers of two strings alias but are not identical (which can only
306 happen via a defective manual construction), then passing them to a
307 bstring function in which one is writable is not defined.
308 5) If the mlen member is larger than the actual accessible length of the data
309 member for a writable bstring, or if the slen member is larger than the
310 readable length of the data member for a readable bstring, then the
311 corresponding bstring operations are undefined.
312 6) Any bstring definition whose header or accessible data portion has been
313 assigned to inaccessible or otherwise illegal memory clearly cannot be
314 acted upon by the bstring library in any way.
315 7) Destroying the source of an incremental split from within the callback
316 and not returning with a negative value (indicating that it should abort)
317 will lead to undefined behaviour. (Though *modifying* or adjusting the
318 state of the source data, even if those modification fail within the
319 bstrlib API, has well defined behavior.)
320 8) Modifying a bstring which is write protected by direct access has
323 While this may seem like a long list, with the exception of invalid uses of
324 the writeAllow macro, and source destruction during an iterative split
325 without an accompanying abort, no usage of the bstring API alone can cause
326 any undefined scenario to occurr. I.e., the policy of restricting usage of
327 bstrings to the bstring API can significantly reduce the risk of runtime
328 errors (in practice it should eliminate them) related to string manipulation
329 due to undefined action.
334 A C++ wrapper has been created to enable bstring functionality for C++ in the
335 most natural (for C++ programers) way possible. The mandate for the C++
336 wrapper is different from the base C bstring library. Since the C++ language
337 has far more abstracting capabilities, the CBString structure is considered
338 fully abstracted -- i.e., hand generated CBStrings are not supported (though
339 conversion from a struct tagbstring is allowed) and all detectable errors are
340 manifest as thrown exceptions.
342 - The C++ class definitions are all under the namespace Bstrlib. bstrwrap.h
343 enables this namespace (with a using namespace Bstrlib; directive at the
344 end) unless the macro BSTRLIB_DONT_ASSUME_NAMESPACE has been defined before
347 - Erroneous accesses results in an exception being thrown. The exception
348 parameter is of type "struct CBStringException" which is derived from
349 std::exception if STL is used. A verbose description of the error message
350 can be obtained from the what() method.
352 - CBString is a C++ structure derived from a struct tagbstring. An address
353 of a CBString cast to a bstring must not be passed to bdestroy. The bstring
354 C API has been made C++ safe and can be used directly in a C++ project.
356 - It includes constructors which can take a char, '\0' terminated char
357 buffer, tagbstring, (char, repeat-value), a length delimited buffer or a
358 CBStringList to initialize it.
360 - Concatenation is performed with the + and += operators. Comparisons are
361 done with the ==, !=, <, >, <= and >= operators. Note that == and != use
362 the biseq call, while <, >, <= and >= use bstrcmp.
364 - CBString's can be directly cast to const character buffers.
366 - CBString's can be directly cast to double, float, int or unsigned int so
367 long as the CBString are decimal representations of those types (otherwise
368 an exception will be thrown). Converting the other way should be done with
369 the format(a) method(s).
371 - CBString contains the length, character and [] accessor methods. The
372 character and [] accessors are aliases of each other. If the bounds for
373 the string are exceeded, an exception is thrown. To avoid the overhead for
374 this check, first cast the CBString to a (const char *) and use [] to
375 dereference the array as normal. Note that the character and [] accessor
376 methods allows both reading and writing of individual characters.
378 - The methods: format, formata, find, reversefind, findcaseless,
379 reversefindcaseless, midstr, insert, insertchrs, replace, findreplace,
380 findreplacecaseless, remove, findchr, nfindchr, alloc, toupper, tolower,
381 gets, read are analogous to the functions that can be found in the C API.
383 - The caselessEqual and caselessCmp methods are analogous to biseqcaseless
384 and bstricmp functions respectively.
386 - Note that just like the bformat function, the format and formata methods do
387 not automatically cast CBStrings into char * strings for "%s"-type
394 /* The casts are necessary */
395 hw.format ("%s, %s", (const char *)h, (const char *)w);
397 - The methods trunc and repeat have been added instead of using pattern.
399 - ltrim, rtrim and trim methods have been added. These remove characters
400 from a given character string set (defaulting to the whitespace characters)
401 from either the left, right or both ends of the CBString, respectively.
403 - The method setsubstr is also analogous in functionality to bsetstr, except
404 that it cannot be passed NULL. Instead the method fill and the fill-style
405 constructor have been supplied to enable this functionality.
407 - The writeprotect(), writeallow() and iswriteprotected() methods are
408 analogous to the bwriteprotect(), bwriteallow() and biswriteprotected()
409 macros in the C API. Write protection semantics in CBString are stronger
410 than with the C API in that indexed character assignment is checked for
411 write protection. However, unlike with the C API, a write protected
412 CBString can be destroyed by the destructor.
414 - CBStream is a C++ structure which wraps a struct bStream (its not derived
415 from it, since destruction is slightly different). It is constructed by
416 passing in a bNread function pointer and a stream parameter cast to void *.
417 This structure includes methods for detecting eof, setting the buffer
418 length, reading the whole stream or reading entries line by line or block
419 by block, an unread function, and a peek function.
421 - If STL is available, the CBStringList structure is derived from a vector of
422 CBString with various split methods. The split method has been overloaded
423 to accept either a character or CBString as the second parameter (when the
424 split parameter is a CBString any character in that CBString is used as a
425 seperator). The splitstr method takes a CBString as a substring seperator.
426 Joins can be performed via a CBString constructor which takes a
427 CBStringList as a parameter, or just using the CBString::join() method.
429 - If there is proper support for std::iostreams, then the >> and << operators
430 and the getline() function have been added (with semantics the same as
431 those for std::string).
436 A mutable bstring is kind of analogous to a small (two entry) linked list
437 allocated by malloc, with all aliasing completely under programmer control.
438 I.e., manipulation of one bstring will never affect any other distinct
439 bstring unless explicitely constructed to do so by the programmer via hand
440 construction or via building a reference. Bstrlib also does not use any
441 static or global storage, so there are no hidden unremovable race conditions.
442 Bstrings are also clearly not inherently thread local. So just like
443 char *'s, bstrings can be passed around from thread to thread and shared and
444 so on, so long as modifications to a bstring correspond to some kind of
445 exclusive access lock as should be expected (or if the bstring is read-only,
446 which can be enforced by bstring write protection) for any sort of shared
447 object in a multithreaded environment.
452 For convenience, a bsafe module has been included. The idea is that if this
453 module is included, inadvertant usage of the most dangerous C functions will
454 be overridden and lead to an immediate run time abort. Of course, it should
455 be emphasized that usage of this module is completely optional. The
456 intention is essentially to provide an option for creating project safety
457 rules which can be enforced mechanically rather than socially. This is
458 useful for larger, or open development projects where its more difficult to
459 enforce social rules or "coding conventions".
464 Bstrlib is written for the C and C++ languages, which have inherent weaknesses
465 that cannot be easily solved:
467 1. Memory leaks: Forgetting to call bdestroy on a bstring that is about to be
468 unreferenced, just as forgetting to call free on a heap buffer that is
469 about to be dereferenced. Though bstrlib itself is leak free.
470 2. Read before write usage: In C, declaring an auto bstring does not
471 automatically fill it with legal/valid contents. This problem has been
472 somewhat mitigated in C++. (The bstrDeclare and bstrFree macros from
473 bstraux can be used to help mitigate this problem.)
475 Other problems not addressed:
477 3. Built-in mutex usage to automatically avoid all bstring internal race
478 conditions in multitasking environments: The problem with trying to
479 implement such things at this low a level is that it is typically more
480 efficient to use locks in higher level primitives. There is also no
481 platform independent way to implement locks or mutexes.
482 4. Unicode/widecharacter support.
484 Note that except for spotty support of wide characters, the default C
485 standard library does not address any of these problems either.
487 Configurable compilation options
488 --------------------------------
490 All configuration options are meant solely for the purpose of compiler
491 compatibility. Configuration options are not meant to change the semantics
492 or capabilities of the library, except where it is unavoidable.
494 Since some C++ compilers don't include the Standard Template Library and some
495 have the options of disabling exception handling, a number of macros can be
496 used to conditionally compile support for each of this:
500 - defining this will enable the used of the Standard Template Library.
501 Defining BSTRLIB_CAN_USE_STL overrides the BSTRLIB_CANNOT_USE_STL macro.
503 BSTRLIB_CANNOT_USE_STL
505 - defining this will disable the use of the Standard Template Library.
506 Defining BSTRLIB_CAN_USE_STL overrides the BSTRLIB_CANNOT_USE_STL macro.
508 BSTRLIB_CAN_USE_IOSTREAM
510 - defining this will enable the used of streams from class std. Defining
511 BSTRLIB_CAN_USE_IOSTREAM overrides the BSTRLIB_CANNOT_USE_IOSTREAM macro.
513 BSTRLIB_CANNOT_USE_IOSTREAM
515 - defining this will disable the use of streams from class std. Defining
516 BSTRLIB_CAN_USE_IOSTREAM overrides the BSTRLIB_CANNOT_USE_IOSTREAM macro.
518 BSTRLIB_THROWS_EXCEPTIONS
520 - defining this will enable the exception handling within bstring.
521 Defining BSTRLIB_THROWS_EXCEPTIONS overrides the
522 BSTRLIB_DOESNT_THROWS_EXCEPTIONS macro.
524 BSTRLIB_DOESNT_THROW_EXCEPTIONS
526 - defining this will disable the exception handling within bstring.
527 Defining BSTRLIB_THROWS_EXCEPTIONS overrides the
528 BSTRLIB_DOESNT_THROW_EXCEPTIONS macro.
530 Note that these macros must be defined consistently throughout all modules
531 that use CBStrings including bstrwrap.cpp.
533 Some older C compilers do not support functions such as vsnprintf. This is
534 handled by the following macro variables:
538 - defining this indicates that the compiler does not support vsnprintf.
539 This will cause bformat and bformata to not be declared. Note that
540 for some compilers, such as Turbo C, this is set automatically.
541 Defining BSTRLIB_NOVSNP overrides the BSTRLIB_VSNP_OK macro.
545 - defining this will disable the autodetection of compilers the do not
546 support of compilers that do not support vsnprintf.
547 Defining BSTRLIB_NOVSNP overrides the BSTRLIB_VSNP_OK macro.
549 Semantic compilation options
550 ----------------------------
552 Bstrlib comes with very few compilation options for changing the semantics of
553 of the library. These are described below.
555 BSTRLIB_DONT_ASSUME_NAMESPACE
557 - Defining this before including bstrwrap.h will disable the automatic
558 enabling of the Bstrlib namespace for the C++ declarations.
560 BSTRLIB_DONT_USE_VIRTUAL_DESTRUCTOR
562 - Defining this will make the CBString destructor non-virtual.
566 - Defining this will cause the bstrlib modules bstrlib.c and bstrwrap.cpp
567 to invoke a #include "memdbg.h". memdbg.h has to be supplied by the user.
569 Note that these macros must be defined consistently throughout all modules
570 that use bstrings or CBStrings including bstrlib.c, bstraux.c and
573 ===============================================================================
578 bstrlib.c - C implementaion of bstring functions.
579 bstrlib.h - C header file for bstring functions.
580 bstraux.c - C example that implements trivial additional functions.
581 bstraux.h - C header for bstraux.c
582 bstest.c - C unit/regression test for bstrlib.c
584 bstrwrap.cpp - C++ implementation of CBString.
585 bstrwrap.h - C++ header file for CBString.
586 test.cpp - C++ unit/regression test for bstrwrap.cpp
588 bsafe.c - C runtime stubs to abort usage of unsafe C functions.
589 bsafe.h - C header file for bsafe.c functions.
591 C projects need only include bstrlib.h and compile/link bstrlib.c to use the
592 bstring library. C++ projects need to additionally include bstrwrap.h and
593 compile/link bstrwrap.cpp. For both, there may be a need to make choices
594 about feature configuration as described in the "Configurable compilation
595 options" in the section above.
597 Other files that are included in this archive are:
599 license.txt - The BSD license for Bstrlib
600 gpl.txt - The GPL version 2
601 security.txt - A security statement useful for auditting Bstrlib
602 porting.txt - A guide to porting Bstrlib
603 bstrlib.txt - This file
605 ===============================================================================
610 extern bstring bfromcstr (const char * str);
612 Take a standard C library style '\0' terminated char buffer and generate
613 a bstring with the same contents as the char buffer. If an error occurs
618 bstring b = bfromcstr ("Hello");
620 fprintf (stderr, "Out of memory");
622 puts ((char *) b->data);
625 ..........................................................................
627 extern bstring bfromcstralloc (int mlen, const char * str);
629 Create a bstring which contains the contents of the '\0' terminated
630 char * buffer str. The memory buffer backing the bstring is at least
631 mlen characters in length. If an error occurs NULL is returned.
635 bstring b = bfromcstralloc (64, someCstr);
636 if (b) b->data[63] = 'x';
638 The idea is that this will set the 64th character of b to 'x' if it is at
639 least 64 characters long otherwise do nothing. And we know this is well
640 defined so long as b was successfully created, since it will have been
641 allocated with at least 64 characters.
643 ..........................................................................
645 extern bstring blk2bstr (const void * blk, int len);
647 Create a bstring whose contents are described by the contiguous buffer
648 pointing to by blk with a length of len bytes. Note that this function
649 creates a copy of the data in blk, rather than simply referencing it.
650 Compare with the blk2tbstr macro. If an error occurs NULL is returned.
652 ..........................................................................
654 extern char * bstr2cstr (const_bstring s, char z);
656 Create a '\0' terminated char buffer which contains the contents of the
657 bstring s, except that any contained '\0' characters are converted to the
658 character in z. This returned value should be freed with bcstrfree(), by
659 the caller. If an error occurs NULL is returned.
661 ..........................................................................
663 extern int bcstrfree (char * s);
665 Frees a C-string generated by bstr2cstr (). This is normally unnecessary
666 since it just wraps a call to free (), however, if malloc () and free ()
667 have been redefined as a macros within the bstrlib module (via macros in
668 the memdbg.h backdoor) with some difference in behaviour from the std
669 library functions, then this allows a correct way of freeing the memory
670 that allows higher level code to be independent from these macro
673 ..........................................................................
675 extern bstring bstrcpy (const_bstring b1);
677 Make a copy of the passed in bstring. The copied bstring is returned if
678 there is no error, otherwise NULL is returned.
680 ..........................................................................
682 extern int bassign (bstring a, const_bstring b);
684 Overwrite the bstring a with the contents of bstring b. Note that the
685 bstring a must be a well defined and writable bstring. If an error
686 occurs BSTR_ERR is returned and a is not overwritten.
688 ..........................................................................
690 int bassigncstr (bstring a, const char * str);
692 Overwrite the string a with the contents of char * string str. Note that
693 the bstring a must be a well defined and writable bstring. If an error
694 occurs BSTR_ERR is returned and a may be partially overwritten.
696 ..........................................................................
698 int bassignblk (bstring a, const void * s, int len);
700 Overwrite the string a with the contents of the block (s, len). Note that
701 the bstring a must be a well defined and writable bstring. If an error
702 occurs BSTR_ERR is returned and a is not overwritten.
704 ..........................................................................
706 extern int bassignmidstr (bstring a, const_bstring b, int left, int len);
708 Overwrite the bstring a with the middle of contents of bstring b
709 starting from position left and running for a length len. left and
710 len are clamped to the ends of b as with the function bmidstr. Note that
711 the bstring a must be a well defined and writable bstring. If an error
712 occurs BSTR_ERR is returned and a is not overwritten.
714 ..........................................................................
716 extern bstring bmidstr (const_bstring b, int left, int len);
718 Create a bstring which is the substring of b starting from position left
719 and running for a length len (clamped by the end of the bstring b.) If
720 there was no error, the value of this constructed bstring is returned
721 otherwise NULL is returned.
723 ..........................................................................
725 extern int bdelete (bstring s1, int pos, int len);
727 Removes characters from pos to pos+len-1 and shifts the tail of the
728 bstring starting from pos+len to pos. len must be positive for this call
729 to have any effect. The section of the bstring described by (pos, len)
730 is clamped to boundaries of the bstring b. The value BSTR_OK is returned
731 if the operation is successful, otherwise BSTR_ERR is returned.
733 ..........................................................................
735 extern int bconcat (bstring b0, const_bstring b1);
737 Concatenate the bstring b1 to the end of bstring b0. The value BSTR_OK
738 is returned if the operation is successful, otherwise BSTR_ERR is
741 ..........................................................................
743 extern int bconchar (bstring b, char c);
745 Concatenate the character c to the end of bstring b. The value BSTR_OK
746 is returned if the operation is successful, otherwise BSTR_ERR is
749 ..........................................................................
751 extern int bcatcstr (bstring b, const char * s);
753 Concatenate the char * string s to the end of bstring b. The value
754 BSTR_OK is returned if the operation is successful, otherwise BSTR_ERR is
757 ..........................................................................
759 extern int bcatblk (bstring b, const void * s, int len);
761 Concatenate a fixed length buffer (s, len) to the end of bstring b. The
762 value BSTR_OK is returned if the operation is successful, otherwise
763 BSTR_ERR is returned.
765 ..........................................................................
767 extern int biseq (const_bstring b0, const_bstring b1);
769 Compare the bstring b0 and b1 for equality. If the bstrings differ, 0
770 is returned, if the bstrings are the same, 1 is returned, if there is an
771 error, -1 is returned. If the length of the bstrings are different, this
772 function has O(1) complexity. Contained '\0' characters are not treated
773 as a termination character.
775 Note that the semantics of biseq are not completely compatible with
776 bstrcmp because of its different treatment of the '\0' character.
778 ..........................................................................
780 extern int bisstemeqblk (const_bstring b, const void * blk, int len);
782 Compare beginning of bstring b0 with a block of memory of length len for
783 equality. If the beginning of b0 differs from the memory block (or if b0
784 is too short), 0 is returned, if the bstrings are the same, 1 is returned,
785 if there is an error, -1 is returned.
787 ..........................................................................
789 extern int biseqcaseless (const_bstring b0, const_bstring b1);
791 Compare two bstrings for equality without differentiating between case.
792 If the bstrings differ other than in case, 0 is returned, if the bstrings
793 are the same, 1 is returned, if there is an error, -1 is returned. If
794 the length of the bstrings are different, this function is O(1). '\0'
795 termination characters are not treated in any special way.
797 ..........................................................................
799 extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len);
801 Compare beginning of bstring b0 with a block of memory of length len
802 without differentiating between case for equality. If the beginning of b0
803 differs from the memory block other than in case (or if b0 is too short),
804 0 is returned, if the bstrings are the same, 1 is returned, if there is an
805 error, -1 is returned.
807 ..........................................................................
809 extern int biseqcstr (const_bstring b, const char *s);
811 Compare the bstring b and char * bstring s. The C string s must be '\0'
812 terminated at exactly the length of the bstring b, and the contents
813 between the two must be identical with the bstring b with no '\0'
814 characters for the two contents to be considered equal. This is
815 equivalent to the condition that their current contents will be always be
816 equal when comparing them in the same format after converting one or the
817 other. If they are equal 1 is returned, if they are unequal 0 is
818 returned and if there is a detectable error BSTR_ERR is returned.
820 ..........................................................................
822 extern int biseqcstrcaseless (const_bstring b, const char *s);
824 Compare the bstring b and char * string s. The C string s must be '\0'
825 terminated at exactly the length of the bstring b, and the contents
826 between the two must be identical except for case with the bstring b with
827 no '\0' characters for the two contents to be considered equal. This is
828 equivalent to the condition that their current contents will be always be
829 equal ignoring case when comparing them in the same format after
830 converting one or the other. If they are equal, except for case, 1 is
831 returned, if they are unequal regardless of case 0 is returned and if
832 there is a detectable error BSTR_ERR is returned.
834 ..........................................................................
836 extern int bstrcmp (const_bstring b0, const_bstring b1);
838 Compare the bstrings b0 and b1 for ordering. If there is an error,
839 SHRT_MIN is returned, otherwise a value less than or greater than zero,
840 indicating that the bstring pointed to by b0 is lexicographically less
841 than or greater than the bstring pointed to by b1 is returned. If the
842 bstring lengths are unequal but the characters up until the length of the
843 shorter are equal then a value less than, or greater than zero,
844 indicating that the bstring pointed to by b0 is shorter or longer than the
845 bstring pointed to by b1 is returned. 0 is returned if and only if the
846 two bstrings are the same. If the length of the bstrings are different,
847 this function is O(n). Like its standard C library counter part, the
848 comparison does not proceed past any '\0' termination characters
851 The seemingly odd error return value, merely provides slightly more
852 granularity than the undefined situation given in the C library function
853 strcmp. The function otherwise behaves very much like strcmp().
855 Note that the semantics of bstrcmp are not completely compatible with
856 biseq because of its different treatment of the '\0' termination
859 ..........................................................................
861 extern int bstrncmp (const_bstring b0, const_bstring b1, int n);
863 Compare the bstrings b0 and b1 for ordering for at most n characters. If
864 there is an error, SHRT_MIN is returned, otherwise a value is returned as
865 if b0 and b1 were first truncated to at most n characters then bstrcmp
866 was called with these new bstrings are paremeters. If the length of the
867 bstrings are different, this function is O(n). Like its standard C
868 library counter part, the comparison does not proceed past any '\0'
869 termination characters encountered.
871 The seemingly odd error return value, merely provides slightly more
872 granularity than the undefined situation given in the C library function
873 strncmp. The function otherwise behaves very much like strncmp().
875 ..........................................................................
877 extern int bstricmp (const_bstring b0, const_bstring b1);
879 Compare two bstrings without differentiating between case. The return
880 value is the difference of the values of the characters where the two
881 bstrings first differ, otherwise 0 is returned indicating that the
882 bstrings are equal. If the lengths are different, then a difference from
883 0 is given, but if the first extra character is '\0', then it is taken to
884 be the value UCHAR_MAX+1.
886 ..........................................................................
888 extern int bstrnicmp (const_bstring b0, const_bstring b1, int n);
890 Compare two bstrings without differentiating between case for at most n
891 characters. If the position where the two bstrings first differ is
892 before the nth position, the return value is the difference of the values
893 of the characters, otherwise 0 is returned. If the lengths are different
894 and less than n characters, then a difference from 0 is given, but if the
895 first extra character is '\0', then it is taken to be the value
898 ..........................................................................
900 extern int bdestroy (bstring b);
902 Deallocate the bstring passed. Passing NULL in as a parameter will have
903 no effect. Note that both the header and the data portion of the bstring
904 will be freed. No other bstring function which modifies one of its
905 parameters will free or reallocate the header. Because of this, in
906 general, bdestroy cannot be called on any declared struct tagbstring even
907 if it is not write protected. A bstring which is write protected cannot
908 be destroyed via the bdestroy call. Any attempt to do so will result in
909 no action taken, and BSTR_ERR will be returned.
911 Note to C++ users: Passing in a CBString cast to a bstring will lead to
912 undefined behavior (free will be called on the header, rather than the
913 CBString destructor.) Instead just use the ordinary C++ language
914 facilities to dealloc a CBString.
916 ..........................................................................
918 extern int binstr (const_bstring s1, int pos, const_bstring s2);
920 Search for the bstring s2 in s1 starting at position pos and looking in a
921 forward (increasing) direction. If it is found then it returns with the
922 first position after pos where it is found, otherwise it returns BSTR_ERR.
923 The algorithm used is brute force; O(m*n).
925 ..........................................................................
927 extern int binstrr (const_bstring s1, int pos, const_bstring s2);
929 Search for the bstring s2 in s1 starting at position pos and looking in a
930 backward (decreasing) direction. If it is found then it returns with the
931 first position after pos where it is found, otherwise return BSTR_ERR.
932 Note that the current position at pos is tested as well -- so to be
933 disjoint from a previous forward search it is recommended that the
934 position be backed up (decremented) by one position. The algorithm used
935 is brute force; O(m*n).
937 ..........................................................................
939 extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2);
941 Search for the bstring s2 in s1 starting at position pos and looking in a
942 forward (increasing) direction but without regard to case. If it is
943 found then it returns with the first position after pos where it is
944 found, otherwise it returns BSTR_ERR. The algorithm used is brute force;
947 ..........................................................................
949 extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2);
951 Search for the bstring s2 in s1 starting at position pos and looking in a
952 backward (decreasing) direction but without regard to case. If it is
953 found then it returns with the first position after pos where it is
954 found, otherwise return BSTR_ERR. Note that the current position at pos
955 is tested as well -- so to be disjoint from a previous forward search it
956 is recommended that the position be backed up (decremented) by one
957 position. The algorithm used is brute force; O(m*n).
959 ..........................................................................
961 extern int binchr (const_bstring b0, int pos, const_bstring b1);
963 Search for the first position in b0 starting from pos or after, in which
964 one of the characters in b1 is found. This function has an execution
965 time of O(b0->slen + b1->slen). If such a position does not exist in b0,
966 then BSTR_ERR is returned.
968 ..........................................................................
970 extern int binchrr (const_bstring b0, int pos, const_bstring b1);
972 Search for the last position in b0 no greater than pos, in which one of
973 the characters in b1 is found. This function has an execution time
974 of O(b0->slen + b1->slen). If such a position does not exist in b0,
975 then BSTR_ERR is returned.
977 ..........................................................................
979 extern int bninchr (const_bstring b0, int pos, const_bstring b1);
981 Search for the first position in b0 starting from pos or after, in which
982 none of the characters in b1 is found and return it. This function has
983 an execution time of O(b0->slen + b1->slen). If such a position does
984 not exist in b0, then BSTR_ERR is returned.
986 ..........................................................................
988 extern int bninchrr (const_bstring b0, int pos, const_bstring b1);
990 Search for the last position in b0 no greater than pos, in which none of
991 the characters in b1 is found and return it. This function has an
992 execution time of O(b0->slen + b1->slen). If such a position does not
993 exist in b0, then BSTR_ERR is returned.
995 ..........................................................................
997 extern int bstrchr (const_bstring b, int c);
999 Search for the character c in the bstring b forwards from the start of
1000 the bstring. Returns the position of the found character or BSTR_ERR if
1003 NOTE: This has been implemented as a macro on top of bstrchrp ().
1005 ..........................................................................
1007 extern int bstrrchr (const_bstring b, int c);
1009 Search for the character c in the bstring b backwards from the end of the
1010 bstring. Returns the position of the found character or BSTR_ERR if it is
1013 NOTE: This has been implemented as a macro on top of bstrrchrp ().
1015 ..........................................................................
1017 extern int bstrchrp (const_bstring b, int c, int pos);
1019 Search for the character c in b forwards from the position pos
1020 (inclusive). Returns the position of the found character or BSTR_ERR if
1023 ..........................................................................
1025 extern int bstrrchrp (const_bstring b, int c, int pos);
1027 Search for the character c in b backwards from the position pos in bstring
1028 (inclusive). Returns the position of the found character or BSTR_ERR if
1031 ..........................................................................
1033 extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill);
1035 Overwrite the bstring b0 starting at position pos with the bstring b1. If
1036 the position pos is past the end of b0, then the character "fill" is
1037 appended as necessary to make up the gap between the end of b0 and pos.
1038 If b1 is NULL, it behaves as if it were a 0-length bstring. The value
1039 BSTR_OK is returned if the operation is successful, otherwise BSTR_ERR is
1042 ..........................................................................
1044 extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill);
1046 Inserts the bstring s2 into s1 at position pos. If the position pos is
1047 past the end of s1, then the character "fill" is appended as necessary to
1048 make up the gap between the end of s1 and pos. The value BSTR_OK is
1049 returned if the operation is successful, otherwise BSTR_ERR is returned.
1051 ..........................................................................
1053 extern int binsertch (bstring s1, int pos, int len, unsigned char fill);
1055 Inserts the character fill repeatedly into s1 at position pos for a
1056 length len. If the position pos is past the end of s1, then the
1057 character "fill" is appended as necessary to make up the gap between the
1058 end of s1 and the position pos + len (exclusive). The value BSTR_OK is
1059 returned if the operation is successful, otherwise BSTR_ERR is returned.
1061 ..........................................................................
1063 extern int breplace (bstring b1, int pos, int len, const_bstring b2,
1064 unsigned char fill);
1066 Replace a section of a bstring from pos for a length len with the bstring
1067 b2. If the position pos is past the end of b1 then the character "fill"
1068 is appended as necessary to make up the gap between the end of b1 and
1071 ..........................................................................
1073 extern int bfindreplace (bstring b, const_bstring find,
1074 const_bstring replace, int position);
1076 Replace all occurrences of the find substring with a replace bstring
1077 after a given position in the bstring b. The find bstring must have a
1078 length > 0 otherwise BSTR_ERR is returned. This function does not
1079 perform recursive per character replacement; that is to say successive
1080 searches resume at the position after the last replace.
1084 bfindreplace (a0 = bfromcstr("aabaAb"), a1 = bfromcstr("a"),
1085 a2 = bfromcstr("aa"), 0);
1087 Should result in changing a0 to "aaaabaaAb".
1089 This function performs exactly (b->slen - position) bstring comparisons,
1090 and data movement is bounded above by character volume equivalent to size
1091 of the output bstring.
1093 ..........................................................................
1095 extern int bfindreplacecaseless (bstring b, const_bstring find,
1096 const_bstring replace, int position);
1098 Replace all occurrences of the find substring, ignoring case, with a
1099 replace bstring after a given position in the bstring b. The find bstring
1100 must have a length > 0 otherwise BSTR_ERR is returned. This function
1101 does not perform recursive per character replacement; that is to say
1102 successive searches resume at the position after the last replace.
1106 bfindreplacecaseless (a0 = bfromcstr("AAbaAb"), a1 = bfromcstr("a"),
1107 a2 = bfromcstr("aa"), 0);
1109 Should result in changing a0 to "aaaabaaaab".
1111 This function performs exactly (b->slen - position) bstring comparisons,
1112 and data movement is bounded above by character volume equivalent to size
1113 of the output bstring.
1115 ..........................................................................
1117 extern int balloc (bstring b, int length);
1119 Increase the allocated memory backing the data buffer for the bstring b
1120 to a length of at least length. If the memory backing the bstring b is
1121 already large enough, not action is performed. This has no effect on the
1122 bstring b that is visible to the bstring API. Usually this function will
1123 only be used when a minimum buffer size is required coupled with a direct
1124 access to the ->data member of the bstring structure.
1126 Be warned that like any other bstring function, the bstring must be well
1127 defined upon entry to this function. I.e., doing something like:
1129 b->slen *= 2; /* ?? Most likely incorrect */
1130 balloc (b, b->slen);
1132 is invalid, and should be implemented as:
1135 if (BSTR_OK == balloc (b, t = (b->slen * 2))) b->slen = t;
1137 This function will return with BSTR_ERR if b is not detected as a valid
1138 bstring or length is not greater than 0, otherwise BSTR_OK is returned.
1140 ..........................................................................
1142 extern int ballocmin (bstring b, int length);
1144 Change the amount of memory backing the bstring b to at least length.
1145 This operation will never truncate the bstring data including the
1146 extra terminating '\0' and thus will not decrease the length to less than
1147 b->slen + 1. Note that repeated use of this function may cause
1148 performance problems (realloc may be called on the bstring more than
1149 the O(log(INT_MAX)) times). This function will return with BSTR_ERR if b
1150 is not detected as a valid bstring or length is not greater than 0,
1151 otherwise BSTR_OK is returned.
1155 if (BSTR_OK == ballocmin (b, 64)) b->data[63] = 'x';
1157 The idea is that this will set the 64th character of b to 'x' if it is at
1158 least 64 characters long otherwise do nothing. And we know this is well
1159 defined so long as the ballocmin call was successfully, since it will
1160 ensure that b has been allocated with at least 64 characters.
1162 ..........................................................................
1164 int btrunc (bstring b, int n);
1166 Truncate the bstring to at most n characters. This function will return
1167 with BSTR_ERR if b is not detected as a valid bstring or n is less than
1168 0, otherwise BSTR_OK is returned.
1170 ..........................................................................
1172 extern int bpattern (bstring b, int len);
1174 Replicate the starting bstring, b, end to end repeatedly until it
1175 surpasses len characters, then chop the result to exactly len characters.
1176 This function operates in-place. This function will return with BSTR_ERR
1177 if b is NULL or of length 0, otherwise BSTR_OK is returned.
1179 ..........................................................................
1181 extern int btoupper (bstring b);
1183 Convert contents of bstring to upper case. This function will return with
1184 BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK is returned.
1186 ..........................................................................
1188 extern int btolower (bstring b);
1190 Convert contents of bstring to lower case. This function will return with
1191 BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK is returned.
1193 ..........................................................................
1195 extern int bltrimws (bstring b);
1197 Delete whitespace contiguous from the left end of the bstring. This
1198 function will return with BSTR_ERR if b is NULL or of length 0, otherwise
1199 BSTR_OK is returned.
1201 ..........................................................................
1203 extern int brtrimws (bstring b);
1205 Delete whitespace contiguous from the right end of the bstring. This
1206 function will return with BSTR_ERR if b is NULL or of length 0, otherwise
1207 BSTR_OK is returned.
1209 ..........................................................................
1211 extern int btrimws (bstring b);
1213 Delete whitespace contiguous from both ends of the bstring. This function
1214 will return with BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK
1217 ..........................................................................
1219 extern int bstrListCreate (void);
1221 Create an empty struct bstrList. The struct bstrList output structure is
1222 declared as follows:
1229 The entry field actually is an array with qty number entries. The mlen
1230 record counts the maximum number of bstring's for which there is memory
1231 in the entry record.
1233 The Bstrlib API does *NOT* include a comprehensive set of functions for
1234 full management of struct bstrList in an abstracted way. The reason for
1235 this is because aliasing semantics of the list are best left to the user
1236 of this function, and performance varies wildly depending on the
1237 assumptions made. For a complete list of bstring data type it is
1238 recommended that the C++ public std::vector<CBString> be used, since its
1239 semantics are usage are more standard.
1241 ..........................................................................
1243 extern int bstrListDestroy (struct bstrList * sl);
1245 Destroy a struct bstrList structure that was returned by the bsplit
1246 function. Note that this will destroy each bstring in the ->entry array
1247 as well. See bstrListCreate() above for structure of struct bstrList.
1249 ..........................................................................
1251 extern int bstrListAlloc (struct bstrList * sl, int msz);
1253 Ensure that there is memory for at least msz number of entries for the
1256 ..........................................................................
1258 extern int bstrListAllocMin (struct bstrList * sl, int msz);
1260 Try to allocate the minimum amount of memory for the list to include at
1261 least msz entries or sl->qty whichever is greater.
1263 ..........................................................................
1265 extern struct bstrList * bsplit (bstring str, unsigned char splitChar);
1267 Create an array of sequential substrings from str divided by the
1268 character splitChar. Successive occurrences of the splitChar will be
1269 divided by empty bstring entries, following the semantics from the Python
1270 programming language. To reclaim the memory from this output structure,
1271 bstrListDestroy () should be called. See bstrListCreate() above for
1272 structure of struct bstrList.
1274 ..........................................................................
1276 extern struct bstrList * bsplits (bstring str, const_bstring splitStr);
1278 Create an array of sequential substrings from str divided by any
1279 character contained in splitStr. An empty splitStr causes a single entry
1280 bstrList containing a copy of str to be returned. See bstrListCreate()
1281 above for structure of struct bstrList.
1283 ..........................................................................
1285 extern struct bstrList * bsplitstr (bstring str, const_bstring splitStr);
1287 Create an array of sequential substrings from str divided by the entire
1288 substring splitStr. An empty splitStr causes a single entry bstrList
1289 containing a copy of str to be returned. See bstrListCreate() above for
1290 structure of struct bstrList.
1292 ..........................................................................
1294 extern bstring bjoin (const struct bstrList * bl, const_bstring sep);
1296 Join the entries of a bstrList into one bstring by sequentially
1297 concatenating them with the sep bstring in between. If sep is NULL, it
1298 is treated as if it were the empty bstring. Note that:
1300 bjoin (l = bsplit (b, s->data[0]), s);
1302 should result in a copy of b, if s->slen is 1. If there is an error NULL
1303 is returned, otherwise a bstring with the correct result is returned.
1304 See bstrListCreate() above for structure of struct bstrList.
1306 ..........................................................................
1308 extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos,
1309 int (* cb) (void * parm, int ofs, int len), void * parm);
1311 Iterate the set of disjoint sequential substrings over str starting at
1312 position pos divided by the character splitChar. The parm passed to
1313 bsplitcb is passed on to cb. If the function cb returns a value < 0,
1314 then further iterating is halted and this value is returned by bsplitcb.
1316 Note: Non-destructive modification of str from within the cb function
1317 while performing this split is not undefined. bsplitcb behaves in
1318 sequential lock step with calls to cb. I.e., after returning from a cb
1319 that return a non-negative integer, bsplitcb continues from the position
1320 1 character after the last detected split character and it will halt
1321 immediately if the length of str falls below this point. However, if the
1322 cb function destroys str, then it *must* return with a negative value,
1323 otherwise bsplitcb will continue in an undefined manner.
1325 This function is provided as an incremental alternative to bsplit that is
1326 abortable and which does not impose additional memory allocation.
1328 ..........................................................................
1330 extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos,
1331 int (* cb) (void * parm, int ofs, int len), void * parm);
1333 Iterate the set of disjoint sequential substrings over str starting at
1334 position pos divided by any of the characters in splitStr. An empty
1335 splitStr causes the whole str to be iterated once. The parm passed to
1336 bsplitcb is passed on to cb. If the function cb returns a value < 0,
1337 then further iterating is halted and this value is returned by bsplitcb.
1339 Note: Non-destructive modification of str from within the cb function
1340 while performing this split is not undefined. bsplitscb behaves in
1341 sequential lock step with calls to cb. I.e., after returning from a cb
1342 that return a non-negative integer, bsplitscb continues from the position
1343 1 character after the last detected split character and it will halt
1344 immediately if the length of str falls below this point. However, if the
1345 cb function destroys str, then it *must* return with a negative value,
1346 otherwise bsplitscb will continue in an undefined manner.
1348 This function is provided as an incremental alternative to bsplits that
1349 is abortable and which does not impose additional memory allocation.
1351 ..........................................................................
1353 extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos,
1354 int (* cb) (void * parm, int ofs, int len), void * parm);
1356 Iterate the set of disjoint sequential substrings over str starting at
1357 position pos divided by the entire substring splitStr. An empty splitStr
1358 causes each character of str to be iterated. The parm passed to bsplitcb
1359 is passed on to cb. If the function cb returns a value < 0, then further
1360 iterating is halted and this value is returned by bsplitcb.
1362 Note: Non-destructive modification of str from within the cb function
1363 while performing this split is not undefined. bsplitstrcb behaves in
1364 sequential lock step with calls to cb. I.e., after returning from a cb
1365 that return a non-negative integer, bsplitstrcb continues from the position
1366 1 character after the last detected split character and it will halt
1367 immediately if the length of str falls below this point. However, if the
1368 cb function destroys str, then it *must* return with a negative value,
1369 otherwise bsplitscb will continue in an undefined manner.
1371 This function is provided as an incremental alternative to bsplitstr that
1372 is abortable and which does not impose additional memory allocation.
1374 ..........................................................................
1376 extern bstring bformat (const char * fmt, ...);
1378 Takes the same parameters as printf (), but rather than outputting
1379 results to stdio, it forms a bstring which contains what would have been
1380 output. Note that if there is an early generation of a '\0' character,
1381 the bstring will be truncated to this end point.
1383 Note that %s format tokens correspond to '\0' terminated char * buffers,
1384 not bstrings. To print a bstring, first dereference data element of the
1387 /* b1->data needs to be '\0' terminated, so tagbstrings generated
1388 by blk2tbstr () might not be suitable. */
1389 b0 = bformat ("Hello, %s", b1->data);
1391 Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been
1392 compiled the bformat function is not present.
1394 ..........................................................................
1396 extern int bformata (bstring b, const char * fmt, ...);
1398 In addition to the initial output buffer b, bformata takes the same
1399 parameters as printf (), but rather than outputting results to stdio, it
1400 appends the results to the initial bstring parameter. Note that if
1401 there is an early generation of a '\0' character, the bstring will be
1402 truncated to this end point.
1404 Note that %s format tokens correspond to '\0' terminated char * buffers,
1405 not bstrings. To print a bstring, first dereference data element of the
1408 /* b1->data needs to be '\0' terminated, so tagbstrings generated
1409 by blk2tbstr () might not be suitable. */
1410 bformata (b0 = bfromcstr ("Hello"), ", %s", b1->data);
1412 Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been
1413 compiled the bformata function is not present.
1415 ..........................................................................
1417 extern int bassignformat (bstring b, const char * fmt, ...);
1419 After the first parameter, it takes the same parameters as printf (), but
1420 rather than outputting results to stdio, it outputs the results to
1421 the bstring parameter b. Note that if there is an early generation of a
1422 '\0' character, the bstring will be truncated to this end point.
1424 Note that %s format tokens correspond to '\0' terminated char * buffers,
1425 not bstrings. To print a bstring, first dereference data element of the
1428 /* b1->data needs to be '\0' terminated, so tagbstrings generated
1429 by blk2tbstr () might not be suitable. */
1430 bassignformat (b0 = bfromcstr ("Hello"), ", %s", b1->data);
1432 Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been
1433 compiled the bassignformat function is not present.
1435 ..........................................................................
1437 extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist);
1439 The bvcformata function formats data under control of the format control
1440 string fmt and attempts to append the result to b. The fmt parameter is
1441 the same as that of the printf function. The variable argument list is
1442 replaced with arglist, which has been initialized by the va_start macro.
1443 The size of the output is upper bounded by count. If the required output
1444 exceeds count, the string b is not augmented with any contents and a value
1445 below BSTR_ERR is returned. If a value below -count is returned then it
1446 is recommended that the negative of this value be used as an update to the
1447 count in a subsequent pass. On other errors, such as running out of
1448 memory, parameter errors or numeric wrap around BSTR_ERR is returned.
1449 BSTR_OK is returned when the output is successfully generated and
1452 Note: There is no sanity checking of arglist, and this function is
1453 destructive of the contents of b from the b->slen point onward. If there
1454 is an early generation of a '\0' character, the bstring will be truncated
1457 Although this function is part of the external API for Bstrlib, the
1458 interface and semantics (length limitations, and unusual return codes)
1459 are fairly atypical. The real purpose for this function is to provide an
1460 engine for the bvformata macro.
1462 Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been
1463 compiled the bvcformata function is not present.
1465 ..........................................................................
1467 extern bstring bread (bNread readPtr, void * parm);
1468 typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem,
1471 Read an entire stream into a bstring, verbatum. The readPtr function
1472 pointer is compatible with fread sematics, except that it need not obtain
1473 the stream data from a file. The intention is that parm would contain
1474 the stream data context/state required (similar to the role of the FILE*
1475 I/O stream parameter of fread.)
1477 Abstracting the block read function allows for block devices other than
1478 file streams to be read if desired. Note that there is an ANSI
1479 compatibility issue if "fread" is used directly; see the ANSI issues
1482 ..........................................................................
1484 extern int breada (bstring b, bNread readPtr, void * parm);
1486 Read an entire stream and append it to a bstring, verbatum. Behaves
1487 like bread, except that it appends it results to the bstring b.
1488 BSTR_ERR is returned on error, otherwise 0 is returned.
1490 ..........................................................................
1492 extern bstring bgets (bNgetc getcPtr, void * parm, char terminator);
1493 typedef int (* bNgetc) (void * parm);
1495 Read a bstring from a stream. As many bytes as is necessary are read
1496 until the terminator is consumed or no more characters are available from
1497 the stream. If read from the stream, the terminator character will be
1498 appended to the end of the returned bstring. The getcPtr function must
1499 have the same semantics as the fgetc C library function (i.e., returning
1500 an integer whose value is negative when there are no more characters
1501 available, otherwise the value of the next available unsigned character
1502 from the stream.) The intention is that parm would contain the stream
1503 data context/state required (similar to the role of the FILE* I/O stream
1504 parameter of fgets.) If no characters are read, or there is some other
1505 detectable error, NULL is returned.
1507 bgets will never call the getcPtr function more often than necessary to
1508 construct its output (including a single call, if required, to determine
1509 that the stream contains no more characters.)
1511 Abstracting the character stream function and terminator character allows
1512 for different stream devices and string formats other than '\n'
1513 terminated lines in a file if desired (consider \032 terminated email
1514 messages, in a UNIX mailbox for example.)
1516 For files, this function can be used analogously as fgets as follows:
1519 if (fp) b = bgets ((bNgetc) fgetc, fp, '\n');
1521 (Note that only one terminator character can be used, and that '\0' is
1522 not assumed to terminate the stream in addition to the terminator
1523 character. This is consistent with the semantics of fgets.)
1525 ..........................................................................
1527 extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator);
1529 Read from a stream and concatenate to a bstring. Behaves like bgets,
1530 except that it appends it results to the bstring b. The value 1 is
1531 returned if no characters are read before a negative result is returned
1532 from getcPtr. Otherwise BSTR_ERR is returned on error, and 0 is returned
1533 in other normal cases.
1535 ..........................................................................
1537 extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator);
1539 Read from a stream and concatenate to a bstring. Behaves like bgets,
1540 except that it assigns the results to the bstring b. The value 1 is
1541 returned if no characters are read before a negative result is returned
1542 from getcPtr. Otherwise BSTR_ERR is returned on error, and 0 is returned
1543 in other normal cases.
1545 ..........................................................................
1547 extern struct bStream * bsopen (bNread readPtr, void * parm);
1549 Wrap a given open stream (described by a fread compatible function
1550 pointer and stream handle) into an open bStream suitable for the bstring
1551 library streaming functions.
1553 ..........................................................................
1555 extern void * bsclose (struct bStream * s);
1557 Close the bStream, and return the handle to the stream that was
1558 originally used to open the given stream. If s is NULL or detectably
1559 invalid, NULL will be returned.
1561 ..........................................................................
1563 extern int bsbufflength (struct bStream * s, int sz);
1565 Set the length of the buffer used by the bStream. If sz is the macro
1566 BSTR_BS_BUFF_LENGTH_GET (which is 0), the length is not set. If s is
1567 NULL or sz is negative, the function will return with BSTR_ERR, otherwise
1568 this function returns with the previous length.
1570 ..........................................................................
1572 extern int bsreadln (bstring r, struct bStream * s, char terminator);
1574 Read a bstring terminated by the terminator character or the end of the
1575 stream from the bStream (s) and return it into the parameter r. The
1576 matched terminator, if found, appears at the end of the line read. If
1577 the stream has been exhausted of all available data, before any can be
1578 read, BSTR_ERR is returned. This function may read additional characters
1579 into the stream buffer from the core stream that are not returned, but
1580 will be retained for subsequent read operations. When reading from high
1581 speed streams, this function can perform significantly faster than bgets.
1583 ..........................................................................
1585 extern int bsreadlna (bstring r, struct bStream * s, char terminator);
1587 Read a bstring terminated by the terminator character or the end of the
1588 stream from the bStream (s) and concatenate it to the parameter r. The
1589 matched terminator, if found, appears at the end of the line read. If
1590 the stream has been exhausted of all available data, before any can be
1591 read, BSTR_ERR is returned. This function may read additional characters
1592 into the stream buffer from the core stream that are not returned, but
1593 will be retained for subsequent read operations. When reading from high
1594 speed streams, this function can perform significantly faster than bgets.
1596 ..........................................................................
1598 extern int bsreadlns (bstring r, struct bStream * s, bstring terminators);
1600 Read a bstring terminated by any character in the terminators bstring or
1601 the end of the stream from the bStream (s) and return it into the
1602 parameter r. This function may read additional characters from the core
1603 stream that are not returned, but will be retained for subsequent read
1606 ..........................................................................
1608 extern int bsreadlnsa (bstring r, struct bStream * s, bstring terminators);
1610 Read a bstring terminated by any character in the terminators bstring or
1611 the end of the stream from the bStream (s) and concatenate it to the
1612 parameter r. If the stream has been exhausted of all available data,
1613 before any can be read, BSTR_ERR is returned. This function may read
1614 additional characters from the core stream that are not returned, but
1615 will be retained for subsequent read operations.
1617 ..........................................................................
1619 extern int bsread (bstring r, struct bStream * s, int n);
1621 Read a bstring of length n (or, if it is fewer, as many bytes as is
1622 remaining) from the bStream. This function will read the minimum
1623 required number of additional characters from the core stream. When the
1624 stream is at the end of the file BSTR_ERR is returned, otherwise BSTR_OK
1627 ..........................................................................
1629 extern int bsreada (bstring r, struct bStream * s, int n);
1631 Read a bstring of length n (or, if it is fewer, as many bytes as is
1632 remaining) from the bStream and concatenate it to the parameter r. This
1633 function will read the minimum required number of additional characters
1634 from the core stream. When the stream is at the end of the file BSTR_ERR
1635 is returned, otherwise BSTR_OK is returned.
1637 ..........................................................................
1639 extern int bsunread (struct bStream * s, const_bstring b);
1641 Insert a bstring into the bStream at the current position. These
1642 characters will be read prior to those that actually come from the core
1645 ..........................................................................
1647 extern int bspeek (bstring r, const struct bStream * s);
1649 Return the number of currently buffered characters from the bStream that
1650 will be read prior to reads from the core stream, and append it to the
1653 ..........................................................................
1655 extern int bssplitscb (struct bStream * s, const_bstring splitStr,
1656 int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
1658 Iterate the set of disjoint sequential substrings over the stream s
1659 divided by any character from the bstring splitStr. The parm passed to
1660 bssplitscb is passed on to cb. If the function cb returns a value < 0,
1661 then further iterating is halted and this return value is returned by
1664 Note: At the point of calling the cb function, the bStream pointer is
1665 pointed exactly at the position right after having read the split
1666 character. The cb function can act on the stream by causing the bStream
1667 pointer to move, and bssplitscb will continue by starting the next split
1668 at the position of the pointer after the return from cb.
1670 However, if the cb causes the bStream s to be destroyed then the cb must
1671 return with a negative value, otherwise bssplitscb will continue in an
1674 This function is provided as way to incrementally parse through a file
1675 or other generic stream that in total size may otherwise exceed the
1676 practical or desired memory available. As with the other split callback
1677 based functions this is abortable and does not impose additional memory
1680 ..........................................................................
1682 extern int bssplitstrcb (struct bStream * s, const_bstring splitStr,
1683 int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
1685 Iterate the set of disjoint sequential substrings over the stream s
1686 divided by the entire substring splitStr. The parm passed to
1687 bssplitstrcb is passed on to cb. If the function cb returns a
1688 value < 0, then further iterating is halted and this return value is
1689 returned by bssplitstrcb.
1691 Note: At the point of calling the cb function, the bStream pointer is
1692 pointed exactly at the position right after having read the split
1693 character. The cb function can act on the stream by causing the bStream
1694 pointer to move, and bssplitstrcb will continue by starting the next
1695 split at the position of the pointer after the return from cb.
1697 However, if the cb causes the bStream s to be destroyed then the cb must
1698 return with a negative value, otherwise bssplitscb will continue in an
1701 This function is provided as way to incrementally parse through a file
1702 or other generic stream that in total size may otherwise exceed the
1703 practical or desired memory available. As with the other split callback
1704 based functions this is abortable and does not impose additional memory
1707 ..........................................................................
1709 extern int bseof (const struct bStream * s);
1711 Return the defacto "EOF" (end of file) state of a stream (1 if the
1712 bStream is in an EOF state, 0 if not, and BSTR_ERR if stream is closed or
1713 detectably erroneous.) When the readPtr callback returns a value <= 0
1714 the stream reaches its "EOF" state. Note that bunread with non-empty
1715 content will essentially turn off this state, and the stream will not be
1716 in its "EOF" state so long as its possible to read more data out of it.
1718 Also note that the semantics of bseof() are slightly different from
1719 something like feof(). I.e., reaching the end of the stream does not
1720 necessarily guarantee that bseof() will return with a value indicating
1721 that this has happened. bseof() will only return indicating that it has
1722 reached the "EOF" and an attempt has been made to read past the end of
1728 The macros described below are shown in a prototype form indicating their
1729 intended usage. Note that the parameters passed to these macros will be
1730 referenced multiple times. As with all macros, programmer care is
1731 required to guard against unintended side effects.
1733 int blengthe (const_bstring b, int err);
1735 Returns the length of the bstring. If the bstring is NULL err is
1738 ..........................................................................
1740 int blength (const_bstring b);
1742 Returns the length of the bstring. If the bstring is NULL, the length
1745 ..........................................................................
1747 int bchare (const_bstring b, int p, int c);
1749 Returns the p'th character of the bstring b. If the position p refers to
1750 a position that does not exist in the bstring or the bstring is NULL,
1753 ..........................................................................
1755 char bchar (const_bstring b, int p);
1757 Returns the p'th character of the bstring b. If the position p refers to
1758 a position that does not exist in the bstring or the bstring is NULL,
1759 then '\0' is returned.
1761 ..........................................................................
1763 char * bdatae (bstring b, char * err);
1765 Returns the char * data portion of the bstring b. If b is NULL, err is
1768 ..........................................................................
1770 char * bdata (bstring b);
1772 Returns the char * data portion of the bstring b. If b is NULL, NULL is
1775 ..........................................................................
1777 char * bdataofse (bstring b, int ofs, char * err);
1779 Returns the char * data portion of the bstring b offset by ofs. If b is
1780 NULL, err is returned.
1782 ..........................................................................
1784 char * bdataofs (bstring b, int ofs);
1786 Returns the char * data portion of the bstring b offset by ofs. If b is
1787 NULL, NULL is returned.
1789 ..........................................................................
1791 struct tagbstring var = bsStatic ("...");
1793 The bsStatic macro allows for static declarations of literal string
1794 constants as struct tagbstring structures. The resulting tagbstring does
1795 not need to be freed or destroyed. Note that this macro is only well
1796 defined for string literal arguments. For more general string pointers,
1797 use the btfromcstr macro.
1799 The resulting struct tagbstring is permanently write protected. Attempts
1800 to write to this struct tagbstring from any bstrlib function will lead to
1801 BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct
1802 tagbstring has no effect.
1804 ..........................................................................
1806 <void * blk, int len> <- bsStaticBlkParms ("...")
1808 The bsStaticBlkParms macro emits a pair of comma seperated parameters
1809 corresponding to the block parameters for the block functions in Bstrlib
1810 (i.e., blk2bstr, bcatblk, blk2tbstr, bisstemeqblk, bisstemeqcaselessblk.)
1811 Note that this macro is only well defined for string literal arguments.
1815 bstring b = blk2bstr (bsStaticBlkParms ("Fast init. "));
1816 bcatblk (b, bsStaticBlkParms ("No frills fast concatenation."));
1818 These are faster than using bfromcstr() and bcatcstr() respectively
1819 because the length of the inline string is known as a compile time
1820 constant. Also note that seperate struct tagbstring declarations for
1821 holding the output of a bsStatic() macro are not required.
1823 ..........................................................................
1825 void btfromcstr (struct tagbstring& t, const char * s);
1827 Fill in the tagbstring t with the '\0' terminated char buffer s. This
1828 action is purely reference oriented; no memory management is done. The
1829 data member is just assigned s, and slen is assigned the strlen of s.
1830 The s parameter is accessed exactly once in this macro.
1832 The resulting struct tagbstring is initially write protected. Attempts
1833 to write to this struct tagbstring in a write protected state from any
1834 bstrlib function will lead to BSTR_ERR being returned. Invoke the
1835 bwriteallow on this struct tagbstring to make it writeable (though this
1836 requires that s be obtained from a function compatible with malloc.)
1838 ..........................................................................
1840 void btfromblk (struct tagbstring& t, void * s, int len);
1842 Fill in the tagbstring t with the data buffer s with length len. This
1843 action is purely reference oriented; no memory management is done. The
1844 data member of t is just assigned s, and slen is assigned len. Note that
1845 the buffer is not appended with a '\0' character. The s and len
1846 parameters are accessed exactly once each in this macro.
1848 The resulting struct tagbstring is initially write protected. Attempts
1849 to write to this struct tagbstring in a write protected state from any
1850 bstrlib function will lead to BSTR_ERR being returned. Invoke the
1851 bwriteallow on this struct tagbstring to make it writeable (though this
1852 requires that s be obtained from a function compatible with malloc.)
1854 ..........................................................................
1856 void btfromblkltrimws (struct tagbstring& t, void * s, int len);
1858 Fill in the tagbstring t with the data buffer s with length len after it
1859 has been left trimmed. This action is purely reference oriented; no
1860 memory management is done. The data member of t is just assigned to a
1861 pointer inside the buffer s. Note that the buffer is not appended with a
1862 '\0' character. The s and len parameters are accessed exactly once each
1865 The resulting struct tagbstring is permanently write protected. Attempts
1866 to write to this struct tagbstring from any bstrlib function will lead to
1867 BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct
1868 tagbstring has no effect.
1870 ..........................................................................
1872 void btfromblkrtrimws (struct tagbstring& t, void * s, int len);
1874 Fill in the tagbstring t with the data buffer s with length len after it
1875 has been right trimmed. This action is purely reference oriented; no
1876 memory management is done. The data member of t is just assigned to a
1877 pointer inside the buffer s. Note that the buffer is not appended with a
1878 '\0' character. The s and len parameters are accessed exactly once each
1881 The resulting struct tagbstring is permanently write protected. Attempts
1882 to write to this struct tagbstring from any bstrlib function will lead to
1883 BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct
1884 tagbstring has no effect.
1886 ..........................................................................
1888 void btfromblktrimws (struct tagbstring& t, void * s, int len);
1890 Fill in the tagbstring t with the data buffer s with length len after it
1891 has been left and right trimmed. This action is purely reference
1892 oriented; no memory management is done. The data member of t is just
1893 assigned to a pointer inside the buffer s. Note that the buffer is not
1894 appended with a '\0' character. The s and len parameters are accessed
1895 exactly once each in this macro.
1897 The resulting struct tagbstring is permanently write protected. Attempts
1898 to write to this struct tagbstring from any bstrlib function will lead to
1899 BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct
1900 tagbstring has no effect.
1902 ..........................................................................
1904 void bmid2tbstr (struct tagbstring& t, bstring b, int pos, int len);
1906 Fill the tagbstring t with the substring from b, starting from position
1907 pos with a length len. The segment is clamped by the boundaries of
1908 the bstring b. This action is purely reference oriented; no memory
1909 management is done. Note that the buffer is not appended with a '\0'
1910 character. Note that the t parameter to this macro may be accessed
1911 multiple times. Note that the contents of t will become undefined
1912 if the contents of b change or are destroyed.
1914 The resulting struct tagbstring is permanently write protected. Attempts
1915 to write to this struct tagbstring in a write protected state from any
1916 bstrlib function will lead to BSTR_ERR being returned. Invoking the
1917 bwriteallow macro on this struct tagbstring will have no effect.
1919 ..........................................................................
1921 void bvformata (int& ret, bstring b, const char * format, lastarg);
1923 Append the bstring b with printf like formatting with the format control
1924 string, and the arguments taken from the ... list of arguments after
1925 lastarg passed to the containing function. If the containing function
1926 does not have ... parameters or lastarg is not the last named parameter
1927 before the ... then the results are undefined. If successful, the
1928 results are appended to b and BSTR_OK is assigned to ret. Otherwise
1929 BSTR_ERR is assigned to ret.
1933 void dbgerror (FILE * fp, const char * fmt, ...) {
1936 bvformata (ret, b = bfromcstr ("DBG: "), fmt, fmt);
1937 if (BSTR_OK == ret) fputs ((char *) bdata (b), fp);
1941 Note that if the BSTRLIB_NOVSNP macro was set when bstrlib had been
1942 compiled the bvformata macro will not link properly. If the
1943 BSTRLIB_NOVSNP macro has been set, the bvformata macro will not be
1946 ..........................................................................
1948 void bwriteprotect (struct tagbstring& t);
1950 Disallow bstring from being written to via the bstrlib API. Attempts to
1951 write to the resulting tagbstring from any bstrlib function will lead to
1952 BSTR_ERR being returned.
1954 Note: bstrings which are write protected cannot be destroyed via bdestroy.
1956 Note to C++ users: Setting a CBString as write protected will not prevent
1957 it from being destroyed by the destructor.
1959 ..........................................................................
1961 void bwriteallow (struct tagbstring& t);
1963 Allow bstring to be written to via the bstrlib API. Note that such an
1964 action makes the bstring both writable and destroyable. If the bstring is
1965 not legitimately writable (as is the case for struct tagbstrings
1966 initialized with a bsStatic value), the results of this are undefined.
1968 Note that invoking the bwriteallow macro may increase the number of
1969 reallocs by one more than necessary for every call to bwriteallow
1970 interleaved with any bstring API which writes to this bstring.
1972 ..........................................................................
1974 int biswriteprotected (struct tagbstring& t);
1976 Returns 1 if the bstring is write protected, otherwise 0 is returned.
1978 ===============================================================================
1983 The bstest module is just a unit test for the bstrlib module. For correct
1984 implementations of bstrlib, it should execute with 0 failures being reported.
1985 This test should be utilized if modifications/customizations to bstrlib have
1986 been performed. It tests each core bstrlib function with bstrings of every
1987 mode (read-only, NULL, static and mutable) and ensures that the expected
1988 semantics are observed (including results that should indicate an error). It
1989 also tests for aliasing support. Passing bstest is a necessary but not a
1990 sufficient condition for ensuring the correctness of the bstrlib module.
1996 The test module is just a unit test for the bstrwrap module. For correct
1997 implementations of bstrwrap, it should execute with 0 failures being
1998 reported. This test should be utilized if modifications/customizations to
1999 bstrwrap have been performed. It tests each core bstrwrap function with
2000 CBStrings write protected or not and ensures that the expected semantics are
2001 observed (including expected exceptions.) Note that exceptions cannot be
2002 disabled to run this test. Passing test is a necessary but not a sufficient
2003 condition for ensuring the correctness of the bstrwrap module.
2005 ===============================================================================
2007 Using Bstring and CBString as an alternative to the C library
2008 -------------------------------------------------------------
2010 First let us give a table of C library functions and the alternative bstring
2011 functions and CBString methods that should be used instead of them.
2013 C-library Bstring alternative CBString alternative
2014 --------- ------------------- --------------------
2016 strcpy bassign = operator
2017 strncpy bassignmidstr ::midstr
2018 strcat bconcat += operator
2019 strncat bconcat + btrunc += operator + ::trunc
2020 strtok bsplit, bsplits ::split
2021 sprintf b(assign)format ::format
2022 snprintf b(assign)format + btrunc ::format + ::trunc
2023 vsprintf bvformata bvformata
2025 vsnprintf bvformata + btrunc bvformata + btrunc
2026 vfprintf bvformata + fputs use bvformata + fputs
2027 strcmp biseq, bstrcmp comparison operators.
2028 strncmp bstrncmp, memcmp bstrncmp, memcmp
2029 strlen ->slen, blength ::length
2030 strdup bstrcpy constructor
2031 strset bpattern ::fill
2032 strstr binstr ::find
2033 strpbrk binchr ::findchr
2034 stricmp bstricmp cast & use bstricmp
2035 strlwr btolower cast & use btolower
2036 strupr btoupper cast & use btoupper
2037 strrev bReverse (aux module) cast & use bReverse
2038 strchr bstrchr cast & use bstrchr
2039 strspnp use strspn use strspn
2040 ungetc bsunread bsunread
2042 The top 9 C functions listed here are troublesome in that they impose memory
2043 management in the calling function. The Bstring and CBstring interfaces have
2044 built-in memory management, so there is far less code with far less potential
2045 for buffer overrun problems. strtok can only be reliably called as a "leaf"
2046 calculation, since it (quite bizarrely) maintains hidden internal state. And
2047 gets is well known to be broken no matter what. The Bstrlib alternatives do
2048 not suffer from those sorts of problems.
2050 The substitute for strncat can be performed with higher performance by using
2051 the blk2tbstr macro to create a presized second operand for bconcat.
2053 C-library Bstring alternative CBString alternative
2054 --------- ------------------- --------------------
2055 strspn strspn acceptable strspn acceptable
2056 strcspn strcspn acceptable strcspn acceptable
2057 strnset strnset acceptable strnset acceptable
2058 printf printf acceptable printf acceptable
2059 puts puts acceptable puts acceptable
2060 fprintf fprintf acceptable fprintf acceptable
2061 fputs fputs acceptable fputs acceptable
2062 memcmp memcmp acceptable memcmp acceptable
2064 Remember that Bstring (and CBstring) functions will automatically append the
2065 '\0' character to the character data buffer. So by simply accessing the data
2066 buffer directly, ordinary C string library functions can be called directly
2067 on them. Note that bstrcmp is not the same as memcmp in exactly the same way
2068 that strcmp is not the same as memcmp.
2070 C-library Bstring alternative CBString alternative
2071 --------- ------------------- --------------------
2072 fread balloc + fread ::alloc + fread
2073 fgets balloc + fgets ::alloc + fgets
2075 These are odd ones because of the exact sizing of the buffer required. The
2076 Bstring and CBString alternatives requires that the buffers are forced to
2077 hold at least the prescribed length, then just use fread or fgets directly.
2078 However, typically the automatic memory management of Bstring and CBstring
2079 will make the typical use of fgets and fread to read specifically sized
2080 strings unnecessary.
2082 Implementation Choices
2083 ----------------------
2088 The bstring library has more overhead versus straight char buffers for most
2089 functions. This overhead is essentially just the memory management and
2090 string header allocation. This overhead usually only shows up for small
2091 string manipulations. The performance loss has to be considered in
2092 light of the following:
2094 1) What would be the performance loss of trying to write this management
2095 code in one's own application?
2096 2) Since the bstring library source code is given, a sufficiently powerful
2097 modern inlining globally optimizing compiler can remove function call
2100 Since the data type is exposed, a developer can replace any unsatisfactory
2101 function with their own inline implementation. And that is besides the main
2102 point of what the better string library is mainly meant to provide. Any
2103 overhead lost has to be compared against the value of the safe abstraction
2104 for coupling memory management and string functionality.
2106 Performance of the C interface:
2107 ...............................
2109 The algorithms used have performance advantages versus the analogous C
2110 library functions. For example:
2112 1. bfromcstr/blk2str/bstrcpy versus strcpy/strdup. By using memmove instead
2113 of strcpy, the break condition of the copy loop is based on an independent
2114 counter (that should be allocated in a register) rather than having to
2115 check the results of the load. Modern out-of-order executing CPUs can
2116 parallelize the final branch mis-predict penality with the loading of the
2117 source string. Some CPUs will also tend to have better built-in hardware
2118 support for counted memory moves than load-compare-store. (This is a
2119 minor, but non-zero gain.)
2120 2. biseq versus strcmp. If the strings are unequal in length, bsiseq will
2121 return in O(1) time. If the strings are aliased, or have aliased data
2122 buffers, biseq will return in O(1) time. strcmp will always be O(k),
2123 where k is the length of the common prefix or the whole string if they are
2125 3. ->slen versus strlen. ->slen is obviously always O(1), while strlen is
2126 always O(n) where n is the length of the string.
2127 4. bconcat versus strcat. Both rely on precomputing the length of the
2128 destination string argument, which will favor the bstring library. On
2129 iterated concatenations the performance difference can be enormous.
2130 5. bsreadln versus fgets. The bsreadln function reads large blocks at a time
2131 from the given stream, then parses out lines from the buffers directly.
2132 Some C libraries will implement fgets as a loop over single fgetc calls.
2133 Testing indicates that the bsreadln approach can be several times faster
2134 for fast stream devices (such as a file that has been entirely cached.)
2135 6. bsplits/bsplitscb versus strspn. Accelerators for the set of match
2136 characters are generated only once.
2138 Practical testing indicates that in general Bstrlib is never signifcantly
2139 slower than the C library for common operations, while very often having a
2140 performance advantage that ranges from significant to massive. Even for
2141 functions like b(n)inchr versus str(c)spn() (where, in theory, there is no
2142 advantage for the Bstrlib architecture) the performance of Bstrlib is vastly
2143 superior to most tested C library implementations.
2145 Some of Bstrlib's extra functionality also lead to inevitable performance
2146 advantages over typical C solutions. For example, using the blk2tbstr macro,
2147 one can (in O(1) time) generate an internal substring by reference while not
2148 disturbing the original string. If disturbing the original string is not an
2149 option, typically, a comparable C solution would have to make a copy of the
2150 substring to provide similar functionality. Another example is reverse
2151 character set scanning -- the str(c)spn functions only scan in a forward
2152 direction which can complicate some parsing algorithms.
2154 Where high performance char * based algorithms are available, Bstrlib can
2155 still leverage them by accessing the ->data field on bstrings. So
2156 realistically Bstrlib can never be significantly slower than any standard
2157 '\0' terminated char * based solutions.
2159 Performance of the C++ interface:
2160 .................................
2162 The C++ interface has been designed with an emphasis on abstraction and safety
2163 first. However, since it is substantially a wrapper for the C bstring
2164 functions, for longer strings the performance comments described in the
2165 "Performance of the C interface" section above still apply. Note that the
2166 (CBString *) type can be directly cast to a (bstring) type, and passed as
2167 parameters to the C functions (though a CBString must never be passed to
2170 Probably the most controversial choice is performing full bounds checking on
2171 the [] operator. This decision was made because 1) the fast alternative of
2172 not bounds checking is still available by first casting the CBString to a
2173 (const char *) buffer or to a (struct tagbstring) then derefencing .data and
2174 2) because the lack of bounds checking is seen as one of the main weaknesses
2175 of C/C++ versus other languages. This check being done on every access leads
2176 to individual character extraction being actually slower than other languages
2177 in this one respect (other language's compilers will normally dedicate more
2178 resources on hoisting or removing bounds checking as necessary) but otherwise
2179 bring C++ up to the level of other languages in terms of functionality.
2181 It is common for other C++ libraries to leverage the abstractions provided by
2182 C++ to use reference counting and "copy on write" policies. While these
2183 techniques can speed up some scenarios, they impose a problem with respect to
2184 thread safety. bstrings and CBStrings can be properly protected with
2185 "per-object" mutexes, meaning that two bstrlib calls can be made and execute
2186 simultaneously, so long as the bstrings and CBstrings are distinct. With a
2187 reference count and alias before copy on write policy, global mutexes are
2188 required that prevent multiple calls to the strings library to execute
2189 simultaneously regardless of whether or not the strings represent the same
2192 One interesting trade off in CBString is that the default constructor is not
2193 trivial. I.e., it always prepares a ready to use memory buffer. The purpose
2194 is to ensure that there is a uniform internal composition for any functioning
2195 CBString that is compatible with bstrings. It also means that the other
2196 methods in the class are not forced to perform "late initialization" checks.
2197 In the end it means that construction of CBStrings are slower than other
2198 comparable C++ string classes. Initial testing, however, indicates that
2199 CBString outperforms std::string and MFC's CString, for example, in all other
2200 operations. So to work around this weakness it is recommended that CBString
2201 declarations be pushed outside of inner loops.
2203 Practical testing indicates that with the exception of the caveats given
2204 above (constructors and safe index character manipulations) the C++ API for
2205 Bstrlib generally outperforms popular standard C++ string classes. Amongst
2206 the standard libraries and compilers, the quality of concatenation operations
2207 varies wildly and very little care has gone into search functions. Bstrlib
2208 dominates those performance benchmarks.
2213 The bstring functions which write and modify bstrings will automatically
2214 reallocate the backing memory for the char buffer whenever it is required to
2215 grow. The algorithm for resizing chosen is to snap up to sizes that are a
2216 power of two which are sufficient to hold the intended new size. Memory
2217 reallocation is not performed when the required size of the buffer is
2218 decreased. This behavior can be relied on, and is necessary to make the
2219 behaviour of balloc deterministic. This trades off additional memory usage
2220 for decreasing the frequency for required reallocations:
2222 1. For any bstring whose size never exceeds n, its buffer is not ever
2223 reallocated more than log_2(n) times for its lifetime.
2224 2. For any bstring whose size never exceeds n, its buffer is never more than
2225 2*(n+1) in length. (The extra characters beyond 2*n are to allow for the
2226 implicit '\0' which is always added by the bstring modifying functions.)
2228 Decreasing the buffer size when the string decreases in size would violate 1)
2229 above and in real world case lead to pathological heap thrashing. Similarly,
2230 allocating more tightly than "least power of 2 greater than necessary" would
2231 lead to a violation of 1) and have the same potential for heap thrashing.
2233 Property 2) needs emphasizing. Although the memory allocated is always a
2234 power of 2, for a bstring that grows linearly in size, its buffer memory also
2235 grows linearly, not exponentially. The reason is that the amount of extra
2236 space increases with each reallocation, which decreases the frequency of
2237 future reallocations.
2239 Obviously, given that bstring writing functions may reallocate the data
2240 buffer backing the target bstring, one should not attempt to cache the data
2241 buffer address and use it after such bstring functions have been called.
2242 This includes making reference struct tagbstrings which alias to a writable
2245 balloc or bfromcstralloc can be used to preallocate the minimum amount of
2246 space used for a given bstring. This will reduce even further the number of
2247 times the data portion is reallocated. If the length of the string is never
2248 more than one less than the memory length then there will be no further
2251 Note that invoking the bwriteallow macro may increase the number of reallocs
2252 by one more than necessary for every call to bwriteallow interleaved with any
2253 bstring API which writes to this bstring.
2255 The library does not use any mechanism for automatic clean up for the C API.
2256 Thus explicit clean up via calls to bdestroy() are required to avoid memory
2259 Constant and static tagbstrings:
2260 ................................
2262 A struct tagbstring can be write protected from any bstrlib function using
2263 the bwriteprotect macro. A write protected struct tagbstring can then be
2264 reset to being writable via the bwriteallow macro. There is, of course, no
2265 protection from attempts to directly access the bstring members. Modifying a
2266 bstring which is write protected by direct access has undefined behavior.
2268 static struct tagbstrings can be declared via the bsStatic macro. They are
2269 considered permanently unwritable. Such struct tagbstrings's are declared
2270 such that attempts to write to it are not well defined. Invoking either
2271 bwriteallow or bwriteprotect on static struct tagbstrings has no effect.
2273 struct tagbstring's initialized via btfromcstr or blk2tbstr are protected by
2274 default but can be made writeable via the bwriteallow macro. If bwriteallow
2275 is called on such struct tagbstring's, it is the programmer's responsibility
2278 1) the buffer supplied was allocated from the heap.
2279 2) bdestroy is not called on this tagbstring (unless the header itself has
2280 also been allocated from the heap.)
2281 3) free is called on the buffer to reclaim its memory.
2283 bwriteallow and bwriteprotect can be invoked on ordinary bstrings (they have
2284 to be dereferenced with the (*) operator to get the levels of indirection
2285 correct) to give them write protection.
2290 The memory buffer is actually declared "unsigned char *" instead of "char *".
2291 The reason for this is to trigger compiler warnings whenever uncasted char
2292 buffers are assigned to the data portion of a bstring. This will draw more
2293 diligent programmers into taking a second look at the code where they
2294 have carelessly left off the typically required cast. (Research from
2295 AT&T/Lucent indicates that additional programmer eyeballs is one of the most
2296 effective mechanisms at ferreting out bugs.)
2301 The bgets, bread and bStream functions use function pointers to obtain
2302 strings from data streams. The function pointer declarations have been
2303 specifically chosen to be compatible with the fgetc and fread functions.
2304 While this may seem to be a convoluted way of implementing fgets and fread
2305 style functionality, it has been specifically designed this way to ensure
2306 that there is no dependency on a single narrowly defined set of device
2307 interfaces, such as just stream I/O. In the embedded world, its quite
2308 possible to have environments where such interfaces may not exist in the
2309 standard C library form. Furthermore, the generalization that this opens up
2310 allows for more sophisticated uses for these functions (performing an fgets
2311 like function on a socket, for example.) By using function pointers, it also
2312 allows such abstract stream interfaces to be created using the bstring library
2313 itself while not creating a circular dependency.
2315 Use of int's for sizes:
2316 .......................
2318 This is just a recognition that 16bit platforms with requirements for strings
2319 that are larger than 64K and 32bit+ platforms with requirements for strings
2320 that are larger than 4GB are pretty marginal. The main focus is for 32bit
2321 platforms, and emerging 64bit platforms with reasonable < 4GB string
2322 requirements. Using ints allows for negative values which has meaning
2323 internally to bstrlib.
2325 Semantic consideration:
2326 .......................
2328 Certain care needs to be taken when copying and aliasing bstrings. A bstring
2329 is essentially a pointer type which points to a multipart abstract data
2330 structure. Thus usage, and lifetime of bstrings have semantics that follow
2331 these considerations. For example:
2334 struct tagbstring t;
2336 a = bfromcstr("Hello"); /* Create new bstring and copy "Hello" into it. */
2337 b = a; /* Alias b to the contents of a. */
2338 t = *a; /* Create a current instance pseudo-alias of a. */
2339 bconcat (a, b); /* Double a and b, t is now undefined. */
2340 bdestroy (a); /* Destroy the contents of both a and b. */
2342 Variables of type bstring are really just references that point to real
2343 bstring objects. The equal operator (=) creates aliases, and the asterisk
2344 dereference operator (*) creates a kind of alias to the current instance (which
2345 is generally not useful for any purpose.) Using bstrcpy() is the correct way
2346 of creating duplicate instances. The ampersand operator (&) is useful for
2347 creating aliases to struct tagbstrings (remembering that constructed struct
2348 tagbstrings are not writable by default.)
2350 CBStrings use complete copy semantics for the equal operator (=), and thus do
2351 not have these sorts of issues.
2356 Bstrings have a simple, exposed definition and construction, and the library
2357 itself is open source. So most debugging is going to be fairly straight-
2358 forward. But the memory for bstrings come from the heap, which can often be
2359 corrupted indirectly, and it might not be obvious what has happened even from
2360 direct examination of the contents in a debugger or a core dump. There are
2361 some tools such as Purify, Insure++ and Electric Fence which can help solve
2362 such problems, however another common approach is to directly instrument the
2363 calls to malloc, realloc, calloc, free, memcpy, memmove and/or other calls
2364 by overriding them with macro definitions.
2366 Although the user could hack on the Bstrlib sources directly as necessary to
2367 perform such an instrumentation, Bstrlib comes with a built-in mechanism for
2368 doing this. By defining the macro BSTRLIB_MEMORY_DEBUG and providing an
2369 include file named memdbg.h this will force the core Bstrlib modules to
2370 attempt to include this file. In such a file, macros could be defined which
2371 overrides Bstrlib's useage of the C standard library.
2373 Rather than calling malloc, realloc, free, memcpy or memmove directly, Bstrlib
2374 emits the macros bstr__alloc, bstr__realloc, bstr__free, bstr__memcpy and
2375 bstr__memmove in their place respectively. By default these macros are simply
2376 assigned to be equivalent to their corresponding C standard library function
2377 call. However, if they are given earlier macro definitions (via the back
2378 door include file) they will not be given their default definition. In this
2379 way Bstrlib's interface to the standard library can be changed but without
2380 having to directly redefine or link standard library symbols (both of which
2381 are not strictly ANSI C compliant.)
2383 An example definition might include:
2385 #define bstr__alloc(sz) X_malloc ((sz), __LINE__, __FILE__)
2387 which might help contextualize heap entries in a debugging environment.
2389 The NULL parameter and sanity checking of bstrings is part of the Bstrlib
2390 API, and thus Bstrlib itself does not present any different modes which would
2391 correspond to "Debug" or "Release" modes. Bstrlib always contains mechanisms
2392 which one might think of as debugging features, but retains the performance
2393 and small memory footprint one would normally associate with release mode
2396 Integration Microsoft's Visual Studio debugger:
2397 ...............................................
2399 Microsoft's Visual Studio debugger has a capability of customizable mouse
2400 float over data type descriptions. This is accomplished by editting the
2401 AUTOEXP.DAT file to include the following:
2404 tagbstring =slen=<slen> mlen=<mlen> <data,st>
2405 Bstrlib::CBStringList =count=<size()>
2407 In Visual C++ 6.0 this file is located in the directory:
2409 C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin
2411 and in Visual Studio .NET 2003 its located here:
2413 C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\Debugger
2415 This will improve the ability of debugging with Bstrlib under Visual Studio.
2420 Bstrlib does not come with explicit security features outside of its fairly
2421 comprehensive error detection, coupled with its strict semantic support.
2422 That is to say that certain common security problems, such as buffer overrun,
2423 constant overwrite, arbitrary truncation etc, are far less likely to happen
2424 inadvertently. Where it does help, Bstrlib maximizes its advantage by
2425 providing developers a simple adoption path that lets them leave less secure
2426 string mechanisms behind. The library will not leave developers wanting, so
2427 they will be less likely to add new code using a less secure string library
2428 to add functionality that might be missing from Bstrlib.
2430 That said there are a number of security ideas not addressed by Bstrlib:
2432 1. Race condition exploitation (i.e., verifying a string's contents, then
2433 raising the privilege level and execute it as a shell command as two
2434 non-atomic steps) is well beyond the scope of what Bstrlib can provide. It
2435 should be noted that MFC's built-in string mutex actually does not solve this
2436 problem either -- it just removes immediate data corruption as a possible
2437 outcome of such exploit attempts (it can be argued that this is worse, since
2438 it will leave no trace of the exploitation). In general race conditions have
2439 to be dealt with by careful design and implementation; it cannot be assisted
2440 by a string library.
2442 2. Any kind of access control or security attributes to prevent usage in
2443 dangerous interfaces such as system(). Perl includes a "trust" attribute
2444 which can be endowed upon strings that are intended to be passed to such
2445 dangerous interfaces. However, Perl's solution reflects its own limitations
2446 -- notably that it is not a strongly typed language. In the example code for
2447 Bstrlib, there is a module called taint.cpp. It demonstrates how to write a
2448 simple wrapper class for managing "untainted" or trusted strings using the
2449 type system to prevent questionable mixing of ordinary untrusted strings with
2450 untainted ones then passing them to dangerous interfaces. In this way the
2451 security correctness of the code reduces to auditing the direct usages of
2452 dangerous interfaces or promotions of tainted strings to untainted ones.
2454 3. Encryption of string contents is way beyond the scope of Bstrlib.
2455 Maintaining encrypted string contents in the futile hopes of thwarting things
2456 like using system-level debuggers to examine sensitive string data is likely
2457 to be a wasted effort (imagine a debugger that runs at a higher level than a
2458 virtual processor where the application runs). For more standard encryption
2459 usages, since the bstring contents are simply binary blocks of data, this
2460 should pose no problem for usage with other standard encryption libraries.
2465 The Better String Library is known to compile and function correctly with the
2466 following compilers:
2468 - Microsoft Visual C++
2470 - Intel's C/C++ compiler (Windows)
2471 - The GNU C/C++ compiler (cygwin and Linux on PPC64)
2475 Setting of configuration options should be unnecessary for these compilers
2476 (unless exceptions are being disabled or STLport has been added to WATCOM
2477 C/C++). Bstrlib has been developed with an emphasis on portability. As such
2478 porting it to other compilers should be straight forward. This package
2479 includes a porting guide (called porting.txt) which explains what issues may
2480 exist for porting Bstrlib to different compilers and environments.
2485 1. The function pointer types bNgetc and bNread have prototypes which are very
2486 similar to, but not exactly the same as fgetc and fread respectively.
2487 Basically the FILE * parameter is replaced by void *. The purpose of this
2488 was to allow one to create other functions with fgetc and fread like
2489 semantics without being tied to ANSI C's file streaming mechanism. I.e., one
2490 could very easily adapt it to sockets, or simply reading a block of memory,
2491 or procedurally generated strings (for fractal generation, for example.)
2493 The problem is that invoking the functions (bNgetc)fgetc and (bNread)fread is
2494 not technically legal in ANSI C. The reason being that the compiler is only
2495 able to coerce the function pointers themselves into the target type, however
2496 are unable to perform any cast (implicit or otherwise) on the parameters
2497 passed once invoked. I.e., if internally void * and FILE * need some kind of
2498 mechanical coercion, the compiler will not properly perform this conversion
2499 and thus lead to undefined behavior.
2501 Apparently a platform from Data General called "Eclipse" and another from
2502 Tandem called "NonStop" have a different representation for pointers to bytes
2503 and pointers to words, for example, where coercion via casting is necessary.
2504 (Actual confirmation of the existence of such machines is hard to come by, so
2505 it is prudent to be skeptical about this information.) However, this is not
2506 an issue for any known contemporary platforms. One may conclude that such
2507 platforms are effectively apocryphal even if they do exist.
2509 To correctly work around this problem to the satisfaction of the ANSI
2510 limitations, one needs to create wrapper functions for fgets and/or
2511 fread with the prototypes of bNgetc and/or bNread respectively which performs
2512 no other action other than to explicitely cast the void * parameter to a
2513 FILE *, and simply pass the remaining parameters straight to the function
2516 The wrappers themselves are trivial:
2518 size_t freadWrap (void * buff, size_t esz, size_t eqty, void * parm) {
2519 return fread (buff, esz, eqty, (FILE *) parm);
2522 int fgetcWrap (void * parm) {
2523 return fgetc ((FILE *) parm);
2526 These have not been supplied in bstrlib or bstraux to prevent unnecessary
2527 linking with file I/O functions.
2529 2. vsnprintf is not available on all compilers. Because of this, the bformat
2530 and bformata functions (and format and formata methods) are not guaranteed to
2531 work properly. For those compilers that don't have vsnprintf, the
2532 BSTRLIB_NOVSNP macro should be set before compiling bstrlib, and the format
2533 functions/method will be disabled.
2535 The more recent ANSI C standards have specified the required inclusion of a
2538 3. The bstrlib function names are not unique in the first 6 characters. This
2539 is only an issue for older C compiler environments which do not store more
2540 than 6 characters for function names.
2542 4. The bsafe module defines macros and function names which are part of the
2543 C library. This simply overrides the definition as expected on all platforms
2544 tested, however it is not sanctioned by the ANSI standard. This module is
2545 clearly optional and should be omitted on platforms which disallow its
2546 undefined semantics.
2548 In practice the real issue is that some compilers in some modes of operation
2549 can/will inline these standard library functions on a module by module basis
2550 as they appear in each. The linker will thus have no opportunity to override
2551 the implementation of these functions for those cases. This can lead to
2552 inconsistent behaviour of the bsafe module on different platforms and
2555 ===============================================================================
2557 Comparison with Microsoft's CString class
2558 -----------------------------------------
2560 Although developed independently, CBStrings have very similar functionality to
2561 Microsoft's CString class. However, the bstring library has significant
2562 advantages over CString:
2564 1. Bstrlib is a C-library as well as a C++ library (using the C++ wrapper).
2566 - Thus it is compatible with more programming environments and
2567 available to a wider population of programmers.
2569 2. The internal structure of a bstring is considered exposed.
2571 - A single contiguous block of data can be cut into read-only pieces by
2572 simply creating headers, without allocating additional memory to create
2573 reference copies of each of these sub-strings.
2574 - In this way, using bstrings in a totally abstracted way becomes a choice
2575 rather than an imposition. Further this choice can be made differently
2576 at different layers of applications that use it.
2578 3. Static declaration support precludes the need for constructor
2581 - Allows for static declarations of constant strings that has no
2582 additional constructor overhead.
2584 4. Bstrlib is not attached to another library.
2586 - Bstrlib is designed to be easily plugged into any other library
2587 collection, without dependencies on other libraries or paradigms (such
2590 The bstring library also comes with a few additional functions that are not
2591 available in the CString class:
2596 - breplace (this is different from CString::Replace())
2597 - Writable indexed characters (for example a[i]='x')
2599 Interestingly, although Microsoft did implement mid$(), left$() and right$()
2600 functional analogues (these are functions from GWBASIC) they seem to have
2601 forgotten that mid$() could be also used to write into the middle of a string.
2602 This functionality exists in Bstrlib with the bsetstr() and breplace()
2605 Among the disadvantages of Bstrlib is that there is no special support for
2606 localization or wide characters. Such things are considered beyond the scope
2607 of what bstrings are trying to deliver. CString essentially supports the
2608 older UCS-2 version of Unicode via widechar_t as an application-wide compile
2611 CString's also use built-in mechanisms for ensuring thread safety under all
2612 situations. While this makes writing thread safe code that much easier, this
2613 built-in safety feature has a price -- the inner loops of each CString method
2614 runs in its own critical section (grabbing and releasing a light weight mutex
2615 on every operation.) The usual way to decrease the impact of a critical
2616 section performance penalty is to amortize more operations per critical
2617 section. But since the implementation of CStrings is fixed as a one critical
2618 section per-operation cost, there is no way to leverage this common
2619 performance enhancing idea.
2621 The search facilities in Bstrlib are comparable to those in MFC's CString
2622 class, though it is missing locale specific collation. But because Bstrlib
2623 is interoperable with C's char buffers, it will allow programmers to write
2624 their own string searching mechanism (such as Boyer-Moore), or be able to
2625 choose from a variety of available existing string searching libraries (such
2626 as those for regular expressions) without difficulty.
2628 Microsoft used a very non-ANSI conforming trick in its implementation to
2629 allow printf() to use the "%s" specifier to output a CString correctly. This
2630 can be convenient, but it is inherently not portable. CBString requires an
2631 explicit cast, while bstring requires the data member to be dereferenced.
2632 Microsoft's own documentation recommends casting, instead of relying on this
2635 Comparison with C++'s std::string
2636 ---------------------------------
2638 This is the C++ language's standard STL based string class.
2640 1. There is no C implementation.
2641 2. The [] operator is not bounds checked.
2642 3. Missing a lot of useful functions like printf-like formatting.
2643 4. Some sub-standard std::string implementations (SGI) are necessarily unsafe
2644 to use with multithreading.
2645 5. Limited by STL's std::iostream which in turn is limited by ifstream which
2646 can only take input from files. (Compare to CBStream's API which can take
2648 6. Extremely uneven performance across implementations.
2650 Comparison with ISO C TR 24731 proposal
2651 ---------------------------------------
2653 Following the ISO C99 standard, Microsoft has proposed a group of C library
2654 extensions which are supposedly "safer and more secure". This proposal is
2655 expected to be adopted by the ISO C standard which follows C99.
2657 The proposal reveals itself to be very similar to Microsoft's "StrSafe"
2658 library. The functions are basically the same as other standard C library
2659 string functions except that destination parameters are paired with an
2660 additional length parameter of type rsize_t. rsize_t is the same as size_t,
2661 however, the range is checked to make sure its between 1 and RSIZE_MAX. Like
2662 Bstrlib, the functions perform a "parameter check". Unlike Bstrlib, when a
2663 parameter check fails, rather than simply outputing accumulatable error
2664 statuses, they call a user settable global error function handler, and upon
2665 return of control performs no (additional) detrimental action. The proposal
2666 covers basic string functions as well as a few non-reenterable functions
2667 (asctime, ctime, and strtok).
2669 1. Still based solely on char * buffers (and therefore strlen() and strcat()
2670 is still O(n), and there are no faster streq() comparison functions.)
2671 2. No growable string semantics.
2672 3. Requires manual buffer length synchronization in the source code.
2673 4. No attempt to enhance functionality of the C library.
2674 5. Introduces a new error scenario (strings exceeding RSIZE_MAX length).
2676 The hope is that by exposing the buffer length requirements there will be
2677 fewer buffer overrun errors. However, the error modes are really just
2678 transformed, rather than removed. The real problem of buffer overflows is
2679 that they all happen as a result of erroneous programming. So forcing
2680 programmers to manually deal with buffer limits, will make them more aware of
2681 the problem but doesn't remove the possibility of erroneous programming. So
2682 a programmer that erroneously mixes up the rsize_t parameters is no better off
2683 from a programmer that introduces potential buffer overflows through other
2684 more typical lapses. So at best this may reduce the rate of erroneous
2685 programming, rather than making any attempt at removing failure modes.
2687 The error handler can discriminate between types of failures, but does not
2688 take into account any callsite context. So the problem is that the error is
2689 going to be manifest in a piece of code, but there is no pointer to that
2690 code. It would seem that passing in the call site __FILE__, __LINE__ as
2691 parameters would be very useful, but the API clearly doesn't support such a
2692 thing (it would increase code bloat even more than the extra length
2693 parameter does, and would require macro tricks to implement).
2695 The Bstrlib C API takes the position that error handling needs to be done at
2696 the callsite, and just tries to make it as painless as possible. Furthermore,
2697 error modes are removed by supporting auto-growing strings and aliasing. For
2698 capturing errors in more central code fragments, Bstrlib's C++ API uses
2699 exception handling extensively, which is superior to the leaf-only error
2702 Comparison with Managed String Library CERT proposal
2703 ----------------------------------------------------
2705 The main webpage for the managed string library:
2706 http://www.cert.org/secure-coding/managedstring.html
2708 Robert Seacord at CERT has proposed a C string library that he calls the
2709 "Managed String Library" for C. Like Bstrlib, it introduces a new type
2710 which is called a managed string. The structure of a managed string
2711 (string_m) is like a struct tagbstring but missing the length field. This
2712 internal structure is considered opaque. The length is, like the C standard
2713 library, always computed on the fly by searching for a terminating NUL on
2714 every operation that requires it. So it suffers from every performance
2715 problem that the C standard library suffers from. Interoperating with C
2716 string APIs (like printf, fopen, or anything else that takes a string
2717 parameter) requires copying to additionally allocating buffers that have to
2718 be manually freed -- this makes this library probably slower and more
2719 cumbersome than any other string library in existence.
2721 The library gives a fully populated error status as the return value of every
2722 string function. The hope is to be able to diagnose all problems
2723 specifically from the return code alone. Comparing this to Bstrlib, which
2724 aways returns one consistent error message, might make it seem that Bstrlib
2725 would be harder to debug; but this is not true. With Bstrlib, if an error
2726 occurs there is always enough information from just knowing there was an error
2727 and examining the parameters to deduce exactly what kind of error has
2728 happened. The managed string library thus gives up nested function calls
2729 while achieving little benefit, while Bstrlib does not.
2731 One interesting feature that "managed strings" has is the idea of data
2732 sanitization via character set whitelisting. That is to say, a globally
2733 definable filter that makes any attempt to put invalid characters into strings
2734 lead to an error and not modify the string. The author gives the following
2737 // create valid char set
2738 if (retValue = strcreate_m(&str1, "abc") ) {
2741 "Error %d from strcreate_m.\n",
2745 if (retValue = setcharset(str1)) {
2748 "Error %d from setcharset().\n",
2752 if (retValue = strcreate_m(&str1, "aabbccabc")) {
2755 "Error %d from strcreate_m.\n",
2759 // create string with invalid char set
2760 if (retValue = strcreate_m(&str1, "abbccdabc")) {
2763 "Error %d from strcreate_m.\n",
2768 Which we can compare with a more Bstrlib way of doing things:
2770 bstring bCreateWithFilter (const char * cstr, const_bstring filter) {
2771 bstring b = bfromcstr (cstr);
2772 if (BSTR_ERR != bninchr (b, filter) && NULL != b) {
2773 fprintf (stderr, "Filter violation.\n");
2780 struct tagbstring charFilter = bsStatic ("abc");
2781 bstring str1 = bCreateWithFilter ("aabbccabc", &charFilter);
2782 bstring str2 = bCreateWithFilter ("aabbccdabc", &charFilter);
2784 The first thing we should notice is that with the Bstrlib approach you can
2785 have different filters for different strings if necessary. Furthermore,
2786 selecting a charset filter in the Managed String Library is uni-contextual.
2787 That is to say, there can only be one such filter active for the entire
2788 program, which means its usage is not well defined for intermediate library
2789 usage (a library that uses it will interfere with user code that uses it, and
2790 vice versa.) It is also likely to be poorly defined in multi-threading
2793 There is also a question as to whether the data sanitization filter is checked
2794 on every operation, or just on creation operations. Since the charset can be
2795 set arbitrarily at run time, it might be set *after* some managed strings have
2796 been created. This would seem to imply that all functions should run this
2797 additional check every time if there is an attempt to enforce this. This
2798 would make things tremendously slow. On the other hand, if it is assumed that
2799 only creates and other operations that take char *'s as input need be checked
2800 because the charset was only supposed to be called once at and before any
2801 other managed string was created, then one can see that its easy to cover
2802 Bstrlib with equivalent functionality via a few wrapper calls such as the
2803 example given above.
2805 And finally we have to question the value of sanitation in the first place.
2806 For example, for httpd servers, there is generally a requirement that the
2807 URLs parsed have some form that avoids undesirable translation to local file
2808 system filenames or resources. The problem is that the way URLs can be
2809 encoded, it must be completely parsed and translated to know if it is using
2810 certain invalid character combinations. That is to say, merely filtering
2811 each character one at a time is not necessarily the right way to ensure that
2812 a string has safe contents.
2814 In the article that describes this proposal, it is claimed that it fairly
2815 closely approximates the existing C API semantics. On this point we should
2816 compare this "closeness" with Bstrlib:
2818 Bstrlib Managed String Library
2819 ------- ----------------------
2821 Pointer arithmetic Segment arithmetic N/A
2823 Use in C Std lib ->data, or bdata{e} getstr_m(x,*) ... free(x)
2825 String literals bsStatic, bsStaticBlk strcreate_m()
2827 Transparency Complete None
2829 Its pretty clear that the semantic mapping from C strings to Bstrlib is fairly
2830 straightforward, and that in general semantic capabilities are the same or
2831 superior in Bstrlib. On the other hand the Managed String Library is either
2832 missing semantics or changes things fairly significantly.
2834 Comparison with Annexia's c2lib library
2835 ---------------------------------------
2837 This library is available at:
2838 http://www.annexia.org/freeware/c2lib
2840 1. Still based solely on char * buffers (and therefore strlen() and strcat()
2841 is still O(n), and there are no faster streq() comparison functions.)
2842 Their suggestion that alternatives which wrap the string data type (such as
2843 bstring does) imposes a difficulty in interoperating with the C langauge's
2844 ordinary C string library is not founded.
2845 2. Introduction of memory (and vector?) abstractions imposes a learning
2846 curve, and some kind of memory usage policy that is outside of the strings
2847 themselves (and therefore must be maintained by the developer.)
2848 3. The API is massive, and filled with all sorts of trivial (pjoin) and
2849 controvertial (pmatch -- regular expression are not sufficiently
2850 standardized, and there is a very large difference in performance between
2851 compiled and non-compiled, REs) functions. Bstrlib takes a decidely
2852 minimal approach -- none of the functionality in c2lib is difficult or
2853 challenging to implement on top of Bstrlib (except the regex stuff, which
2854 is going to be difficult, and controvertial no matter what.)
2855 4. Understanding why c2lib is the way it is pretty much requires a working
2856 knowledge of Perl. bstrlib requires only knowledge of the C string library
2857 while providing just a very select few worthwhile extras.
2858 5. It is attached to a lot of cruft like a matrix math library (that doesn't
2859 include any functions for getting the determinant, eigenvectors,
2860 eigenvalues, the matrix inverse, test for singularity, test for
2861 orthogonality, a grahm schmit orthogonlization, LU decomposition ... I
2864 Convincing a development house to use c2lib is likely quite difficult. It
2865 introduces too much, while not being part of any kind of standards body. The
2866 code must therefore be trusted, or maintained by those that use it. While
2867 bstring offers nothing more on this front, since its so much smaller, covers
2868 far less in terms of scope, and will typically improve string performance,
2869 the barrier to usage should be much smaller.
2871 Comparison with stralloc/qmail
2872 ------------------------------
2874 More information about this library can be found here:
2875 http://www.canonical.org/~kragen/stralloc.html or here:
2876 http://cr.yp.to/lib/stralloc.html
2878 1. Library is very very minimal. A little too minimal.
2879 2. Untargetted source parameters are not declared const.
2880 3. Slightly different expected emphasis (like _cats function which takes an
2881 ordinary C string char buffer as a parameter.) Its clear that the
2882 remainder of the C string library is still required to perform more
2883 useful string operations.
2885 The struct declaration for their string header is essentially the same as that
2886 for bstring. But its clear that this was a quickly written hack whose goals
2887 are clearly a subset of what Bstrlib supplies. For anyone who is served by
2888 stralloc, Bstrlib is complete substitute that just adds more functionality.
2890 stralloc actually uses the interesting policy that a NULL data pointer
2891 indicates an empty string. In this way, non-static empty strings can be
2892 declared without construction. This advantage is minimal, since static empty
2893 bstrings can be declared inline without construction, and if the string needs
2894 to be written to it should be constructed from an empty string (or its first
2895 initializer) in any event.
2900 This is the string class used in the wxWindows project. A description of
2901 wxString can be found here:
2902 http://www.wxwindows.org/manuals/2.4.2/wx368.htm#wxstring
2904 This C++ library is similar to CBString. However, it is littered with
2905 trivial functions (IsAscii, UpperCase, RemoveLast etc.)
2907 1. There is no C implementation.
2908 2. The memory management strategy is to allocate a bounded fixed amount of
2909 additional space on each resize, meaning that it does not have the
2910 log_2(n) property that Bstrlib has (it will thrash very easily, cause
2911 massive fragmentation in common heap implementations, and can easily be a
2912 common source of performance problems).
2913 3. The library uses a "copy on write" strategy, meaning that it has to deal
2914 with multithreading problems.
2919 This is a highly orthogonal C string library with an emphasis on
2920 networking/realtime programming. It can be found here:
2921 http://www.and.org/vstr/
2923 1. The convoluted internal structure does not contain a '\0' char * compatible
2924 buffer, so interoperability with the C library a non-starter.
2925 2. The API and implementation is very large (owing to its orthogonality) and
2926 can lead to difficulty in understanding its exact functionality.
2927 3. An obvious dependency on gnu tools (confusing make configure step)
2928 4. Uses a reference counting system, meaning that it is not likely to be
2931 The implementation has an extreme emphasis on performance for nontrivial
2932 actions (adds, inserts and deletes are all constant or roughly O(#operations)
2933 time) following the "zero copy" principle. This trades off performance of
2934 trivial functions (character access, char buffer access/coersion, alias
2935 detection) which becomes significantly slower, as well as incremental
2936 accumulative costs for its searching/parsing functions. Whether or not Vstr
2937 wins any particular performance benchmark will depend a lot on the benchmark,
2938 but it should handily win on some, while losing dreadfully on others.
2940 The learning curve for Vstr is very steep, and it doesn't come with any
2941 obvious way to build for Windows or other platforms without gnu tools. At
2942 least one mechanism (the iterator) introduces a new undefined scenario
2943 (writing to a Vstr while iterating through it.) Vstr has a very large
2944 footprint, and is very ambitious in its total functionality. Vstr has no C++
2947 Vstr usage requires context initialization via vstr_init() which must be run
2948 in a thread-local context. Given the totally reference based architecture
2949 this means that sharing Vstrings across threads is not well defined, or at
2950 least not safe from race conditions. This API is clearly geared to the older
2951 standard of fork() style multitasking in UNIX, and is not safely transportable
2952 to modern shared memory multithreading available in Linux and Windows. There
2953 is no portable external solution making the library thread safe (since it
2954 requires a mutex around each Vstr context -- not each string.)
2956 In the documentation for this library, a big deal is made of its self hosted
2957 s(n)printf-like function. This is an issue for older compilers that don't
2958 include vsnprintf(), but also an issue because Vstr has a slow conversion to
2959 '\0' terminated char * mechanism. That is to say, using "%s" to format data
2960 that originates from Vstr would be slow without some sort of native function
2961 to do so. Bstrlib sidesteps the issue by relying on what snprintf-like
2962 functionality does exist and having a high performance conversion to a char *
2963 compatible string so that "%s" can be used directly.
2968 This is a fairly extensive string library, that includes full unicode support
2969 and targetted at the goal of out performing MFC and STL. The architecture,
2970 similarly to MFC's CStrings, is a copy on write reference counting mechanism.
2972 http://www.utilitycode.com/str/default.aspx
2977 This library, like Vstr, uses a ref counting system. There is only so deeply
2978 I can analyze it, since I don't have a license for it. However, performance
2979 improvements over MFC's and STL, doesn't seem like a sufficient reason to
2980 move your source base to it. For example, in the future, Microsoft may
2981 improve the performance CString.
2983 It should be pointed out that performance testing of Bstrlib has indicated
2984 that its relative performance advantage versus MFC's CString and STL's
2985 std::string is at least as high as that for the Str library.
2990 A handful of functional extensions to the C library that add dynamic string
2992 http://www.mibsoftware.com/libmib/astring/
2994 This package basically references strings through char ** pointers and assumes
2995 they are pointing to the top of an allocated heap entry (or NULL, in which
2996 case memory will be newly allocated from the heap.) So its still up to user
2997 to mix and match the older C string functions with these functions whenever
2998 pointer arithmetic is used (i.e., there is no leveraging of the type system
2999 to assert semantic differences between references and base strings as Bstrlib
3000 does since no new types are introduced.) Unlike Bstrlib, exact string length
3001 meta data is not stored, thus requiring a strlen() call on *every* string
3002 writing operation. The library is very small, covering only a handful of C's
3005 While this is better than nothing, it is clearly slower than even the
3006 standard C library, less safe and less functional than Bstrlib.
3008 To explain the advantage of using libmib, their website shows an example of
3009 how dangerous C code:
3012 char *pszExtraPath = ";/usr/local/bin";
3014 strcpy(buf,getenv("PATH")); /* oops! could overrun! */
3015 strcat(buf,pszExtraPath); /* Could overrun as well! */
3017 printf("Checking...%s\n",buf); /* Some printfs overrun too! */
3019 is avoided using libmib:
3021 char *pasz = 0; /* Must initialize to 0 */
3023 char *pszExtraPath = ";/usr/local/bin";
3025 if (!astrcpy(&pasz,getenv("PATH"))) /* malloc error */ exit(-1);
3026 if (!astrcat(&pasz,pszExtraPath)) /* malloc error */ exit(-1);
3028 /* Finally, a "limitless" printf! we can use */
3029 asprintf(&paszOut,"Checking...%s\n",pasz);fputs(paszOut,stdout);
3031 astrfree(&pasz); /* Can use free(pasz) also. */
3034 However, compare this to Bstrlib:
3038 bcatcstr (b = bfromcstr (getenv ("PATH")), ";/usr/local/bin");
3039 out = bformat ("Checking...%s\n", bdatae (b, "<Out of memory>"));
3040 /* if (out && b) */ fputs (bdatae (out, "<Out of memory>"), stdout);
3044 Besides being shorter, we can see that error handling can be deferred right
3045 to the very end. Also, unlike the above two versions, if getenv() returns
3046 with NULL, the Bstrlib version will not exhibit undefined behavior.
3047 Initialization starts with the relevant content rather than an extra
3048 autoinitialization step.
3053 An attempt to add to the standard C library with a number of common useful
3054 functions, including additional string functions.
3055 http://libclc.sourceforge.net/
3057 1. Uses standard char * buffer, and adopts C 99's usage of "restrict" to pass
3058 the responsibility to guard against aliasing to the programmer.
3059 2. Adds no safety or memory management whatsoever.
3060 3. Most of the supplied string functions are completely trivial.
3062 The goals of libclc and Bstrlib are clearly quite different.
3067 http://firestuff.org/
3069 1. Uses standard char * buffer, and adopts C 99's usage of "restrict" to pass
3070 the responsibility to guard against aliasing to the programmer.
3071 2. Mixes char * and length wrapped buffers (estr) functions, doubling the API
3072 size, with safety limited to only half of the functions.
3074 Firestring was originally just a wrapper of char * functionality with extra
3075 length parameters. However, it has been augmented with the inclusion of the
3076 estr type which has similar functionality to stralloc. But firestring does
3077 not nearly cover the functional scope of Bstrlib.
3079 Safe C String Library
3080 ---------------------
3082 A library written for the purpose of increasing safety and power to C's string
3083 handling capabilities.
3084 http://www.zork.org/safestr/safestr.html
3086 1. While the safestr_* functions are safe in of themselves, interoperating
3087 with char * string has dangerous unsafe modes of operation.
3088 2. The architecture of safestr's causes the base pointer to change. Thus,
3089 its not practical/safe to store a safestr in multiple locations if any
3090 single instance can be manipulated.
3091 3. Dependent on an additional error handling library.
3092 4. Uses reference counting, meaning that it is either not thread safe or
3093 slow and not portable.
3095 I think the idea of reallocating (and hence potentially changing) the base
3096 pointer is a serious design flaw that is fatal to this architecture. True
3097 safety is obtained by having automatic handling of all common scenarios
3098 without creating implicit constraints on the user.
3100 Because of its automatic temporary clean up system, it cannot use "const"
3101 semantics on input arguments. Interesting anomolies such as:
3104 s = safestr_replace (t = SAFESTR_TEMP ("This is a test"),
3105 SAFESTR_TEMP (" "), SAFESTR_TEMP ("."));
3106 /* t is now undefined. */
3108 are possible. If one defines a function which takes a safestr_t as a
3109 parameter, then the function would not know whether or not the safestr_t is
3110 defined after it passes it to a safestr library function. The author
3111 recommended method for working around this problem is to examine the
3112 attributes of the safestr_t within the function which is to modify any of
3113 its parameters and play games with its reference count. I think, therefore,
3114 that the whole SAFESTR_TEMP idea is also fatally broken.
3116 The library implements immutability, optional non-resizability, and a "trust"
3117 flag. This trust flag is interesting, and suggests that applying any
3118 arbitrary sequence of safestr_* function calls on any set of trusted strings
3119 will result in a trusted string. It seems to me, however, that if one wanted
3120 to implement a trusted string semantic, one might do so by actually creating
3121 a different *type* and only implement the subset of string functions that are
3122 deemed safe (i.e., user input would be excluded, for example.) This, in
3123 essence, would allow the compiler to enforce trust propogation at compile
3124 time rather than run time. Non-resizability is also interesting, however,
3125 it seems marginal (i.e., to want a string that cannot be resized, yet can be
3126 modified and yet where a fixed sized buffer is undesirable.)
3128 ===============================================================================
3133 Dumping a line numbered file:
3137 struct bstrList * lines;
3138 struct tagbstring prefix = bsStatic ("-> ");
3140 if (NULL != (fp = fopen ("bstrlib.txt", "rb"))) {
3141 bstring b = bread ((bNread) fread, fp);
3143 if (NULL != (lines = bsplit (b, '\n'))) {
3144 for (i=0; i < lines->qty; i++) {
3145 binsert (lines->entry[i], 0, &prefix, '?');
3146 printf ("%04d: %s\n", i, bdatae (lines->entry[i], "NULL"));
3148 bstrListDestroy (lines);
3153 For numerous other examples, see bstraux.c, bstraux.h and the example archive.
3155 ===============================================================================
3160 The Better String Library is available under either the BSD license (see the
3161 accompanying license.txt) or the Gnu Public License version 2 (see the
3162 accompanying gpl.txt) at the option of the user.
3164 ===============================================================================
3169 The following individuals have made significant contributions to the design
3170 and testing of the Better String Library:
3178 International Business Machines Corporation
3188 ===============================================================================