Mercurial > ~dholland > hg > ag > index.cgi
view anagram/support/agstring.cpp @ 4:bebb2ba69e1d
maybe help with getting tex to fail properly on error
author | David A. Holland |
---|---|
date | Sat, 18 Apr 2020 17:12:17 -0400 |
parents | 13d2b8934445 |
children | 57b2cc9b87f7 |
line wrap: on
line source
/********************************************************** 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; } */