19ff3de7b1c784bd03f20ad23f5f7f18bde5292c
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;
106 }
110 static int dprintDouble(Writer &outs,
111 double val,
112 int flag, int width, int precision)
113 {
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;
204 }
206 static int dprintString(Writer &outs,
207 char *arg,
208 int flags, int width, int precision)
209 {
210 while (*arg)
211 {
212 if (outs.put(*arg++) < 0)
213 return -1;
214 }
216 return 1;
217 }
221 static char *getint(char *s, int *ret)
222 {
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;
241 }
245 static int dprintf(Writer &outs, const char *fmt, va_list ap)
246 {
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;
367 }
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)
380 {
381 closed = false;
382 }
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()
390 {
391 if (closed)
392 return 0;
393 return source.available();
394 }
397 /**
398 * Closes this input stream and releases any system resources
399 * associated with the stream.
400 */
401 void BasicInputStream::close()
402 {
403 if (closed)
404 return;
405 source.close();
406 closed = true;
407 }
409 /**
410 * Reads the next byte of data from the input stream. -1 if EOF
411 */
412 int BasicInputStream::get()
413 {
414 if (closed)
415 return -1;
416 return source.get();
417 }
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)
430 {
431 closed = false;
432 }
434 /**
435 * Closes this output stream and releases any system resources
436 * associated with this stream.
437 */
438 void BasicOutputStream::close()
439 {
440 if (closed)
441 return;
442 destination.close();
443 closed = true;
444 }
446 /**
447 * Flushes this output stream and forces any buffered output
448 * bytes to be written out.
449 */
450 void BasicOutputStream::flush()
451 {
452 if (closed)
453 return;
454 destination.flush();
455 }
457 /**
458 * Writes the specified byte to this output stream.
459 */
460 int BasicOutputStream::put(XMLCh ch)
461 {
462 if (closed)
463 return -1;
464 if (destination.put(ch) < 0)
465 return -1;
466 return 1;
467 }
471 //#########################################################################
472 //# B A S I C R E A D E R
473 //#########################################################################
476 /**
477 *
478 */
479 BasicReader::BasicReader(Reader &sourceReader)
480 {
481 source = &sourceReader;
482 }
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()
490 {
491 if (source)
492 return source->available();
493 else
494 return 0;
495 }
498 /**
499 * Closes this reader and releases any system resources
500 * associated with the reader.
501 */
502 void BasicReader::close()
503 {
504 if (source)
505 source->close();
506 }
508 /**
509 * Reads the next byte of data from the reader.
510 */
511 int BasicReader::get()
512 {
513 if (source)
514 return source->get();
515 else
516 return -1;
517 }
524 /**
525 * Reads a line of data from the reader.
526 */
527 DOMString BasicReader::readLine()
528 {
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;
538 }
540 /**
541 * Reads a line of data from the reader.
542 */
543 DOMString BasicReader::readWord()
544 {
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;
554 }
557 static bool getLong(DOMString &str, long *val)
558 {
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;
566 }
568 static bool getULong(const DOMString &str, unsigned long *val)
569 {
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;
578 }
580 static bool getDouble(const DOMString &str, double *val)
581 {
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;
590 }
595 /**
596 *
597 */
598 Reader &BasicReader::readBool (bool& val )
599 {
600 DOMString buf = readWord();
601 if (buf == "true")
602 val = true;
603 else
604 val = false;
605 return *this;
606 }
608 /**
609 *
610 */
611 Reader &BasicReader::readShort (short& val )
612 {
613 DOMString buf = readWord();
614 long ival;
615 if (getLong(buf, &ival))
616 val = (short) ival;
617 return *this;
618 }
620 /**
621 *
622 */
623 Reader &BasicReader::readUnsignedShort (unsigned short& val )
624 {
625 DOMString buf = readWord();
626 unsigned long ival;
627 if (getULong(buf, &ival))
628 val = (unsigned short) ival;
629 return *this;
630 }
632 /**
633 *
634 */
635 Reader &BasicReader::readInt (int& val )
636 {
637 DOMString buf = readWord();
638 long ival;
639 if (getLong(buf, &ival))
640 val = (int) ival;
641 return *this;
642 }
644 /**
645 *
646 */
647 Reader &BasicReader::readUnsignedInt (unsigned int& val )
648 {
649 DOMString buf = readWord();
650 unsigned long ival;
651 if (getULong(buf, &ival))
652 val = (unsigned int) ival;
653 return *this;
654 }
656 /**
657 *
658 */
659 Reader &BasicReader::readLong (long& val )
660 {
661 DOMString buf = readWord();
662 long ival;
663 if (getLong(buf, &ival))
664 val = ival;
665 return *this;
666 }
668 /**
669 *
670 */
671 Reader &BasicReader::readUnsignedLong (unsigned long& val )
672 {
673 DOMString buf = readWord();
674 unsigned long ival;
675 if (getULong(buf, &ival))
676 val = ival;
677 return *this;
678 }
680 /**
681 *
682 */
683 Reader &BasicReader::readFloat (float& val )
684 {
685 DOMString buf = readWord();
686 double ival;
687 if (getDouble(buf, &ival))
688 val = (float)ival;
689 return *this;
690 }
692 /**
693 *
694 */
695 Reader &BasicReader::readDouble (double& val )
696 {
697 DOMString buf = readWord();
698 double ival;
699 if (getDouble(buf, &ival))
700 val = ival;
701 return *this;
702 }
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)
713 {
714 }
718 /**
719 * Close the underlying OutputStream
720 */
721 void InputStreamReader::close()
722 {
723 inputStream.close();
724 }
726 /**
727 * Flush the underlying OutputStream
728 */
729 int InputStreamReader::available()
730 {
731 return inputStream.available();
732 }
734 /**
735 * Overloaded to receive its bytes from an InputStream
736 * rather than a Reader
737 */
738 int InputStreamReader::get()
739 {
740 //Do we need conversions here?
741 int ch = (XMLCh)inputStream.get();
742 return ch;
743 }
747 //#########################################################################
748 //# S T D R E A D E R
749 //#########################################################################
752 /**
753 *
754 */
755 StdReader::StdReader()
756 {
757 inputStream = new StdInputStream();
758 }
760 /**
761 *
762 */
763 StdReader::~StdReader()
764 {
765 delete inputStream;
766 }
770 /**
771 * Close the underlying OutputStream
772 */
773 void StdReader::close()
774 {
775 inputStream->close();
776 }
778 /**
779 * Flush the underlying OutputStream
780 */
781 int StdReader::available()
782 {
783 return inputStream->available();
784 }
786 /**
787 * Overloaded to receive its bytes from an InputStream
788 * rather than a Reader
789 */
790 int StdReader::get()
791 {
792 //Do we need conversions here?
793 XMLCh ch = (XMLCh)inputStream->get();
794 return ch;
795 }
801 //#########################################################################
802 //# B A S I C W R I T E R
803 //#########################################################################
805 /**
806 *
807 */
808 BasicWriter::BasicWriter(const Writer &destinationWriter)
809 {
810 destination = (Writer *)&destinationWriter;
811 }
813 /**
814 * Closes this writer and releases any system resources
815 * associated with this writer.
816 */
817 void BasicWriter::close()
818 {
819 if (destination)
820 destination->close();
821 }
823 /**
824 * Flushes this output stream and forces any buffered output
825 * bytes to be written out.
826 */
827 void BasicWriter::flush()
828 {
829 if (destination)
830 destination->flush();
831 }
833 /**
834 * Writes the specified byte to this output writer.
835 */
836 int BasicWriter::put(XMLCh ch)
837 {
838 if (destination && destination->put(ch)>=0)
839 return 1;
840 return -1;
841 }
843 /**
844 * Provide printf()-like formatting
845 */
846 /*
847 Writer &BasicWriter::printf(char *fmt, ...)
848 {
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;
857 }
858 */
859 Writer &BasicWriter::printf(char *fmt, ...)
860 {
861 va_list args;
862 va_start(args, fmt);
863 dprintf(*this, fmt, args);
865 return *this;
866 }
869 /**
870 * Writes the specified character to this output writer.
871 */
872 Writer &BasicWriter::writeChar(char ch)
873 {
874 XMLCh uch = ch;
875 put(uch);
876 return *this;
877 }
880 /**
881 * Writes the specified standard string to this output writer.
882 */
883 Writer &BasicWriter::writeString(const DOMString &str)
884 {
885 for (int i=0; i< (int)str.size(); i++)
886 put(str[i]);
887 return *this;
888 }
891 /**
892 *
893 */
894 Writer &BasicWriter::writeBool (bool val )
895 {
896 if (val)
897 writeString("true");
898 else
899 writeString("false");
900 return *this;
901 }
904 /**
905 *
906 */
907 Writer &BasicWriter::writeShort (short val )
908 {
909 char buf[32];
910 snprintf(buf, 31, "%d", val);
911 writeString(buf);
912 return *this;
913 }
917 /**
918 *
919 */
920 Writer &BasicWriter::writeUnsignedShort (unsigned short val )
921 {
922 char buf[32];
923 snprintf(buf, 31, "%u", val);
924 writeString(buf);
925 return *this;
926 }
928 /**
929 *
930 */
931 Writer &BasicWriter::writeInt (int val)
932 {
933 char buf[32];
934 snprintf(buf, 31, "%d", val);
935 writeString(buf);
936 return *this;
937 }
939 /**
940 *
941 */
942 Writer &BasicWriter::writeUnsignedInt (unsigned int val)
943 {
944 char buf[32];
945 snprintf(buf, 31, "%u", val);
946 writeString(buf);
947 return *this;
948 }
950 /**
951 *
952 */
953 Writer &BasicWriter::writeLong (long val)
954 {
955 char buf[32];
956 snprintf(buf, 31, "%ld", val);
957 writeString(buf);
958 return *this;
959 }
961 /**
962 *
963 */
964 Writer &BasicWriter::writeUnsignedLong(unsigned long val)
965 {
966 char buf[32];
967 snprintf(buf, 31, "%lu", val);
968 writeString(buf);
969 return *this;
970 }
972 /**
973 *
974 */
975 Writer &BasicWriter::writeFloat(float val)
976 {
977 char buf[32];
978 snprintf(buf, 31, "%8.3f", val);
979 writeString(buf);
980 return *this;
981 }
983 /**
984 *
985 */
986 Writer &BasicWriter::writeDouble(double val)
987 {
988 char buf[32];
989 snprintf(buf, 31, "%8.3f", val);
990 writeString(buf);
991 return *this;
992 }
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)
1004 {
1005 }
1009 /**
1010 * Close the underlying OutputStream
1011 */
1012 void OutputStreamWriter::close()
1013 {
1014 flush();
1015 outputStream.close();
1016 }
1018 /**
1019 * Flush the underlying OutputStream
1020 */
1021 void OutputStreamWriter::flush()
1022 {
1023 outputStream.flush();
1024 }
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)
1031 {
1032 //Do we need conversions here?
1033 int intCh = (int) ch;
1034 if (outputStream.put(intCh) < 0)
1035 return -1;
1036 return 1;
1037 }
1039 //#########################################################################
1040 //# S T D W R I T E R
1041 //#########################################################################
1044 /**
1045 *
1046 */
1047 StdWriter::StdWriter()
1048 {
1049 outputStream = new StdOutputStream();
1050 }
1053 /**
1054 *
1055 */
1056 StdWriter::~StdWriter()
1057 {
1058 delete outputStream;
1059 }
1063 /**
1064 * Close the underlying OutputStream
1065 */
1066 void StdWriter::close()
1067 {
1068 flush();
1069 outputStream->close();
1070 }
1072 /**
1073 * Flush the underlying OutputStream
1074 */
1075 void StdWriter::flush()
1076 {
1077 outputStream->flush();
1078 }
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)
1085 {
1086 //Do we need conversions here?
1087 int intCh = (int) ch;
1088 if (outputStream->put(intCh) < 0)
1089 return -1;
1090 return 1;
1091 }
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 //#########################################################################