#pragma implementation
#include "Str.h"
extern "C" {
#include <stdio.h>
#include <float.h>
#include <ctype.h>
#ifdef SYSV
#include <string.h>
#define bcopy(from, to, len) (memcpy((to), (from), (len)))
#else
#include <strings.h>
#endif
}
#include "set_error.h"
const char Str::empty_string = 0;
void Str::clear(void) {
if (alloc_len) {
if (alloc_len >= 16*1024) {
delete [] adr;
adr = (char *)&empty_string;
alloc_len = 0;
fail = 0;
return;
} else {
*adr = 0;
}
len = 0;
}
return;
};
void Str::expand(void) {
unsigned long newlen = alloc_len * 2;
if (newlen == 0) newlen = 31;
if (alloc_len >= 64*1024) newlen = alloc_len + 64*1024;
char * nadr = new char[newlen+1];
if (nadr == 0) {
fail = -1;
set_error("Str::expand ","unable to allocate more memory");
return;
}
bcopy(adr, nadr, len+1);
if (alloc_len) delete [] adr;
adr = nadr;
alloc_len = newlen;
}
void Str::fill(char fill) {
if (len) {
char * d = adr;
unsigned long l = len-1;
do {
*d++ = fill;
} while (l--);
}
}
Str::Str (unsigned long int length) {
if (length == 0) {
adr = ((char *)&empty_string);
len = 0;
fail = 0;
alloc_len = 0;
return;
}
adr = new char[length+1];
if (adr) {
*(adr) = 0;
*(adr+length) = 0;
fail = 0;
len = length;
alloc_len = length;
} else {
fail = -1;
len = 0;
alloc_len = 0;
}
}
Str::Str(const char * text) {
alloc_len = 31;
adr = new char[31+1];
len = 0;
fail = 0;
for (;;) {
if (adr == 0) {
fail = -1;
len = 0;
alloc_len = 0;
}
char * dst = adr+len;
unsigned long cnt = alloc_len - len;
while (cnt) {
char c = *text++;
*dst++ = c;
if (c == 0) {
return;
}
len++;
cnt--;
}
expand();
}
}
Str::Str(const char * text, unsigned long length) {
if (length == 0) {
adr = ((char *)&empty_string);
len = 0;
fail = 0;
alloc_len = 0;
return;
}
adr = new char[length+1];
if (adr == 0) {
set_error("Str: ","unable to construct string");
fail = -1;
len = 0;
alloc_len = 0;
return;
}
len = length;
alloc_len = length;
bcopy(text, adr, len);
*(adr+len) = 0;
fail = 0;
}
Str::Str(const Str & rv) {
if (rv.len == 0) {
adr = ((char *)&empty_string);
len = 0;
fail = 0;
alloc_len = 0;
return;
}
adr = new char[rv.len+1];
if (adr == 0) {
set_error("Str: ","unable to copy-construct string");
fail = -1;
len = 0;
alloc_len = 0;
return;
}
len = rv.len;
alloc_len = rv.len;
bcopy(rv.adr, adr, len+1);
fail = 0;
}
const Str & Str::operator=(const Str & rv) {
if (rv.len == 0) {
if (alloc_len < 16*1024) {
len = 0;
if (alloc_len) *adr = 0;
fail = 0;
return *this;
} else {
delete [] adr;
adr = ((char *)&empty_string);
len = 0;
fail = 0;
alloc_len = 0;
return *this;
}
}
if ( (rv.len <= alloc_len) && (alloc_len - rv.len < 16*1024) ) {
// we don't need to allocate new memory, just copy
// the string and adjust len
bcopy (rv.adr, adr, rv.len+1);
len = rv.len;
return *this;
}
if (alloc_len) delete [] adr;
adr = new char[rv.len+1];
if (adr == 0) {
set_error("Str::operator= ","unable to copy-construct string");
fail = -1;
len = 0;
alloc_len = 0;
return *this;
}
len = rv.len;
alloc_len = rv.len;
bcopy(rv.adr, adr, len+1);
fail = 0;
return *this;
}
unsigned long Str::val(void) const {
unsigned long int v = 0;
unsigned long int i;
const char * a;
char c;
if (len > 2 && left(2) == "0x") {
for (a=adr+2, i=len-2; i!=0; i--) {
c = *a++;
if ( (c >= '0') && (c <= '9') ) {
v <<= 4;
v += c-'0';
} else if ( (c >= 'a') && (c <= 'f') ) {
v <<= 4;
v += c-('a'-10);
} else if ( (c >= 'A') && (c <= 'F') ) {
v <<= 4;
v += c-('A'-10);
} else break;
}
} else if ( len > 2 && left(2) == "0b" ) {
for (a=adr+2, i=len-2; i!=0; i--) {
c = *a++;
if ( c == '0' ) {
v <<= 1;
} else if ( c == '1' ) {
v <<= 1;
v++;
} else break;
}
} else {
for (a=adr, i=len; i!=0; i--) {
c = *a++;
if ( (c < '0') || (c > '9') ) break;
v *= 10;
v += (unsigned long int) (c-'0');
}
}
return v;
}
unsigned long long Str::vall(void) const {
unsigned long long v = 0;
unsigned long i;
const char * a;
char c;
if (len > 2 && left(2) == "0x") {
for (a=adr+2, i=len-2; i!=0; i--) {
c = *a++;
if ( (c >= '0') && (c <= '9') ) {
v <<= 4;
v += c-'0';
} else if ( (c >= 'a') && (c <= 'f') ) {
v <<= 4;
v += c-('a'-10);
} else if ( (c >= 'A') && (c <= 'F') ) {
v <<= 4;
v += c-('A'-10);
} else break;
}
} else if ( len > 2 && left(2) == "0b" ) {
for (a=adr+2, i=len-2; i!=0; i--) {
c = *a++;
if ( c == '0' ) {
v <<= 1;
} else if ( c == '1' ) {
v <<= 1;
v++;
} else break;
}
} else {
for (a=adr, i=len; i!=0; i--) {
c = *a++;
if ( (c < '0') || (c > '9') ) break;
v *= 10;
v += (unsigned long long) (c-'0');
}
}
return v;
}
long Str::sval(void) const {
if (len == 0) return 0;
if (*adr == '-') {
long v = (long) right(len-1).val();
return -v;
}
else {
return val();
}
}
long long Str::svall(void) const {
if (len == 0) return 0;
if (*adr == '-') {
long long v = (long long) right(len-1).vall();
return -v;
}
else {
return vall();
}
}
Str Str::next_word(void) {
Str res;
char c;
unsigned long i;
unsigned long j;
for (i = 0; i<len; i++) {
c=*(adr+i);
if ((c != 0x20 ) && (c != 9)) break;
}
if (i==len) {
len = 0;
return Str();
}
char qflag = 0;
for (j = i; j<len; j++) {
c = *(adr+j);
if (!qflag) {
if ((c==0x20 ) || (c==9)) break;
if (c==0x22) qflag = -1;
}
else {
if (c==0x22) qflag = 0;
}
}
if ( (*(adr+i) == 0x22) && (*(adr+j-1) == 0x22) ) {
res = Str((adr+i+1),(j-i)-2);
}
else {
res = Str((adr+i),j-i);
}
if (j==len) {
len = 0;
*adr = 0;
}
else {
bcopy(adr+j, adr, 1+len-j);
len = len-j;
}
return res;
}
Str Str::next_line(void) {
Str res;
unsigned long i = index(0x0a);
if (i == (unsigned long)~0) {
res = Str(*this);
len = 0;
*adr = 0;
return res;
}
res = before(i);
if (len > i+1) {
bcopy((adr+i+1), adr, 1+len-(i+1));
}
len -= i+1;
return res;
}
Str Str::operator+(const Str & rv) const {
Str res(len+rv.len);
if (len) bcopy(adr, res.adr, len);
if (rv.len) bcopy(rv.adr, res.adr+len, rv.len);
return res;
}
Str Str::operator+(char rv) const {
Str res(len+1);
if (len) bcopy(adr, res.adr, len);
*(res.adr+len) = rv;
return res;
}
Str Str::operator+=(const Str & rv) {
if (! rv.len) return *this;
if (len+rv.len <= alloc_len) {
bcopy(rv.adr, adr+len, rv.len);
len += rv.len;
*(adr+len) = 0;
} else {
if (rv.len < 64*1024 && rv.len < len) {
expand();
if (alloc_len >= len+rv.len) {
bcopy(rv.adr, adr+len, rv.len);
len += rv.len;
*(adr+len) = 0;
} else {
fail = -1;
set_error("Str::operator+ ","unable to allocate more memory");
}
} else {
char * nadr = new char[len+rv.len+1];
if (nadr == 0) {
fail = -1;
set_error("Str::operator+ ","unable to allocate more memory");
return *this;
}
bcopy(adr, nadr, len);
bcopy(rv.adr, nadr+len, rv.len);
if (alloc_len) delete [] adr;
adr = nadr;
len += rv.len;
*(adr+len) = 0;
alloc_len = len;
}
}
return *this;
}
int Str::operator==(const char * p) const {
const char * a = adr;
unsigned long cnt = 0;
for (;;) {
char c = *p++;
if (cnt == len) {
if (c == 0) return -1;
return 0;
}
if (c == 0) return 0;
if (c != *a++) return 0;
cnt++;
}
return 0;
}
int Str::operator==(const Str & rv) const {
if (len != rv.len) return 0;
if (len == 0) return -1;
const char * a = adr;
const char * b = rv.adr;
unsigned long cnt = len-1;
do {
if (*a++ != *b++) return 0;
} while (cnt--);
return -1;
}
int Str::operator<(const char * p) const {
const char * a = adr;
unsigned long cnt = 0;
for (;;) {
char c = *p++;
if (len == cnt) {
if (c == 0)
return 0;
return -1;
}
if (c == 0)
return 0;
if (c != *a)
return (*a < c);
a++; cnt++;
}
}
int Str::operator<(const Str & rv) const {
unsigned long p = (rv.len < len)? rv.len : len;
const char * a = adr;
const char * b = rv.adr;
if (len && rv.len) {
for (; p!=0; p--) {
if (*a != *b) break;
a++;
b++;
}
if (p) {
if (*a < *b) return -1;
else return 0;
}
else {
return (len < rv.len);
}
}
else {
if (len == rv.len) return 0;
if (len == 0) return -1;
else return 0;
}
}
int Str::compare (const Str & rv) const {
unsigned long p = (rv.len < len)? rv.len : len;
const char * a = adr;
const char * b = rv.adr;
if (len && rv.len) {
for (; p!=0; p--) {
if (*a != *b) break;
a++;
b++;
}
if (p) {
if (*a < *b) return -1;
else return 1;
}
else {
if (len == rv.len) return 0;
if (len < rv.len) return -1;
return 1;
}
}
else {
if (len == rv.len) return 0;
if (len == 0) return -1;
else return 1;
}
}
int Str::operator>(const Str & rv) const {
unsigned long p = (rv.len < len)? rv.len : len;
const char * a = adr;
const char * b = rv.adr;
if (len && rv.len) {
for (; p!=0; p--) {
if (*a != *b) break;
a++;
b++;
}
if (p) {
if (*a > *b) return -1;
else return 0;
}
else {
return (len > rv.len);
}
}
else {
if (len == rv.len) return 0;
if (len == 0) return 0;
else return -1;
}
}
Str Str::sub(unsigned long from, unsigned long to) const {
if (to > len) to = len;
if (from >= to) return Str((unsigned long) 0);
return Str(adr+from, to-from);
};
unsigned long Str::index(const Str & match, unsigned long offset) const {
if (match.len == 0) return 0;
const char * m = match.adr;
char c = *m++; // erstes zeichen
const char * o = adr+offset;
for (; offset+match.length() <= len; offset++) {
if (*o++ == c) {
if (match.len == 1) return offset;
const char * a = m;
const char * b = o;
unsigned long l = match.len - 2;
do {
if ( *a++ != *b++ ) break;
} while (l--);
if (l == (unsigned long)~0) return offset;
}
}
return (unsigned long)~0;
}
unsigned long Str::index(char match, unsigned long offset) const {
if (offset >= len) return ~(unsigned long)0;
const char * a = adr+offset;
for (; offset < len; offset++) {
if ((*a++) == match) break;
}
if (offset < len) return offset;
else return ~(unsigned long)0;
}
unsigned long Str::rindex(char match, unsigned long offset) const {
if (offset >= len) return ~(unsigned long)0;
const char * a = adr+len-offset;
unsigned long i = (len-offset)-1;
for (; i != ~(unsigned long)0; i--) {
if ((*(--a)) == match) break;
}
return i;
}
Str NtoStr(unsigned long val, short int width) {
char vbuf[20];
register short p = 1;
register char * a = vbuf+20;
for (;; p++) {
*(--a) = (char)'0'+(val % 10);
val /= 10;
if (val == 0) break;
}
Str res=Str(vbuf+(20-p),p);
if (width) {
if ((unsigned long)width > res.length()) {
Str tmp(width-res.length());
tmp.fill();
return tmp+res;
}
else {
return res.sub(res.length()-width,res.length());
}
}
else{
return res;
}
}
Str SNtoStr(long val, short int width) {
if (val >= 0) {
return NtoStr(val, width);
}
else {
if (width > 1) width--;
val = -val;
return Str("-")+NtoStr((unsigned long)val, width);
}
}
static char HexTab[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
static char HexBuf[8];
Str NtoHex(unsigned long val, unsigned short width) {
if (width > 8) width = 8;
{
short x = 7;
char * c = HexBuf;
do {
*c++ = '0';
} while (x--);
}
char * c = &HexBuf[8];
short cnt = 0;
do {
cnt++;
*(--c) = HexTab[val & 0xf];
val >>= 4;
} while (val != 0);
if (width) return Str(&(HexBuf[8-width]), width);
return Str(&(HexBuf[8-cnt]), cnt);
}
Str & Str::to_upper(void) {
char * a = adr;
for (unsigned long i = 0; i < len; i++) {
*a = upper(*a);
a++;
}
return *this;
}
Str & Str::to_lower(void) {
char * a = adr;
for (unsigned long i = 0; i < len; i++) {
*a = lower(*a);
a++;
}
return *this;
}
Str LtoStr(long num) {
Str res(4);
// if (res.fail) return Str();
char * c = (char *)res;
*c++ = (num & 0xff000000) >> 24;
*c++ = (num & 0xff0000) >> 16;
*c++ = (num & 0xff00) >> 8;
*c++ = (num & 0xff);
return res;
}
Str operator+(const char * lv, const Str & rv) {
return Str(lv)+rv;
}
Str FtoStr(double val) {
Str res;
static char buf[40];
sprintf(buf,"%1.*g",DBL_DIG,val);
res = Str(buf);
return res;
}
void Str::implode_escape_sequences(void) {
char *i,*o;
i = o = adr;
int n = len;
while(n--) {
if(*i == '\\' &&
isdigit(i[1]) &&
isdigit(i[2]) &&
isdigit(i[3])) {
int c;
sscanf(i+1, "%3o", &c);
*o++ = c;
i += 4;
len -= 3;
n -= 3;
}
else {
*o++ = *i++;
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1