/* * Copyright (c) 1995, 1996 Gunther Schadow. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "pg_config.h" IDENT("@(#) Strbase.cc (Gunther Schadow) 12/19/96"); #pragma implementation #include "Strbase.h" #include "DataTypeCode.h" #include "misc.h" #include "ioext.h" #include "xios.h" #include "stdlib.h" #include "stdio.h" // for sprintf(3) only #include "exception.h" #include "logfile.h" #include #include #include "ParseTrace.h" ostream& escprotect(ostream& os, const char* s); char *escexpand(Delimiters& del, char* s); bool Strbase::do_8th_bit_protection = true; Strbase::Strbase(DataTypeCode::Value type, const char* s) : Primtype(type) { _string = NULL; if(s != NULL) { if(*s != 0) { _string = strdup(s); Primtype::set(); } else Primtype::nullify(); } else Primtype::unset(); } const Strbase& Strbase::operator = (const char* s) { if(_string != s) { if(_string != NULL) { delete [] _string; _string = NULL; } if(s == NULL) Primtype::unset(); else if(*s == 0) Primtype::nullify(); else { _string = strdup(s); Primtype::set(); } } return *this; } Strbase::Strbase(const Strbase& x) : Primtype(x) { if(x._string == NULL) _string = NULL; else _string = strdup(x._string); } const Strbase& Strbase::operator = (const Strbase& x) { if(&x != this) { if(_string != NULL) delete [] _string; Primtype::operator =(x); if(x._string == NULL) _string = NULL; else _string = strdup(x._string); } return *this; } Strbase::~Strbase() { if(_string != NULL) { delete [] _string; _string = NULL; } } inline Strbase::operator const char *() const { if(ispresent()) if(isnull()) return ""; else return _string; else return NULL; } void Strbase::unset() { if(_string != NULL) { delete [] _string; _string = NULL; } Primtype::unset(); } void Strbase::nullify() { if(_string != NULL) { delete [] _string; _string = NULL; } Primtype::nullify(); } bool Strbase::operator == (const Strbase& x) const { bool Ea = ispresent(); bool Eb = x.ispresent(); bool Na = isnull(); bool Nb = x.isnull(); if(Ea && Eb) // both must exist if(Na && Nb) // and either both are null return TRUE; else if(!Na && !Nb) // or both are non-null if(strcmp(_string,x._string) == 0) // and have the same string value return TRUE; else // otherwise not! return FALSE; else return FALSE; else return FALSE; } result Strbase::input(istream& is) { if(_string != NULL) { delete [] _string; _string = NULL; } if(isdebug(is)) FATAL("can't input from debug stream"); LOGDEBUG("hl7/astm"); _string = strip(gets(is, getdel(is))); if(*_string != 0) { if( strcmp(_string,NULLVAL) == 0 ) nullify(); else { _string = escexpand(delims(is), _string); Primtype::set(); } } else unset(); return SUCCESS; } void Strbase::output(ostream& os) const { if(ishl7er(os) || isastmer(os)) { LOGDEBUG("hl7/astm"); if(ispresent()) if(isnull()) os << NULLVAL; else escprotect(os, _string); } else { LOGDEBUG("debug"); os << DSBGR0 << (const char *)DataTypeCode((DataTypeCode::Value)type()) << "typ" << DSBGR1; if(ispresent()) if(isnull()) os << DSNULL; else os << DSFRST DSBQUO << _string << DSEQUO; else os << DSNOPS; os << DSEGRP; } } char *escexpand(Delimiters& del, char* str) { const char e = del.getesc(); const char f = del.getfld(); const char r = del.getrep(); const char s = del.getcmp(); const char t = del.getscm(); const char *p = str; // read pointer char *q = str; // write pointer char c; while(1) { while(*p != e) if(*p == 0) { *q=0; return str; } else *q++=*p++; p++; c = *p++; LOGDEBUG("found `%c'", c); switch(toupper(c)) { case 'E': *q++=e; break; case 'F': *q++=f; break; case 'R': *q++=r; break; case 'S': *q++=s; break; case 'T': *q++=t; break; case 'X': { char dd[3]; dd[2]=0; char *de; char c; while(1) { if(*p == 0) goto estring; else if(*p == e) goto finish; else dd[0]=*p++; if(*p == 0) goto estring; else if(*p == e) goto eesc; else dd[1]=*p++; c = strtoul(dd, &de, 16); if(*de != 0) { record_parse_error("syntax error in X `%s'", dd); EPARSE("syntax error in X `%s'", dd); goto finish; } else *q++ = c; } } default: record_parse_warning("unknown esc command `%c'", c); LOGWARNING("unknown esc command `%c'", c); *q++ = e; while(*p != e) if(*p == 0) goto estring; else *q++ = *p++; *q++ = e; } finish: while(*p != e) if(*p == 0) goto estring; else p++; p++; continue; eesc: p++; record_parse_error("premajor end of esc sequence `%c'", c); EPARSE("premajor end of esc sequence `%c'", c); continue; } estring: record_parse_error("premajor end of esc sequence `%c'", c); EPARSE("end of field in esc sequence `%c'", c); *q=0; return str; } ostream& escprotect(ostream& os, const char* str) { size_t nod = Delimiters::toplevel - Delimiters::esclevel; char del[nod]; // the delimiters strncpy(del, getdel(os, Delimiters::esclevel), nod); del[nod-1] = 0; // cut off last delimiter (segment delimiter) char pdel[nod] = "ETSRF"; // substitution characters char e = del[0]; // escape character char c; char *p; for(c=*str ; c!=0; c=*++str) { p = strchr(del, c); // is c a delimiter? if(p!=NULL) os << e << pdel[p-del] << e; else { if(isprint(c)) // is c a printable character? os << (u_char)c; else if(!Strbase::do_8th_bit_protection && (c&0x80)) os << (u_char)c; else // if not: print all following unprintables in hex form { os << e << 'X'; do { os.form("%02X", (u_int)(*(u_char*)str)); str++; } while( !isprint(*str) && *str!=0 ); str--; os << e; } } } return os; } Strbase::Strbase(DataTypeCode::Value type, int x) : Primtype(type) { _string = NULL; char buf[20]; sprintf(buf, "%d", x); operator = (buf); } Strbase::Strbase(DataTypeCode::Value type, long x) : Primtype(type) { _string = NULL; char buf[30]; sprintf(buf, "%ld", x); operator = (buf); } Strbase::Strbase(DataTypeCode::Value type, double x) : Primtype(type) { _string = NULL; char buf[40]; sprintf(buf, "%f", x); operator = (buf); } const Strbase &Strbase::operator += (const Strbase &x) { if(x._string != NULL) { size_t len2 = strlen(x._string); if(_string == NULL) { if(len2 > 0) { _string = strdup(x._string); Primtype::set(); } else if(x.isnull()) { Primtype::nullify(); } } else { size_t len1 = strlen(_string); char *s = _string; _string = new char [len1 + len2 + 1]; memcpy(_string, s, len1); memcpy(_string + len1, x._string, len2); _string[len1 + len2] = '\0'; delete [] s; } } return *this; } const Strbase &Strbase::operator += (const char *x) { if(x != NULL) { size_t len2 = strlen(x); if(_string == NULL) { if(len2 > 0) { _string = strdup(x); Primtype::set(); } else Primtype::nullify(); } else { size_t len1 = strlen(_string); char *s = _string; _string = new char [len1 + len2 + 1]; memcpy(_string, s, len1); memcpy(_string + len1, x, len2); _string[len1 + len2] = '\0'; delete [] s; } } return *this; } inline bool Strbase::operator == (const char *x) const { if(_string == NULL || x == NULL) if(_string == NULL && x == NULL) return true; else return false; else return strcmp(_string,x) == 0; }