// ========================================================================== // // @(#) $Id: Codec.C,v 1.4 2000/10/19 03:21:57 brian Exp $ // // -------------------------------------------------------------------------- // // Copyright (C) 1997-2000 Brian Bidulock // // All Rights Reserved. // // This library is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation; either version 2.1 of the License, or (at // your option) any later version. // // This library 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 Lesser Public License // for more details. // // You should have received a copy of the GNU Lesser General Public License // along with this library; if not, write to the Free Software Foundation, // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // Last Modified $Date: 2000/10/19 03:21:57 $ by $Author: brian $ // // -------------------------------------------------------------------------- // // $Log: Codec.C,v $ // Revision 1.4 2000/10/19 03:21:57 brian // Whoops, messed up when adding headers. // // Revision 1.3 2000/10/13 15:45:51 brian // First public release. // // ========================================================================== static char const ident[] = "$Id: Codec.C,v 1.4 2000/10/19 03:21:57 brian Exp $"; #pragma implementation #include "Codec.H" #include #include #include Error::Error(char* d,char* l) { desc = d; label = l; }; void Error::errout() { cout.form("ERROR at %s: %s\n",label,desc); }; Invalid::Invalid(char* l) : Error("Unexpected value." ,l) { errout(); }; Bounds ::Bounds (char* l) : Error("Out of bounds." ,l) { errout(); }; Repeats::Repeats(char* l) : Error("Non-integer repeat." ,l) { errout(); }; SpecErr::SpecErr(char* l) : Error("Specification error." ,l) { errout(); }; NullPtr::NullPtr(char* l) : Error("Null parm pointer." ,l) { errout(); }; int NewFlag::crumb = 1; // start non-zero NewFlag::NewFlag() { value = 0; }; NewFlag::NewFlag(bool b) { if (b) value = crumb; else value = 0; }; NewFlag::NewFlag(int i) { if (i) value = crumb; else value = 0; }; NewFlag::operator bool() { if (value>crumb) value=0; // clear really old flags return (value==crumb); }; NewFlag::operator int() { if (value>crumb) value=0; // clear really old flags return (value==crumb); }; void NewFlag::clearFlags() { crumb++; if (!crumb) crumb++; }; void FramePointer::set(char* p, int l) { pointer = p; length = l*8; offset = 0; size = length; end = 0; }; FramePointer::FramePointer(char* p, int l) { pointer = p; length = l*8; offset = 0; size = length; end = 0; }; FramePointer::FramePointer() { pointer = 0; length = 0; offset = 0; size = 0; end = 0; }; FramePointer::operator int() { return (size+7)>>3; }; FramePointer::operator char*() { return pointer; }; FramePointer::operator void*() { return pointer; }; char* FramePointer::point() { return pointer + (offset>>3); }; int Codec::variant = Codec::ansi; NewFlag Codec::pass2 = false; NewFlag Codec::pass2req = false; int Codec::bldseq = 0; bool Codec::encode(Codec* c,char* p,int& l) { FramePointer f(p,l); bldseq = 0; // reset build sequence number try { c->encode(f); } catch (...) { bldseq = 0; return false; } if (pass2req) { cout << "Starting pass 2...\n"; pass2 = true; f.offset = 0; try { c->encode(f); } catch (Error E) { E.errout(); bldseq = 0; return false; } }; l = (f.end+7)>>3; bldseq = 0; return true; }; bool Codec::decode(Codec* c,char* p,int l) { NewFlag::clearFlags(); FramePointer f(p,l); bldseq = 0; // reset build sequence number try { c->decode(f); } catch (Error E) { E.errout(); bldseq = 0; return false; } bldseq = 0; return true; }; void Codec::report(Codec* c) { c->report(); cout.width(78); cout.fill('-'); cout << "-" << '\n'; }; void Codec::rebuild() { NewFlag::clearFlags(); }; Codec::Codec(char* l, char* t, int s, int x) : frame(NULL,0) { label = l; title = t; size = s; spare = x; exists = false; built = false; bound = false; dfltval = 0; mnem = NULL; text = NULL; master = true; bldord = 0; }; Codec::Codec(const Codec& original) { label = original.label; title = original.title; size = original.size; spare = original.spare; exists = false; built = false; bound = false; dfltval = original.dfltval; mnem = NULL; text = NULL; master = false; bldord = 0; }; Codec* Codec::copy() { return new Codec(*this); }; Codec* Codec::newcopy(char* l,char *t) { return new Codec(l,t,size,spare); }; Codec::~Codec() { }; void Codec::decode(FramePointer& p) { frame = p; frame.size = size; exists = true; }; void Codec::encode(FramePointer& p) { frame = p; frame.size = size; if (!(pass2&&exists)) { if (built) bldseq = bldord; built = false; exists = true; } }; void Codec::bits(int j) { int siz, btm, top, bit, i; cout.width(3); cout.setf(ios::right,ios::adjustfield); if ((j==0)&&(frame.offset&0x7)) { cout.fill(' '); cout << "|" << ' '; } else { cout.fill('0'); cout << (frame.offset>>3)+j+1 << ' '; } siz = frame.size+(j?(frame.offset&0x7):0)-j*8; btm = 8-(j?0:frame.offset&0x7); top = btm-siz; bit = 0x1 << ((top>0?btm-1-top:btm-1)+j*8-(j?(frame.offset&0x7):0)); for (i=0;i<8;i++) { if (i=btm) { cout << '.'; continue; } if (value&bit) cout << '1'; else cout << '0'; bit = bit >> 1; } }; void Codec::report() { bits(0); cout << ' '; cout.width(22); cout.setf(ios::left,ios::adjustfield); cout.fill(' '); cout << title; cout.width(0); cout << " : "; }; void Codec::morebits() { if (frame.size+(frame.offset&0x7)+spare>24) { cout.form("--- ******** | . :\n"); } else { if (frame.size+(frame.offset&0x7)+spare>8) { bits(1); cout << " | . :\n"; } if (frame.size+(frame.offset&0x7)+spare>16) { bits(2); cout << " | . :\n"; } } }; void Codec::build() { bldord = bldseq++; built = true; }; bool Codec::set(int v) { value = v; bldord = bldseq++; built = true; bound = true; return built; }; bool Codec::set(char* m) { return false; }; bool Codec::set(char* p, int l) { frame.set(p,l); bldord = bldseq++; built = true; bound = true; return built; }; bool Codec::get(int& v) { if (exists) v = value; return exists; }; bool Codec::get(char*& m) { return false; }; bool Codec::get(char*& p, int& l) { if (exists) { p = frame.point(); l = (frame.size+7)/8; } return exists; }; bool Codec::test(int v) { if (!exists) return false; return value == v; }; bool Codec::test(char* m) { return false; }; bool Codec::test(char* p, int l) { if (!exists) return false; if (l!=frame.size/8) return false; return memcmp(p,frame.point(),l)==0; }; List::List(char* l, char* t, int s, int c, int b,Codec** a) : Codec(l,t,s,0) { contents = c; branches = b; content = a; }; List::List(const List& original) : Codec(original) { contents = original.contents; branches = original.branches; }; List* List::newcopy(char* l,char* t) { return new List(l,t,size,contents,branches,content); }; List::~List() { int i; for (i=0;ireport(); }; void List::decode(FramePointer& p) { if (p.lengthdecode(p); } catch (...) { invalid = true; for (;iinvalid = true; frame.size = p.offset - frame.offset; throw; } frame.size = p.offset - frame.offset; exists = true; }; void List::encode(FramePointer& p) { if (p.lengthencode(p); frame.size = p.offset - frame.offset; if (!(pass2&&exists)) { if (built) bldseq = bldord; built = false; exists = true; } }; Header::Header(char* l, char* t, int s, int c,int b, Codec** a) : List(l,t,s,c,b,a) { }; Content::Content(char* l, char* t, int s, int c,int b, Codec** a) : List(l,t,s,c,b,a) { }; Parameter::Parameter(char* l, char* t, int s, int c, int b, Codec** a) : List(l,t,s,c,b,a) { }; Parameter::Parameter(const Parameter& original) : List(original) { }; ParameterR::ParameterR(char* l,char* t,int s,int c,int b,Codec** a) : Parameter(l,t,s,c,b,a) { next = NULL; }; ParameterR::ParameterR(ParameterR& original) : Parameter(original) { next = original.next; original.next = this; }; ParameterR* ParameterR::copy() { return new ParameterR(*this); }; ParameterR* ParameterR::newcopy(char* l,char* t) { return new ParameterR(l,t,size,contents,branches,content); }; ParameterR::~ParameterR() { if (next) delete next; }; void ParameterR::decode(FramePointer& p) { if (p.lengthdecode(p); } catch (...) { invalid = true; for (;iinvalid = true; frame.size = p.offset - frame.offset; throw; } frame.size = p.offset - frame.offset; exists = true; ParameterR* temp = this->copy(); temp->decode(p); }; void ParameterR::encode(FramePointer& p) { if (p.lengthencode(p); frame.size = p.offset - frame.offset; if (!(pass2&&exists)) { if (built) bldseq = bldord; built = false; exists = true; } }; void ParameterR::report() { Parameter::report(); if (next) next->report(); }; ParameterG::ParameterG(char* l,char* t,...) : Parameter(l,t,0,0,0,NULL) { int i; va_list argptr; va_start(argptr,t); while (va_arg(argptr,void*)) contents++; va_end (argptr); if (contents) content = new (Codec*)[contents]; va_start(argptr,t); for (i=0;isize==-1) size = -1; if ((size!=-1)&&(sizesize)) size = content[i]->size; } va_end (argptr); }; ParameterG::ParameterG(const ParameterG& original) : Parameter(original) { content = original.content; contents = original.contents; branches = original.branches; int i; for (i=0;idecode(p); // this is the pointer if (content[0]->value!=0) { f.offset += content[0]->value*8; int i; for (i=1;idecode(f); if (p.endtext = "End of Optional Parameters"; content[0]->mnem = "EOP"; } exists = true; }; void ParameterP::encode(FramePointer& p) { if (p.length>3)*8; // point octet beyond current encoding FramePointer s(f),l(p); content[0]->set((f.offset-p.offset)>>3); // calculate and set offset content[0]->encode(p); // encode the pointer if (pass2) { int i; for (i=1;iencode(f); // encode frame if (p.endset(0); // zero the pointer content[0]->encode(l); // reencode the pointer content[0]->text = "End of Optional Parameters"; content[0]->mnem = "EOP"; } } else { pass2req = true; } if (!(pass2&&exists)) { if (built) bldseq = bldord; built = false; exists = true; } }; ParameterPL::ParameterPL(char* l,char* t,int s,int c,int b,Codec** a) : Parameter(l,t,s,c,b,a) { }; void ParameterPL::decode(FramePointer& p) { if (p.lengthdecode(p); // this is the pointer if (content[0]->value==0) { invalid = true; throw NullPtr(label); } f.offset += content[0]->value*8; content[1]->decode(f); // this is the length if (f.lengthvalue*8) { invalid = true; throw Bounds(label); } f.length = f.offset+content[1]->value*8; int i; for (i=2;idecode(f); if (p.end>3)*8; // point octet beyond current encoding content[0]->set((f.offset-p.offset)>>3); // calculate and set offset content[0]->encode(p); // encode the pointer if (pass2) { FramePointer s(f); // get pointer to size indicator for later content[1]->encode(f); // preencode the length int i; for (i=2;iencode(f); // encode frame content[1]->set((f.offset-s.offset-8)>>3); // calculate and set length content[1]->encode(s); // reencode the length if (p.enddecode(p); // this is the pointer if (content[0]->value!=0) { // not end of parameters f.offset += content[0]->value*8; // offset frame content[1]->decode(f); // this is the label if (content[1]->value!=0) { // not end of parameters content[2]->decode(f); // this is the length if (f.lengthvalue*8) { // check length content[2]->invalid = true; throw Bounds(content[2]->label); } f.length = f.offset+content[2]->value*8; // set the length try { for (i=3;idecode(f); // decode } catch (...) { }; Codec* temp = this->copy(); temp->decode(p); } else { content[1]->text = "End of Optional Parameters"; content[1]->mnem = "EOP"; } if (p.endtext = "End of Optional Parameters"; content[0]->mnem = "EOP"; } exists = true; }; void ParameterPNL::encode(FramePointer& p) { if (master) { if (next) delete next; next = NULL; } if (p.length>3)*8;// point octet beyond current encoding l = f; // mark where frame starts content[0]->set((f.offset-p.offset)>>3); // calculate and set offset content[0]->encode(p); // encode the pointer bool found = false; // check for parameters to encode for (j=0;j<((Bra*)content[3])->vals;j++) { if ( ((Bra*)content[3])->val[j].path->built ) { found = true; break; } } if (found) { if (pass2) { content[1]->encode(f); // preencode the label s = f; // get pointer to size for later content[2]->encode(f); // preencode the length for (i=3;iencode(f); // encode content[2]->set((f.offset-s.offset-8)>>3); // calc&set length content[2]->encode(s); // reencode the length if (p.endcopy(); temp->encode(p); } else { pass2req = true; ((Bra*)content[3])->val[j].path->built = false; Codec* temp = this->copy(); temp->encode(p); ((Bra*)content[3])->val[j].path->built = true; } } else { if (pass2) { content[1]->set(0); // set for end of parameters content[1]->encode(f); // encode the label content[1]->text = "End of Optional Parameters"; content[1]->mnem = "EOP"; if (p.endreport(); }; ParameterNL::ParameterNL(char* l,char* t,int s,int c,int b,Codec** a) : Parameter(l,t,s,c,b,a) { next = NULL; }; ParameterNL::ParameterNL(ParameterNL& original) : Parameter(original) { next = original.next; original.next = this; }; ParameterNL* ParameterNL::newcopy(char* l,char* t) { return new ParameterNL(l,t,size,contents,branches,content); }; ParameterNL::~ParameterNL() { if (next) delete next; }; void ParameterNL::decode(FramePointer& p) { if (master) { if (next) delete next; next = NULL; } if (p.lengthdecode(p); // this is the label if (content[0]->value!=0) { // not end of parameters content[1]->decode(p); // this is the length if (p.lengthvalue*8) { // check length content[1]->invalid = true; throw Bounds(content[1]->label); } FramePointer f(p); // new sized frame f.length = f.offset+content[1]->value*8; // set the length try { for (i=2;idecode(f); // decode } catch (...) { }; frame.size = f.offset - p.offset; p.offset = f.length; // jump past sized frame Codec* temp = this->copy(); temp->decode(p); } else { content[0]->text = "End of Optional Parameters"; content[0]->mnem = "EOP"; } exists = true; }; void ParameterNL::encode(FramePointer& p) { if (master) { if (next) delete next; next = NULL; } if (p.lengthvals;j++) { if ( ((Bra*)content[2])->val[j].path->built ) { found = true; break; } } if (found) { content[0]->encode(p); // preencode the label FramePointer s(p); // get pointer to size for later content[1]->encode(p); // preencode the length for (i=2;iencode(p); // encode content[1]->set((p.offset-s.offset-8)>>3); // calc&set length content[1]->encode(s); // reencode the length Codec* temp = this->copy(); temp->encode(p); } else { if (!master) { content[0]->set(0); // set for end of parameters content[0]->encode(p); // encode the label content[0]->text = "End of Optional Parameters"; content[0]->mnem = "EOP"; } else { return; } } if (p.endreport(); }; Field::Field(char* l, char* t, int s, int x) : Codec(l,t,s,x) { }; void Field::decode(FramePointer& p) { if (p.length<(p.offset+size+spare)) { invalid = true; cout.form("length = %d, offset = %d, size = %d, spare = %d\n", p.length,p.offset,size,spare); throw Bounds(label); } if (!exists) { text = NULL; mnem = NULL; } char* ptr = p.point(); frame = p; value = 0; value |= ptr[3]; value = value << 8; value |= ptr[2]; value = value << 8; value |= ptr[1]; value = value << 8; value |= ptr[0]; value = value >> (p.offset&0x7); int mask; if ((size>0)&&(size<=32)) mask = (0x1<0)&&((size+spare)<=32)) mask = (0x1<<(size+spare))-1; else mask = -1; oldvalue &= ~(mask << (p.offset&0x7)); oldvalue |= ((value&mask) << (p.offset&0x7)); ptr[0] = oldvalue&0xff; oldvalue = oldvalue >> 8; ptr[1] = oldvalue&0xff; oldvalue = oldvalue >> 8; ptr[2] = oldvalue&0xff; oldvalue = oldvalue >> 8; ptr[3] = oldvalue&0xff; frame.size = size; p.offset += frame.size+spare; if (p.end < p.offset) p.end = p.offset; if (!(pass2&&exists)) { if (built) bldseq = bldord; built = false; exists = true; } }; void Field::report() { if (!exists&&!invalid) return; Codec::report(); if (invalid) cout.form("BAD "); if (size) cout.form("%d",value); if (text) cout.form(" - %s",text); cout << '\n'; Codec::morebits(); }; OctetString::OctetString(char* l, char *t, int s) : Codec(l,t,s,0) { dfltval = 0; }; void OctetString::decode(FramePointer& p) { p.offset = (p.offset+7)&(~0x7); if (p.length>3);i++) ptr[i] = frame.point()[i]; } else { if (size>0) { frame.size = size; int i; for (i=0;i<(frame.size>>3);i++) ptr[i] = dfltval; } else { frame.size = 0; } } p.size = frame.size; frame = p; p.offset += p.size; if (p.end < p.offset) p.end = p.offset; if (!(pass2&&exists)) { if (built) bldseq = bldord; built = false; exists = true; } }; void OctetString::report() { if (!exists&&!invalid) return; int i,j; char* ptr = frame.point(); int len = (frame.size+7)/8; i=0; j=0; value = ptr[0]; Codec::report(); if (invalid) cout << "BAD"; else while (i>4)&0xf]; } cout << '\n'; }; AsciiString::AsciiString(char* l,char* t,int s) : OctetString(l,t,s) { dfltval = (int)'?'; }; void AsciiString::report() { if (!exists&&!invalid) return; int i; char* ptr = frame.point(); int len = (frame.size+7)/8; Codec::report(); if (invalid) cout << "BAD"; else for (i=0;ivalue) || (val[i].indx == -1) ) { found = true; break; } } if (found) { if (!branch->mnem) branch->mnem = val[i].path->label; if (!branch->text) branch->text = val[i].path->title; try { val[i].path->decode(p); } catch (...) { invalid = true; throw; } } else { invalid = true; branch->invalid = true; } exists = found; }; void Bra::encode(FramePointer& p) { bool found = false; frame = p; frame.size = size; int i; if (branch->bound) { // value was bound and built, find value and encode out for (i=0;ivalue) || (val[i].indx == -1) ) { found = true; break; } } } else { // value not bound, find out which path was built first int first; int order = MAXINT; for (i=0;ibuilt ) { found = true; if (val[i].path->bldordbldord; }; } } if (found) { // rebuild new value :note: this will also bind the value i = first; branch->set(val[i].indx); if (branch->exists) { FramePointer t = branch->frame; branch->encode(t); } } else { // value not bound, branch not built, encode default path for (i=0;ivalue) || (val[i].indx == -1) ) { found = true; break; } } } } if (found) { if (!branch->mnem) branch->mnem = val[i].path->label; if (!branch->text) branch->text = val[i].path->title; val[i].path->encode(p); if (!(pass2&&exists)) { if (built) bldseq = bldord; built = false; exists = true; } } }; void Bra::report() { if (!exists&&!invalid) return; bool found = false; int i; for (i=0;ivalue) || (val[i].indx == -1) ) { found = true; break; } } if (found) { val[i].path->report(); return; } }; bool Bra::set(char* m) { bool found = false; int i; for (i=0;ilabel)==0) ) { found = true; break; } } if (found) { branch->set(val[i].indx); } return found; }; bool Bra::get(char*& m) { if (!exists&&!invalid) return false; bool found = false; int i; for (i=0;ivalue) || (val[i].indx == -1) ) { found = true; break; } } if (found) { m = val[i].path->label; } return found; }; bool Bra::test(char* m) { if (!exists&&!invalid) return false; bool found = false; int i; for (i=0;ilabel)==0) ) { found = true; break; } } if (found) return (branch->value==val[i].indx); return found; };