/******************************************************************************* * BString.cc Beams String Class * T.Barnaby, BEAm Ltd, 15/7/92 * updated by D.Korchagin, CERN AB-BI-SW, 2007-08-31 ******************************************************************************* */ #ifndef __Lynx__ #else #include <stdarg.h> #endif #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdarg.h> #include <ctype.h> #include "BString.h" #ifndef __Lynx__ #else inline int vasprintf(char **resultp, const char *format, va_list args) { int ret_val; int size = 512 * sizeof (char); *resultp = (char *) malloc (size); while ((((ret_val = vsprintf(*resultp, format, args)) >= size) || (ret_val < 0)) && (*resultp != NULL)) *resultp = (char *) realloc (*resultp, size = (ret_val < 0) ? (2 * size) : (size + sizeof('\0'))); return ret_val; } #endif #define DEBUG 0 # define STRIP 0x7f # define MINUS '-' static int gmatch(const char *s, const char *p){ int scc; char c; if (scc = *s++) { if ((scc &= STRIP) == 0) scc=0200; } switch (c = *p++) { case '[': { int ok; int lc; int notflag = 0; ok = 0; lc = 077777; if (*p == '!') { notflag = 1; p++; } while (c = *p++) { if (c == ']') return(ok ? gmatch(s, p) : 0); else if (c == MINUS) { if (notflag) { if (scc < lc || scc > *(p++)) ok++; else return(0); } else { if (lc <= scc && scc <= (*p++)) ok++; } } else { lc = c & STRIP; if (notflag) { if (scc && scc != lc) ok++; else return(0); } else { if (scc == lc) ok++; } } } return(0); } default: if ((c & STRIP) != scc) return(0); case '?': return(scc ? gmatch(s, p) : 0); case '\\': c = *p++; if((c & STRIP) != scc) return(0); case '*': while (*p == '*') p++; if (*p == 0) return(1); --s; while (*s) { if (gmatch(s++, p)) return(1); } return(0); case '!': return !gmatch(--s, p); case 0: return(scc == 0); } } BString::~BString(){ if(ostr && (ostr->deleteRef() == 0)){ delete ostr; } } BString::BString() { ostr = 0; } BString::BString(const BString& string) { if(string.ostr) ostr = string.ostr->addRef(); else ostr = 0; } BString::BString(const char* str) { if(str && str[0]){ ostr = new BRefData(strlen(str) + 1); strcpy(ostr->data(), str); } else { ostr = 0; } } BString::BString(char ch) { ostr = new BRefData(2); ostr->data()[0] = ch; ostr->data()[1] = 0; } BString::BString(int value) { char buf[32]; sprintf(buf, "%d", value); ostr = new BRefData(strlen(buf) + 1); strcpy(ostr->data(), buf); } BString::BString(unsigned int value) { char buf[32]; sprintf(buf, "%u", value); ostr = new BRefData(strlen(buf) + 1); strcpy(ostr->data(), buf); } BString::BString(long value) { char buf[32]; sprintf(buf, "%ld", value); ostr = new BRefData(strlen(buf) + 1); strcpy(ostr->data(), buf); } BString::BString(unsigned long long value) { char buf[32]; sprintf(buf, "%lld", value); ostr = new BRefData(strlen(buf) + 1); strcpy(ostr->data(), buf); } BString::BString(double value) { char buf[32]; sprintf(buf, "%f", value); ostr = new BRefData(strlen(buf) + 1); strcpy(ostr->data(), buf); } void BString::Init(const char* str) { if(str && str[0]){ ostr = new BRefData(strlen(str) + 1); strcpy(ostr->data(), str); } else { ostr = 0; } } BString BString::convert(char value){ char buf[128]; sprintf(buf, "%c", value); return buf; } BString BString::convert(int value){ char buf[128]; sprintf(buf, "%d", value); return buf; } BString BString::convert(unsigned int value){ char buf[128]; sprintf(buf, "%u", value); return buf; } BString BString::convert(long value){ char buf[128]; sprintf(buf, "%ld", value); return buf; } BString BString::convert(double value){ char buf[128]; sprintf(buf, "%f", value); return buf; } BString BString::convert(unsigned long long value){ char buf[128]; sprintf(buf, "%lld", value); return buf; } BString BString::convertHex(int value){ char buf[128]; sprintf(buf, "0x%x", value); return buf; } BString BString::convertHex(unsigned int value){ char buf[128]; sprintf(buf, "0x%x", value); return buf; } BString BString::copy(){ return BString(retStr()); } void BString::strChanged(){ } int BString::len() const { if(ostr && ostr->len()) return ostr->len() - 1; else return 0; } BString& BString::truncate(int l) { if(ostr){ ostr = ostr->copy(); if(l < len()){ ostr->setLen(l + 1); ostr->data()[l] = '\0'; } strChanged(); } return *this; } BString& BString::pad(int l) { if(ostr){ ostr = ostr->copy(); while(l > len()){ *this = *this + " "; } strChanged(); } return *this; } BString& BString::toUpper(){ char* s; if(ostr){ ostr = ostr->copy(); for(s = ostr->data(); *s; s++) *s = toupper(*s); } return *this; } BString& BString::toLower(){ char* s; if(ostr){ ostr = ostr->copy(); for(s = ostr->data(); *s; s++) *s = tolower(*s); } return *this; } void BString::removeNL(){ if(ostr){ ostr = ostr->copy(); if(len() && (ostr->data()[len() - 1] == '\n')) truncate(len() - 1); } } BString BString::subString(int start, int l) const { BString s; if(ostr && inString(start) && len()){ s = &ostr->data()[start]; if(l >= 0) s.truncate(l); } return s; } int BString::inString(int pos) const { if((pos >= 0) && (pos <= len())) return 1; else return 0; } int BString::del(int start, int l){ char* d; char* s; if(ostr){ ostr = ostr->copy(); if(inString(start) && len()){ if(l > (len() - start)) l = len() - start; d = &ostr->data()[start]; s = &ostr->data()[start + l]; while(*d++ = *s++); ostr->setLen(ostr->len() - l); strChanged(); return 1; } } return 0; } int BString::insert(int start, BString str){ BString s; if(inString(start)){ if(start) s = subString(0, start); s = s + str; s = s + subString(start, -1); *this = s; strChanged(); return 1; } return 0; } void BString::printf(const char* fmt, ...) { va_list ap; int l; char* s = 0; if(ostr && ostr->deleteRef() == 0) delete ostr; ostr = 0; va_start(ap, fmt); l = vasprintf(&s, fmt, ap); va_end(ap); if(l >= 0){ *this = s; free(s); } } int BString::find(char ch) const { char* a; if(ostr && (a = strchr(ostr->data(), ch))) return a - ostr->data(); else return -1; } int BString::findReverse(char ch) const { char* a; if(ostr && (a = strrchr(ostr->data(), ch))) return a - ostr->data(); else return -1; } int BString::isSpace(char ch) const { return ((ch == ',') || (ch == ' ') || (ch == '\t') || (ch == '\n') || (ch == '\r')); } BString BString::field(int field) const { char* ps; char* pe; BString s; if(ostr){ ps = ostr->data(); while(field && ps && *ps){ while(*ps && !isSpace(*ps)){ if(*ps == '"'){ ps++; while(*ps && (*ps != '"')) ps++; } else if(*ps == '('){ ps++; while(*ps && (*ps != ')')) ps++; } ps++; } while(*ps && isSpace(*ps)) ps++; field--; } pe = ps; while(*pe && !isSpace(*pe)){ if(*pe == '"'){ pe++; while(*pe && (*pe != '"')) pe++; } else if(*pe == '('){ pe++; while(*pe && (*pe != ')')) pe++; } pe++; } if(*ps == '"'){ ps++; pe--; } s = ps; s.truncate(pe - ps); } return s; } char** BString::fields(){ BString a; char** r; char** o; int f; o = r = new char* [64 + 1]; for(f = 0; f < 64; f++){ a = field(f); if(a != ""){ *o = new char [a.len() + 1]; strcpy(*o, a.retStr()); } else { break; } o++; } *o = 0; return r; } BList<BString> BString::getTokenList(BString separators){ BList<BString> list; BString s = *this; BString t; while((t = s.pullToken(separators)) != ""){ list.append(t.removeSeparators(separators)); } return list; } BString BString::pullToken(BString terminators){ char* p = 0; int s; int e; int n; BString ret; if(ostr){ p = ostr->data(); s = 0; while(*p && strchr(terminators, *p)){ s++; p++; } e = s; while(*p && !strchr(terminators, *p)){ e++; p++; } n = e; while(*p && strchr(terminators, *p)){ n++; p++; } ret = subString(s, e - s); *this = subString(n, -1); } return ret; } BString BString::removeSeparators(BString separators){ char* p = 0; int s; int e; if(ostr){ p = ostr->data(); s = 0; while(*p && strchr(separators, *p)){ s++; p++; } e = len() - 1; if(e > 0){ p = ostr->data() + len() - 1; while(*p && strchr(separators, *p)){ e--; p--; } } return subString(s, e - s + 1); } else { return ""; } } BString BString::pullSeparators(BString separators){ char* p = 0; int e; BString ret; if(ostr){ p = ostr->data(); e = 0; while(*p && strchr(separators, *p)){ e++; p++; } ret = subString(0, e); *this = subString(e, -1); } return ret; } BString BString::pullWord(){ return pullToken(" \t\n"); } BString BString::pullLine(){ return pullToken("\n"); } int BString::compare(const BString& string) const { return strcmp(retStr(), string.retStr()); } int BString::compareWild(const BString& string) const { return gmatch(retStr(), string.retStr()); } int BString::compareWildExpression(const BString& string) const { BString e; int n; for(n = 0; (e = string.field(n)) != ""; n++){ if(e[0] == '!'){ if(gmatch(retStr(), e.retStr() + 1)){ return 0; } } else { if(gmatch(retStr(), e.retStr())){ return 1; } } } return 0; } const char* BString::retStr() const { if(ostr) return ostr->data(); else return ""; } char* BString::retStrDup() const { if(ostr) return strdup(ostr->data()); else return strdup(""); } int BString::retInt() const { if(ostr) return strtol(ostr->data(), NULL, 0); else return 0; } unsigned int BString::retUInt() const { if(ostr) return strtoul(ostr->data(), NULL, 0); else return 0; } double BString::retDouble() const { if(ostr) return strtod(ostr->data(), NULL); else return 0; } BString BString::add(const BString& string) const { BString s; if(ostr || string.ostr){ s.ostr = new BRefData(len() + string.len() + 1); s.ostr->data()[0] = '\0'; if(ostr) strcat(s.ostr->data(), ostr->data()); if(string.ostr) strcat(s.ostr->data(), string.ostr->data()); } return s; } BString& BString::operator=(const BString& string) { if(this != &string){ if(ostr && (ostr->deleteRef() == 0)) delete ostr; if(string.ostr) ostr = string.ostr->addRef(); else ostr = 0; strChanged(); } return *this; } char& BString::operator[](int pos){ if(ostr){ return ostr->data()[pos]; } else { fprintf(stderr, "BString: array operator out of range\n"); exit(1); } } #ifdef ZAP BString operator+(const char* a1, BString& a2) { return (BString)a1 + a2; } #endif std::ostream& operator<<(std::ostream& o, BString& s){ o << s.retStr(); return o; } std::istream& operator>>(std::istream& i, BString& s){ char buf[1024]; i >> buf; s = (BString)buf; return i; }