Mercurial > ~dholland > hg > ag > index.cgi
diff anagram/support/agstring.cpp @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children | 57b2cc9b87f7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/anagram/support/agstring.cpp Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,578 @@ +/********************************************************** + +The AnaGram Class Library + +The AgString Class +Copyright 1997-2002 Parsifal Software. All Rights Reserved. +See the file COPYING for license and usage terms. + +***********************************************************/ + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include "port.h" + +#include "agstring.h" +#include "assert.h" +#include "csexp.h" // sigh... XXX (for agToUpper) + +//#define INCLUDE_LOGGING +#include "log.h" + + +void AgString::allocate(unsigned n) { + // XXX shouldn't this be just n+sizeof(short)? There's no need to round + // up, and this isn't a correct roundup anyway... + // (and what if malloc returns NULL?) + store = (char *) malloc(((n+sizeof(short))/sizeof(short) + 1)*sizeof(short)) + + sizeof(short); +} + +void AgString::lock() { + if (store) { + (((short *) (void *)store)[-1])++; + } +} + +void AgString::unlock() { + if (store && --(((short *) (void *) store)[-1]) <= 0) { + //delete [] (store - sizeof(short)); + free(store - sizeof(short)); + } + store = 0; +} + +AgString::AgString(const char *s) + : AgIndexedContainer<char>() +{ + LOGSECTION("AgString::AgString(const char *)"); + LOGV(s); + if (s) { + allocate(strlen(s)); + assert(store != 0); + ((short *) (void *)store)[-1] = 1; + strcpy(store, s); + LOGV(store); + } + else store = 0; +} + +AgString::AgString(const unsigned n) +{ + if (n) { + allocate(n); + assert(store != 0); + ((short *) (void *)store)[-1] = 1; + memset(store, 0, n+1); + } + else { + store = 0; + } +} + +AgString::AgString(const char *s, const unsigned n) +{ + if (n) { + allocate(n); + unsigned k = strlen(s); + if (n < k) { + k = n; + } + assert(store != 0); + ((short *)(void *) store)[-1] = 1; + if (s) { + strncpy(store, s, k); + } + store[k] = 0; + } + else { + store = 0; + } +} + +AgString::AgString(const AgString &s, const unsigned n) +{ + if (n) { + allocate(n); + assert(store != 0); + ((short *)(void *) store)[-1] = 1; + if (s.store) { + strncpy(store, s.store, n); + } + store[n] = 0; + } + else { + store = 0; + } +} + +char &AgString::operator [] (const unsigned x) { + assert(x < size()); + return store[x]; +} + +const char &AgString::operator [] (const unsigned x) const { + assert(x < size()); + return store[x]; +} + +AgString &AgString::operator = (const AgString &s) { + unlock(); + store = s.store; + lock(); + return *this; +} + +AgString &AgString::toUpper() { + if (store) { + char *s = store; + while (*s) { + *s = (char) agToUpper(*s); + s++; + } + } + return *this; +} + +/* +AgString &AgString::toLower() { + if (store) { + char *s = store; + while (*s) { + *s = (char) tolower(*s); + s++; + } + } + return *this; +} +*/ + +int AgString::operator < (const AgString &s) const { + //LOGSECTION("AgString::operator <"); + if (store == s.store) { + return 0; + } + else if (store && s.store) { + //LOGV(store) LCV(s.store); + return strcmp(store, s.store) < 0; + } + else { + return store == 0; + } +} + +int AgString::operator < (const char *s) const { + if (store == s) { + return 0; + } + else if (store && s) { + return strcmp(store, s) < 0; + } + else { + return store == 0; + } +} + +int AgString::operator <= (const AgString &s) const { + if (store == s.store) { + return 1; + } + else if (store && s.store) { + return strcmp(store, s.store) <= 0; + } + else { + return store == 0; + } +} + +int AgString::operator <= (const char *s) const { + if (store == s) { + return 1; + } + else if (store && s) { + return strcmp(store, s) <= 0; + } + else { + return store == 0; + } +} + +int AgString::operator > (const AgString &s) const { + if (store == s.store) { + return 0; + } + else if (store && s.store) { + return strcmp(store, s.store) > 0; + } + else { + return s.store == 0; + } +} + +int AgString::operator > (const char *s) const { + if (store == s) { + return 0; + } + else if (store && s) { + return strcmp(store, s) > 0; + } + else { + return s == 0; + } +} + +int AgString::operator >= (const AgString &s) const { + if (store == s.store) { + return 1; + } + else if (store && s.store) { + return strcmp(store, s.store) >= 0; + } + else { + return s.store == 0; + } +} + +int AgString::operator >= (const char *s) const { + if (store == s) { + return 1; + } + else if (store && s) { + return strcmp(store, s) >= 0; + } + else { + return s == 0; + } +} + +int AgString::iEq(const AgString &s) const { + if (store == s.store) { + return 1; + } + if (store && s.store) { + return stricmp(store, s.store) == 0; + } + else { + return 0; + } +} + +int AgString::iEq(const char *s) const { + if (store == s) { + return 1; + } + if (store && s) { + return stricmp(store, s) == 0; + } + else { + return 0; + } +} + +int AgString::operator == (const AgString &s) const { + if (store == s.store) { + return 1; + } + if (store && s.store) { + return strcmp(store, s.store) == 0; + } + else { + return 0; + } +} + +int AgString::operator == (const char *s) const { + if (store == s) { + return 1; + } + if (store && s) { + return strcmp(store, s) == 0; + } + else { + return 0; + } +} + +int AgString::operator != (const AgString &s) const { + if (store == s.store) { + return 0; + } + if (store && s.store) { + return strcmp(store, s.store) != 0; + } + else { + return 1; + } +} + +int AgString::operator != (const char *s) const { + if (store == s) { + return 0; + } + if (store && s) { + return strcmp(store, s) != 0; + } + else { + return 1; + } +} + +AgString AgString::format(const char *fs, ...) { + va_list ap; + int n; + + if (fs == NULL) { + return AgString(); + } + //int bufLength = 3*strlen(fs); + //if (bufLength < 2000) bufLength = 2000; + //char *buf = new char[bufLength]; + char buf[2000]; + + //assert(buf != NULL); + + va_start(ap, fs); + n = vsprintf(buf, fs, ap); + assert(n < 2000); + va_end(ap); + + AgString result(buf, n); + //delete [] buf; + return result; +} + + +// concatenation operators + +AgString AgString::concat(const char *s) const { + LOGSECTION("AgString::concat"); + LOGV(store) LCV(s); + if (s == NULL) { + return *this; + } + if (store == NULL) { + return AgString(s); + } + AgString result(store, size() + strlen(s)); + LOGV(result); + strcat(result.pointer(), s); + LOGV(result); + return result; +} + +AgString AgString::concat(const AgString s) const { + if (s.store == NULL) { + return *this; + } + if (store == NULL) { + return s; + } + AgString result(store, size() + s.size()); + strcat(result.pointer(), s.pointer()); + return result; +} + +AgString::Cut AgString::firstCut(const char c) const { + LOGSECTION("AgString::firstCut(char)"); + if (store) { + char *p = strchr(store, c); + LOGV(p) LCV(c); +/* + int n = p ? (int)( p - store) : -1; + return AgString::Cut(*this, n); +*/ + if (p) { + return AgString::Cut(*this, p - store); + } + } + return AgString::Cut(); +} + +AgString::Cut AgString::lastCut(const char c) const { + //LOGSECTION("lastCut"); + if (store) { + char *p = strrchr(store, c); + //LOGV(store); + //LOGV(c); + //LOGV(p); + int n = p ? (int) (p - store) : strlen(store); + return AgString::Cut(*this, n); + } + return AgString::Cut(); +} + +AgString::Cut AgString::firstCut(const char *s) const { + LOGSECTION("firstCut(const char *)"); + if (store) { + unsigned k = strcspn(store, s); + LOGV(store); + LOGV(s); + LOGV(k); + if (k < size()) { + return AgString::Cut(*this, k); + } + } + return AgString::Cut(); +} + +AgString::Cut AgString::lastCut(const char *s) const { + //LOGSECTION("lastCut"); + if (store) { + int k = size(); + while (k--) { + if (strchr(s, store[k])) { + //LOGV(store); + //LOGV(&store[k]); + //LOGV(k); + return AgString::Cut(*this, k); + } + } + return AgString::Cut(*this, size()); + } + return AgString::Cut(); +} + +AgString::Cut::Cut(const AgString &s, const int x) + : store(s.pointer()) + , index(x) +{ + if (store) { + assert((unsigned) x <= strlen(store)); + } + lock(); +} + +void AgString::Cut::lock() { + if (store) { + (((short *) (void *)store)[-1])++; + } +} + +void AgString::Cut::unlock() { + if (store && --(((short *) (void *) store)[-1]) <= 0) { + //delete [] (store - sizeof(short)); + free(store - sizeof(short)); + store = 0; + } +} + +char &AgString::Cut::character() const { + assert(store != 0); + return store[index]; +} + +AgString AgString::Cut::leftI() const { + //LOGSECTION("Cut::leftI"); + //LOGV(store); + //LOGV(index); + if (store == 0 || index < 0) { + return AgString(); + } + /* Include the separator... but not if it's the null terminator. */ + int pos = index; + if (store[pos]) { + pos++; + } + return AgString(store, pos); +} + +AgString AgString::Cut::leftX() const { + LOGSECTION("Cut::leftX"); + LOGV(store); + LOGV(index); + if (store == 0 || index <= 0) { + return AgString(); + } + /* Does this end up with the wrong length if store[index]==0? XXX */ + return AgString(store, index); +} + +AgString AgString::Cut::rightI() const { + //LOGSECTION("Cut::rightI"); + //LOGV(store); + //LOGV(index); + if (store == 0) { + return AgString(); + } + if (index < 0) { + return AgString(store); + } + return AgString(store + index); +} + +AgString AgString::Cut::rightX() const { + //LOGSECTION("Cut::rightX"); + //LOGV(store); + //LOGV(index); + if (store == 0) { + return AgString(); + } + /* Exclude the separator... but not if it's the null terminator. */ + int pos = index; + if (store[pos]) { + pos++; + } + return AgString(store + pos); +} + +/* +AgString AgString::Cut::insertLeft(const AgString &s) const { + AgString newString(store, strlen(store) + s.size()); + char *p = newString.pointer(); + p[index] = 0; + strcat(p, s.pointer()); + strcat(p, store+index); + return newString; +} + +AgString AgString::Cut::insertLeft(const char *s) const { + AgString newString(store, strlen(store) + strlen(s)); + char *p = newString.pointer(); + p[index] = 0; + strcat(p, s); + strcat(p, store+index); + return newString; +} + +AgString AgString::Cut::insertRight(const AgString &s) const { + AgString newString(store, strlen(store) + s.size()); + char *p = newString.pointer(); + p[index+1] = 0; + strcat(p, s.pointer()); + strcat(p, store+index+1); + return newString; +} + +AgString AgString::Cut::insertRight(const char *s) const { + AgString newString(store, strlen(store) + strlen(s)); + char *p = newString.pointer(); + p[index+1] = 0; + strcat(p, s); + strcat(p, store+index+1); + return newString; +} + +AgString AgString::Cut::replace(const AgString &s) const { + if (store == 0) return AgString(); + if (index < 0 || index > strlen(store)) return AgString(store); + AgString newString(store, strlen(store) + s.size() - 1); + char *p = newString.pointer(); + p[index] = 0; + if (s.size()) strcat(p, s.pointer()); + strcat(p, store+index+1); + return newString; +} + +AgString AgString::Cut::replace(const char *s) const { + if (store == 0) return AgString(); + if (index < 0 || index > strlen(store)) return AgString(store); + int n = s!= 0 ? strlen(s) : 0; + AgString newString(store, strlen(store) + n - 1); + char *p = newString.pointer(); + p[index] = 0; + if (n) strcat(p, s); + strcat(p, store+index+1); + return newString; +} +*/