domstream.cpp revision 2e87fc3a12d79f84eb120d27701937b9e30e1512
/*
* Phoebe DOM Implementation.
*
* This is a C++ approximation of the W3C DOM model, which follows
* fairly closely the specifications in the various .idl files, copies of
* which are provided for reference. Most important is this one:
*
*
* Authors:
* Bob Jamison
*
* Copyright (C) 2006-2008 Bob Jamison
*
* 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 General 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* inherited from iostreams, and includes any extra
* functionality that we might need.
*
*/
#include <cstdio>
#include <math.h>
#include <stdarg.h>
#include "domstream.h"
namespace org
{
namespace w3c
{
namespace dom
{
namespace io
{
//#########################################################################
//# U T I L I T Y
//#########################################################################
{
for (;;)
{
if (ch<0)
break;
}
}
/*
//#########################################################################
//# F O R M A T T E D P R I N T I N G
//#########################################################################
static char const *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
*/
// static int dprintInt(Writer &outs,
// long arg, int base,
// int flag, int width, int /*precision*/)
/*{
DOMString buf;
//### Get the digits
while (arg > 0)
{
int ch = arg % base;
buf.insert(buf.begin(), digits[ch]);
arg /= base;
}
if (flag == '#' && base == 16)
{
buf.insert(buf.begin(), 'x');
buf.insert(buf.begin(), '0');
}
if (buf.size() == 0)
buf = "0";
int pad = width - (int)buf.size();
for (int i=0 ; i<pad ; i++)
buf.insert(buf.begin(), '0');
//### Output the result
for (unsigned int i=0 ; i<buf.size() ; i++)
{
if (outs.put(buf[i]) < 0)
return -1;
}
return 1;
}
static int dprintDouble(Writer &outs, double val,
int flag, int width, int precision)
{
DOMString buf;
//printf("int:%f frac:%f\n", intPart, fracPart);
bool negative = false;
if (val < 0)
{
negative = true;
val = -val;
}
int intDigits = 0;
double scale = 1.0;
while (scale < val)
{
intDigits++;
scale *= 10.0;
}
double intPart;
double fracPart = modf(val, &intPart);
if (precision <= 0)
precision = 5;
//### How many pad digits?
int pad = width - intDigits;
if (precision > 0)
pad -= precision + 1;
else if (flag == '#')
pad--;
//### Signs
if (negative)
buf.push_back('-');
else if (flag == '+')
buf.push_back('+');
//### Prefix pad
if (pad > 0 && flag == '0')
{
while (pad--)
buf.push_back('0');
}
//### Integer digits
intPart = (intPart + 0.1 ) / scale; // turn 12345.678 to .12345678
while (intDigits--)
{
intPart *= 10.0;
double dig;
intPart = modf(intPart, &dig);
char ch = '0' + (int)dig;
buf.push_back(ch);
}
if (buf.size() == 0)
buf = "0";
//### Decimal point
if (flag == '#' || precision > 0)
{
buf.push_back('.');
}
//### Fractional digits
while (precision--)
{
fracPart *= 10.0;
double dig;
fracPart = modf(fracPart, &dig);
char ch = '0' + (int)dig;
buf.push_back(ch);
}
//### Left justify if requested
if (pad > 0 && flag == '-')
{
while (pad--)
buf.push_back(' ');
}
//### Output the result
for (unsigned int i=0 ; i<buf.size() ; i++)
{
if (outs.put(buf[i]) < 0)
return -1;
}
return 1;
}
*/
/**
* Output a string. We veer from the standard a tiny bit.
* Normally, a flag of '#' is undefined for strings. We use
* it as an indicator that the user wants to XML-escape any
* XML entities.
*/
// static int dprintString(Writer &outs, const DOMString &str,
// int flags, int /*width*/, int /*precision*/)
/*{
int len = str.size();
if (flags == '#')
{
for (int pos = 0; pos < len; pos++)
{
XMLCh ch = (XMLCh) str[pos];
if (ch == '&')
outs.writeString("&r;");
else if (ch == '<')
outs.writeString("<");
else if (ch == '>')
outs.writeString(">");
else if (ch == '"')
outs.writeString(""");
else if (ch == '\'')
outs.writeString("'");
else
outs.put(ch);
}
}
else
{
outs.writeString(str);
}
return 1;
}
static int getint(const DOMString &buf, int pos, int *ret)
{
int len = buf.size();
if (!len)
{
*ret = 0;
return pos;
}
bool has_sign = false;
int val = 0;
if (buf[pos] == '-')
{
has_sign = true;
pos++;
}
while (pos < len)
{
XMLCh ch = buf[pos];
if (ch >= '0' && ch <= '9')
val = val * 10 + (ch - '0');
else
break;
pos++;
}
if (has_sign)
val = -val;
*ret = val;
return pos;
}
static int dprintf(Writer &outs, const DOMString &fmt, va_list ap)
{
int len = fmt.size();
for (int pos=0 ; pos < len ; pos++)
{
XMLCh ch = fmt[pos];
//## normal character
if (ch != '%')
{
if (outs.put(ch)<0)
{
return -1;
}
continue;
}
if (++pos >= len)
{
return -1;
}
ch = fmt[pos];
//## is this %% ?
if (ch == '%') // escaped '%'
{
if (outs.put('%')<0)
{
return -1;
}
continue;
}
//## flag
char flag = '\0';
if (ch == '-' || ch == '+' || ch == ' ' ||
ch == '#' || ch == '0')
{
flag = ch;
if (++pos >= len)
{
return -1;
}
ch = fmt[pos];
}
//## width.precision
int width = 0;
int precision = 0;
pos = getint(fmt, pos, &width);
if (pos >= len)
{
return -1;
}
ch = fmt[pos];
if (ch == '.')
{
if (++pos >= len)
{
return -1;
}
pos = getint(fmt, pos, &precision);
if (pos >= len)
{
return -1;
}
ch = fmt[pos];
}
//## length
char length = '\0';
if (ch == 'l' || ch == 'h')
{
length = ch;
if (++pos >= len)
{
return -1;
}
ch = fmt[pos];
}
//## data type
switch (ch)
{
case 'f':
case 'g':
{
double val = va_arg(ap, double);
dprintDouble(outs, val, flag, width, precision);
break;
}
case 'd':
{
long val = 0;
if (length == 'l')
val = va_arg(ap, long);
else if (length == 'h')
val = (long)va_arg(ap, int);
else
val = (long)va_arg(ap, int);
dprintInt(outs, val, 10, flag, width, precision);
break;
}
case 'x':
{
long val = 0;
if (length == 'l')
val = va_arg(ap, long);
else if (length == 'h')
val = (long)va_arg(ap, int);
else
val = (long)va_arg(ap, int);
dprintInt(outs, val, 16, flag, width, precision);
break;
}
case 's':
{
DOMString val = va_arg(ap, char *);
dprintString(outs, val, flag, width, precision);
break;
}
default:
{
break;
}
}
}
return 1;
}
*/
//#########################################################################
//# B A S I C I N P U T S T R E A M
//#########################################################################
/**
*
*/
{
closed = false;
}
/**
* Returns the number of bytes that can be read (or skipped over) from
* this input stream without blocking by the next caller of a method for
* this input stream.
*/
int BasicInputStream::available()
{
if (closed)
return 0;
}
/**
* Closes this input stream and releases any system resources
* associated with the stream.
*/
void BasicInputStream::close()
{
if (closed)
return;
closed = true;
}
/**
* Reads the next byte of data from the input stream. -1 if EOF
*/
int BasicInputStream::get()
{
if (closed)
return -1;
}
//#########################################################################
//# B A S I C O U T P U T S T R E A M
//#########################################################################
/**
*
*/
{
closed = false;
}
/**
* Closes this output stream and releases any system resources
* associated with this stream.
*/
void BasicOutputStream::close()
{
if (closed)
return;
destination.close();
closed = true;
}
/**
* Flushes this output stream and forces any buffered output
* bytes to be written out.
*/
void BasicOutputStream::flush()
{
if (closed)
return;
destination.flush();
}
/**
* Writes the specified byte to this output stream.
*/
{
if (closed)
return -1;
return 1;
}
//#########################################################################
//# B A S I C R E A D E R
//#########################################################################
{
source = &sourceReader;
}
/**
* Returns the number of bytes that can be read (or skipped over) from
* this reader without blocking by the next caller of a method for
* this reader.
*/
int BasicReader::available()
{
if (source)
else
return 0;
}
/**
* Closes this reader and releases any system resources
* associated with the reader.
*/
void BasicReader::close()
{
if (source)
}
/**
* Reads the next byte of data from the reader.
*/
{
if (source)
else
return (gunichar)-1;
}
/**
* Reads a line of data from the reader.
*/
{
while (available() > 0)
{
if (ch == '\n')
break;
}
return str;
}
/**
* Reads a line of data from the reader.
*/
{
while (available() > 0)
{
if (!g_unichar_isprint(ch))
break;
}
return str;
}
{
char *end;
return false;
return true;
}
{
char *end;
return false;
return true;
}
{
char *end;
return false;
return true;
}
{
if (buf == "true")
val = true;
else
val = false;
return *this;
}
{
long ival;
return *this;
}
{
unsigned long ival;
return *this;
}
{
long ival;
return *this;
}
{
unsigned long ival;
return *this;
}
{
long ival;
return *this;
}
{
unsigned long ival;
return *this;
}
{
double ival;
return *this;
}
{
double ival;
return *this;
}
//#########################################################################
//# I N P U T S T R E A M R E A D E R
//#########################################################################
{
}
/**
* Close the underlying OutputStream
*/
void InputStreamReader::close()
{
inputStream.close();
}
/**
* Flush the underlying OutputStream
*/
int InputStreamReader::available()
{
return inputStream.available();
}
/**
* Overloaded to receive its bytes from an InputStream
* rather than a Reader
*/
{
//Do we need conversions here?
return ch;
}
//#########################################################################
//# S T D R E A D E R
//#########################################################################
/**
*
*/
{
inputStream = new StdInputStream();
}
/**
*
*/
{
delete inputStream;
}
/**
* Close the underlying OutputStream
*/
{
inputStream->close();
}
/**
* Flush the underlying OutputStream
*/
{
return inputStream->available();
}
/**
* Overloaded to receive its bytes from an InputStream
* rather than a Reader
*/
{
//Do we need conversions here?
return ch;
}
//#########################################################################
//# B A S I C W R I T E R
//#########################################################################
/**
*
*/
{
}
/**
* Closes this writer and releases any system resources
* associated with this writer.
*/
void BasicWriter::close()
{
if (destination)
destination->close();
}
/**
* Flushes this output stream and forces any buffered output
* bytes to be written out.
*/
void BasicWriter::flush()
{
if (destination)
destination->flush();
}
/**
* Writes the specified byte to this output writer.
*/
{
return 1;
return -1;
}
/**
* Provide printf()-like formatting
*/
{
if (buf) {
}
return *this;
}
/**
* Writes the specified character to this output writer.
*/
{
return *this;
}
/**
* Writes the specified unicode string to this output writer.
*/
{
return *this;
}
/**
* Writes the specified standard string to this output writer.
*/
{
return *this;
}
/**
* Writes the specified character string to this output writer.
*/
{
if (str)
else
tmp = "null";
return *this;
}
/**
*
*/
{
if (val)
writeString("true");
else
writeString("false");
return *this;
}
/**
*
*/
{
if (buf) {
}
return *this;
}
/**
*
*/
{
if (buf) {
}
return *this;
}
/**
*
*/
{
if (buf) {
}
return *this;
}
/**
*
*/
{
if (buf) {
}
return *this;
}
/**
*
*/
{
if (buf) {
}
return *this;
}
/**
*
*/
{
if (buf) {
}
return *this;
}
/**
*
*/
{
#if 1
if (buf) {
}
#else
#endif
return *this;
}
/**
*
*/
{
#if 1
if (buf) {
}
#else
#endif
return *this;
}
//#########################################################################
//# O U T P U T S T R E A M W R I T E R
//#########################################################################
{
}
/**
* Close the underlying OutputStream
*/
void OutputStreamWriter::close()
{
flush();
}
/**
* Flush the underlying OutputStream
*/
void OutputStreamWriter::flush()
{
}
/**
* Overloaded to redirect the output chars from the next Writer
* in the chain to an OutputStream instead.
*/
{
return 1;
return -1;
}
//#########################################################################
//# S T D W R I T E R
//#########################################################################
/**
*
*/
{
outputStream = new StdOutputStream();
}
/**
*
*/
{
delete outputStream;
}
/**
* Close the underlying OutputStream
*/
{
flush();
outputStream->close();
}
/**
* Flush the underlying OutputStream
*/
{
outputStream->flush();
}
/**
* Overloaded to redirect the output chars from the next Writer
* in the chain to an OutputStream instead.
*/
{
return 1;
return -1;
}
//###############################################
//# O P E R A T O R S
//###############################################
//# Normally these would be in the .h, but we
//# just want to be absolutely certain that these
//# are never multiply defined. Easy to maintain,
//# into the .h , and replace the {} with a ;
//###############################################
} //namespace io
} //namespace dom
} //namespace w3c
} //namespace org
//#########################################################################
//# E N D O F F I L E
//#########################################################################