/* $Id$ */ /* * Copyright (c) 1990-1996 Sam Leffler * Copyright (c) 1991-1996 Silicon Graphics, Inc. * HylaFAX is a trademark of Silicon Graphics * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #include "Str.h" #include #include #include #include #define DEFAULT_FORMAT_BUFFER 4096 char fxStr::emptyString = '\0'; fxStr fxStr::null; fxStr::fxStr(u_int l) { slength = l+1; if (l>0) { data = (char*) malloc(slength); memset(data,0,slength); } else data = &emptyString; } fxStr::fxStr(const char *s) { u_int l = strlen(s)+1; if (l>1) { data = (char*) malloc(l); memcpy(data,s,l); } else { data = &emptyString; } slength = l; } fxStr::fxStr(const char *s, u_int len) { if (len>0) { data = (char*) malloc(len+1); memcpy(data,s,len); data[len] = 0; } else data = &emptyString; slength = len+1; } fxStr::fxStr(const fxStr& s) { slength = s.slength; if (slength > 1) { data = (char*) malloc(slength); memcpy(data,s.data,slength); } else { data = &emptyString; } } fxStr::fxStr(const fxTempStr& t) { slength = t.slength; if (t.slength>1) { data = (char*) malloc(slength); memcpy(data,t.data,slength); } else { data = &emptyString; } } fxStr::fxStr(int a, const char * format) { fxStr s = fxStr::format((format) ? format : "%d", a); slength = s.slength; if (slength > 1) { data = (char*) malloc(slength); memcpy(data, s.data, slength); } else { data = &emptyString; } } fxStr::fxStr(long a, const char * format) { fxStr s = fxStr::format((format) ? format : "%ld", a); slength = s.slength; if (slength > 1) { data = (char*) malloc(slength); memcpy(data, s.data, slength); } else { data = &emptyString; } } fxStr::fxStr(float a, const char * format) { fxStr s = fxStr::format((format) ? format : "%g", a); slength = s.slength; if (slength > 1) { data = (char*) malloc(slength); memcpy(data, s.data, slength); } else { data = &emptyString; } } fxStr::fxStr(double a, const char * format) { fxStr s = fxStr::format((format) ? format : "%lg", a); slength = s.slength; if (slength > 1) { data = (char*) malloc(slength); memcpy(data, s.data, slength); } else { data = &emptyString; } } fxStr::~fxStr() { assert(data); if (data != &emptyString) free(data); } fxStr fxStr::format(const char* fmt ...) { int size = DEFAULT_FORMAT_BUFFER; fxStr s; va_list ap; va_start(ap, fmt); s.data = (char*)malloc(size); int len = vsnprintf(s.data, size, fmt, ap); va_end(ap); while (len < 0 || len >= size) { if (len < 0 && errno != 0) return s; if (len >= size) { size = len + 1; } else { size *= 2; } s.data = (char*)realloc(s.data, size); va_start(ap, fmt); len = vsnprintf(s.data, size, fmt, ap); va_end(ap); } if (size > len + 1) { s.data = (char*) realloc(s.data, len + 1); } s.slength = len + 1; return s; //XXX this is return by value which is inefficient } fxStr fxStr::vformat(const char* fmt, va_list ap) { //XXX can truncate but cant do much about it without va_copy int size = DEFAULT_FORMAT_BUFFER; fxStr s; char* tmp = NULL; int len = 0; do { if (len) size *= 2; tmp = (char*)realloc(tmp, size); va_list ac; va_copy(ac, ap); len = vsnprintf(tmp, size, fmt, ac); va_end(ac); fxAssert(len >= 0, "Str::vformat() error in vsnprintf"); } while (len > size); if (size > len + 1) { tmp = (char*) realloc(tmp, len + 1); } s.data = tmp; s.slength = len + 1; return s; //XXX this is return by value which is inefficient } fxStr fxStr::extract(u_int start, u_int chars) const { fxAssert(start+chars 0); if (slength - chars <= 1) { resizeInternal(0); slength = 1; } else { memmove(data+start, data+start+chars, (u_int)move); slength -= chars; } } fxStr fxStr::cut(u_int start, u_int chars) { fxAssert(start+chars0, "Str::insert(char): Invalid index"); /* * When move is one we are always moving \0; but beware * that the previous string might have been null before * the call to resizeInternal; so set the byte explicitly. */ if (move == 1) data[posn+1] = '\0'; else memmove(data+posn+1, data+posn, (size_t) move); // move string tail data[posn] = a; slength = nl; } u_int fxStr::replace(char a, char b) { u_int count = 0; char * buf = data; u_int counter = slength-1; while (counter--) { if (*buf == a) { *buf = b; count++; } buf++; } return count; } void fxStr::resizeInternal(u_int chars) { if (slength > 1) { if (chars > 0) { if (chars >= slength) { data = (char*) realloc(data,chars+1); } } else { assert(data != &emptyString); free(data); data = &emptyString; } } else { assert(data == &emptyString); if (chars) { data = (char*) malloc(chars+1); } } } void fxStr::resize(u_int chars, bool) { resizeInternal(chars); if (chars != 0) { if (slength == 1) // NB: special case for emptyString memset(data, 0, chars+1); else { if (chars >= slength) // zero expanded data segment memset(data+slength, 0, chars+1-slength); else // null terminate shortened string data[chars] = 0; } } else ; // now points to emptyString slength = chars+1; } void fxStr::setMaxLength(u_int len) { if (slength>1) resizeInternal(fxmax(len,slength-1)); } void fxStr::operator=(const fxTempStr& s) { resizeInternal(s.slength-1); memcpy(data,s.data,s.slength); slength = s.slength; } void fxStr::operator=(const fxStr& s) { if (data == s.data && slength == s.slength) return; resizeInternal(s.slength-1); memcpy(data,s.data,s.slength); slength = s.slength; } void fxStr::operator=(const char *s) { u_int nl = strlen(s) + 1; resizeInternal(nl-1); slength = nl; memcpy(data,s,slength); } void fxStr::append(const char * s, u_int l) { if (!l) l = strlen(s); if (!l) return; u_int nl = slength + l; resizeInternal(nl-1); memcpy(data+slength-1, s, l); slength = nl; data[slength-1] = 0; } void fxStr::append(char a) { resizeInternal(slength); slength++; data[slength-2] = a; data[slength-1] = 0; } bool operator==(const fxStr& a,const fxStr& b) { return (a.slength == b.slength) && (memcmp(a.data,b.data,a.slength) == 0); } bool operator==(const fxStr& a,const char* b) { return (a.slength == strlen(b)+1) && (memcmp(a.data,b,a.slength) == 0); } bool operator==(const char* b, const fxStr& a) { return (a.slength == strlen(b)+1) && (memcmp(a.data,b,a.slength) == 0); } bool operator!=(const fxStr& a,const fxStr& b) { return (a.slength != b.slength) || (memcmp(a.data,b.data,a.slength) != 0); } bool operator!=(const fxStr& a,const char* b) { return (a.slength != strlen(b)+1) || (memcmp(a.data,b,a.slength) != 0); } bool operator!=(const char* b, const fxStr& a) { return (a.slength != strlen(b)+1) || (memcmp(a.data,b,a.slength) != 0); } bool operator>=(const fxStr& a,const fxStr& b) { return strcmp(a,b) >= 0; } bool operator>=(const fxStr& a,const char* b) { return strcmp(a,b) >= 0; } bool operator>=(const char* a, const fxStr& b) { return strcmp(a,b) >= 0; } bool operator>(const fxStr& a,const fxStr& b) { return strcmp(a,b) > 0; } bool operator>(const fxStr& a,const char* b) { return strcmp(a,b) > 0; } bool operator>(const char* a, const fxStr& b) { return strcmp(a,b) > 0; } bool operator<=(const fxStr& a,const fxStr& b) { return strcmp(a,b) <= 0; } bool operator<=(const fxStr& a,const char* b) { return strcmp(a,b) <= 0; } bool operator<=(const char* a, const fxStr& b) { return strcmp(a,b) <= 0; } bool operator<(const fxStr& a,const fxStr& b) { return strcmp(a,b) < 0; } bool operator<(const fxStr& a,const char* b) { return strcmp(a,b) < 0; } bool operator<(const char* a, const fxStr& b) { return strcmp(a,b) < 0; } int compare(const fxStr&a, const fxStr&b) { return strcmp(a,b); } int compare(const fxStr&a, const char*b) { return strcmp(a,b); } int compare(const char *a, const char *b) { return strcmp(a,b); } static int quickFind(char a, const char * buf, u_int buflen) { while (buflen--) if (*buf++ == a) return 1; return 0; } u_int fxStr::next(u_int posn, char a) const { fxAssert(posn sizeof(indata)) { // Have to malloc. data = (char*) malloc(slength + bl); memcpy(data, indata, slength - 1); } } else { // Temporary is already too large. data = (char*) realloc(data, slength + bl); } // concatenate data memcpy(data+slength-1, b, bl); slength += bl; data[slength-1] = 0; return *this; } fxTempStr operator|(const fxStr &a, const fxStr &b) { return fxTempStr(a.data, a.slength-1, b.data, b.slength-1); } fxTempStr operator|(const fxStr &a, const char *b) { return fxTempStr(a.data, a.slength-1, b, strlen(b)); } fxTempStr operator|(const char *a, const fxStr &b) { return fxTempStr(a, strlen(a), b.data, b.slength-1); }