Code

19ff3de7b1c784bd03f20ad23f5f7f18bde5292c
[inkscape.git] / src / dom / io / domstream.cpp
1 /**
2  * Phoebe DOM Implementation.
3  *
4  * This is a C++ approximation of the W3C DOM model, which follows
5  * fairly closely the specifications in the various .idl files, copies of
6  * which are provided for reference.  Most important is this one:
7  *
8  * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html
9  *
10  * Authors:
11  *   Bob Jamison
12  *
13  * Copyright (C) 2006 Bob Jamison
14  *
15  *  This library is free software; you can redistribute it and/or
16  *  modify it under the terms of the GNU Lesser General Public
17  *  License as published by the Free Software Foundation; either
18  *  version 2.1 of the License, or (at your option) any later version.
19  *
20  *  This library is distributed in the hope that it will be useful,
21  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  *  Lesser General Public License for more details.
24  *
25  *  You should have received a copy of the GNU Lesser General Public
26  *  License along with this library; if not, write to the Free Software
27  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
28  */
30 /**
31  * Our base input/output stream classes.  These are is directly
32  * inherited from iostreams, and includes any extra
33  * functionality that we might need.
34  *
35  */
37 #include <math.h>
38 #include <stdarg.h>
40 #include "domstream.h"
41 #include "dom/charclass.h"
43 namespace org
44 {
45 namespace w3c
46 {
47 namespace dom
48 {
49 namespace io
50 {
53 //#########################################################################
54 //# U T I L I T Y
55 //#########################################################################
57 void pipeStream(InputStream &source, OutputStream &dest)
58 {
59     for (;;)
60         {
61         int ch = source.get();
62         if (ch<0)
63             break;
64         dest.put(ch);
65         }
66     dest.flush();
67 }
71 //#########################################################################
72 //# F O R M A T T E D    P R I N T I N G
73 //#########################################################################
75 static char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
77 static int dprintInt(Writer &outs,
78                      long arg, int base,
79                      int flag, int width, int precision)
80 {
82     DOMString buf;
84     //### Get the digits
85     while (arg > 0)
86         {
87         int ch = arg % base;
88         buf.insert(buf.begin(), digits[ch]);        
89         arg /= base;        
90         }
92     if (flag == '#' && base == 16)
93         {
94         buf.insert(buf.begin(), 'x');
95         buf.insert(buf.begin(), '0');
96         }
98     //### Output the result
99     for (unsigned int i=0 ; i<buf.size() ; i++)
100         {
101         if (outs.put(buf[i]) < 0)
102             return -1;
103         }
105     return 1;
110 static int dprintDouble(Writer &outs,
111                         double val, 
112                         int flag, int width, int precision)
115     DOMString buf;
117     //printf("int:%f  frac:%f\n", intPart, fracPart);
119     bool negative = false;
120     if (val < 0)
121         {
122         negative = true;
123         val = -val;
124         }
126     int intDigits = 0;
127     double scale = 1.0;
128     while (scale < val)
129         {
130         intDigits++;
131         scale *= 10.0;
132         }
134     double intPart;
135     double fracPart = modf(val, &intPart);
137     if (precision <= 0)
138         precision = 5;
140     //### How many pad digits?
141     int pad = width - intDigits;
142     if (precision > 0)
143         pad -= precision + 1;
144     else if (flag == '#')
145         pad--;
148     //### Signs
149     if (negative)
150         buf.push_back('-');
151     else if (flag == '+')
152         buf.push_back('+');
154     //### Prefix pad
155     if (pad > 0 && flag == '0')
156         {
157         while (pad--)
158             buf.push_back('0');
159         }
161     //### Integer digits
162     intPart = (intPart + 0.1 ) / scale;    // turn 12345.678 to .12345678
163     while (intDigits--)
164         {
165         intPart *= 10.0;
166         double dig;
167         intPart = modf(intPart, &dig);
168         char ch = '0' + (int)dig;
169         buf.push_back(ch);
170         }
171     if (buf.size() == 0)
172         buf = "0";
174     //### Decimal point
175     if (flag == '#' || precision > 0)
176         {
177         buf.push_back('.');
178         }    
180     //### Fractional digits
181     while (precision--)
182         {
183         fracPart *= 10.0;
184         double dig;
185         fracPart = modf(fracPart, &dig);
186         char ch = '0' + (int)dig;
187         buf.push_back(ch);
188         }
190     //### Left justify if requested
191     if (pad > 0 && flag == '-')
192         {
193         while (pad--)
194             buf.push_back(' ');
195         }
197     //### Output the result
198     for (unsigned int i=0 ; i<buf.size() ; i++)
199         {
200         if (outs.put(buf[i]) < 0)
201             return -1;
202         }
203     return 1;
206 static int dprintString(Writer &outs,
207                         char *arg, 
208                         int flags, int width, int precision)
210     while (*arg)
211         {
212         if (outs.put(*arg++) < 0)
213             return -1;
214         }
216     return 1;
221 static char *getint(char *s, int *ret)
223     bool has_sign = false;
224     int val = 0;
225     if (*s == '-')
226         {
227         has_sign = true;
228         s++;
229         }
230     while (*s >= '0' && *s <= '9')
231         {
232         val = val * 10 + (*s - '0');
233         s++;
234         }
235     if (has_sign)
236         val = -val;
238     *ret = val;
240     return s;
245 static int dprintf(Writer &outs, const char *fmt, va_list ap)
248     char *s = (char *) fmt;
250     while (*s)
251         {
252         unsigned char ch = *s++;
254         if (ch != '%')
255             {
256             if (outs.put(ch)<0)
257                 {
258                 return -1;
259                 }
260             }
261         else
262             //expecting  %[flag][width][.precision][length][char]
263             {
264             if (!*s)
265                 {
266                 return -1;
267                 }
268             if (*s == '%') // escaped '%'
269                 {
270                 if (outs.put('%')<0)
271                     {
272                     return -1;
273                     }
274                 s++;
275                 continue;
276                 }
277             char flag = '\0';
278             if (*s == '-' || *s == '+' || *s == ' ' ||
279                 *s == '#' || *s == '0')
280                 {
281                 flag = *s++;
282                 if (!*s)
283                     {
284                     return -1;
285                     }
286                 }
287             int width     = 0;
288             int precision = 0;
289             s = getint(s, &width);
290             if (!*s)
291                 {
292                 return -1;
293                 }
294             if (*s == '.')
295                 {
296                 s++;
297                 if (!*s)
298                     {
299                     return -1;
300                     }
301                 s = getint(s, &precision);
302                 }
303             char length = '\0';
304             if (*s == 'l' || *s == 'h')
305                 {
306                 length = *s++;
307                 if (!*s)
308                     {
309                     return -1;
310                     }
311                 }
312             ch = *s++;
313             if (!ch)
314                 {
315                 return -1;
316                 }
317             switch (ch)
318                 {
319                 case 'f':
320                 case 'g':
321                     {
322                     double val = va_arg(ap, double);
323                     dprintDouble(outs, val, flag, width, precision);
324                     break;
325                     }
326                 case 'd':
327                     {
328                     long val = 0;
329                     if (length == 'l')
330                         val = va_arg(ap, long);
331                     else if (length == 'h')
332                         val = (long)va_arg(ap, int);
333                     else
334                         val = (long)va_arg(ap, int);
335                     dprintInt(outs, val, 10, flag, width, precision);
336                     break;
337                     }
338                 case 'x':
339                     {
340                     long val = 0;
341                     if (length == 'l')
342                         val = va_arg(ap, long);
343                     else if (length == 'h')
344                         val = (long)va_arg(ap, int);
345                     else
346                         val = (long)va_arg(ap, int);
347                     dprintInt(outs, val, 16, flag, width, precision);
348                     break;
349                     }
350                 case 's':
351                     {
352                     char *val = va_arg(ap, char *);
353                     dprintString(outs, val, flag, width, precision);
354                     break;
355                     }
356                 default:
357                     {
358                     break;
359                     }
360                 }
361             }
363         }
366     return 1;
370 //#########################################################################
371 //# B A S I C    I N P U T    S T R E A M
372 //#########################################################################
375 /**
376  *
377  */
378 BasicInputStream::BasicInputStream(const InputStream &sourceStream)
379                    : source((InputStream &)sourceStream)
381     closed = false;
384 /**
385  * Returns the number of bytes that can be read (or skipped over) from
386  * this input stream without blocking by the next caller of a method for
387  * this input stream.
388  */
389 int BasicInputStream::available()
391     if (closed)
392         return 0;
393     return source.available();
397 /**
398  *  Closes this input stream and releases any system resources
399  *  associated with the stream.
400  */
401 void BasicInputStream::close()
403     if (closed)
404         return;
405     source.close();
406     closed = true;
409 /**
410  * Reads the next byte of data from the input stream.  -1 if EOF
411  */
412 int BasicInputStream::get()
414     if (closed)
415         return -1;
416     return source.get();
421 //#########################################################################
422 //# B A S I C    O U T P U T    S T R E A M
423 //#########################################################################
425 /**
426  *
427  */
428 BasicOutputStream::BasicOutputStream(const OutputStream &destinationStream)
429                      : destination((OutputStream &)destinationStream)
431     closed = false;
434 /**
435  * Closes this output stream and releases any system resources
436  * associated with this stream.
437  */
438 void BasicOutputStream::close()
440     if (closed)
441         return;
442     destination.close();
443     closed = true;
446 /**
447  *  Flushes this output stream and forces any buffered output
448  *  bytes to be written out.
449  */
450 void BasicOutputStream::flush()
452     if (closed)
453         return;
454     destination.flush();
457 /**
458  * Writes the specified byte to this output stream.
459  */
460 int BasicOutputStream::put(XMLCh ch)
462     if (closed)
463         return -1;
464     if (destination.put(ch) < 0)
465         return -1;
466     return 1;
471 //#########################################################################
472 //# B A S I C    R E A D E R
473 //#########################################################################
476 /**
477  *
478  */
479 BasicReader::BasicReader(Reader &sourceReader)
481     source = &sourceReader;
484 /**
485  * Returns the number of bytes that can be read (or skipped over) from
486  * this reader without blocking by the next caller of a method for
487  * this reader.
488  */
489 int BasicReader::available()
491     if (source)
492         return source->available();
493     else
494         return 0;
498 /**
499  *  Closes this reader and releases any system resources
500  *  associated with the reader.
501  */
502 void BasicReader::close()
504     if (source)
505         source->close();
508 /**
509  * Reads the next byte of data from the reader.
510  */
511 int BasicReader::get()
513     if (source)
514         return source->get();
515     else
516         return -1;
524 /**
525  * Reads a line of data from the reader.
526  */
527 DOMString BasicReader::readLine()
529     DOMString str;
530     while (available() > 0)
531         {
532         XMLCh ch = get();
533         if (ch == '\n')
534             break;
535         str.push_back(ch);
536         }
537     return str;
540 /**
541  * Reads a line of data from the reader.
542  */
543 DOMString BasicReader::readWord()
545     DOMString str;
546     while (available() > 0)
547         {
548         XMLCh ch = get();
549         if (isWhitespace(ch))
550             break;
551         str.push_back(ch);
552         }
553     return str;
557 static bool getLong(DOMString &str, long *val)
559     const char *begin = str.c_str();
560     char *end;
561     long ival = strtol(begin, &end, 10);
562     if (str == end)
563         return false;
564     *val = ival;
565     return true;
568 static bool getULong(const DOMString &str, unsigned long *val)
570     DOMString tmp = str;
571     char *begin = (char *)tmp.c_str();
572     char *end;
573     unsigned long ival = strtoul(begin, &end, 10);
574     if (begin == end)
575         return false;
576     *val = ival;
577     return true;
580 static bool getDouble(const DOMString &str, double *val)
582     DOMString tmp = str;
583     const char *begin = tmp.c_str();
584     char *end;
585     double ival = strtod(begin, &end);
586     if (begin == end)
587         return false;
588     *val = ival;
589     return true;
595 /**
596  *
597  */
598 Reader &BasicReader::readBool (bool& val )
600     DOMString buf = readWord();
601     if (buf == "true")
602         val = true;
603     else
604         val = false;
605     return *this;
608 /**
609  *
610  */
611 Reader &BasicReader::readShort (short& val )
613     DOMString buf = readWord();
614     long ival;
615     if (getLong(buf, &ival))
616         val = (short) ival;
617     return *this;
620 /**
621  *
622  */
623 Reader &BasicReader::readUnsignedShort (unsigned short& val )
625     DOMString buf = readWord();
626     unsigned long ival;
627     if (getULong(buf, &ival))
628         val = (unsigned short) ival;
629     return *this;
632 /**
633  *
634  */
635 Reader &BasicReader::readInt (int& val )
637     DOMString buf = readWord();
638     long ival;
639     if (getLong(buf, &ival))
640         val = (int) ival;
641     return *this;
644 /**
645  *
646  */
647 Reader &BasicReader::readUnsignedInt (unsigned int& val )
649     DOMString buf = readWord();
650     unsigned long ival;
651     if (getULong(buf, &ival))
652         val = (unsigned int) ival;
653     return *this;
656 /**
657  *
658  */
659 Reader &BasicReader::readLong (long& val )
661     DOMString buf = readWord();
662     long ival;
663     if (getLong(buf, &ival))
664         val = ival;
665     return *this;
668 /**
669  *
670  */
671 Reader &BasicReader::readUnsignedLong (unsigned long& val )
673     DOMString buf = readWord();
674     unsigned long ival;
675     if (getULong(buf, &ival))
676         val = ival;
677     return *this;
680 /**
681  *
682  */
683 Reader &BasicReader::readFloat (float& val )
685     DOMString buf = readWord();
686     double ival;
687     if (getDouble(buf, &ival))
688         val = (float)ival;
689     return *this;
692 /**
693  *
694  */
695 Reader &BasicReader::readDouble (double& val )
697     DOMString buf = readWord();
698     double ival;
699     if (getDouble(buf, &ival))
700         val = ival;
701     return *this;
706 //#########################################################################
707 //# I N P U T    S T R E A M    R E A D E R
708 //#########################################################################
711 InputStreamReader::InputStreamReader(const InputStream &inputStreamSource)
712                      : inputStream((InputStream &)inputStreamSource)
718 /**
719  *  Close the underlying OutputStream
720  */
721 void InputStreamReader::close()
723     inputStream.close();
726 /**
727  *  Flush the underlying OutputStream
728  */
729 int InputStreamReader::available()
731     return inputStream.available();
734 /**
735  *  Overloaded to receive its bytes from an InputStream
736  *  rather than a Reader
737  */
738 int InputStreamReader::get()
740     //Do we need conversions here?
741     int ch = (XMLCh)inputStream.get();
742     return ch;
747 //#########################################################################
748 //# S T D    R E A D E R
749 //#########################################################################
752 /**
753  *
754  */
755 StdReader::StdReader()
757     inputStream = new StdInputStream();
760 /**
761  *
762  */
763 StdReader::~StdReader()
765     delete inputStream;
770 /**
771  *  Close the underlying OutputStream
772  */
773 void StdReader::close()
775     inputStream->close();
778 /**
779  *  Flush the underlying OutputStream
780  */
781 int StdReader::available()
783     return inputStream->available();
786 /**
787  *  Overloaded to receive its bytes from an InputStream
788  *  rather than a Reader
789  */
790 int StdReader::get()
792     //Do we need conversions here?
793     XMLCh ch = (XMLCh)inputStream->get();
794     return ch;
801 //#########################################################################
802 //# B A S I C    W R I T E R
803 //#########################################################################
805 /**
806  *
807  */
808 BasicWriter::BasicWriter(const Writer &destinationWriter)
810     destination = (Writer *)&destinationWriter;
813 /**
814  * Closes this writer and releases any system resources
815  * associated with this writer.
816  */
817 void BasicWriter::close()
819     if (destination)
820         destination->close();
823 /**
824  *  Flushes this output stream and forces any buffered output
825  *  bytes to be written out.
826  */
827 void BasicWriter::flush()
829     if (destination)
830         destination->flush();
833 /**
834  * Writes the specified byte to this output writer.
835  */
836 int BasicWriter::put(XMLCh ch)
838     if (destination && destination->put(ch)>=0)
839         return 1;
840     return -1;
843 /**
844  * Provide printf()-like formatting
845  */
846 /*
847 Writer &BasicWriter::printf(char *fmt, ...)
849     va_list args;
850     va_start(args, fmt);
851     //replace this wish vsnprintf()
852     vsnprintf(formatBuf, 2047, fmt, args);
853     va_end(args);
854     writeString(formatBuf);
856     return *this;
858 */
859 Writer &BasicWriter::printf(char *fmt, ...)
861     va_list args;
862     va_start(args, fmt);
863     dprintf(*this, fmt, args);
865     return *this;
869 /**
870  * Writes the specified character to this output writer.
871  */
872 Writer &BasicWriter::writeChar(char ch)
874     XMLCh uch = ch;
875     put(uch);
876     return *this;
880 /**
881  * Writes the specified standard string to this output writer.
882  */
883 Writer &BasicWriter::writeString(const DOMString &str)
885     for (int i=0; i< (int)str.size(); i++)
886         put(str[i]);
887     return *this;
891 /**
892  *
893  */
894 Writer &BasicWriter::writeBool (bool val )
896     if (val)
897         writeString("true");
898     else
899         writeString("false");
900     return *this;
904 /**
905  *
906  */
907 Writer &BasicWriter::writeShort (short val )
909     char buf[32];
910     snprintf(buf, 31, "%d", val);
911     writeString(buf);
912     return *this;
917 /**
918  *
919  */
920 Writer &BasicWriter::writeUnsignedShort (unsigned short val )
922     char buf[32];
923     snprintf(buf, 31, "%u", val);
924     writeString(buf);
925     return *this;
928 /**
929  *
930  */
931 Writer &BasicWriter::writeInt (int val)
933     char buf[32];
934     snprintf(buf, 31, "%d", val);
935     writeString(buf);
936     return *this;
939 /**
940  *
941  */
942 Writer &BasicWriter::writeUnsignedInt (unsigned int val)
944     char buf[32];
945     snprintf(buf, 31, "%u", val);
946     writeString(buf);
947     return *this;
950 /**
951  *
952  */
953 Writer &BasicWriter::writeLong (long val)
955     char buf[32];
956     snprintf(buf, 31, "%ld", val);
957     writeString(buf);
958     return *this;
961 /**
962  *
963  */
964 Writer &BasicWriter::writeUnsignedLong(unsigned long val)
966     char buf[32];
967     snprintf(buf, 31, "%lu", val);
968     writeString(buf);
969     return *this;
972 /**
973  *
974  */
975 Writer &BasicWriter::writeFloat(float val)
977     char buf[32];
978     snprintf(buf, 31, "%8.3f", val);
979     writeString(buf);
980     return *this;
983 /**
984  *
985  */
986 Writer &BasicWriter::writeDouble(double val)
988     char buf[32];
989     snprintf(buf, 31, "%8.3f", val);
990     writeString(buf);
991     return *this;
997 //#########################################################################
998 //# O U T P U T    S T R E A M    W R I T E R
999 //#########################################################################
1002 OutputStreamWriter::OutputStreamWriter(OutputStream &outputStreamDest)
1003                      : outputStream(outputStreamDest)
1009 /**
1010  *  Close the underlying OutputStream
1011  */
1012 void OutputStreamWriter::close()
1014     flush();
1015     outputStream.close();
1018 /**
1019  *  Flush the underlying OutputStream
1020  */
1021 void OutputStreamWriter::flush()
1023       outputStream.flush();
1026 /**
1027  *  Overloaded to redirect the output chars from the next Writer
1028  *  in the chain to an OutputStream instead.
1029  */
1030 int OutputStreamWriter::put(XMLCh ch)
1032     //Do we need conversions here?
1033     int intCh = (int) ch;
1034     if (outputStream.put(intCh) < 0)
1035         return -1;
1036     return 1;
1039 //#########################################################################
1040 //# S T D    W R I T E R
1041 //#########################################################################
1044 /**
1045  *
1046  */
1047 StdWriter::StdWriter()
1049     outputStream = new StdOutputStream();
1053 /**
1054  *
1055  */
1056 StdWriter::~StdWriter()
1058     delete outputStream;
1063 /**
1064  *  Close the underlying OutputStream
1065  */
1066 void StdWriter::close()
1068     flush();
1069     outputStream->close();
1072 /**
1073  *  Flush the underlying OutputStream
1074  */
1075 void StdWriter::flush()
1077       outputStream->flush();
1080 /**
1081  *  Overloaded to redirect the output chars from the next Writer
1082  *  in the chain to an OutputStream instead.
1083  */
1084 int StdWriter::put(XMLCh ch)
1086     //Do we need conversions here?
1087     int intCh = (int) ch;
1088     if (outputStream->put(intCh) < 0)
1089         return -1;
1090     return 1;
1104 //###############################################
1105 //# O P E R A T O R S
1106 //###############################################
1107 //# Normally these would be in the .h, but we
1108 //# just want to be absolutely certain that these
1109 //# are never multiply defined.  Easy to maintain,
1110 //# though.  Just occasionally copy/paste these
1111 //# into the .h , and replace the {} with a ;
1112 //###############################################
1117 Reader& operator>> (Reader &reader, bool& val )
1118         { return reader.readBool(val); }
1120 Reader& operator>> (Reader &reader, short &val)
1121         { return reader.readShort(val); }
1123 Reader& operator>> (Reader &reader, unsigned short &val)
1124         { return reader.readUnsignedShort(val); }
1126 Reader& operator>> (Reader &reader, int &val)
1127         { return reader.readInt(val); }
1129 Reader& operator>> (Reader &reader, unsigned int &val)
1130         { return reader.readUnsignedInt(val); }
1132 Reader& operator>> (Reader &reader, long &val)
1133         { return reader.readLong(val); }
1135 Reader& operator>> (Reader &reader, unsigned long &val)
1136         { return reader.readUnsignedLong(val); }
1138 Reader& operator>> (Reader &reader, float &val)
1139         { return reader.readFloat(val); }
1141 Reader& operator>> (Reader &reader, double &val)
1142         { return reader.readDouble(val); }
1147 Writer& operator<< (Writer &writer, char val)
1148     { return writer.writeChar(val); }
1150 Writer& operator<< (Writer &writer, const DOMString &val)
1151     { return writer.writeString(val); }
1153 Writer& operator<< (Writer &writer, bool val)
1154     { return writer.writeBool(val); }
1156 Writer& operator<< (Writer &writer, short val)
1157     { return writer.writeShort(val); }
1159 Writer& operator<< (Writer &writer, unsigned short val)
1160     { return writer.writeUnsignedShort(val); }
1162 Writer& operator<< (Writer &writer, int val)
1163     { return writer.writeInt(val); }
1165 Writer& operator<< (Writer &writer, unsigned int val)
1166     { return writer.writeUnsignedInt(val); }
1168 Writer& operator<< (Writer &writer, long val)
1169     { return writer.writeLong(val); }
1171 Writer& operator<< (Writer &writer, unsigned long val)
1172     { return writer.writeUnsignedLong(val); }
1174 Writer& operator<< (Writer &writer, float val)
1175     { return writer.writeFloat(val); }
1177 Writer& operator<< (Writer &writer, double val)
1178     { return writer.writeDouble(val); }
1182 }  //namespace io
1183 }  //namespace dom
1184 }  //namespace w3c
1185 }  //namespace org
1188 //#########################################################################
1189 //# E N D    O F    F I L E
1190 //#########################################################################