swbuf.h

00001 /******************************************************************************
00002 *  swbuf.h  - code for SWBuf used as a transport and utility for data buffers
00003 *
00004 * $Id: swbuf.h 2072 2007-09-02 20:13:18Z scribe $
00005 *
00006 * Copyright 2003 CrossWire Bible Society (http://www.crosswire.org)
00007 *       CrossWire Bible Society
00008 *       P. O. Box 2528
00009 *       Tempe, AZ  85280-2528
00010 *
00011 * This program is free software; you can redistribute it and/or modify it
00012 * under the terms of the GNU General Public License as published by the
00013 * Free Software Foundation version 2.
00014 *
00015 * This program is distributed in the hope that it will be useful, but
00016 * WITHOUT ANY WARRANTY; without even the implied warranty of
00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 * General Public License for more details.
00019 *
00020 */
00021 
00022 #ifndef SWBUF_H
00023 #define SWBUF_H
00024 
00025 #include <defs.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #ifdef __BORLANDC__
00029 #include <mem.h>
00030 #endif
00031 
00032 SWORD_NAMESPACE_START
00033 
00034 
00035 #define JUNKBUFSIZE 8191
00036 
00044 class SWDLLEXPORT SWBuf {
00045         char *buf;
00046         char *end;
00047         char *endAlloc;
00048         char fillByte;
00049         unsigned long allocSize;
00050         static char *nullStr;
00051         static char junkBuf[JUNKBUFSIZE];
00052 
00053         inline void assureMore(size_t pastEnd) {
00054                 if (size_t(endAlloc-end) < pastEnd) {
00055                         assureSize(allocSize + pastEnd);
00056                 }
00057         }
00058 
00059         inline void assureSize(size_t checkSize) {
00060                 if (checkSize > allocSize) {
00061                         long size = (end - buf);
00062                         checkSize += 128;
00063                         buf = (char *)((allocSize) ? realloc(buf, checkSize) : malloc(checkSize));
00064                         allocSize = checkSize;
00065                         end = (buf + size);
00066                         *end = 0;
00067                         endAlloc = buf + allocSize - 1;
00068                 }
00069         }
00070 
00071         inline void init(size_t initSize) {
00072                 fillByte = ' ';
00073                 allocSize = 0;
00074                 buf = nullStr;
00075                 end = buf;
00076                 endAlloc = buf;
00077                 if (initSize)
00078                         assureSize(initSize);
00079         }
00080 
00081 
00082 public:
00083 
00084         /******************************************************************************
00085         * SWBuf Constructor - Creates an empty SWBuf object
00086         *
00087         */
00088         inline SWBuf() {
00089                 init(0);
00090         }
00091 
00097         SWBuf(const char *initVal, unsigned long initSize = 0);
00098 //      SWBuf(unsigned long initSize);
00099 
00105         SWBuf(char initVal, unsigned long initSize = 0);
00106 
00112         SWBuf(const SWBuf &other, unsigned long initSize = 0);
00113 
00114         /******************************************************************************
00115         * SWBuf Destructor - Cleans up instance of SWBuf
00116         */
00117         inline ~SWBuf() {
00118                 if ((buf) && (buf != nullStr))
00119                         free(buf);
00120         }
00121 
00128         inline void setFillByte(char ch) { fillByte = ch; }
00129 
00135         inline char getFillByte() { return fillByte; }
00136 
00140         inline const char *c_str() const{ return buf; }
00141 
00146         inline char &charAt(unsigned long pos) { return ((pos <= (unsigned long)(end - buf)) ? buf[pos] : ((*junkBuf=0),*junkBuf)); }
00147 
00152         inline unsigned long size() const { return length(); }
00153 
00159         inline void size(unsigned long newSize) { if (end - buf - newSize) setSize(newSize); }
00160 
00164         inline unsigned long length() const { return end - buf; }
00165 
00171         inline void set(const SWBuf &newVal) {
00172                 unsigned long len = newVal.length() + 1;
00173                 assureSize(len);
00174 //              const char *n = newVal.c_str();
00175 //              for (end = buf;len;len--) *end++ = *n++;
00176                 memcpy(buf, newVal.c_str(), len);
00177                 end = buf + (len - 1);
00178         }
00179 
00185         inline void set(const char *newVal) {
00186                 if (newVal) {
00187                         unsigned long len = strlen(newVal) + 1;
00188                         assureSize(len);
00189                         memcpy(buf, newVal, len);
00190                         end = buf + (len - 1);
00191                 }
00192                 else {
00193                         assureSize(1);
00194                         end = buf;
00195                         *end = 0;
00196                 }
00197         }
00198 
00216         void setFormatted(const char *format, ...);
00217 
00222         void setSize(unsigned long len);
00227         inline void resize(unsigned long len) { setSize(len); }
00228 
00235         void append(const char *str, long max = -1);
00236 
00243         inline void append(const SWBuf &str, long max = -1) { append(str.c_str(), max); }
00244 
00250         inline void append(char ch) {
00251                 assureMore(1);
00252                 *end++ = ch;
00253                 *end = 0;
00254         }
00255 
00272         void appendFormatted(const char *format, ...);
00273         
00281         void insert(unsigned long pos, const char* str, unsigned long start = 0, signed long max = -1);
00282 
00290         inline void insert(unsigned long pos, const SWBuf &str, unsigned long start = 0, signed long max = -1) {
00291                 insert(pos, str.c_str(), start, max);
00292         };
00293 
00299         inline void insert(unsigned long pos, char c) {
00300                 insert(pos, SWBuf(c));
00301         }
00302 
00309         inline char *getRawData() { return buf; }
00310 
00311         inline operator const char *() const { return c_str(); }
00312         inline char &operator[](unsigned long pos) { return charAt(pos); }
00313         inline char &operator[](long pos) { return charAt((unsigned long)pos); }
00314         inline char &operator[](unsigned int pos) { return charAt((unsigned long)pos); }
00315         inline char &operator[](int pos) { return charAt((unsigned long)pos); }
00316         inline SWBuf &operator =(const char *newVal) { set(newVal); return *this; }
00317         inline SWBuf &operator =(const SWBuf &other) { set(other); return *this; }
00318         inline SWBuf &operator +=(const char *str) { append(str); return *this; }
00319         inline SWBuf &operator +=(char ch) { append(ch); return *this; }
00320         inline SWBuf &operator -=(unsigned long len) { setSize(length()-len); return *this; }
00321         inline SWBuf &operator --(int) { operator -=(1); return *this; }
00322 
00323         inline SWBuf &operator <<(unsigned long n) { if (n && length()) { n = (n<=length())?n:(length()-1); memmove(buf, buf+n, length()-n); (*this)-=n; } return *this; }
00324         inline SWBuf &operator >>(unsigned long n) { setSize(length()+n); memmove(buf+n, buf, length()-n); return *this; }
00325         inline SWBuf operator +(const SWBuf &other) const {
00326                 SWBuf retVal = buf;
00327                 retVal += other;
00328                 return retVal;
00329         }
00330         inline SWBuf operator +(char ch) const { return (*this) + SWBuf(ch); }
00331 
00332         inline SWBuf &trimStart() { while (size() && (strchr("\t\r\n ", *(buf)))) *this << 1; return *this; }
00333         inline SWBuf &trimEnd() { while (size() && (strchr("\t\r\n ", *(end-1)))) setSize(size()-1); return *this; }
00334         inline SWBuf &trim() { trimStart(); return trimEnd(); }
00335         // this could be nicer, like replacing a contiguous series of target bytes with single replacement; offering replacement const char *
00336         inline SWBuf &replaceBytes(const char *targets, char newByte) { for (unsigned int i = 0; (i < size()); i++) { if (strchr(targets, buf[i])) buf[i] = newByte; } return *this; }
00337 
00338         inline bool startsWith(const SWBuf &prefix) const { return !strncmp(c_str(), prefix.c_str(), prefix.size()); }
00339         inline bool endsWith(const SWBuf &postfix) const { return (size() >= postfix.size())?!strncmp(end-postfix.size(), postfix.c_str(), postfix.size()):false; }
00340         inline int compare(const SWBuf &other) const { return strcmp(c_str(), other.c_str()); }
00341         inline bool operator ==(const SWBuf &other) const { return !compare(other); }
00342         inline bool operator !=(const SWBuf &other) const { return compare(other); }
00343         inline bool operator > (const SWBuf &other) const { return compare(other) > 0; }
00344         inline bool operator < (const SWBuf &other) const { return compare(other) < 0; }
00345         inline bool operator <=(const SWBuf &other) const { return compare(other) <= 0; }
00346         inline bool operator >=(const SWBuf &other) const { return compare(other) >= 0; }
00347 
00348         inline bool startsWith(const char *prefix) const { return !strncmp(c_str(), prefix, strlen(prefix)); }
00349         inline bool endsWith(const char *postfix) const { unsigned int psize = strlen(postfix); return (size() >= psize)?!strncmp(end-psize, postfix, psize):false; }
00350         inline int compare(const char *other) const { return strcmp(c_str(), other); }
00351         inline bool operator ==(const char *other) const { return !compare(other); }
00352         inline bool operator !=(const char *other) const { return compare(other); }
00353         inline bool operator > (const char *other) const { return compare(other) > 0; }
00354         inline bool operator < (const char *other) const { return compare(other) < 0; }
00355         inline bool operator <=(const char *other) const { return compare(other) <= 0; }
00356         inline bool operator >=(const char *other) const { return compare(other) >= 0; }
00357 };
00358 
00359 
00360 
00361 SWORD_NAMESPACE_END
00362 #endif