// ---------------------------------------------------------------------------
// - XsmBuffer.cpp -
// - afnix:xml module - xsm character buffer 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 "Vector.hpp"
#include "Utility.hpp"
#include "Unicode.hpp"
#include "XsmBuffer.hpp"
#include "Exception.hpp"
namespace afnix {
// -------------------------------------------------------------------------
// - private section -
// -------------------------------------------------------------------------
// return true if the character a valid space
static inline bool is_spcc (const t_quad c) {
if (c == 0x00000020) return true;
if (c == 0x00000009) return true;
if (c == 0x0000000D) return true;
if (c == 0x0000000A) return true;
return false;
}
// -------------------------------------------------------------------------
// - class section -
// -------------------------------------------------------------------------
// create a new buffer class with a default size of 1024 characters
XsmBuffer::XsmBuffer (void) {}
// create a new buffer with a string
XsmBuffer::XsmBuffer (const String& xval) : XsoBuffer (xval) {}
// copy construct this buffer
XsmBuffer::XsmBuffer (const XsmBuffer& that) : XsoBuffer (that) {}
// assign a buffer to this one
XsmBuffer& XsmBuffer::operator = (const XsmBuffer& that){
// check for equality
if (this == &that) return *this;
// copy the base class
XsoBuffer::operator = (that);
// here it is
return *this;
}
// return true if the buffer is not empty after striping
bool XsmBuffer::isnext (void) {
stripl ();
return (d_blen > 0);
}
// return true if the character is a space
bool XsmBuffer::isspc (const t_quad c) const {
return is_spcc (c);
}
// strip the buffer with leading space
void XsmBuffer::stripl (void) {
while (empty () == false) {
t_quad c = read ();
if (is_spcc (c) == true) continue;
pushback (c);
break;
}
}
// strip the buffer with trailing blank
void XsmBuffer::stripr (void) {
while (d_blen > 0) {
t_quad c = p_ubuf[d_blen-1];
if (is_spcc (c) == false) break;
d_blen--;
}
}
// strip the buffer in the middle
void XsmBuffer::stripm (void) {
// do nothing if negligeable
if (d_blen == 0) return;
// get a new buffer
t_quad* ubuf = new t_quad[d_blen];
// loop and accumulate with one space only
long index = 0;
for(long i = 0; i < d_blen; i++) {
// get the character
t_quad c = p_ubuf[i];
// add it if valid
if (is_spcc (c) == false) {
ubuf[index++] = c;
continue;
}
// always add one at the beginning
if (index == 0) {
ubuf[index] = blkq;
continue;
}
// add a space if preceding it nos a space
if (is_spcc (ubuf[index-1]) == false) ubuf[index++] = blkq;
}
// clean old buffer and update
delete [] p_ubuf;
p_ubuf = ubuf;
d_blen = index;
}
// strip the buffer with leading and trealing blanks
void XsmBuffer::strip (void) {
stripl ();
stripr ();
}
// get the next available general string in this buffer
String XsmBuffer::getnstr (void) {
// create a working buffer
XsmBuffer buf;
// strip left the bufefr
stripl ();
// read character from the buffer until it is empty
while (empty () == false) {
t_quad c = read ();
if (is_spcc (c) == true) break;
buf.add (c);
}
// get the string name
return buf.tostring ();
}
// get the next available word
String XsmBuffer::getword (void) {
// create a working buffer
XsmBuffer buf;
// read character from the buffer until it is empty
while (empty () == false) {
t_quad c = read ();
// check for word constituent
if (Unicode::iswcc (c) == false) {
if (buf.empty () == false) break;
continue;
}
// check for non combining at the beginning
if (Unicode::isncc (c) == false) {
if (buf.empty () == true) continue;
}
// add the character
buf.add (c);
}
// get the string name
return buf.tostring ();
}
// get the next available attribute in this buffer
Property XsmBuffer::getattr (void) {
// create a working buffer
XsmBuffer buf;
// initialize property name and value
String name = "";
String pval = "";
// strip left the buffer
stripl ();
// get the name first
s_name:
t_quad c = read ();
if (c == nilq) {
if (buf.empty () == true) goto s_serr;
name = buf.tostring ();
buf.reset ();
goto s_done;
}
if (is_spcc (c) == true) goto s_echk;
if (c == Unicode::toquad ('=')) {
pushback (c);
goto s_echk;
}
buf.add (c);
goto s_name;
// check the equal (=) character
s_echk:
c = read ();
if (c == nilq) goto s_serr;
if (is_spcc (c) == true) goto s_echk;
if (c == Unicode::toquad ('=')) {
name = buf.tostring ();
buf.reset ();
stripl ();
goto s_pval;
}
goto s_serr;
// get the " or ' starting character
s_pval:
c = read ();
if (c == nilq) goto s_serr;
if (is_spcc (c) == true) goto s_serr;
if (c == Unicode::toquad ('\'')) goto s_sqav;
if (c == Unicode::toquad ('"')) goto s_dqav;
goto s_nqav;
// single quoted attribute value
s_sqav:
c = read ();
if (c == nilq) goto s_serr;
if (c == Unicode::toquad ('\'')) goto s_done;
buf.add (c);
goto s_sqav;
// double quoted attribute value
s_dqav:
c = read ();
if (c == nilq) goto s_serr;
if (c == Unicode::toquad ('"')) goto s_done;
buf.add (c);
goto s_dqav;
// non quoted attribute value
s_nqav:
c = read ();
if (c == nilq) goto s_done;
if (is_spcc (c) == true) goto s_done;
buf.add (c);
goto s_nqav;
// syntax error
s_serr:
throw Exception ("xsm-error", "syntax error while reading attribute",
buf.tostring ());
// get attribute value
s_done:
pval = buf.tostring ();
return Property (name, pval);
}
}
syntax highlighted by Code2HTML, v. 0.9.1