/* * 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("@(#) NMtyp.cc (Gunther Schadow) 12/19/96"); #pragma implementation #include "NMtyp.h" #include "logfile.h" #include "exception.h" #include "xios.h" #include "ioext.h" #include #include #include #include "STtyp.h" #include "IDtyp.h" #include "DataTypeCode.h" #include #include #include "ParseTrace.h" /* * DATA TYPE * * NM() -- numeric value */ NMtyp::NMtyp() : Primtype(DataTypeCode::NMval) { _is_float = FALSE; _int = 0; _precision = 0; } NMtyp::NMtyp(int x) : Primtype(DataTypeCode::NMval) { _is_float = FALSE; _int = x; _precision = 0; Primtype::set(); } NMtyp::NMtyp(long x) : Primtype(DataTypeCode::NMval) { _is_float = FALSE; _int = x; _precision = 0; Primtype::set(); } NMtyp::NMtyp(unsigned int x) : Primtype(DataTypeCode::NMval) { _is_float = FALSE; _int = x; _precision = 0; Primtype::set(); } NMtyp::NMtyp(double x, int prec) : Primtype(DataTypeCode::NMval) { _is_float = TRUE; _float = x; _precision = prec; Primtype::set(); } NMtyp::NMtyp(const char *s) : Primtype(DataTypeCode::NMval) { _is_float = FALSE; _int = 0; _precision = 0; if(s != NULL) { if(*s == '\0') nullify(); else { istrstream is(s); xios xis(is); hl7er(is); input(is); } } } const NMtyp& NMtyp::operator = (long x) { _is_float = FALSE; _int = x; Primtype::set(); return *this; } const NMtyp& NMtyp::operator = (double x) { _is_float = TRUE; _float = x; _precision = 0; Primtype::set(); return *this; } const NMtyp& NMtyp::operator = (const char *s) { if(s == NULL) unset(); else if(*s == '\0') nullify(); else { istrstream is(s); xios xis(is); hl7er(is); input(is); } return *this; } bool NMtyp::isfloat() { if(ispresent() && !isnull()) return _is_float; else FATAL("access into non-present object"); } bool NMtyp::isint() { if(ispresent() && !isnull()) return !_is_float; else FATAL("access into non-present object"); } NMtyp::operator long() const { if(ispresent() && !isnull()) { if(_is_float) return (long)_float; else return _int; } else FATAL("access into non-present object"); } NMtyp::operator double() const { if(ispresent() && !isnull()) { if(_is_float) return _float; else return (double)_int; } else FATAL("access into non-present object"); } result NMtyp::input(istream& is) { if(isdebug(is)) FATAL("can't read from debug stream"); LOGDEBUG("hl7/astm"); char * const field_string = gets(is, getdel(is)); char *s = field_string; if( *s == 0 ) goto is_not_present; else if( strcmp(s, NULLVAL) == 0 ) goto is_null; else { /* clear any previous error, since strtol doesn't have another way * of indicating an error */ errno = 0; char *end_of_long; char *end_of_double; long longbuf = strtol(s, &end_of_long,10); int sign; s = strpbrk(s, "-+1234567890"); // seek the first numeric (incl. `+' `-') if(s == NULL) { record_parse_error("numeric expected in `%s'", field_string); EPARSE("numeric expected in `%s'", field_string); } else if(*s == '-') sign = -1; else sign = +1; // compute the number of significant digits: // - look forward to the first non-0 digit char *first_non_null = strpbrk(s, "123456789"); if(first_non_null != NULL && end_of_long > first_non_null) _precision = end_of_long - first_non_null; else _precision = 0; if( errno == 0 ) { if( *end_of_long == 0 ) // we stopped at the end of the string { _int = longbuf; goto is_int; } else if( *end_of_long == '.' ) // fractional part follows { if(end_of_long[1] != '\0') { _float = strtod(end_of_long,&end_of_double); if( errno == 0 ) if( *end_of_double == 0 ) { _float = sign * (sign * longbuf + _float); // compute the number of significant digits if(_precision == 0) // no non-0 digits found yet { // seek to a non-0 digit char *p = strpbrk(end_of_long, "123456789"); if(p == NULL) // no non-0 digit found, i.e. { // our string is /0?.0*/ we // take the number of zeroes as the precision _precision = 1 + strspn(end_of_long+1, "0"); } else _precision = strspn(p, "0123456789"); } else { end_of_long++; // p points to the 1/10 digit _precision += strspn(end_of_long, "0123456789"); } goto is_float; } else { record_parse_error("syntax error in `%s'[%d]", field_string, end_of_double-field_string); EPARSE("syntax error in `%s'[%d]", field_string, end_of_double-field_string); } else // error occured { record_parse_error("numeric in `%s'[%d]", field_string, end_of_double-field_string); ERROS("strtod on `%s'", field_string, end_of_double-field_string); } } else { _float = (double)longbuf; goto is_float; } } else // conversion stopped due to junk { record_parse_error("syntax error in `%s'[%d]", field_string, end_of_long-field_string); EPARSE("syntax error in `%s'[%d]", field_string, end_of_long-field_string); } } else // error occured if( errno == ERANGE ) // result too large, try a double { errno = 0; _float = strtod(s,&end_of_double); if( errno != 0 ) // again too large! { record_parse_error("numeric in `%s'[%d]", field_string, end_of_double-field_string); ERROS("strtod on `%s'", field_string, end_of_double-field_string); } else if( *end_of_double == 0 ) // here we go. { // compute the number of significant digits char *p = strpbrk(s, "123456789"); _precision = strspn(p, "0123456789"); p += _precision; if(*p++ == '.') _precision += strspn(p, "0123456789"); goto is_float; } else // junk found { record_parse_error("syntax error in `%s'[%d]", field_string, end_of_double-field_string); EPARSE("syntax error in `%s'[%d]", field_string, end_of_double-field_string); } } else // other errors should not occur but ... ERROS("strtol on `%s'", s); } FATAL("how did I come to this point??"); is_null: Primtype::nullify(); goto finish; is_not_present: Primtype::unset(); goto finish; is_int: _is_float = FALSE; goto is_present; is_float: _is_float = TRUE; goto is_present; is_present: Primtype::set(); goto finish; finish: delete [] s; return SUCCESS; } void NMtyp::output(ostream& os) const { if(ishl7er(os) || isastmer(os)) { LOGDEBUG("hl7/astm"); if (ispresent()) { if (isnull()) os << NULLVAL; else { if (_is_float) { os.precision(_precision); ios::fmtflags fl = os.flags(ios::dec|ios::showpoint); os << _float; os.flags(fl); } else os << dec << _int; } } } else /* debug */ { LOGDEBUG("debug"); os << DSBGR0 "NMtyp" DSBGR1; if (ispresent()) if (isnull()) os << DSNULL; else if (_is_float) { os.precision(_precision); ios::fmtflags fl = os.flags(ios::dec|ios::showpoint); os << DSFRST "float" DSSEPR << _float << DSSEPR << _precision; os.flags(fl); } else os << DSFRST "int" DSSEPR << dec << _int; else os << DSNOPS; os << DSEGRP; } } #define BUFSIZE 256 NMtyp::operator STtyp () const return st { if (ispresent()) { char buf[BUFSIZE]; if (isnull()) buf[0] = '\0'; else { ostrstream os(buf, BUFSIZE); if (_is_float) { os.precision(_precision); ios::fmtflags fl = os.flags(ios::dec|ios::showpoint); os << _float << '\0'; os.flags(fl); } else os << _int << '\0'; } st = buf; } } NMtyp::operator IDtyp () const return st { if (ispresent()) { char buf[BUFSIZE]; if (isnull()) buf[0] = '\0'; else { ostrstream os(buf, BUFSIZE); if (_is_float) { os.precision(_precision); ios::fmtflags fl = os.flags(ios::dec|ios::showpoint); os << _float << '\0'; os.flags(fl); } else os << _int << '\0'; } st = buf; } }