方法聲明(dstring.h):
/****************************************************************************<br /> * Dynamic strings<br /> ****************************************************************************/<br />/*<br /> * tcl.h --<br /> *<br /> * This header file describes the externally-visible facilities<br /> * of the Tcl interpreter.<br /> *<br /> * Copyright (c) 1987-1994 The Regents of the University of California.<br /> * Copyright (c) 1994-1996 Sun Microsystems, Inc.<br /> *<br /> * See the file "license.terms" for information on usage and redistribution<br /> * of this file, and for a DISCLAIMER OF ALL WARRANTIES.<br /> *<br /> * SCCS: @(#) tcl.h 1.283 96/10/02 17:17:39<br /> */<br />#ifndef DSTRING_H<br />#define DSTRING_H<br />#ifdef __cplusplus<br />extern "C"<br />{<br />#endif<br />#define kDstringStaticSize 200<br />typedef struct DString {<br /> char *pString; /* Points to beginning of string: either<br /> * staticSpace below or a malloc'ed array. */<br /> int length; /* Number of non-NULL characters in the<br /> * string. */<br /> int spaceAvl; /* Total number of bytes available for the<br /> * string and its terminating NULL char. */<br /> char staticSpace[kDstringStaticSize];<br /> /* Space to use in common case where string<br /> * is small. */<br />} DString;<br />#define DStringLength(dsPtr) ((dsPtr)->length)<br />#define DStringValue(dsPtr) ((dsPtr)->pString)<br />#define DStringTrunc DStringSetLength<br />char*<br />DStringAppend(DString* dsPtr,<br /> const char* string,<br /> int length);<br />void<br />DStringFree(DString* dsPtr);<br />void<br />DStringInit(DString* dsPtr);<br />void<br />DStringSetLength(DString* dsPtr,<br /> int length);<br />void<br />DStringSprintf(DString* pDs,<br /> const char* pFormat,<br /> ...);<br />char*<br />DStringAppendLowerCase(DString* pDs,<br /> const char* pIn,<br /> int length);<br />#ifdef __cplusplus<br />}<br />#endif<br />#endif<br />
實現(dstring.c):
/****************************************************************************<br /> *<br /> * Dynamic strings<br /> ****************************************************************************/<br />/*<br /> * tcl.h --<br /> *<br /> * This header file describes the externally-visible facilities<br /> * of the Tcl interpreter.<br /> *<br /> * Copyright (c) 1987-1994 The Regents of the University of California.<br /> * Copyright (c) 1994-1996 Sun Microsystems, Inc.<br /> *<br /> * See the file "license.terms" for information on usage and redistribution<br /> * of this file, and for a DISCLAIMER OF ALL WARRANTIES.<br /> *<br /> * SCCS: @(#) tcl.h 1.283 96/10/02 17:17:39<br /> */</p><p>#include "dstring.h"<br />#include <stdarg.h><br />#include <stdio.h><br />#include <ctype.h><br />#include <stdlib.h><br />#include <string.h><br />#include "str_strsafe.h"<br />/*<br /> *----------------------------------------------------------------------<br /> *<br /> * DStringInit --<br /> *<br /> * Initializes a dynamic string, discarding any previous contents<br /> * of the string (DStringFree should have been called already<br /> * if the dynamic string was previously in use).<br /> *<br /> * Results:<br /> * None.<br /> *<br /> * Side effects:<br /> * The dynamic string is initialized to be empty.<br /> *<br /> *----------------------------------------------------------------------<br /> */<br />void<br />DStringInit(DString* pDs)<br />{<br /> pDs->pString = pDs->staticSpace;<br /> pDs->length = 0;<br /> pDs->spaceAvl = kDstringStaticSize;<br /> pDs->staticSpace[0] = 0;<br />}<br />/*<br /> *----------------------------------------------------------------------<br /> *<br /> * DStringAppend --<br /> *<br /> * Append more characters to the current value of a dynamic string.<br /> *<br /> * Results:<br /> * The return value is a pointer to the dynamic string's new value.<br /> *<br /> * Side effects:<br /> * Length bytes from string (or all of string if length is less<br /> * than zero) are added to the current value of the string. Memory<br /> * gets reallocated if needed to accomodate the string's new size.<br /> *<br /> *----------------------------------------------------------------------<br /> */<br />char *<br />DStringAppend(DString *pDs,<br /> const char* string,<br /> int length)<br />{<br /> int newSize;<br /> char* newString;<br /> char* dst;<br /> const char* end;<br /> if (length < 0) {<br /> length = strlen(string);<br /> }<br /> newSize = length + pDs->length;<br /> /*<br /> * Allocate a larger buffer for the string if the current one isn't<br /> * large enough. Allocate extra space in the new buffer so that there<br /> * will be room to grow before we have to allocate again.<br /> */<br /> if (newSize >= pDs->spaceAvl) {<br /> pDs->spaceAvl = newSize*2;<br /> newString = (char *) malloc((unsigned) pDs->spaceAvl);<br /> memcpy((void *)newString, (void *) pDs->pString,<br /> (size_t) pDs->length);<br /> if (pDs->pString != pDs->staticSpace) {<br /> free(pDs->pString);<br /> }<br /> pDs->pString = newString;<br /> }<br /> /*<br /> * Copy the new string into the buffer at the end of the old<br /> * one.<br /> */<br /> for (dst = pDs->pString + pDs->length, end = string+length;<br /> string < end; string++, dst++) {<br /> *dst = *string;<br /> }<br /> *dst = 0;<br /> pDs->length += length;<br /> return pDs->pString;<br />}<br />/*<br /> *----------------------------------------------------------------------<br /> *<br /> * DStringSetLength --<br /> *<br /> * Change the length of a dynamic string. This can cause the<br /> * string to either grow or shrink, depending on the value of<br /> * length.<br /> *<br /> * Results:<br /> * None.<br /> *<br /> * Side effects:<br /> * The length of pDsis changed to length and a null byte is<br /> * stored at that position in the string. If length is larger<br /> * than the space allocated for pDs, then a panic occurs.<br /> *<br /> *----------------------------------------------------------------------<br /> */<br />void<br />DStringSetLength(DString* pDs,<br /> int length)<br />{<br /> if (length < 0) {<br /> length = 0;<br /> }<br /> if (length >= pDs->spaceAvl) {<br /> char *newString;<br /> pDs->spaceAvl = length+1;<br /> newString = (char *) malloc((unsigned) pDs->spaceAvl);<br /> /*<br /> * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string<br /> * to a larger buffer, since there may be embedded NULLs in the<br /> * string in some cases.<br /> */<br /> memcpy((void *) newString, (void*) pDs->pString,<br /> (size_t) pDs->length);<br /> if (pDs->pString != pDs->staticSpace) {<br /> free(pDs->pString);<br /> }<br /> pDs->pString = newString;<br /> }<br /> pDs->length = length;<br /> pDs->pString[length] = 0;<br />}<br />/*<br /> *----------------------------------------------------------------------<br /> *<br /> * DStringFree --<br /> *<br /> * Frees up any memory allocated for the dynamic string and<br /> * reinitializes the string to an empty state.<br /> *<br /> * Results:<br /> * None.<br /> *<br /> * Side effects:<br /> * The previous contents of the dynamic string are lost, and<br /> * the new value is an empty string.<br /> *<br /> *----------------------------------------------------------------------<br /> */<br />void<br />DStringFree(DString* pDs)<br />{<br /> if (pDs->pString != pDs->staticSpace) {<br /> free(pDs->pString);<br /> }<br /> pDs->pString = pDs->staticSpace;<br /> pDs->length = 0;<br /> pDs->spaceAvl = kDstringStaticSize;<br /> pDs->staticSpace[0] = 0;<br />}<br />/*<br /> * DStringSprintf --<br /> *<br /> * Append a formatted string to a dstring<br /> */<br />void<br />DStringSprintf(DString* pDs,<br /> const char* pFormat,<br /> ...)<br />{<br />#ifdef _WIN32<br /> va_list args;<br /> char message[256];<br /> char * buf;<br /> size_t bufCchSize;<br /> buf = &(message[0]);<br /> bufCchSize = sizeof(message);<br /> va_start(args, pFormat);<br /># ifndef DISABLE_STRSAFE<br /> for (;;)<br /> {<br /> /* TODO: this only works on windows with recent C library */<br /> HRESULT hr = StringCchVPrintfA(buf, bufCchSize, pFormat, args);<br /> if (S_OK == hr)<br /> break;<br /> if (STRSAFE_E_INSUFFICIENT_BUFFER != hr)<br /> {<br /> /* any error other than buffer not big enough:<br /> a) should not happen<br /> b) means we give up */<br /> goto Error;<br /> }<br /> /* we have to make the buffer bigger. The algorithm used to calculate<br /> the new size is arbitrary (aka. educated guess) */<br /> if (buf != &(message[0]))<br /> free(buf);<br /> if (bufCchSize < 4*1024)<br /> bufCchSize += bufCchSize;<br /> else<br /> bufCchSize += 1024;<br /> buf = (char *)malloc(bufCchSize*sizeof(char));<br /> if (NULL == buf)<br /> goto Error;<br /> }<br /># else /* strsafe is disabled */<br /> {<br /> int len = vsnprintf(buf, bufCchSize, pFormat, args);</p><p> if(len >= bufCchSize)<br /> {<br /> bufCchSize = len + 1;<br /> buf = (char *)malloc(bufCchSize*sizeof(char));<br /> if (NULL == buf)<br /> goto Error;</p><p> len = vsnprintf(buf, bufCchSize, pFormat, args);<br /> }</p><p> if(len < 0)<br /> goto Error;<br /> }<br /># endif<br /> va_end(args);<br /> DStringAppend(pDs, buf, -1);<br />Error:<br /> if (buf != &(message[0]))<br /> free((void*)buf);<br /> return;<br />#else<br /> va_list args;<br /> char* pBuffer;<br /> int len;<br /> va_start(args, pFormat);<br /> len = vasprintf(&pBuffer, pFormat, args);<br /> DStringAppend(pDs, pBuffer, len);<br /> free(pBuffer);<br /> va_end(args);<br />#endif<br />}<br />/****************************************************************************<br /> * DStringAppendLowerCase --<br /> *<br /> * Append text to a dstring lowercased<br /> */<br />char*<br />DStringAppendLowerCase(DString* pDs,<br /> const char* string,<br /> int length)<br />{<br /> int newSize;<br /> char* newString;<br /> char* dst;<br /> const char* end;<br /> if (length < 0) {<br /> length = strlen(string);<br /> }<br /> newSize = length + pDs->length;<br /> /*<br /> * Allocate a larger buffer for the string if the current one isn't<br /> * large enough. Allocate extra space in the new buffer so that there<br /> * will be room to grow before we have to allocate again.<br /> */<br /> if (newSize >= pDs->spaceAvl) {<br /> pDs->spaceAvl = newSize*2;<br /> newString = (char *) malloc((unsigned) pDs->spaceAvl);<br /> memcpy((void *)newString, (void *) pDs->pString,<br /> (size_t) pDs->length);<br /> if (pDs->pString != pDs->staticSpace) {<br /> free(pDs->pString);<br /> }<br /> pDs->pString = newString;<br /> }<br /> /*<br /> * Copy the new string into the buffer at the end of the old<br /> * one.<br /> */<br /> for (dst = pDs->pString + pDs->length, end = string+length;<br /> string < end; string++, dst++) {<br /> *dst = tolower(*string);<br /> }<br /> *dst = 0;<br /> pDs->length += length;<br /> return pDs->pString;<br />}<br />
其他:
str_strsafe.h
/* Written by Krzysztof Kowalczyk (http://blog.kowalczyk.info)<br /> The author disclaims copyright to this source code. */<br />#ifndef __STR_STRSAFE_H<br />#define __STR_STRSAFE_H<br />/* When using MSVC, use <strsafe.h>, emulate it on other compiler (e.g. mingw) */<br />#ifndef DISABLE_STRSAFE<br /> #include <strsafe.h><br />#else<br /> #include <stdio.h><br /> #include <string.h><br /> #include <windows.h><br /> #defineSTRSAFE_E_INSUFFICIENT_BUFFER -1<br /> #define_vsnprintf_s(p,s,z,f,a)vsnprintf(p,s,f,a)</p><p> /* WARNING: the return values of these two pairs of functions aren't<br /> compatible. The strsafe functions return an error code and the standard C<br /> functions return a character count */<br /> #defineStringCchVPrintfAvsnprintf<br /> #defineStringCchPrintfAsnprintf</p><p> #define_stricmpstrcasecmp<br /> #define_strnicmpstrncasecmp<br />#endif<br />#endif<br />