Code

7b0a7e1d2b6cfa1bd6e14d5aef2350cca49f1b27
[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         }
172     //### Decimal point
173     if (flag == '#' || precision > 0)
174         {
175         buf.push_back('.');
176         }    
178     //### Fractional digits
179     while (precision--)
180         {
181         fracPart *= 10.0;
182         double dig;
183         fracPart = modf(fracPart, &dig);
184         char ch = '0' + (int)dig;
185         buf.push_back(ch);
186         }
188     //### Left justify if requested
189     if (pad > 0 && flag == '-')
190         {
191         while (pad--)
192             buf.push_back(' ');
193         }
195     //### Output the result
196     for (unsigned int i=0 ; i<buf.size() ; i++)
197         {
198         if (outs.put(buf[i]) < 0)
199             return -1;
200         }
201     return 1;
204 static int dprintString(Writer &outs,
205                         char *arg, 
206                         int flags, int width, int precision)
208     while (*arg)
209         {
210         if (outs.put(*arg++) < 0)
211             return -1;
212         }
214     return 1;
219 static char *getint(char *s, int *ret)
221     bool has_sign = false;
222     int val = 0;
223     if (*s == '-')
224         {
225         has_sign = true;
226         s++;
227         }
228     while (*s >= '0' && *s <= '9')
229         {
230         val = val * 10 + (*s - '0');
231         s++;
232         }
233     if (has_sign)
234         val = -val;
236     *ret = val;
238     return s;
243 static int dprintf(Writer &outs, const char *fmt, va_list ap)
246     char *s = (char *) fmt;
248     while (*s)
249         {
250         unsigned char ch = *s++;
252         if (ch != '%')
253             {
254             if (outs.put(ch)<0)
255                 {
256                 return -1;
257                 }
258             }
259         else
260             //expecting  %[flag][width][.precision][length][char]
261             {
262             if (!*s)
263                 {
264                 return -1;
265                 }
266             if (*s == '%') // escaped '%'
267                 {
268                 if (outs.put('%')<0)
269                     {
270                     return -1;
271                     }
272                 s++;
273                 continue;
274                 }
275             char flag = '\0';
276             if (*s == '-' || *s == '+' || *s == ' ' ||
277                 *s == '#' || *s == '0')
278                 {
279                 flag = *s++;
280                 if (!*s)
281                     {
282                     return -1;
283                     }
284                 }
285             int width     = 0;
286             int precision = 0;
287             s = getint(s, &width);
288             if (!*s)
289                 {
290                 return -1;
291                 }
292             if (*s == '.')
293                 {
294                 s++;
295                 if (!*s)
296                     {
297                     return -1;
298                     }
299                 s = getint(s, &precision);
300                 }
301             char length = '\0';
302             if (*s == 'l' || *s == 'h')
303                 {
304                 length = *s++;
305                 if (!*s)
306                     {
307                     return -1;
308                     }
309                 }
310             ch = *s++;
311             if (!ch)
312                 {
313                 return -1;
314                 }
315             switch (ch)
316                 {
317                 case 'f':
318                 case 'g':
319                     {
320                     double val = va_arg(ap, double);
321                     dprintDouble(outs, val, flag, width, precision);
322                     break;
323                     }
324                 case 'd':
325                     {
326                     long val = 0;
327                     if (length == 'l')
328                         val = va_arg(ap, long);
329                     else if (length == 'h')
330                         val = (long)va_arg(ap, int);
331                     else
332                         val = (long)va_arg(ap, int);
333                     dprintInt(outs, val, 10, flag, width, precision);
334                     break;
335                     }
336                 case 'x':
337                     {
338                     long val = 0;
339                     if (length == 'l')
340                         val = va_arg(ap, long);
341                     else if (length == 'h')
342                         val = (long)va_arg(ap, int);
343                     else
344                         val = (long)va_arg(ap, int);
345                     dprintInt(outs, val, 16, flag, width, precision);
346                     break;
347                     }
348                 case 's':
349                     {
350                     char *val = va_arg(ap, char *);
351                     dprintString(outs, val, flag, width, precision);
352                     break;
353                     }
354                 default:
355                     {
356                     break;
357                     }
358                 }
359             }
361         }
364     return 1;
368 //#########################################################################
369 //# B A S I C    I N P U T    S T R E A M
370 //#########################################################################
373 /**
374  *
375  */
376 BasicInputStream::BasicInputStream(const InputStream &sourceStream)
377                    : source((InputStream &)sourceStream)
379     closed = false;
382 /**
383  * Returns the number of bytes that can be read (or skipped over) from
384  * this input stream without blocking by the next caller of a method for
385  * this input stream.
386  */
387 int BasicInputStream::available()
389     if (closed)
390         return 0;
391     return source.available();
395 /**
396  *  Closes this input stream and releases any system resources
397  *  associated with the stream.
398  */
399 void BasicInputStream::close()
401     if (closed)
402         return;
403     source.close();
404     closed = true;
407 /**
408  * Reads the next byte of data from the input stream.  -1 if EOF
409  */
410 int BasicInputStream::get()
412     if (closed)
413         return -1;
414     return source.get();
419 //#########################################################################
420 //# B A S I C    O U T P U T    S T R E A M
421 //#########################################################################
423 /**
424  *
425  */
426 BasicOutputStream::BasicOutputStream(const OutputStream &destinationStream)
427                      : destination((OutputStream &)destinationStream)
429     closed = false;
432 /**
433  * Closes this output stream and releases any system resources
434  * associated with this stream.
435  */
436 void BasicOutputStream::close()
438     if (closed)
439         return;
440     destination.close();
441     closed = true;
444 /**
445  *  Flushes this output stream and forces any buffered output
446  *  bytes to be written out.
447  */
448 void BasicOutputStream::flush()
450     if (closed)
451         return;
452     destination.flush();
455 /**
456  * Writes the specified byte to this output stream.
457  */
458 int BasicOutputStream::put(XMLCh ch)
460     if (closed)
461         return -1;
462     if (destination.put(ch) < 0)
463         return -1;
464     return 1;
469 //#########################################################################
470 //# B A S I C    R E A D E R
471 //#########################################################################
474 /**
475  *
476  */
477 BasicReader::BasicReader(Reader &sourceReader)
479     source = &sourceReader;
482 /**
483  * Returns the number of bytes that can be read (or skipped over) from
484  * this reader without blocking by the next caller of a method for
485  * this reader.
486  */
487 int BasicReader::available()
489     if (source)
490         return source->available();
491     else
492         return 0;
496 /**
497  *  Closes this reader and releases any system resources
498  *  associated with the reader.
499  */
500 void BasicReader::close()
502     if (source)
503         source->close();
506 /**
507  * Reads the next byte of data from the reader.
508  */
509 int BasicReader::get()
511     if (source)
512         return source->get();
513     else
514         return -1;
522 /**
523  * Reads a line of data from the reader.
524  */
525 DOMString BasicReader::readLine()
527     DOMString str;
528     while (available() > 0)
529         {
530         XMLCh ch = get();
531         if (ch == '\n')
532             break;
533         str.push_back(ch);
534         }
535     return str;
538 /**
539  * Reads a line of data from the reader.
540  */
541 DOMString BasicReader::readWord()
543     DOMString str;
544     while (available() > 0)
545         {
546         XMLCh ch = get();
547         if (isWhitespace(ch))
548             break;
549         str.push_back(ch);
550         }
551     return str;
555 static bool getLong(DOMString &str, long *val)
557     const char *begin = str.c_str();
558     char *end;
559     long ival = strtol(begin, &end, 10);
560     if (str == end)
561         return false;
562     *val = ival;
563     return true;
566 static bool getULong(const DOMString &str, unsigned long *val)
568     DOMString tmp = str;
569     char *begin = (char *)tmp.c_str();
570     char *end;
571     unsigned long ival = strtoul(begin, &end, 10);
572     if (begin == end)
573         return false;
574     *val = ival;
575     return true;
578 static bool getDouble(const DOMString &str, double *val)
580     DOMString tmp = str;
581     const char *begin = tmp.c_str();
582     char *end;
583     double ival = strtod(begin, &end);
584     if (begin == end)
585         return false;
586     *val = ival;
587     return true;
593 /**
594  *
595  */
596 Reader &BasicReader::readBool (bool& val )
598     DOMString buf = readWord();
599     if (buf == "true")
600         val = true;
601     else
602         val = false;
603     return *this;
606 /**
607  *
608  */
609 Reader &BasicReader::readShort (short& val )
611     DOMString buf = readWord();
612     long ival;
613     if (getLong(buf, &ival))
614         val = (short) ival;
615     return *this;
618 /**
619  *
620  */
621 Reader &BasicReader::readUnsignedShort (unsigned short& val )
623     DOMString buf = readWord();
624     unsigned long ival;
625     if (getULong(buf, &ival))
626         val = (unsigned short) ival;
627     return *this;
630 /**
631  *
632  */
633 Reader &BasicReader::readInt (int& val )
635     DOMString buf = readWord();
636     long ival;
637     if (getLong(buf, &ival))
638         val = (int) ival;
639     return *this;
642 /**
643  *
644  */
645 Reader &BasicReader::readUnsignedInt (unsigned int& val )
647     DOMString buf = readWord();
648     unsigned long ival;
649     if (getULong(buf, &ival))
650         val = (unsigned int) ival;
651     return *this;
654 /**
655  *
656  */
657 Reader &BasicReader::readLong (long& val )
659     DOMString buf = readWord();
660     long ival;
661     if (getLong(buf, &ival))
662         val = ival;
663     return *this;
666 /**
667  *
668  */
669 Reader &BasicReader::readUnsignedLong (unsigned long& val )
671     DOMString buf = readWord();
672     unsigned long ival;
673     if (getULong(buf, &ival))
674         val = ival;
675     return *this;
678 /**
679  *
680  */
681 Reader &BasicReader::readFloat (float& val )
683     DOMString buf = readWord();
684     double ival;
685     if (getDouble(buf, &ival))
686         val = (float)ival;
687     return *this;
690 /**
691  *
692  */
693 Reader &BasicReader::readDouble (double& val )
695     DOMString buf = readWord();
696     double ival;
697     if (getDouble(buf, &ival))
698         val = ival;
699     return *this;
704 //#########################################################################
705 //# I N P U T    S T R E A M    R E A D E R
706 //#########################################################################
709 InputStreamReader::InputStreamReader(const InputStream &inputStreamSource)
710                      : inputStream((InputStream &)inputStreamSource)
716 /**
717  *  Close the underlying OutputStream
718  */
719 void InputStreamReader::close()
721     inputStream.close();
724 /**
725  *  Flush the underlying OutputStream
726  */
727 int InputStreamReader::available()
729     return inputStream.available();
732 /**
733  *  Overloaded to receive its bytes from an InputStream
734  *  rather than a Reader
735  */
736 int InputStreamReader::get()
738     //Do we need conversions here?
739     int ch = (XMLCh)inputStream.get();
740     return ch;
745 //#########################################################################
746 //# S T D    R E A D E R
747 //#########################################################################
750 /**
751  *
752  */
753 StdReader::StdReader()
755     inputStream = new StdInputStream();
758 /**
759  *
760  */
761 StdReader::~StdReader()
763     delete inputStream;
768 /**
769  *  Close the underlying OutputStream
770  */
771 void StdReader::close()
773     inputStream->close();
776 /**
777  *  Flush the underlying OutputStream
778  */
779 int StdReader::available()
781     return inputStream->available();
784 /**
785  *  Overloaded to receive its bytes from an InputStream
786  *  rather than a Reader
787  */
788 int StdReader::get()
790     //Do we need conversions here?
791     XMLCh ch = (XMLCh)inputStream->get();
792     return ch;
799 //#########################################################################
800 //# B A S I C    W R I T E R
801 //#########################################################################
803 /**
804  *
805  */
806 BasicWriter::BasicWriter(const Writer &destinationWriter)
808     destination = (Writer *)&destinationWriter;
811 /**
812  * Closes this writer and releases any system resources
813  * associated with this writer.
814  */
815 void BasicWriter::close()
817     if (destination)
818         destination->close();
821 /**
822  *  Flushes this output stream and forces any buffered output
823  *  bytes to be written out.
824  */
825 void BasicWriter::flush()
827     if (destination)
828         destination->flush();
831 /**
832  * Writes the specified byte to this output writer.
833  */
834 int BasicWriter::put(XMLCh ch)
836     if (destination && destination->put(ch)>=0)
837         return 1;
838     return -1;
841 /**
842  * Provide printf()-like formatting
843  */
844 /*
845 Writer &BasicWriter::printf(char *fmt, ...)
847     va_list args;
848     va_start(args, fmt);
849     //replace this wish vsnprintf()
850     vsnprintf(formatBuf, 2047, fmt, args);
851     va_end(args);
852     writeString(formatBuf);
854     return *this;
856 */
857 Writer &BasicWriter::printf(char *fmt, ...)
859     va_list args;
860     va_start(args, fmt);
861     dprintf(*this, fmt, args);
863     return *this;
867 /**
868  * Writes the specified character to this output writer.
869  */
870 Writer &BasicWriter::writeChar(char ch)
872     XMLCh uch = ch;
873     put(uch);
874     return *this;
878 /**
879  * Writes the specified standard string to this output writer.
880  */
881 Writer &BasicWriter::writeString(const DOMString &str)
883     for (int i=0; i< (int)str.size(); i++)
884         put(str[i]);
885     return *this;
889 /**
890  *
891  */
892 Writer &BasicWriter::writeBool (bool val )
894     if (val)
895         writeString("true");
896     else
897         writeString("false");
898     return *this;
902 /**
903  *
904  */
905 Writer &BasicWriter::writeShort (short val )
907     char buf[32];
908     snprintf(buf, 31, "%d", val);
909     writeString(buf);
910     return *this;
915 /**
916  *
917  */
918 Writer &BasicWriter::writeUnsignedShort (unsigned short val )
920     char buf[32];
921     snprintf(buf, 31, "%u", val);
922     writeString(buf);
923     return *this;
926 /**
927  *
928  */
929 Writer &BasicWriter::writeInt (int val)
931     char buf[32];
932     snprintf(buf, 31, "%d", val);
933     writeString(buf);
934     return *this;
937 /**
938  *
939  */
940 Writer &BasicWriter::writeUnsignedInt (unsigned int val)
942     char buf[32];
943     snprintf(buf, 31, "%u", val);
944     writeString(buf);
945     return *this;
948 /**
949  *
950  */
951 Writer &BasicWriter::writeLong (long val)
953     char buf[32];
954     snprintf(buf, 31, "%ld", val);
955     writeString(buf);
956     return *this;
959 /**
960  *
961  */
962 Writer &BasicWriter::writeUnsignedLong(unsigned long val)
964     char buf[32];
965     snprintf(buf, 31, "%lu", val);
966     writeString(buf);
967     return *this;
970 /**
971  *
972  */
973 Writer &BasicWriter::writeFloat(float val)
975     char buf[32];
976     snprintf(buf, 31, "%8.3f", val);
977     writeString(buf);
978     return *this;
981 /**
982  *
983  */
984 Writer &BasicWriter::writeDouble(double val)
986     char buf[32];
987     snprintf(buf, 31, "%8.3f", val);
988     writeString(buf);
989     return *this;
995 //#########################################################################
996 //# O U T P U T    S T R E A M    W R I T E R
997 //#########################################################################
1000 OutputStreamWriter::OutputStreamWriter(OutputStream &outputStreamDest)
1001                      : outputStream(outputStreamDest)
1007 /**
1008  *  Close the underlying OutputStream
1009  */
1010 void OutputStreamWriter::close()
1012     flush();
1013     outputStream.close();
1016 /**
1017  *  Flush the underlying OutputStream
1018  */
1019 void OutputStreamWriter::flush()
1021       outputStream.flush();
1024 /**
1025  *  Overloaded to redirect the output chars from the next Writer
1026  *  in the chain to an OutputStream instead.
1027  */
1028 int OutputStreamWriter::put(XMLCh ch)
1030     //Do we need conversions here?
1031     int intCh = (int) ch;
1032     if (outputStream.put(intCh) < 0)
1033         return -1;
1034     return 1;
1037 //#########################################################################
1038 //# S T D    W R I T E R
1039 //#########################################################################
1042 /**
1043  *
1044  */
1045 StdWriter::StdWriter()
1047     outputStream = new StdOutputStream();
1051 /**
1052  *
1053  */
1054 StdWriter::~StdWriter()
1056     delete outputStream;
1061 /**
1062  *  Close the underlying OutputStream
1063  */
1064 void StdWriter::close()
1066     flush();
1067     outputStream->close();
1070 /**
1071  *  Flush the underlying OutputStream
1072  */
1073 void StdWriter::flush()
1075       outputStream->flush();
1078 /**
1079  *  Overloaded to redirect the output chars from the next Writer
1080  *  in the chain to an OutputStream instead.
1081  */
1082 int StdWriter::put(XMLCh ch)
1084     //Do we need conversions here?
1085     int intCh = (int) ch;
1086     if (outputStream->put(intCh) < 0)
1087         return -1;
1088     return 1;
1102 //###############################################
1103 //# O P E R A T O R S
1104 //###############################################
1105 //# Normally these would be in the .h, but we
1106 //# just want to be absolutely certain that these
1107 //# are never multiply defined.  Easy to maintain,
1108 //# though.  Just occasionally copy/paste these
1109 //# into the .h , and replace the {} with a ;
1110 //###############################################
1115 Reader& operator>> (Reader &reader, bool& val )
1116         { return reader.readBool(val); }
1118 Reader& operator>> (Reader &reader, short &val)
1119         { return reader.readShort(val); }
1121 Reader& operator>> (Reader &reader, unsigned short &val)
1122         { return reader.readUnsignedShort(val); }
1124 Reader& operator>> (Reader &reader, int &val)
1125         { return reader.readInt(val); }
1127 Reader& operator>> (Reader &reader, unsigned int &val)
1128         { return reader.readUnsignedInt(val); }
1130 Reader& operator>> (Reader &reader, long &val)
1131         { return reader.readLong(val); }
1133 Reader& operator>> (Reader &reader, unsigned long &val)
1134         { return reader.readUnsignedLong(val); }
1136 Reader& operator>> (Reader &reader, float &val)
1137         { return reader.readFloat(val); }
1139 Reader& operator>> (Reader &reader, double &val)
1140         { return reader.readDouble(val); }
1145 Writer& operator<< (Writer &writer, char val)
1146     { return writer.writeChar(val); }
1148 Writer& operator<< (Writer &writer, const DOMString &val)
1149     { return writer.writeString(val); }
1151 Writer& operator<< (Writer &writer, bool val)
1152     { return writer.writeBool(val); }
1154 Writer& operator<< (Writer &writer, short val)
1155     { return writer.writeShort(val); }
1157 Writer& operator<< (Writer &writer, unsigned short val)
1158     { return writer.writeUnsignedShort(val); }
1160 Writer& operator<< (Writer &writer, int val)
1161     { return writer.writeInt(val); }
1163 Writer& operator<< (Writer &writer, unsigned int val)
1164     { return writer.writeUnsignedInt(val); }
1166 Writer& operator<< (Writer &writer, long val)
1167     { return writer.writeLong(val); }
1169 Writer& operator<< (Writer &writer, unsigned long val)
1170     { return writer.writeUnsignedLong(val); }
1172 Writer& operator<< (Writer &writer, float val)
1173     { return writer.writeFloat(val); }
1175 Writer& operator<< (Writer &writer, double val)
1176     { return writer.writeDouble(val); }
1180 }  //namespace io
1181 }  //namespace dom
1182 }  //namespace w3c
1183 }  //namespace org
1186 //#########################################################################
1187 //# E N D    O F    F I L E
1188 //#########################################################################