// --------------------------------------------------------------------------- // - XsoStream.cpp - // - afnix:xml module - xml/xsm input stream class implementation - // --------------------------------------------------------------------------- // - This program is free software; you can redistribute it and/or modify - // - it provided that this copyright notice is kept intact. - // - - // - 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. In no event shall - // - the copyright holder be liable for any direct, indirect, incidental or - // - special damages arising in any way out of the use of this software. - // --------------------------------------------------------------------------- // - copyright (c) 1999-2007 amaury darsch - // --------------------------------------------------------------------------- #include "Unicode.hpp" #include "XsoStream.hpp" #include "Exception.hpp" namespace afnix { // ------------------------------------------------------------------------- // - private section - // ------------------------------------------------------------------------- // the default xml stream timeout static const long XSO_STREAM_TOUT = -1L; // the xml character reference static const t_quad XSO_CHAR_AM = 0x00000026; static const t_quad XSO_CHAR_DZ = 0x00000023; static const t_quad XSO_CHAR_SC = 0x0000003B; // ------------------------------------------------------------------------- // - class section - // ------------------------------------------------------------------------- // create a new xml stream XsoStream::XsoStream (Input* is) { if (is == nilp) { throw Exception ("xml-error", "invalid nil input stream"); } Object::iref (p_is = is); d_lnum = 1; d_xbuf.reset (); } // destroy this xml stream XsoStream::~XsoStream (void) { Object::tref (p_is); } // return the current line number long XsoStream::getlnum (void) const { return d_lnum; } // set the stream encoding mode void XsoStream::setemod (const String& mode) { p_is->setemod (mode); } // return true if the stream is valid bool XsoStream::valid (void) const { return p_is->valid (XSO_STREAM_TOUT); } // read the next available character t_quad XsoStream::rduc (void) { // check the xml buffer first if (d_xbuf.empty () == false) { t_quad c = d_xbuf.read (); if (c == eolq) d_lnum++; return c; } // check for & character t_quad c = p_is->rduc (); if (c != XSO_CHAR_AM) { if (c == eolq) d_lnum++; return c; } d_xbuf.add (c); // check for # chracter c = p_is->rduc (); if (c == eofq) { p_is->pushback (c); c = d_xbuf.read (); if (c == eolq) d_lnum++; return c; } d_xbuf.add (c); if (c != XSO_CHAR_DZ) { c = d_xbuf.read (); if (c == eolq) d_lnum++; return c; } // accumulate characters until a ; character s_cref: c = p_is->rduc (); switch (c) { case XSO_CHAR_SC: c = d_xbuf.tocref (); d_xbuf.reset (); return c; case blkq: case tabq: case eolq: case eofq: p_is->pushback (c); c = d_xbuf.read (); if (c == eolq) d_lnum++; return c; default: d_xbuf.add (c); goto s_cref; } // we should never be here throw Exception ("internal-error", "out-of-bound rduc with xso stream"); } // pushback a character void XsoStream::pushback (const t_quad c) { if ((c == eolq) && (d_lnum > 1)) d_lnum--; d_xbuf.pushback (c); } }