7b0a7e1d2b6cfa1bd6e14d5aef2350cca49f1b27
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 }
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;
202 }
204 static int dprintString(Writer &outs,
205 char *arg,
206 int flags, int width, int precision)
207 {
208 while (*arg)
209 {
210 if (outs.put(*arg++) < 0)
211 return -1;
212 }
214 return 1;
215 }
219 static char *getint(char *s, int *ret)
220 {
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;
239 }
243 static int dprintf(Writer &outs, const char *fmt, va_list ap)
244 {
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;
365 }
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)
378 {
379 closed = false;
380 }
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()
388 {
389 if (closed)
390 return 0;
391 return source.available();
392 }
395 /**
396 * Closes this input stream and releases any system resources
397 * associated with the stream.
398 */
399 void BasicInputStream::close()
400 {
401 if (closed)
402 return;
403 source.close();
404 closed = true;
405 }
407 /**
408 * Reads the next byte of data from the input stream. -1 if EOF
409 */
410 int BasicInputStream::get()
411 {
412 if (closed)
413 return -1;
414 return source.get();
415 }
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)
428 {
429 closed = false;
430 }
432 /**
433 * Closes this output stream and releases any system resources
434 * associated with this stream.
435 */
436 void BasicOutputStream::close()
437 {
438 if (closed)
439 return;
440 destination.close();
441 closed = true;
442 }
444 /**
445 * Flushes this output stream and forces any buffered output
446 * bytes to be written out.
447 */
448 void BasicOutputStream::flush()
449 {
450 if (closed)
451 return;
452 destination.flush();
453 }
455 /**
456 * Writes the specified byte to this output stream.
457 */
458 int BasicOutputStream::put(XMLCh ch)
459 {
460 if (closed)
461 return -1;
462 if (destination.put(ch) < 0)
463 return -1;
464 return 1;
465 }
469 //#########################################################################
470 //# B A S I C R E A D E R
471 //#########################################################################
474 /**
475 *
476 */
477 BasicReader::BasicReader(Reader &sourceReader)
478 {
479 source = &sourceReader;
480 }
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()
488 {
489 if (source)
490 return source->available();
491 else
492 return 0;
493 }
496 /**
497 * Closes this reader and releases any system resources
498 * associated with the reader.
499 */
500 void BasicReader::close()
501 {
502 if (source)
503 source->close();
504 }
506 /**
507 * Reads the next byte of data from the reader.
508 */
509 int BasicReader::get()
510 {
511 if (source)
512 return source->get();
513 else
514 return -1;
515 }
522 /**
523 * Reads a line of data from the reader.
524 */
525 DOMString BasicReader::readLine()
526 {
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;
536 }
538 /**
539 * Reads a line of data from the reader.
540 */
541 DOMString BasicReader::readWord()
542 {
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;
552 }
555 static bool getLong(DOMString &str, long *val)
556 {
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;
564 }
566 static bool getULong(const DOMString &str, unsigned long *val)
567 {
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;
576 }
578 static bool getDouble(const DOMString &str, double *val)
579 {
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;
588 }
593 /**
594 *
595 */
596 Reader &BasicReader::readBool (bool& val )
597 {
598 DOMString buf = readWord();
599 if (buf == "true")
600 val = true;
601 else
602 val = false;
603 return *this;
604 }
606 /**
607 *
608 */
609 Reader &BasicReader::readShort (short& val )
610 {
611 DOMString buf = readWord();
612 long ival;
613 if (getLong(buf, &ival))
614 val = (short) ival;
615 return *this;
616 }
618 /**
619 *
620 */
621 Reader &BasicReader::readUnsignedShort (unsigned short& val )
622 {
623 DOMString buf = readWord();
624 unsigned long ival;
625 if (getULong(buf, &ival))
626 val = (unsigned short) ival;
627 return *this;
628 }
630 /**
631 *
632 */
633 Reader &BasicReader::readInt (int& val )
634 {
635 DOMString buf = readWord();
636 long ival;
637 if (getLong(buf, &ival))
638 val = (int) ival;
639 return *this;
640 }
642 /**
643 *
644 */
645 Reader &BasicReader::readUnsignedInt (unsigned int& val )
646 {
647 DOMString buf = readWord();
648 unsigned long ival;
649 if (getULong(buf, &ival))
650 val = (unsigned int) ival;
651 return *this;
652 }
654 /**
655 *
656 */
657 Reader &BasicReader::readLong (long& val )
658 {
659 DOMString buf = readWord();
660 long ival;
661 if (getLong(buf, &ival))
662 val = ival;
663 return *this;
664 }
666 /**
667 *
668 */
669 Reader &BasicReader::readUnsignedLong (unsigned long& val )
670 {
671 DOMString buf = readWord();
672 unsigned long ival;
673 if (getULong(buf, &ival))
674 val = ival;
675 return *this;
676 }
678 /**
679 *
680 */
681 Reader &BasicReader::readFloat (float& val )
682 {
683 DOMString buf = readWord();
684 double ival;
685 if (getDouble(buf, &ival))
686 val = (float)ival;
687 return *this;
688 }
690 /**
691 *
692 */
693 Reader &BasicReader::readDouble (double& val )
694 {
695 DOMString buf = readWord();
696 double ival;
697 if (getDouble(buf, &ival))
698 val = ival;
699 return *this;
700 }
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)
711 {
712 }
716 /**
717 * Close the underlying OutputStream
718 */
719 void InputStreamReader::close()
720 {
721 inputStream.close();
722 }
724 /**
725 * Flush the underlying OutputStream
726 */
727 int InputStreamReader::available()
728 {
729 return inputStream.available();
730 }
732 /**
733 * Overloaded to receive its bytes from an InputStream
734 * rather than a Reader
735 */
736 int InputStreamReader::get()
737 {
738 //Do we need conversions here?
739 int ch = (XMLCh)inputStream.get();
740 return ch;
741 }
745 //#########################################################################
746 //# S T D R E A D E R
747 //#########################################################################
750 /**
751 *
752 */
753 StdReader::StdReader()
754 {
755 inputStream = new StdInputStream();
756 }
758 /**
759 *
760 */
761 StdReader::~StdReader()
762 {
763 delete inputStream;
764 }
768 /**
769 * Close the underlying OutputStream
770 */
771 void StdReader::close()
772 {
773 inputStream->close();
774 }
776 /**
777 * Flush the underlying OutputStream
778 */
779 int StdReader::available()
780 {
781 return inputStream->available();
782 }
784 /**
785 * Overloaded to receive its bytes from an InputStream
786 * rather than a Reader
787 */
788 int StdReader::get()
789 {
790 //Do we need conversions here?
791 XMLCh ch = (XMLCh)inputStream->get();
792 return ch;
793 }
799 //#########################################################################
800 //# B A S I C W R I T E R
801 //#########################################################################
803 /**
804 *
805 */
806 BasicWriter::BasicWriter(const Writer &destinationWriter)
807 {
808 destination = (Writer *)&destinationWriter;
809 }
811 /**
812 * Closes this writer and releases any system resources
813 * associated with this writer.
814 */
815 void BasicWriter::close()
816 {
817 if (destination)
818 destination->close();
819 }
821 /**
822 * Flushes this output stream and forces any buffered output
823 * bytes to be written out.
824 */
825 void BasicWriter::flush()
826 {
827 if (destination)
828 destination->flush();
829 }
831 /**
832 * Writes the specified byte to this output writer.
833 */
834 int BasicWriter::put(XMLCh ch)
835 {
836 if (destination && destination->put(ch)>=0)
837 return 1;
838 return -1;
839 }
841 /**
842 * Provide printf()-like formatting
843 */
844 /*
845 Writer &BasicWriter::printf(char *fmt, ...)
846 {
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;
855 }
856 */
857 Writer &BasicWriter::printf(char *fmt, ...)
858 {
859 va_list args;
860 va_start(args, fmt);
861 dprintf(*this, fmt, args);
863 return *this;
864 }
867 /**
868 * Writes the specified character to this output writer.
869 */
870 Writer &BasicWriter::writeChar(char ch)
871 {
872 XMLCh uch = ch;
873 put(uch);
874 return *this;
875 }
878 /**
879 * Writes the specified standard string to this output writer.
880 */
881 Writer &BasicWriter::writeString(const DOMString &str)
882 {
883 for (int i=0; i< (int)str.size(); i++)
884 put(str[i]);
885 return *this;
886 }
889 /**
890 *
891 */
892 Writer &BasicWriter::writeBool (bool val )
893 {
894 if (val)
895 writeString("true");
896 else
897 writeString("false");
898 return *this;
899 }
902 /**
903 *
904 */
905 Writer &BasicWriter::writeShort (short val )
906 {
907 char buf[32];
908 snprintf(buf, 31, "%d", val);
909 writeString(buf);
910 return *this;
911 }
915 /**
916 *
917 */
918 Writer &BasicWriter::writeUnsignedShort (unsigned short val )
919 {
920 char buf[32];
921 snprintf(buf, 31, "%u", val);
922 writeString(buf);
923 return *this;
924 }
926 /**
927 *
928 */
929 Writer &BasicWriter::writeInt (int val)
930 {
931 char buf[32];
932 snprintf(buf, 31, "%d", val);
933 writeString(buf);
934 return *this;
935 }
937 /**
938 *
939 */
940 Writer &BasicWriter::writeUnsignedInt (unsigned int val)
941 {
942 char buf[32];
943 snprintf(buf, 31, "%u", val);
944 writeString(buf);
945 return *this;
946 }
948 /**
949 *
950 */
951 Writer &BasicWriter::writeLong (long val)
952 {
953 char buf[32];
954 snprintf(buf, 31, "%ld", val);
955 writeString(buf);
956 return *this;
957 }
959 /**
960 *
961 */
962 Writer &BasicWriter::writeUnsignedLong(unsigned long val)
963 {
964 char buf[32];
965 snprintf(buf, 31, "%lu", val);
966 writeString(buf);
967 return *this;
968 }
970 /**
971 *
972 */
973 Writer &BasicWriter::writeFloat(float val)
974 {
975 char buf[32];
976 snprintf(buf, 31, "%8.3f", val);
977 writeString(buf);
978 return *this;
979 }
981 /**
982 *
983 */
984 Writer &BasicWriter::writeDouble(double val)
985 {
986 char buf[32];
987 snprintf(buf, 31, "%8.3f", val);
988 writeString(buf);
989 return *this;
990 }
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)
1002 {
1003 }
1007 /**
1008 * Close the underlying OutputStream
1009 */
1010 void OutputStreamWriter::close()
1011 {
1012 flush();
1013 outputStream.close();
1014 }
1016 /**
1017 * Flush the underlying OutputStream
1018 */
1019 void OutputStreamWriter::flush()
1020 {
1021 outputStream.flush();
1022 }
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)
1029 {
1030 //Do we need conversions here?
1031 int intCh = (int) ch;
1032 if (outputStream.put(intCh) < 0)
1033 return -1;
1034 return 1;
1035 }
1037 //#########################################################################
1038 //# S T D W R I T E R
1039 //#########################################################################
1042 /**
1043 *
1044 */
1045 StdWriter::StdWriter()
1046 {
1047 outputStream = new StdOutputStream();
1048 }
1051 /**
1052 *
1053 */
1054 StdWriter::~StdWriter()
1055 {
1056 delete outputStream;
1057 }
1061 /**
1062 * Close the underlying OutputStream
1063 */
1064 void StdWriter::close()
1065 {
1066 flush();
1067 outputStream->close();
1068 }
1070 /**
1071 * Flush the underlying OutputStream
1072 */
1073 void StdWriter::flush()
1074 {
1075 outputStream->flush();
1076 }
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)
1083 {
1084 //Do we need conversions here?
1085 int intCh = (int) ch;
1086 if (outputStream->put(intCh) < 0)
1087 return -1;
1088 return 1;
1089 }
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 //#########################################################################