/* * mod_aolserver aolserver emulation --- Copyright 2000 Robert S. Thau. * This file derived from the actual aolserver code, and is distributed * in accord with its license, as follows: * * The contents of this file are subject to the AOLserver Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://aolserver.lcs.mit.edu/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is AOLserver Code and related documentation * distributed by AOL. * * The Initial Developer of the Original Code is America Online, * Inc. Portions created by AOL are Copyright (C) 1999 America Online, * Inc. All Rights Reserved. * * Alternatively, the contents of this file may be used under the terms * of the GNU General Public License (the "GPL"), in which case the * provisions of GPL are applicable instead of those above. If you wish * to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the * License, indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by the GPL. * If you do not delete the provisions above, a recipient may use your * version of this file under either the License or the GPL. */ /* * dstring.c -- * * Ns_DString routines. Ns_DString's are not compatible * with Tcl_DString's. */ #include "nsd.h" /* *========================================================================== * API functions *========================================================================== */ /* *---------------------------------------------------------------------- * Ns_DStringInit -- * * Initialize a Ns_DString object. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Ns_DStringInit(Ns_DString *dsPtr) { dsPtr->string = dsPtr->staticSpace; dsPtr->length = 0; dsPtr->spaceAvl = NS_DSTRING_STATIC_SIZE; dsPtr->staticSpace[0] = 0; dsPtr->addr = NULL; } /* *---------------------------------------------------------------------- * * Ns_DStringVarAppend -- * * Append a variable number of string arguments to a dstring. * * Results: * Pointer to current dstring value. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * Ns_DStringVarAppend(Ns_DString *dsPtr, ...) { register char *s; va_list ap; va_start(ap, dsPtr); while ((s = va_arg(ap, char *)) != NULL) { Ns_DStringAppend(dsPtr, s); } va_end(ap); return dsPtr->string; } /* *---------------------------------------------------------------------- * * Ns_DStringAppendElement -- * * Append a list element to the current value of a dynamic string. * * Results: * The return value is a pointer to the dynamic string's new value. * * Side effects: * String is reformatted as a list element and added to the current * value of the string. Memory gets reallocated if needed to * accomodate the string's new size. * *---------------------------------------------------------------------- */ char * Ns_DStringAppendElement(Ns_DString *dsPtr, char *string) { int newSize, flags; char *dst, *newString; extern int TclNeedSpace(char *, char *); newSize = Tcl_ScanElement(string, &flags) + dsPtr->length + 1; /* * Allocate a larger buffer for the string if the current one isn't * large enough. Allocate extra space in the new buffer so that there * will be room to grow before we have to allocate again. * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string * to a larger buffer, since there may be embedded NULLs in the * string in some cases. */ if (newSize >= dsPtr->spaceAvl) { dsPtr->spaceAvl = newSize*2; newString = ns_malloc((size_t) dsPtr->spaceAvl); memcpy(newString, dsPtr->string, (size_t) dsPtr->length); if (dsPtr->string != dsPtr->staticSpace) { ns_free(dsPtr->string); } dsPtr->string = newString; } /* * Convert the new string to a list element and copy it into the * buffer at the end, with a space, if needed. */ dst = dsPtr->string + dsPtr->length; if (TclNeedSpace(dsPtr->string, dst)) { *dst = ' '; dst++; dsPtr->length++; } dsPtr->length += Tcl_ConvertElement(string, dst, flags); return dsPtr->string; } /* *---------------------------------------------------------------------- * * Ns_DStringExport -- * * Return a copy of the string value on the heap. * Ns_DString is left in an initialized state. * * Results: * Pointer to ns_malloc'ed string which must be eventually freed. * * Side effects: * None. * * *---------------------------------------------------------------------- */ char * Ns_DStringExport(Ns_DString *dsPtr) { char *s; if (dsPtr->string != dsPtr->staticSpace) { s = dsPtr->string; dsPtr->string = dsPtr->staticSpace; } else { s = ns_malloc(dsPtr->length+1); memcpy(s, dsPtr->string, dsPtr->length+1); } Ns_DStringFree(dsPtr); return s; } /* *---------------------------------------------------------------------- * Ns_DStringPrintf -- * * Append a sequence of values using a format string * * Results: * Pointer to the current string value. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * Ns_DStringPrintf(Ns_DString *dsPtr, char *fmt,...) { char buf[4096]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); return Ns_DStringAppend(dsPtr, buf); } /* *---------------------------------------------------------------------- * Ns_DStringFree -- * * Reset to its initialized state and deallocate any allocated * memory. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Ns_DStringFree(Ns_DString *dsPtr) { if (dsPtr->string != dsPtr->staticSpace) { ns_free(dsPtr->string); } dsPtr->string = dsPtr->staticSpace; dsPtr->length = 0; dsPtr->spaceAvl = NS_DSTRING_STATIC_SIZE; dsPtr->staticSpace[0] = 0; } /* *---------------------------------------------------------------------- * * Ns_DStringSetLength -- * * Change the length of a dynamic string. This can cause the * string to either grow or shrink, depending on the value of * length. * * Results: * None. * * Side effects: * The length of dsPtr is changed to length and a null byte is * stored at that position in the string. If length is larger * than the space allocated for dsPtr, then a panic occurs. * *---------------------------------------------------------------------- */ void Ns_DStringSetLength(Ns_DString *dsPtr, int length) { if (length < 0) { length = 0; } if (length >= dsPtr->spaceAvl) { char *newString; dsPtr->spaceAvl = length+1; newString = ns_malloc((size_t) dsPtr->spaceAvl); /* * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string * to a larger buffer, since there may be embedded NULLs in the * string in some cases. */ memcpy(newString, dsPtr->string, (size_t) dsPtr->length); if (dsPtr->string != dsPtr->staticSpace) { ns_free(dsPtr->string); } dsPtr->string = newString; } dsPtr->length = length; dsPtr->string[length] = 0; } /* *---------------------------------------------------------------------- * Ns_DStringTrunc -- * * Truncate the value to a null string. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void Ns_DStringTrunc(Ns_DString *dsPtr, int length) { Ns_DStringSetLength(dsPtr, length); } /* *---------------------------------------------------------------------- * Ns_DStringNAppend -- * * Append a byte copy of the first length bytes of string. * * Results: * Pointer to the current string value. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * Ns_DStringNAppend(Ns_DString *dsPtr, char *string, int length) { int newSize; char *newString; if (length < 0) { length = strlen(string); } newSize = length + dsPtr->length; /* * Allocate a larger buffer for the string if the current one isn't large * enough. Allocate extra space in the new buffer so that there will be * room to grow before we have to allocate again. */ if (newSize >= dsPtr->spaceAvl) { dsPtr->spaceAvl = newSize * 2; newString = (char *) ns_malloc((unsigned) dsPtr->spaceAvl); memcpy(newString, dsPtr->string, dsPtr->length); if (dsPtr->string != dsPtr->staticSpace) { ns_free(dsPtr->string); } dsPtr->string = newString; } /* * Copy the new string into the buffer at the end of the old one. */ memcpy(dsPtr->string + dsPtr->length, string, length); dsPtr->length += length; dsPtr->string[dsPtr->length] = '\0'; return dsPtr->string; } /* *---------------------------------------------------------------------- * Ns_DStringAppendArg -- * * Append a string including its terminating null byte. * * Results: * Pointer to the current string value. * * Side effects: * None. * *---------------------------------------------------------------------- */ char * Ns_DStringAppendArg(Ns_DString *dsPtr, char *string) { return Ns_DStringNAppend(dsPtr, string, strlen(string) + 1); } /* *---------------------------------------------------------------------- * Ns_DStringAppend -- * * Append a string. * * Results: * Pointer to the current string value. * * Side effects: * None. * *---------------------------------------------------------------------- */ #undef Ns_DStringAppend char * Ns_DStringAppend(Ns_DString *dsPtr, char *string) { return Ns_DStringNAppend(dsPtr, string, -1); } /* *---------------------------------------------------------------------- * Ns_DStringLength -- * * Return the length of a string. * * Results: * The length of a string. * * Side effects: * None. * *---------------------------------------------------------------------- */ #undef Ns_DStringLength int Ns_DStringLength(Ns_DString *dsPtr) { return dsPtr->length; } /* *---------------------------------------------------------------------- * Ns_DStringValue -- * * Return a pointer to the current string value. * * Results: * Pointer to the current string value. * * Side effects: * None. * *---------------------------------------------------------------------- */ #undef Ns_DStringValue char * Ns_DStringValue(Ns_DString *dsPtr) { return dsPtr->string; } /* *---------------------------------------------------------------------- * Ns_DStringPop -- * * Pop a DString from the per-thread cache, allocating one * if necessary. Or, for Apache emul, always. (I trust malloc). * * Results: * Pointer to initialized DString. * * Side effects: * Will initialize TLS and config parameters on first use. * *---------------------------------------------------------------------- */ Ns_DString * Ns_DStringPop(void) { Ns_DString *dsPtr; dsPtr = ns_malloc(sizeof(Ns_DString)); Ns_DStringInit(dsPtr); return dsPtr; } /* *---------------------------------------------------------------------- * Ns_DStringPush -- * * Push a DString back on the per-thread cache. * * Results: * None. * * Side effects: * DString may be free'ed if the max entries and/or size has been * exceeded. Or always, in Apache... * *---------------------------------------------------------------------- */ void Ns_DStringPush(Ns_DString *dsPtr) { Ns_DStringFree(dsPtr); }