/* text/astring.c librock_CHISEL _summary allocated string functions Table of Contents. [License and Disclaimer of Warranty] [License Attributes] [How to Reuse this software] [Definitions and header file inclusions] [Function Implementation and inline documentation] [Revision summary and Changelog] */ /*************************************************************/ /***[License and Disclaimer of Warranty]**********************/ /* By copyright law, you must agree to these terms before you modify or copy this software or any part of it. Copyright (c) 2004, Forrest J. Cavalier III Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************/ /***[License Attributes]**************************************/ /* The librock LIDESC tool reports some license attributes. It reports the following for the MIT license used for this software: A notice must be included in documentation or other materials when a binary is distributed. (librock_DOCNOTE_1C_WITHBIN) Notices must remain in source code. (librock_SRCNOTE_1) The Free Software Foundation says this license is a Free software license. (librock_LIDESC_COMBINE_FSF_OK) The Free Software Foundation says this license is GPL compatible. (librock_LIDESC_COMBINE_GPL_OK) The Open Source Initiative approved this license as OSD compliant. (librock_LIDESC_COMBINE_OSD_OK) Note: You may be able to use LIDESC tools to check compatibility with other licenses. */ /*************************************************************/ /***[How to Reuse this software]******************************/ /* 1. Agree to the license and disclaimer of warranty. 2. Read this file for function documentation and examples. Verify the implementation is suitable for you. 3. Define preprocessor symbols for your machine and compilation environment. This file is originally from libROCK: the Reusable Opensource Code and Knowledge library. For an automated update and build system, license certificates, and more, see http://www.mibsoftware.com/librock/ This file is written for ANSI C: librock_CHISEL _portreport_permit_ansi Some comments used for CHISEL portreport suppression (!empty) (!=0). */ /*************************************************************/ /***[Definitions and header file inclusions]******************/ #ifdef librock_ISOLATED #else #define librock_IMPLEMENT_astring #include #include #include #include #include #include #ifndef librock_assert #define librock_assert(a) #endif #endif /* ifdef librock_ISOLATED else */ /**************************************************************/ /*************************************************************/ /***[Function Implementation and inline documentation]********/ #ifdef librock_IMPL_LIDESC #include /* librock_LIDESC_HC=cc598307414a9997b32b60a2e7a8e7c6a13d6438 */ void *librock_LIDESC_astring[] = { "\n" __FILE__ librock_LIDESC_mit "\n", 0 }; #endif /*************************************************************/ /**************************************************************/ librock_PRIVATE void librock_compcheck() { /* Make sure the casts of function types we do later are OK. This code is never called, but will produce errors if the realloc() function is defined with parameter types that don't automatically cast to void * and librock_SIZE_T. */ librock_SIZE_T a = 2; void *f; f = realloc(f,a/*(!=0)*/); } /**************************************************************/ /**************************************************************/ /**************************************************************/ char librock_PTR *librock_astrensureX(char librock_PTR * librock_PTR *ppsz,int cbMin, void *(*reallocfn)(void *,librock_SIZE_T)) {/* Copyright 1998-2004 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ /* This is the core routine for supporting allocated strings. Ensure that there is enough room to copy a string of strlen()==cbMin plus a NUL terminator to *ppsz. */ char librock_PTR *ret; #ifdef librock_MANUAL_astrensure /* librock_astrensure - (re)allocate space to store a NUL terminated string librock_astrfree - deallocate space obtained using librock_astring functions librock_astrstatic - minimize space to store a NUL terminated string librock_astrensureX - (re)allocate space to store a NUL terminated string using specified allocator librock_astrfreeX - deallocate space obtained using librock_astring functions using specified allocator librock_astrstaticX - minimize space to store a NUL terminated string using specified allocator */ /**/ #include #include char * librock_astrensure( char * * ppasz, int len ); /* (re)allocate space to store a NUL terminated string */ void librock_astrfree( char * *ppasz ); /* deallocate space obtained using librock_astring functions */ char * librock_astrstatic( char * * ppasz ); /* minimize space to store a NUL terminated string */ /* The librock_astring family of functions simplify the task of using unlimited size string buffers. Pass in a pointer to a pointer to a char, and buffers are allocated and reallocated as needed with a little extra space to cut down on needing to call realloc(). For most uses, initialize a char pointer to 0, and then call librock_astrcpy() and others, making a final call to librock_astrfree() when finished. Be aware that the buffer will move around in memory. Callers should not keep stale pointers. IMPORTANT: Calls to astring functions will run strlen(), so the caller must always ensure there is a '\0' string terminator at or before pasz+len. librock_astrensure() is what librock_astrcpy and librock_astrcat (and others) use to allocate (or reallocate) a buffer of at least len+1 bytes for direct manipulation. librock_astrensure is suitable for external use also. The caller must not write beyond pasz[len] bytes. Callers which do no direct buffer manipulation (only use librock_astrcpy and others) do not need to call librock_astrensure(). librock_astrfree() deallocates the space and stores 0 at *ppasz; When using the standard realloc(), it is equivalent to a call to free(*ppasz) followed by *ppasz = 0. librock_astrstatic() minimizes storage for the astring, and returns a pointer to the possibly moved string. AFTER THE CALL, THE POINTER IS NO LONGER AN ASTRING. Do not use it as an astring in any other calls. Be sure to call the appropriate deallocator directly, do not use astrfree(). The implementation of astrings "overallocates" to prevent unnecessary copying of "active" strings. This is fine for most astrings. Only if a large number of astrings are persistent ("long-lived") use astrstatic() to realloc exactly what is needed to store the string, for less memory waste. The X suffix versions allow use of a specific memory allocator, instead of the library malloc. Read more below at "Variants" RETURN VALUE: librock_astrensure() librock_astrstatic() return a pointer to the possibly moved buffer. The return value is also stored at *ppasz. The caller must assume pointers into the old buffer are stale after calling these functions. */ /*Typical use:*/ #ifdef librock_TYPICAL_USE_astrstatic char *asz =0; /* Important: initialize to 0 before first call*/ char *ptr; librock_astrcpy(&asz,"Big buffer...."); librock_astrcat(&asz,"Other big buffer...."); printf("Length: %d\n",strlen(asz)); librock_astrfree(&asz); /* . . . */ librock_astrcat(&asz,"strcat to initialized = 0 is fine."); ptr = librock_astrstatic(&asz); /* Sets asz = 0 */ printf("Length: %d\n",strlen(ptr)); free(ptr); /* Not librock_astrfree() here */ /* . . . */ #endif /* For instructive use of librock_astrensure(), see the implementation of librock_afgets. */ /* These functions use the realloc function supplied when the astring implementation was compiled. Supply a realloc function on a per-call basis (useful for memory pooling, optimization, and more), by using the X suffix variants: */ char *librock_astrensureX( char * * ppasz, int len, void *(*reallocfn)(void *,librock_SIZE_T)); void librock_astrfreeX( char * *ppsz, void *(*reallocfn)(void *,librock_SIZE_T)); char * librock_astrstaticX( char * * ppasz, void *(*reallocfn)(void *,librock_SIZE_T)); /* librock_astrfreeX() realloc() librock_astrensureX() // used by librock_astrensure realloc() librock_astrfreeX() // used by librock_astrfree realloc() librock_astrstaticX() // used by librock_astrstatic */ /* Copyright 1998-2000 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License text in librock_LIDESC_HC=cc598307414a9997b32b60a2e7a8e7c6a13d6438 */ #endif /* MANUAL */ /*-------------------------------------------*/ /* The simple version simply does a realloc. */ /* Overallocate, to reduce fragmentation, and efficient reallocs */ if (cbMin < 0) { cbMin = 0; } cbMin = (cbMin / 240) * 256 + 240; cbMin++; /* Always reserve room for the NUL terminator, so that callers don't always have to be adding 1 to strlen()s */ ret = (*reallocfn)(*ppsz,cbMin); if (!ret) { /* realloc couldn't satisfy the request. The existing string is freed to show there was an error. */ librock_astrfreeX(ppsz,reallocfn); return 0; } *ppsz = ret; return *ppsz; } /* librock_astrensureX */ /**************************************************************/ /**************************************************************/ char librock_PTR * librock_astrstaticX(char librock_PTR *librock_PTR *ppsz,void *(*reallocfn)(void *,librock_SIZE_T)) { /* Copyright 1998-2002, Forrest J. Cavalier III d-b-a Mib Software Open-source under MIT license. NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ /* Similar to astrensure, but always does a realloc to the exact string length */ int cbMin; char librock_PTR *ret; if (!*ppsz) { return 0; } cbMin = strlen(*ppsz)+1; /* Always reserve room for the Null terminator, so that callers don't always have to be adding 1 to strlen()s */ ret = (*reallocfn)(*ppsz,cbMin); /* Always realloc */ if (!ret) { /* Oh well, nothing lost */ ret = *ppsz; } else { *ppsz = 0; /* Not an astring anymore */ } return ret; } /* librock_astrstaticX */ /**************************************************************/ /**************************************************************/ void librock_astrfreeX(char librock_PTR * librock_PTR *ppsz,void *(*reallocfn)(void *,librock_SIZE_T)) { /* Copyright 1998-2004 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ if (*ppsz) { (*reallocfn)(*ppsz,0); *ppsz = 0; } return; } /* librock_astrfreeX */ /**************************************************************/ /**************************************************************/ char librock_PTR *librock_astrcpyX(char librock_PTR * librock_PTR *ppsz,const char librock_PTR *src,void *(*reallocfn)(void *,librock_SIZE_T)) { /* Copyright 1998-2004 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ #ifdef librock_MANUAL_astrcpy /* librock_astrcpy - (re)allocate a destination buffer and copy a NUL terminated string. librock_astrn0cpy - (re)allocate buffer and copy a string with limit librock_astrcpyX - (re)allocate a destination buffer and copy a NUL terminated string using specified allocator librock_astrn0cpyX - (re)allocate buffer and copy a string with limit using specified allocator */ /**/ #include char *librock_astrcpy( char * *ppasz, const char *pSrc ); char *librock_astrn0cpy( char * *ppasz, const char *pSrc, int n ); /* These are strcpy() replacements which do automatic reallocation. Instead of a pointer to the destination buffer, these take a pointer to the pointer, so that the buffer can be reallocated if necessary to avoid overrun. These string copying functions update @*ppasz with a pointer to a buffer allocated by _@librock_astrensure() which will contain a copy of the NUL-terminated string at @pSrc. If librock_astrn0cpy() is used, at most the first @n bytes of @pSrc are copied, up to a NUL. Note that librock_astrn0cpy() will not reserve more space, nor copy more bytes than strlen(@pSrc) and the terminating character. Instead, you will want to use librock_astrensure() to reserve space to prepare for memcpy() or other modifying operations. The NUL termination character is always stored by both functions. (NUL is ASCII 00, '\0', which is not to be confused with NULL, (void *) 0.) These functions are part of the Librock allocated string functions. See _@librock_astrensure() for an overview. Since the librock allocated string buffers hold NUL terminated strings, most "read-only" string functions of libc and other libraries, such as strlen(), strchr(), can be used. As with all librock_astr* functions, the caller must assume the buffer will move, and consider all pointers into the old buffer @*ppasz unusable. See the _@librock_afgets() implementation for a good way to use indexes to avoid pointers which go stale. The allocation function, librock_astrensure(), makes realloc requests in multiples of a fixed size. The primary benefit of this strategy is to reduce realloc calls by assuming the buffer is at least a minimum size. For this and other reasons, be sure to call only with *ppasz set to 0 or a value obtained from a previous call to one of these functions. `[h3]Typical Use` */ #ifdef librock_TYPICAL_USE_astrcpy char *asz = 0; librock_astrcpy(&asz,"Long buffer"); librock_astrcat(&asz,"Longer buffer"); printf("%s\n",asz); librock_astrfree(&asz); #endif /* Supply a realloc function on a per-call basis (useful for memory pooling, optimization, and more), by using the X suffix variants: */ #include #include char *librock_astrcpyX( char * *ppasz, const char *pSrc, void *(*reallocfn)(void *,librock_SIZE_T) ); char *librock_astrn0cpyX( char * *ppasz, const char *pSrc, int n, void *(*reallocfn)(void *,librock_SIZE_T) ); /* strlen() strcpy() librock_astrensureX() // used by librock_astrcpyX realloc() librock_astrcpyX() // used by librock_astrcpy memchr() memcpy() librock_astrensureX() // used by librock_astrn0cpyX librock_astrn0cpyX() realloc() // used by librock_astrn0cpy */ /* Copyright 1998-2000 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License text in librock_LIDESC_HC=cc598307414a9997b32b60a2e7a8e7c6a13d6438 */ #endif /* MANUAL */ /*-------------------------------------------*/ int toalloc = strlen(src); if (*ppsz) { **ppsz = '\0'; /* Signal astrensure that don't need to preserve */ } librock_astrensureX(ppsz,toalloc,reallocfn); if (!*ppsz) { return 0; } strcpy(*ppsz,src); return *ppsz; } /**************************************************************/ /**************************************************************/ char librock_PTR *librock_astrn0cpyX(char librock_PTR * librock_PTR *ppsz,const char librock_PTR *pSrc,int len,void *(*reallocfn)(void *,librock_SIZE_T)) { /* Copyright 1998-2004 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ int toalloc; char librock_PTR *pStop; if (*ppsz) { **ppsz = '\0'; /* Signal astrensure that don't need to preserve */ } pStop = memchr(pSrc,'\0',len); if (pStop) { toalloc = pStop - pSrc; } else { toalloc = len; } if (len < toalloc) { toalloc = len; } librock_astrensureX(ppsz,toalloc,reallocfn); if (!*ppsz) { return 0; } memcpy(*ppsz,pSrc,len); /* Don't use strncpy, which zero fills. */ (*ppsz)[len] = '\0'; return *ppsz; } /* astrn0cpyX */ /**************************************************************/ /**************************************************************/ char librock_PTR *librock_astrcatX(char librock_PTR * librock_PTR *ppsz,const char librock_PTR *src,void *(*reallocfn)(void *,librock_SIZE_T)) { /* Copyright 1998-2004 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ #ifdef librock_MANUAL_astrcat /* librock_astrcat - (re)allocate a destination buffer and concatenate a NUL terminated string. librock_astrn0cat - (re)allocate buffer and concatenate a string with limit librock_astrcatX - (re)allocate a destination buffer and concatenate a NUL terminated string using specified allocator librock_astrn0catX - (re)allocate buffer and concatenate a string with limit using specified allocator */ /**/ #include char *librock_astrcat( char * *ppasz, const char *pSrc ); char *librock_astrn0cat( char * *ppasz, const char *pSrc, int n ); /* These are strcat() replacements which do automatic reallocation. Instead of a pointer to the destination buffer, these take a pointer to the pointer, so that the buffer can be reallocated if necessary to avoid overrun. The return value (which is also stored at *ppasz) is a pointer to the possibly moved buffer, which will contain a copy of the NUL terminated string at pSrc appended, (or at most n bytes of pSrc if astrn0cat() is used.) The NUL termination character is always stored by both functions. n cannot be used to reserve more space, or append more bytes than strlen(pSrc) See librock_astrensure() for that need. The point of concatenation is determined by strlen(). The caller must assume pointers into the old buffer are stale after calling these functions. See librock_afgets() implementation for a good way to use indexes and not pointers. The allocation function, librock_astrensure(), makes realloc requests in multiples of a fixed size. The primary benefit of this strategy is to reduce realloc calls by assuming the buffer is at least a minimum size. For this and other reasons, be sure to call only with *ppasz set to 0 or a value obtained from a previous call to one of these functions. Typical Use */ #ifdef librock_TYPICAL_USE_astrcat char *asz = 0; librock_astrcpy(&asz,"Long buffer"); librock_astrcat(&asz,"Longer buffer"); printf("%s\n",asz); librock_astrfree(&asz); #endif /* Supply a realloc function on a per-call basis (useful for memory pooling, optimization, and more), by using the X suffix variants: */ #include #include char *librock_astrcatX( char * *ppasz, const char *pSrc, void *(*reallocfn)(void *,librock_SIZE_T) ); char *librock_astrn0catX( char * *ppasz, const char *pSrc, int n, void *(*reallocfn)(void *,librock_SIZE_T) ); /* strlen() strcpy() librock_astrensureX() // used by librock_astrcatX librock_astrcatX() realloc(). // used by librock_astrcat strlen() memchr() memcpy() librock_astrensureX() // used by librock_astrn0catX librock_astrn0catX() and realloc() // used by librock_astrn0cat */ /* Copyright 1998-2000 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License text in librock_LIDESC_HC=cc598307414a9997b32b60a2e7a8e7c6a13d6438 */ #endif /* MANUAL */ /*-------------------------------------------*/ int toalloc; int len = 0; toalloc = strlen(src); if (*ppsz) { len = strlen(*ppsz); toalloc += len; } librock_astrensureX(ppsz,toalloc,reallocfn); if (!*ppsz) { return 0; } strcpy(*ppsz+len,src); return *ppsz; } /* librock_astrcatX */ /**************************************************************/ /**************************************************************/ char librock_PTR *librock_astrn0catX(char librock_PTR * librock_PTR *ppsz,const char librock_PTR *pSrc,int n,void *(*reallocfn)(void *,librock_SIZE_T)) { /* Copyright 1998-2004 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ char librock_PTR *pStop; int toalloc; int len = 0; if (n < 0) { librock_assert(0&&"librock_astrn0catX called with n < 0"); return *ppsz; } if (n == 0) { /* 3-Feb-99 */ return *ppsz; } pStop = memchr(pSrc,'\0',n); if (pStop) { n = pStop - pSrc; } toalloc = n; if (*ppsz) { len = strlen(*ppsz); toalloc += len; } librock_astrensureX(ppsz,toalloc,reallocfn); if (!*ppsz) { return 0; } memcpy(*ppsz+len,pSrc,n); /* Don't use strncpy, which zero fills. */ (*ppsz)[len+n] = '\0'; return *ppsz; } /* librock_astrn0catX */ /**************************************************************/ /**************************************************************/ char librock_PTR *librock_afgetsX(char librock_PTR * librock_PTR *ppasz,librock_FILE *f,void *(*reallocfn)(void *,librock_SIZE_T)) { /* Copyright 1998-2004 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ #ifdef librock_MANUAL_afgets /* librock_afgets - read line of unlimited length from FILE * librock_afgetsX - read line of unlimited length from FILE * using specified allocator */ /**/ #include #include char *librock_afgets( char * *ppasz, FILE *f ); /* These are fgets() replacements which do automatic reallocation. Instead of a pointer to the destination buffer, these take a pointer to the pointer, so that the buffer can be reallocated if necessary to avoid overrun. librock_afgets will read characters from FILE f until reach EOF, \0, or \n. All characters plus the \n (if it appeared) and a NUL terminator are stored into a (re)alloced buffer obtained by calling librock_astrensure() Note: To preserve \0 in the stream, see librock_afgettoch() instead. The return value is also stored at *ppasz. These functions are part of the Librock allocated string functions. See _@librock_astrensure() for an overview. Since the librock allocated string buffers hold NUL terminated strings, most "read-only" string functions of libc and other libraries, such as strlen(), strchr(), can be used. As with all librock_astr* functions, the caller must assume the buffer will move, and consider all pointers into the old buffer @*ppasz unusable. See the _@librock_afgets() implementation for a good way to use indexes to avoid pointers which go stale. The allocation function, librock_astrensure(), makes realloc requests in multiples of a fixed size. The primary benefit of this strategy is to reduce realloc calls by assuming the buffer is at least a minimum size. For this and other reasons, be sure to call only with *ppasz set to 0 or a value obtained from a previous call to one of these functions. */ /*Typical Use:*/ #ifdef librock_TYPICAL_USE_afgets char *asz =0; /* Be sure to initialize to 0 */ while(librock_afgets(&asz,f)) { /* Process line Here */ } /* As long as go through entire loop, no need to astrfree */ #endif /* This function uses the realloc function supplied when the astring implementation was compiled. Supply a realloc function on a per-call basis (useful for memory pooling, optimization, and more), by using the X suffix variant: */ #include #include char *librock_afgetsX( char * *ppasz, FILE *f, void *(*reallocfn)(void *,size_t) ); /* fgetc() feof() librock_astrensureX() librock_astrfreeX() realloc() // used by librock_afgets */ /* Copyright 1998-2000 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License text in librock_LIDESC_HC=cc598307414a9997b32b60a2e7a8e7c6a13d6438 */ #endif /* MANUAL */ /*-------------------------------------------*/ /*This also shows the proper use of an index, instead of a separate pointer into an astring which can go stale. */ char ch; int room = 0; int ind = 0; while(!feof((FILE *)f)) { if (ind >= room-1) { room += 256; if (!librock_astrensureX(ppasz,room,reallocfn)) { return 0; /* failed */ } } ch = fgetc((FILE *)f); if ((ch == EOF) && feof((FILE *)f)) { break; } (*ppasz)[ind++] = ch; (*ppasz)[ind] = '\0'; if ((ch=='\0') || (ch == '\n')) { return *ppasz; } } if (!ind) { /* Nothing */ librock_astrfreeX(ppasz,reallocfn); return 0; } return *ppasz; } /* librock_afgetsX */ /**************************************************************/ /**************************************************************/ int librock_afgettochX(char librock_PTR * librock_PTR *ppasz,librock_FILE *f,char chStop,void *(*reallocfn)(void *,librock_SIZE_T)) { /* Copyright 1998-2004 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ /* Similar to afgets, but returns at eof, or when ch is obtained. Returns number of characters. */ #ifdef librock_MANUAL_afgettoch /* librock_afgettoch - accumulate from FILE * into realloc'ed buffer until reach EOF or a specified character librock_afgettochX - accumulate from FILE * into realloc'ed buffer until reach EOF or a specified character using specified allocator */ /**/ #include #include int librock_afgettoch( char * *ppasz, FILE *f, char chStop, ); /* Read characters from f until reach EOF or chStop. All characters plus the chStop (if it appeared) and a NUL terminator are stored into a (re)alloced buffer obtained by calling librock_astrensure() The return value is the number of characters read and stored. The location of the (possibly moved) buffer is stored at *ppasz. These functions are part of the Librock allocated string functions. See _@librock_astrensure() for an overview. Since the librock allocated string buffers hold NUL terminated strings, most "read-only" string functions of libc and other libraries, such as strlen(), strchr(), can be used. As with all librock_astr* functions, the caller must assume the buffer will move, and consider all pointers into the old buffer @*ppasz unusable. See the _@librock_afgets() implementation for a good way to use indexes to avoid pointers which go stale. The allocation function, librock_astrensure(), makes realloc requests in multiples of a fixed size. The primary benefit of this strategy is to reduce realloc calls by assuming the buffer is at least a minimum size. For this and other reasons, be sure to call only with *ppasz set to 0 or a value obtained from a previous call to one of these functions. Typical Use */ char *asz =0; while(librock_afgettoch(&asz,f,'\f')) { /* Process asz Here */ } /* librock_afgettochX allows supplying a realloc function on a per-call basis. (Useful for memory pooling, optimization, and more), */ int librock_afgettochX( char * *ppasz, FILE *f, char chStop, void *(*reallocfn)(void *,size_t) ); /* fgetc() feof() librock_astrensureX(), librock_astrfreeX() realloc() // used by librock_afgettoch */ /* Copyright 1998-2000 Forrest J. Cavalier III, http://www.mibsoftware.com Open-source under MIT license. NO WARRANTY. Copies must retain this block. License text in librock_LIDESC_HC=cc598307414a9997b32b60a2e7a8e7c6a13d6438 */ #endif /* MANUAL */ /*-------------------------------------------*/ char ch; int room = 0; int ind = 0; while(!feof((FILE *)f)) { if (ind >= room-1) { room += 256; if (!librock_astrensureX(ppasz,room,reallocfn)) { return 0; /* failed */ } } ch = fgetc((FILE *)f); if ((ch == EOF) && feof((FILE *)f)) { break; } (*ppasz)[ind++] = ch; (*ppasz)[ind] = '\0'; if (ch == chStop) { return ind; } } if (!ind) { /* Nothing */ librock_astrfreeX(ppasz,reallocfn); return 0; } return ind; } /* librock_afgettochX */ /**************************************************************/ /**************************************************************/ /**************************************************************/ char librock_PTR *librock_astrensure(char librock_PTR * librock_PTR *ppasz,int cbMin) { return librock_astrensureX(ppasz,cbMin,(void *(*)(void *,librock_SIZE_T))realloc/*(!=0)*/); } /* librock_astrensure */ /**************************************************************/ /**************************************************************/ char librock_PTR *librock_astrstatic(char librock_PTR *librock_PTR *ppsz) { return librock_astrstaticX(ppsz,(void *(*)(void *,librock_SIZE_T))realloc/*(!=0)*/); } /* librock_astrstatic */ /**************************************************************/ /**************************************************************/ void librock_astrfree(char librock_PTR * librock_PTR *ppasz) { librock_astrfreeX(ppasz,(void *(*)(void *,librock_SIZE_T))realloc/*(!=0)*/); } /* librock_astrfree */ /**************************************************************/ /**************************************************************/ char librock_PTR *librock_astrcpy(char librock_PTR * librock_PTR *ppsz,const char librock_PTR *src) { return librock_astrcpyX(ppsz,src,(void *(*)(void *,librock_SIZE_T))realloc/*(!=0)*/); } /**************************************************************/ /**************************************************************/ char librock_PTR *librock_astrn0cpy(char librock_PTR * librock_PTR *ppsz,const char librock_PTR *pSrc,int len) { return librock_astrn0cpyX(ppsz,pSrc,len,(void *(*)(void *,librock_SIZE_T))realloc/*(!=0)*/); } /* astrn0cpyX */ /**************************************************************/ /**************************************************************/ char librock_PTR *librock_astrcat(char librock_PTR * librock_PTR *ppsz,const char librock_PTR *src) { return librock_astrcatX(ppsz,src,(void *(*)(void *,librock_SIZE_T))realloc/*(!=0)*/); } /* librock_astrcat */ /**************************************************************/ /**************************************************************/ char librock_PTR *librock_astrn0cat(char librock_PTR * librock_PTR *ppsz,const char librock_PTR *pSrc,int n) { return librock_astrn0catX(ppsz,pSrc,n,(void *(*)(void *,librock_SIZE_T))realloc/*(!=0)*/); } /* librock_astrn0cat */ /**************************************************************/ /**************************************************************/ char librock_PTR *librock_afgets(char librock_PTR * librock_PTR *ppasz,librock_FILE *f) { return librock_afgetsX(ppasz,f,(void *(*)(void *,librock_SIZE_T))realloc/*(!=0)*/); } /* librock_afgets */ /**************************************************************/ /**************************************************************/ int librock_afgettoch(char librock_PTR * librock_PTR *ppasz,librock_FILE *f,char chStop) { /* Similar to afgets, but returns at eof, or when ch is obtained. Returns number of characters. */ return librock_afgettochX(ppasz,f,chStop,(void *(*)(void *,librock_SIZE_T))realloc/*(!=0)*/); } /* librock_afgettoch */ /**************************************************************/ /**************************************************************/ /***[Revision summary and Changelog]**************************/ /* $Log: astring.c,v $ Revision 1.11 2004/06/16 19:51:39 fcavalier@mibsoftware.com rights=#1 Table of Contents and LIDESC updates. Revision 1.10 2003/08/05 21:24:46 fcavalier@mibsoftware.com rights=#1 Comment improvements. Revision 1.9 2002/08/01 16:14:06 fcavalier@mibsoftware.com rights=#1 Added #define librock_PRIVATE to NOTLIBROCK section. Revision 1.8 2002/08/01 14:09:48 fcavalier@mibsoftware.com rights=#1 Clean up typical use sections. Added #include to NOTLIBROCK section. Moved CVS log to end. Revision 1.7 2002/07/31 15:29:26 fcavalier@mibsoftware.com rights=#1 LIDESC_HC instead of LIDESC_MD5 Added NOTLIBROCK section. Revision 1.6 2002/04/19 14:57:54 fcavalier@mibsoftware.com rights=#1 Manual page corrections, clarifications. Revision 1.5 2002/04/09 03:28:47 fcavalier@mibsoftware.com rights=#1 FNTYPEs added. Updated LICENSE in manual. Revision 1.4 2002/04/06 04:00:34 fcavalier@mibsoftware.com rights=#1 Add FNTYPE decls for regression tests. Revision 1.3 2002/02/05 21:17:00 fcavalier@mibsoftware.com rights=#1 Standardized chg log Revision 1.2 2002/01/30 16:07:16 fcavalier@mibsoftware.com rights=#1 man pages. Renamed include files Revision 1.1 2002/01/29 14:25:14 fcavalier@mibsoftware.com rights=#1 moved rights#1 Copyright (c) Forrest J Cavalier III d-b-a Mib Software rights#1 License text in librock_LIDESC_HC=cc598307414a9997b32b60a2e7a8e7c6a13d6438 */