/* * 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("@(#) Segment.cc (Gunther Schadow) 12/19/96"); #pragma implementation #include "Segment.h" #include "xios.h" #include "Delimiters.h" #include "misc.h" #include "SegTypeCode.h" #include "exception.h" #include "logfile.h" #include "ParseTrace.h" #define FIELD(i) ( & ( this ->* fieldtab[i].memberp ) ) // was: ((Type *)((caddr_t)this + fieldtab[i].offset)) #define UNUSED(i) ( fieldtab[i].memberp == NULL ) #ifdef PEDANTIC_SEGMENT bool Segment::pedantic = TRUE; #else bool Segment::pedantic = FALSE; #endif Type& Segment::operator [] (unsigned int i) { if(i < nofields) if(UNUSED(i)) { ERROR("unused field cannot be addressed"); } else return *FIELD(i); else FATAL("field number out of range %ud [0 .. %d]", i, nofields); } void Segment::unset() { LOGDEBUG("unset %sseg", (const char *)SegTypeCode(type())); u_int i; for(i=0; iunset(); Structure::unset(); } bool Segment::OK() const { LOGDEBUG("check %sseg", (const char *)SegTypeCode(type())); u_int i; for(i=0; iOK()) return FALSE; return Structure::OK(); } bool Segment::commit() { LOGDEBUG("commit %sseg", (const char *)SegTypeCode(type())); u_int i; bool isset = FALSE; for(i=0; icommit(); isset = isset1 || isset; if(!isset1 && fieldtab[i].required) if(pedantic) ERROR("%s: missing required field %d `%s'", (const char *)SegTypeCode(type()), i, fieldtab[i].name); else LOGWARNING("%s: missing required field %d `%s'", (const char *)SegTypeCode(type()), i, fieldtab[i].name); } if(isset) set(); else if(ispresent()) unset(); // enforce a valid state return isset; } result Segment::input(istream& is) { SegmentTracer tracer(type()); if(input_header(is) != SUCCESS) { unset(); return FAIL; } const char *dset = getdel(is, Delimiters::fldlevel); bool eos_seen = !match(is, dset); if(eos_seen) // if there is nothing but the tag `TAG' { unset(); // the whole segment is absent return SUCCESS; } u_int i; for(i=0; itype(), fieldtab[i].name); if(eos_seen) field->unset(); else { field->input(is); eos_seen = !match(is, dset); } if(fieldtab[i].required && !field->ispresent()) if(pedantic) { record_parse_error("missing required field %d `%s'", i, fieldtab[i].name); EPARSE("missing required field %d `%s'", i, fieldtab[i].name); } else { record_parse_warning("missing required field %d `%s'", i, fieldtab[i].name); LOGWARNING("missing required field %d `%s'", i, fieldtab[i].name); } } match(is, getdel(is, Delimiters::seglevel)); set(); return SUCCESS; } void Segment::output(ostream& os) const { output_header(os); if(ishl7er(os) || isastmer(os)) { if(ispresent()) { char eos = *getdel(os, Delimiters::seglevel); char eof = *getdel(os, Delimiters::fldlevel); for(u_int i=0; ioutput(os); if(i==nofields) break; os << DSSEPR; } } else os << DSNOPS; os << DSEGRP; } } result Segment::input_header(istream& is) { SegTypeCode st(type()); LOGDEBUG("input %sseg", (const char *)st); if(!is.ipfx(1)) { if(is.eof()) { LOGDEBUG("end of message"); return FAIL; } else ERROS("error on input stream"); } int taglen; if(ishl7er(is)) taglen = 4; else if(isastmer(is)) taglen = 2; else if(isdebug(is)) { FATAL("can't read from debug stream"); } if(!istouched(is)) { LOGDEBUG("stream is untouched"); streammarker spos(is.rdbuf()); char tag[taglen]; is.get(tag, taglen); if(is.eof()) { LOGDEBUG("end of message"); return FAIL; } SegTypeCode sid; SegTypeCode::Value stcv = (SegTypeCode::Value)sid.lookup(tag); if(stcv==SegTypeCode::invalid || stcv==SegTypeCode::not_present ||stcv==SegTypeCode::null) { record_parse_error("invalid segment id `%s'", tag); EPARSE("invalid segment id `%s'", tag); } if(stcv != (SegTypeCode::Value)st) { LOGWARNING("not found"); is.rdbuf()->seekmark(spos); return FAIL; } } else /* istouched(is) means that the tag is read already */ { LOGDEBUG("stream is touched"); untouch(is); } switch(st) { case SegTypeCode::MSHval: case SegTypeCode::BHSval: case SegTypeCode::FHSval: case SegTypeCode::Hval: delims(is).input(is); break; default: break; } return SUCCESS; } void Segment::output_header(ostream& os) const { SegTypeCode st(type()); LOGDEBUG("output %s", (const char *)st); if(ishl7er(os) || isastmer(os)) { if(ispresent()) { st.output(os); switch(st) { case SegTypeCode::MSHval: case SegTypeCode::BHSval: case SegTypeCode::FHSval: case SegTypeCode::Hval: delims(os).output(os); break; default: break; } } } else { os << DSBGR0 << (const char *)st << "seg" << DSBGR1; if(ispresent()) { switch(st) { case SegTypeCode::MSHval: case SegTypeCode::BHSval: case SegTypeCode::FHSval: case SegTypeCode::Hval: os << DSFRST << delims(os) << DSSEPR; break; default: os << DSFRST; } } } } SegTypeCode::Value Segment::peek(istream& is) { streammarker spos(is.rdbuf()); int taglen; if(ishl7er(is)) taglen = 4; else if(isastmer(is)) taglen = 2; else if(isdebug(is)) { FATAL("can't read from debug stream"); } char tag[taglen]; is.get(tag, taglen); is.rdbuf()->seekmark(spos); SegTypeCode sid; return (SegTypeCode::Value)sid.lookup(tag); }