From 77e8402dd68079c0e245fc8826daf2c6ad334766 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Tue, 26 Sep 2006 16:58:27 +0000 Subject: r18925: Add current snapshot of the ejs-2.0 code. Tridge, will you be incorporating this? (This used to be commit 917af234a8d517f82bd42256a940608a16b988f4) --- source4/lib/appweb/ejs-2.0/mpr/mprBuf.c | 535 ++++++++++++++++++++++++++++++++ 1 file changed, 535 insertions(+) create mode 100644 source4/lib/appweb/ejs-2.0/mpr/mprBuf.c (limited to 'source4/lib/appweb/ejs-2.0/mpr/mprBuf.c') diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprBuf.c b/source4/lib/appweb/ejs-2.0/mpr/mprBuf.c new file mode 100644 index 0000000000..ba9888a9fc --- /dev/null +++ b/source4/lib/appweb/ejs-2.0/mpr/mprBuf.c @@ -0,0 +1,535 @@ +/** + * @file mprBuf.c + * @brief Dynamic buffer module + * @overview + * @remarks + */ + +/******************************************************************************/ +/* + * @copy default + * + * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. + * + * This software is distributed under commercial and open source licenses. + * You may use the GPL open source license described below or you may acquire + * a commercial license from Mbedthis Software. You agree to be fully bound + * by the terms of either license. Consult the LICENSE.TXT distributed with + * this software for full details. + * + * This software is open source; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See the GNU General Public License for more + * details at: http://www.mbedthis.com/downloads/gplLicense.html + * + * This program is distributed WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * This GPL license does NOT permit incorporating this software into + * proprietary programs. If you are unable to comply with the GPL, you must + * acquire a commercial license to use this software. Commercial licenses + * for this software and support services are available from Mbedthis + * Software at http://www.mbedthis.com + * + * @end + */ + + +/********************************** Includes **********************************/ + +#include "mpr.h" + +/**************************** Forward Declarations ****************************/ + +static int grow(MprBuf *bp); + +/*********************************** Code *************************************/ +/* + * Create a new buffer. "maxsize" is the limit to which the buffer can + * ever grow. -1 means no limit. The buffer can ever only fix maxsize-1 bytes. + * "initialSize" is used to define the amount to increase the size of the + * buffer each time if it becomes full. (Note: grow() will exponentially + * increase this number for performance.) + */ + +MprBuf *mprCreateBuf(MprCtx ctx, int initialSize, int maxSize) +{ + MprBuf *bp; + + if (initialSize <= 0) { + initialSize = MPR_DEFAULT_ALLOC; + } + bp = mprAllocTypeZeroed(ctx, MprBuf); + bp->growBy = MPR_BUFSIZE; + bp->maxsize = 0; + mprSetBufSize(bp, initialSize, maxSize); + return bp; +} + +/******************************************************************************/ +/* + * Set the initial buffer parameters and create the first buffer + */ + +void mprSetBufSize(MprBuf *bp, int initialSize, int max) +{ + mprAssert(initialSize > 0); + + if (max > 0 && initialSize > max) { + initialSize = max; + } + + if (bp->buf && bp->growBy > 0) { + mprFree(bp->buf); + } + + bp->buf = (uchar*) mprAlloc(bp, initialSize); + bp->growBy = initialSize; + bp->maxsize = max; + bp->buflen = initialSize; + bp->endbuf = &bp->buf[bp->buflen]; + bp->start = bp->buf; + bp->end = bp->buf; + *bp->start = '\0'; +} + +/******************************************************************************/ + +char *mprStealBuf(MprCtx ctx, MprBuf *bp) +{ + char *str; + + str = (char*) bp->start; + + mprStealAllocBlock(MPR_LOC_ARGS(ctx), bp->start); + + bp->start = bp->end = bp->buf = bp->endbuf = 0; + bp->buflen = 0; + + return str; +} + +/******************************************************************************/ + +void mprAddNullToBuf(MprBuf *bp) +{ + *((char*) bp->end) = (char) '\0'; +} + +/******************************************************************************/ + +void mprAdjustBufEnd(MprBuf *bp, int size) +{ + mprAssert(bp->buflen == (bp->endbuf - bp->buf)); + mprAssert(size < bp->buflen); + + bp->end += size; + if (bp->end >= bp->endbuf) { + bp->end -= bp->buflen; + } + if (bp->end < bp->buf) { + bp->end += bp->buflen; + } + + if (bp->end >= bp->endbuf) { + mprAssert(bp->end < bp->endbuf); + mprFlushBuf(bp); + } +} + +/******************************************************************************/ +/* + * Adjust the start pointer after a user copy + */ + +void mprAdjustBufStart(MprBuf *bp, int size) +{ + mprAssert(bp->buflen == (bp->endbuf - bp->buf)); + mprAssert(size < bp->buflen); + + bp->start += size; + while (bp->start >= bp->endbuf) { + bp->start -= bp->buflen; + } + while (bp->start < bp->buf) { + bp->start += bp->buflen; + } + + /* + * Flush the buffer if the start pointer is corrupted via a bad size + */ + if (bp->start >= bp->endbuf) { + mprAssert(bp->start < bp->endbuf); + mprFlushBuf(bp); + } +} + + +/******************************************************************************/ + +void mprFlushBuf(MprBuf *bp) +{ + bp->start = bp->buf; + bp->end = bp->buf; +} + +/******************************************************************************/ + +int mprGetCharFromBuf(MprBuf *bp) +{ + int c; + + if (bp->start == bp->end) { + return -1; + } + c = (uchar) *bp->start++; + if (bp->start >= bp->endbuf) { + bp->start = bp->buf; + } + return c; +} + +/******************************************************************************/ + +int mprGetBlockFromBuf(MprBuf *bp, uchar *buf, int size) +{ + int thisLen, bytesRead; + + mprAssert(buf); + mprAssert(size > 0); + mprAssert(bp->buflen == (bp->endbuf - bp->buf)); + + /* + * Get the max bytes in a straight copy + */ + bytesRead = 0; + while (size > 0) { + thisLen = mprGetBufLinearData(bp); + thisLen = min(thisLen, size); + if (thisLen <= 0) { + break; + } + + memcpy(buf, bp->start, thisLen); + buf += thisLen; + bp->start += thisLen; + size -= thisLen; + bytesRead += thisLen; + + if (bp->start >= bp->endbuf) { + bp->start = bp->buf; + } + } + return bytesRead; +} + +/******************************************************************************/ + +int mprGetBufLength(MprBuf *bp) +{ + if (bp->start > bp->end) { + return (bp->buflen + (bp->end - bp->start)); + } else { + return (bp->end - bp->start); + } +} + +/******************************************************************************/ + +int mprGetBufLinearData(MprBuf *bp) +{ + return min(mprGetBufLength(bp), (bp->endbuf - bp->start)); +} + +/******************************************************************************/ + +int mprGetBufLinearSpace(MprBuf *bp) +{ + int len = mprGetBufLength(bp); + int space = bp->buflen - len - 1; + return min((bp->endbuf - bp->end), space); +} + +/******************************************************************************/ + +int mprGetBufSize(MprBuf *bp) +{ + return bp->buflen; +} + +/******************************************************************************/ + +int mprGetBufSpace(MprBuf *bp) +{ + return bp->buflen - mprGetBufLength(bp) - 1; +} + +/******************************************************************************/ + +char *mprGetBufOrigin(MprBuf *bp) +{ + return (char*) bp->buf; +} + +/******************************************************************************/ + +char *mprGetBufStart(MprBuf *bp) +{ + return (char*) bp->start; +} + +/******************************************************************************/ + +char *mprGetBufEnd(MprBuf *bp) +{ + return (char*) bp->end; +} + +/******************************************************************************/ + +int mprInsertCharToBuf(MprBuf *bp, int c) +{ + char *cp; + int space; + + mprAssert(bp->buflen == (bp->endbuf - bp->buf)); + + space = bp->buflen - mprGetBufLength(bp) - 1; + if (space < (int) sizeof(char)) { + if (!grow(bp)) { + return -1; + } + } + if (bp->start <= bp->buf) { + bp->start = bp->endbuf; + } + cp = (char*) bp->start; + *--cp = (char) c; + bp->start = (uchar *) cp; + return 0; +} + +/******************************************************************************/ + +int mprLookAtNextCharInBuf(MprBuf *bp) +{ + if (bp->start == bp->end) { + return -1; + } + return *bp->start; +} + +/******************************************************************************/ + +int mprLookAtLastCharInBuf(MprBuf *bp) +{ + if (bp->start == bp->end) { + return -1; + } + return (bp->end == bp->buf) ? bp->endbuf[-1] : bp->end[-1]; +} + +/******************************************************************************/ + +int mprPutCharToBuf(MprBuf *bp, int c) +{ + char *cp; + int space; + + mprAssert(bp->buflen == (bp->endbuf - bp->buf)); + + space = bp->buflen - mprGetBufLength(bp) - 1; + if (space < (int) sizeof(char)) { + if (! grow(bp)) { + return -1; + } + } + + cp = (char*) bp->end; + *cp++ = (char) c; + bp->end = (uchar *) cp; + if (bp->end >= bp->endbuf) { + bp->end = bp->buf; + } + *((char*) bp->end) = (char) '\0'; + return 0; +} + +/******************************************************************************/ + +int mprPutBlockToBuf(MprBuf *bp, const char *str, int size) +{ + int thisLen, bytes, space; + + mprAssert(str); + mprAssert(size >= 0); + mprAssert(bp->buflen == (bp->endbuf - bp->buf)); + + /* + * Add the max we can in one copy + */ + bytes = 0; + while (size > 0) { + space = mprGetBufLinearSpace(bp); + thisLen = min(space, size); + if (thisLen <= 0) { + if (! grow(bp)) { + break; + } + space = mprGetBufLinearSpace(bp); + thisLen = min(space, size); + } + + memcpy(bp->end, str, thisLen); + str += thisLen; + bp->end += thisLen; + size -= thisLen; + bytes += thisLen; + + if (bp->end >= bp->endbuf) { + bp->end = bp->buf; + } + } + *((char*) bp->end) = (char) '\0'; + return bytes; +} + +/******************************************************************************/ + +int mprPutStringToBuf(MprBuf *bp, const char *str) +{ + return mprPutBlockToBuf(bp, str, strlen(str)); +} + +/******************************************************************************/ + +int mprPutFmtStringToBuf(MprBuf *bp, const char *fmt, ...) +{ + va_list ap; + char *buf; + int rc, len, space; + + va_start(ap, fmt); + space = mprGetBufLinearSpace(bp); + + /* + * Add max that the buffer can grow + */ + space += (bp->maxsize - bp->buflen - 1); + + len = mprAllocVsprintf(MPR_LOC_ARGS(bp), &buf, space, fmt, ap); + rc = mprPutBlockToBuf(bp, buf, len); + + mprFree(buf); + va_end(ap); + return rc; +} + +/******************************************************************************/ +/* + * Grow the buffer to fit new data. Return 1 if the buffer can grow. + * Grow using the growBy size specified when creating the buffer. + */ + +static int grow(MprBuf *bp) +{ + uchar *newbuf; + + if (bp->maxsize > 0 && bp->buflen >= bp->maxsize) { + return 0; + } + + newbuf = (uchar*) mprAlloc(bp, bp->buflen + bp->growBy); + if (bp->buf) { + memcpy(newbuf, bp->buf, bp->buflen); + mprFree(bp->buf); + } + + bp->buflen += bp->growBy; + bp->end = newbuf + (bp->end - bp->buf); + bp->start = newbuf + (bp->start - bp->buf); + bp->buf = newbuf; + bp->endbuf = &bp->buf[bp->buflen]; + + /* + * Increase growBy to reduce overhead + */ + bp->growBy *= 2; + if (bp->maxsize > 0 && (bp->buflen + bp->growBy) > bp->maxsize) { + bp->growBy = bp->maxsize - bp->buflen; + } + return 1; +} + +/******************************************************************************/ +/* + * Add a number to the buffer (always null terminated). + */ + +int mprPutIntToBuf(MprBuf *bp, int i) +{ + char numBuf[16]; + int rc; + + mprItoa(numBuf, sizeof(numBuf), i); + rc = mprPutStringToBuf(bp, numBuf); + *((char*) bp->end) = (char) '\0'; + + return rc; +} + +/******************************************************************************/ + +void mprCopyBufDown(MprBuf *bp) +{ + if (mprGetBufLength(bp) == 0) { + mprFlushBuf(bp); + return; + } + memmove(bp->buf, bp->start, (bp->end - bp->start)); + bp->end -= (bp->start - bp->buf); + bp->start = bp->buf; +} + +/******************************************************************************/ + +MprBufProc mprGetBufRefillProc(MprBuf *bp) +{ + return bp->refillProc; +} + +/******************************************************************************/ + +void mprSetBufRefillProc(MprBuf *bp, MprBufProc fn, void *arg) +{ + bp->refillProc = fn; + bp->refillArg = arg; +} + +/******************************************************************************/ + +int mprRefillBuf(MprBuf *bp) +{ + return (bp->refillProc) ? (bp->refillProc)(bp, bp->refillArg) : 0; +} + +/******************************************************************************/ + +void mprResetBufIfEmpty(MprBuf *bp) +{ + if (mprGetBufLength(bp) == 0) { + mprFlushBuf(bp); + } +} + +/******************************************************************************/ +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim:tw=78 + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ -- cgit