/*******************************************************************************
* 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;
}