index 3ffba53feefab4f27719624cd18b41b7f6b0425f..c6234d462e652a7b46384af026d203777c098b03 100644 (file)
--- a/src/dom/io/domstream.cpp
+++ b/src/dom/io/domstream.cpp
*
*/
+#include <math.h>
#include <stdarg.h>
#include "domstream.h"
dest.flush();
}
+
+
+//#########################################################################
+//# F O R M A T T E D P R I N T I N G
+//#########################################################################
+
+static char *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
//#########################################################################
/**
* Writes the specified byte to this output stream.
*/
-void BasicOutputStream::put(XMLCh ch)
+int BasicOutputStream::put(XMLCh ch)
{
if (closed)
- return;
- destination.put(ch);
+ return -1;
+ if (destination.put(ch) < 0)
+ return -1;
+ return 1;
}
/**
* Writes the specified byte to this output writer.
*/
-void BasicWriter::put(XMLCh ch)
+int BasicWriter::put(XMLCh ch)
{
- if (destination)
- destination->put(ch);
+ if (destination && destination->put(ch)>=0)
+ return 1;
+ return -1;
}
/**
* Provide printf()-like formatting
*/
+/*
Writer &BasicWriter::printf(char *fmt, ...)
{
va_list args;
return *this;
}
+*/
+Writer &BasicWriter::printf(const DOMString &fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ dprintf(*this, fmt, args);
+ return *this;
+}
+
+
/**
* Writes the specified character to this output writer.
*/
* Overloaded to redirect the output chars from the next Writer
* in the chain to an OutputStream instead.
*/
-void OutputStreamWriter::put(XMLCh ch)
+int OutputStreamWriter::put(XMLCh ch)
{
//Do we need conversions here?
int intCh = (int) ch;
- outputStream.put(intCh);
+ if (outputStream.put(intCh) < 0)
+ return -1;
+ return 1;
}
//#########################################################################
* Overloaded to redirect the output chars from the next Writer
* in the chain to an OutputStream instead.
*/
-void StdWriter::put(XMLCh ch)
+int StdWriter::put(XMLCh ch)
{
//Do we need conversions here?
int intCh = (int) ch;
- outputStream->put(intCh);
+ if (outputStream->put(intCh) < 0)
+ return -1;
+ return 1;
}