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 <stdarg.h>
39 #include "domstream.h"
40 #include "dom/charclass.h"
42 namespace org
43 {
44 namespace w3c
45 {
46 namespace dom
47 {
48 namespace io
49 {
52 //#########################################################################
53 //# U T I L I T Y
54 //#########################################################################
56 void pipeStream(InputStream &source, OutputStream &dest)
57 {
58 for (;;)
59 {
60 int ch = source.get();
61 if (ch<0)
62 break;
63 dest.put(ch);
64 }
65 dest.flush();
66 }
68 //#########################################################################
69 //# B A S I C I N P U T S T R E A M
70 //#########################################################################
73 /**
74 *
75 */
76 BasicInputStream::BasicInputStream(const InputStream &sourceStream)
77 : source((InputStream &)sourceStream)
78 {
79 closed = false;
80 }
82 /**
83 * Returns the number of bytes that can be read (or skipped over) from
84 * this input stream without blocking by the next caller of a method for
85 * this input stream.
86 */
87 int BasicInputStream::available()
88 {
89 if (closed)
90 return 0;
91 return source.available();
92 }
95 /**
96 * Closes this input stream and releases any system resources
97 * associated with the stream.
98 */
99 void BasicInputStream::close()
100 {
101 if (closed)
102 return;
103 source.close();
104 closed = true;
105 }
107 /**
108 * Reads the next byte of data from the input stream. -1 if EOF
109 */
110 int BasicInputStream::get()
111 {
112 if (closed)
113 return -1;
114 return source.get();
115 }
119 //#########################################################################
120 //# B A S I C O U T P U T S T R E A M
121 //#########################################################################
123 /**
124 *
125 */
126 BasicOutputStream::BasicOutputStream(const OutputStream &destinationStream)
127 : destination((OutputStream &)destinationStream)
128 {
129 closed = false;
130 }
132 /**
133 * Closes this output stream and releases any system resources
134 * associated with this stream.
135 */
136 void BasicOutputStream::close()
137 {
138 if (closed)
139 return;
140 destination.close();
141 closed = true;
142 }
144 /**
145 * Flushes this output stream and forces any buffered output
146 * bytes to be written out.
147 */
148 void BasicOutputStream::flush()
149 {
150 if (closed)
151 return;
152 destination.flush();
153 }
155 /**
156 * Writes the specified byte to this output stream.
157 */
158 void BasicOutputStream::put(XMLCh ch)
159 {
160 if (closed)
161 return;
162 destination.put(ch);
163 }
167 //#########################################################################
168 //# B A S I C R E A D E R
169 //#########################################################################
172 /**
173 *
174 */
175 BasicReader::BasicReader(Reader &sourceReader)
176 {
177 source = &sourceReader;
178 }
180 /**
181 * Returns the number of bytes that can be read (or skipped over) from
182 * this reader without blocking by the next caller of a method for
183 * this reader.
184 */
185 int BasicReader::available()
186 {
187 if (source)
188 return source->available();
189 else
190 return 0;
191 }
194 /**
195 * Closes this reader and releases any system resources
196 * associated with the reader.
197 */
198 void BasicReader::close()
199 {
200 if (source)
201 source->close();
202 }
204 /**
205 * Reads the next byte of data from the reader.
206 */
207 int BasicReader::get()
208 {
209 if (source)
210 return source->get();
211 else
212 return -1;
213 }
220 /**
221 * Reads a line of data from the reader.
222 */
223 DOMString BasicReader::readLine()
224 {
225 DOMString str;
226 while (available() > 0)
227 {
228 XMLCh ch = get();
229 if (ch == '\n')
230 break;
231 str.push_back(ch);
232 }
233 return str;
234 }
236 /**
237 * Reads a line of data from the reader.
238 */
239 DOMString BasicReader::readWord()
240 {
241 DOMString str;
242 while (available() > 0)
243 {
244 XMLCh ch = get();
245 if (isWhitespace(ch))
246 break;
247 str.push_back(ch);
248 }
249 return str;
250 }
253 static bool getLong(DOMString &str, long *val)
254 {
255 const char *begin = str.c_str();
256 char *end;
257 long ival = strtol(begin, &end, 10);
258 if (str == end)
259 return false;
260 *val = ival;
261 return true;
262 }
264 static bool getULong(const DOMString &str, unsigned long *val)
265 {
266 DOMString tmp = str;
267 char *begin = (char *)tmp.c_str();
268 char *end;
269 unsigned long ival = strtoul(begin, &end, 10);
270 if (begin == end)
271 return false;
272 *val = ival;
273 return true;
274 }
276 static bool getDouble(const DOMString &str, double *val)
277 {
278 DOMString tmp = str;
279 const char *begin = tmp.c_str();
280 char *end;
281 double ival = strtod(begin, &end);
282 if (begin == end)
283 return false;
284 *val = ival;
285 return true;
286 }
291 /**
292 *
293 */
294 Reader &BasicReader::readBool (bool& val )
295 {
296 DOMString buf = readWord();
297 if (buf == "true")
298 val = true;
299 else
300 val = false;
301 return *this;
302 }
304 /**
305 *
306 */
307 Reader &BasicReader::readShort (short& val )
308 {
309 DOMString buf = readWord();
310 long ival;
311 if (getLong(buf, &ival))
312 val = (short) ival;
313 return *this;
314 }
316 /**
317 *
318 */
319 Reader &BasicReader::readUnsignedShort (unsigned short& val )
320 {
321 DOMString buf = readWord();
322 unsigned long ival;
323 if (getULong(buf, &ival))
324 val = (unsigned short) ival;
325 return *this;
326 }
328 /**
329 *
330 */
331 Reader &BasicReader::readInt (int& val )
332 {
333 DOMString buf = readWord();
334 long ival;
335 if (getLong(buf, &ival))
336 val = (int) ival;
337 return *this;
338 }
340 /**
341 *
342 */
343 Reader &BasicReader::readUnsignedInt (unsigned int& val )
344 {
345 DOMString buf = readWord();
346 unsigned long ival;
347 if (getULong(buf, &ival))
348 val = (unsigned int) ival;
349 return *this;
350 }
352 /**
353 *
354 */
355 Reader &BasicReader::readLong (long& val )
356 {
357 DOMString buf = readWord();
358 long ival;
359 if (getLong(buf, &ival))
360 val = ival;
361 return *this;
362 }
364 /**
365 *
366 */
367 Reader &BasicReader::readUnsignedLong (unsigned long& val )
368 {
369 DOMString buf = readWord();
370 unsigned long ival;
371 if (getULong(buf, &ival))
372 val = ival;
373 return *this;
374 }
376 /**
377 *
378 */
379 Reader &BasicReader::readFloat (float& val )
380 {
381 DOMString buf = readWord();
382 double ival;
383 if (getDouble(buf, &ival))
384 val = (float)ival;
385 return *this;
386 }
388 /**
389 *
390 */
391 Reader &BasicReader::readDouble (double& val )
392 {
393 DOMString buf = readWord();
394 double ival;
395 if (getDouble(buf, &ival))
396 val = ival;
397 return *this;
398 }
402 //#########################################################################
403 //# I N P U T S T R E A M R E A D E R
404 //#########################################################################
407 InputStreamReader::InputStreamReader(const InputStream &inputStreamSource)
408 : inputStream((InputStream &)inputStreamSource)
409 {
410 }
414 /**
415 * Close the underlying OutputStream
416 */
417 void InputStreamReader::close()
418 {
419 inputStream.close();
420 }
422 /**
423 * Flush the underlying OutputStream
424 */
425 int InputStreamReader::available()
426 {
427 return inputStream.available();
428 }
430 /**
431 * Overloaded to receive its bytes from an InputStream
432 * rather than a Reader
433 */
434 int InputStreamReader::get()
435 {
436 //Do we need conversions here?
437 int ch = (XMLCh)inputStream.get();
438 return ch;
439 }
443 //#########################################################################
444 //# S T D R E A D E R
445 //#########################################################################
448 /**
449 *
450 */
451 StdReader::StdReader()
452 {
453 inputStream = new StdInputStream();
454 }
456 /**
457 *
458 */
459 StdReader::~StdReader()
460 {
461 delete inputStream;
462 }
466 /**
467 * Close the underlying OutputStream
468 */
469 void StdReader::close()
470 {
471 inputStream->close();
472 }
474 /**
475 * Flush the underlying OutputStream
476 */
477 int StdReader::available()
478 {
479 return inputStream->available();
480 }
482 /**
483 * Overloaded to receive its bytes from an InputStream
484 * rather than a Reader
485 */
486 int StdReader::get()
487 {
488 //Do we need conversions here?
489 XMLCh ch = (XMLCh)inputStream->get();
490 return ch;
491 }
497 //#########################################################################
498 //# B A S I C W R I T E R
499 //#########################################################################
501 /**
502 *
503 */
504 BasicWriter::BasicWriter(const Writer &destinationWriter)
505 {
506 destination = (Writer *)&destinationWriter;
507 }
509 /**
510 * Closes this writer and releases any system resources
511 * associated with this writer.
512 */
513 void BasicWriter::close()
514 {
515 if (destination)
516 destination->close();
517 }
519 /**
520 * Flushes this output stream and forces any buffered output
521 * bytes to be written out.
522 */
523 void BasicWriter::flush()
524 {
525 if (destination)
526 destination->flush();
527 }
529 /**
530 * Writes the specified byte to this output writer.
531 */
532 void BasicWriter::put(XMLCh ch)
533 {
534 if (destination)
535 destination->put(ch);
536 }
538 /**
539 * Provide printf()-like formatting
540 */
541 Writer &BasicWriter::printf(char *fmt, ...)
542 {
543 va_list args;
544 va_start(args, fmt);
545 //replace this wish vsnprintf()
546 char buf[256];
547 vsnprintf(buf, 255, fmt, args);
548 va_end(args);
549 if (buf) {
550 writeString(buf);
551 //free(buf);
552 }
553 return *this;
554 }
555 /**
556 * Writes the specified character to this output writer.
557 */
558 Writer &BasicWriter::writeChar(char ch)
559 {
560 XMLCh uch = ch;
561 put(uch);
562 return *this;
563 }
566 /**
567 * Writes the specified standard string to this output writer.
568 */
569 Writer &BasicWriter::writeString(const DOMString &str)
570 {
571 for (int i=0; i< (int)str.size(); i++)
572 put(str[i]);
573 return *this;
574 }
577 /**
578 *
579 */
580 Writer &BasicWriter::writeBool (bool val )
581 {
582 if (val)
583 writeString("true");
584 else
585 writeString("false");
586 return *this;
587 }
590 /**
591 *
592 */
593 Writer &BasicWriter::writeShort (short val )
594 {
595 char buf[32];
596 snprintf(buf, 31, "%d", val);
597 writeString(buf);
598 return *this;
599 }
603 /**
604 *
605 */
606 Writer &BasicWriter::writeUnsignedShort (unsigned short val )
607 {
608 char buf[32];
609 snprintf(buf, 31, "%u", val);
610 writeString(buf);
611 return *this;
612 }
614 /**
615 *
616 */
617 Writer &BasicWriter::writeInt (int val)
618 {
619 char buf[32];
620 snprintf(buf, 31, "%d", val);
621 writeString(buf);
622 return *this;
623 }
625 /**
626 *
627 */
628 Writer &BasicWriter::writeUnsignedInt (unsigned int val)
629 {
630 char buf[32];
631 snprintf(buf, 31, "%u", val);
632 writeString(buf);
633 return *this;
634 }
636 /**
637 *
638 */
639 Writer &BasicWriter::writeLong (long val)
640 {
641 char buf[32];
642 snprintf(buf, 31, "%ld", val);
643 writeString(buf);
644 return *this;
645 }
647 /**
648 *
649 */
650 Writer &BasicWriter::writeUnsignedLong(unsigned long val)
651 {
652 char buf[32];
653 snprintf(buf, 31, "%lu", val);
654 writeString(buf);
655 return *this;
656 }
658 /**
659 *
660 */
661 Writer &BasicWriter::writeFloat(float val)
662 {
663 char buf[32];
664 snprintf(buf, 31, "%8.3f", val);
665 writeString(buf);
666 return *this;
667 }
669 /**
670 *
671 */
672 Writer &BasicWriter::writeDouble(double val)
673 {
674 char buf[32];
675 snprintf(buf, 31, "%8.3f", val);
676 writeString(buf);
677 return *this;
678 }
683 //#########################################################################
684 //# O U T P U T S T R E A M W R I T E R
685 //#########################################################################
688 OutputStreamWriter::OutputStreamWriter(OutputStream &outputStreamDest)
689 : outputStream(outputStreamDest)
690 {
691 }
695 /**
696 * Close the underlying OutputStream
697 */
698 void OutputStreamWriter::close()
699 {
700 flush();
701 outputStream.close();
702 }
704 /**
705 * Flush the underlying OutputStream
706 */
707 void OutputStreamWriter::flush()
708 {
709 outputStream.flush();
710 }
712 /**
713 * Overloaded to redirect the output chars from the next Writer
714 * in the chain to an OutputStream instead.
715 */
716 void OutputStreamWriter::put(XMLCh ch)
717 {
718 //Do we need conversions here?
719 int intCh = (int) ch;
720 outputStream.put(intCh);
721 }
723 //#########################################################################
724 //# S T D W R I T E R
725 //#########################################################################
728 /**
729 *
730 */
731 StdWriter::StdWriter()
732 {
733 outputStream = new StdOutputStream();
734 }
737 /**
738 *
739 */
740 StdWriter::~StdWriter()
741 {
742 delete outputStream;
743 }
747 /**
748 * Close the underlying OutputStream
749 */
750 void StdWriter::close()
751 {
752 flush();
753 outputStream->close();
754 }
756 /**
757 * Flush the underlying OutputStream
758 */
759 void StdWriter::flush()
760 {
761 outputStream->flush();
762 }
764 /**
765 * Overloaded to redirect the output chars from the next Writer
766 * in the chain to an OutputStream instead.
767 */
768 void StdWriter::put(XMLCh ch)
769 {
770 //Do we need conversions here?
771 int intCh = (int) ch;
772 outputStream->put(intCh);
773 }
786 //###############################################
787 //# O P E R A T O R S
788 //###############################################
789 //# Normally these would be in the .h, but we
790 //# just want to be absolutely certain that these
791 //# are never multiply defined. Easy to maintain,
792 //# though. Just occasionally copy/paste these
793 //# into the .h , and replace the {} with a ;
794 //###############################################
799 Reader& operator>> (Reader &reader, bool& val )
800 { return reader.readBool(val); }
802 Reader& operator>> (Reader &reader, short &val)
803 { return reader.readShort(val); }
805 Reader& operator>> (Reader &reader, unsigned short &val)
806 { return reader.readUnsignedShort(val); }
808 Reader& operator>> (Reader &reader, int &val)
809 { return reader.readInt(val); }
811 Reader& operator>> (Reader &reader, unsigned int &val)
812 { return reader.readUnsignedInt(val); }
814 Reader& operator>> (Reader &reader, long &val)
815 { return reader.readLong(val); }
817 Reader& operator>> (Reader &reader, unsigned long &val)
818 { return reader.readUnsignedLong(val); }
820 Reader& operator>> (Reader &reader, float &val)
821 { return reader.readFloat(val); }
823 Reader& operator>> (Reader &reader, double &val)
824 { return reader.readDouble(val); }
829 Writer& operator<< (Writer &writer, char val)
830 { return writer.writeChar(val); }
832 Writer& operator<< (Writer &writer, const DOMString &val)
833 { return writer.writeString(val); }
835 Writer& operator<< (Writer &writer, bool val)
836 { return writer.writeBool(val); }
838 Writer& operator<< (Writer &writer, short val)
839 { return writer.writeShort(val); }
841 Writer& operator<< (Writer &writer, unsigned short val)
842 { return writer.writeUnsignedShort(val); }
844 Writer& operator<< (Writer &writer, int val)
845 { return writer.writeInt(val); }
847 Writer& operator<< (Writer &writer, unsigned int val)
848 { return writer.writeUnsignedInt(val); }
850 Writer& operator<< (Writer &writer, long val)
851 { return writer.writeLong(val); }
853 Writer& operator<< (Writer &writer, unsigned long val)
854 { return writer.writeUnsignedLong(val); }
856 Writer& operator<< (Writer &writer, float val)
857 { return writer.writeFloat(val); }
859 Writer& operator<< (Writer &writer, double val)
860 { return writer.writeDouble(val); }
864 } //namespace io
865 } //namespace dom
866 } //namespace w3c
867 } //namespace org
870 //#########################################################################
871 //# E N D O F F I L E
872 //#########################################################################