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) 2005 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 * Authors:
36 * Bob Jamison <rjamison@titan.com>
37 *
38 * Copyright (C) 2004 Inkscape.org
39 *
40 * Released under GNU GPL, read the file 'COPYING' for more information
41 */
43 #include <stdarg.h>
45 #include "domstream.h"
47 namespace org
48 {
49 namespace w3c
50 {
51 namespace dom
52 {
55 //#########################################################################
56 //# U T I L I T Y
57 //#########################################################################
59 void pipeStream(InputStream &source, OutputStream &dest)
60 {
61 for (;;)
62 {
63 int ch = source.get();
64 if (ch<0)
65 break;
66 dest.put(ch);
67 }
68 dest.flush();
69 }
71 //#########################################################################
72 //# B A S I C I N P U T S T R E A M
73 //#########################################################################
76 /**
77 *
78 */
79 BasicInputStream::BasicInputStream(const InputStream &sourceStream)
80 : source((InputStream &)sourceStream)
81 {
82 closed = false;
83 }
85 /**
86 * Returns the number of bytes that can be read (or skipped over) from
87 * this input stream without blocking by the next caller of a method for
88 * this input stream.
89 */
90 int BasicInputStream::available()
91 {
92 if (closed)
93 return 0;
94 return source.available();
95 }
98 /**
99 * Closes this input stream and releases any system resources
100 * associated with the stream.
101 */
102 void BasicInputStream::close()
103 {
104 if (closed)
105 return;
106 source.close();
107 closed = true;
108 }
110 /**
111 * Reads the next byte of data from the input stream. -1 if EOF
112 */
113 int BasicInputStream::get()
114 {
115 if (closed)
116 return -1;
117 return source.get();
118 }
122 //#########################################################################
123 //# B A S I C O U T P U T S T R E A M
124 //#########################################################################
126 /**
127 *
128 */
129 BasicOutputStream::BasicOutputStream(const OutputStream &destinationStream)
130 : destination((OutputStream &)destinationStream)
131 {
132 closed = false;
133 }
135 /**
136 * Closes this output stream and releases any system resources
137 * associated with this stream.
138 */
139 void BasicOutputStream::close()
140 {
141 if (closed)
142 return;
143 destination.close();
144 closed = true;
145 }
147 /**
148 * Flushes this output stream and forces any buffered output
149 * bytes to be written out.
150 */
151 void BasicOutputStream::flush()
152 {
153 if (closed)
154 return;
155 destination.flush();
156 }
158 /**
159 * Writes the specified byte to this output stream.
160 */
161 void BasicOutputStream::put(XMLCh ch)
162 {
163 if (closed)
164 return;
165 destination.put(ch);
166 }
170 //#########################################################################
171 //# B A S I C R E A D E R
172 //#########################################################################
175 /**
176 *
177 */
178 BasicReader::BasicReader(Reader &sourceReader)
179 {
180 source = &sourceReader;
181 }
183 /**
184 * Returns the number of bytes that can be read (or skipped over) from
185 * this reader without blocking by the next caller of a method for
186 * this reader.
187 */
188 int BasicReader::available()
189 {
190 if (source)
191 return source->available();
192 else
193 return 0;
194 }
197 /**
198 * Closes this reader and releases any system resources
199 * associated with the reader.
200 */
201 void BasicReader::close()
202 {
203 if (source)
204 source->close();
205 }
207 /**
208 * Reads the next byte of data from the reader.
209 */
210 int BasicReader::get()
211 {
212 if (source)
213 return source->get();
214 else
215 return -1;
216 }
223 /**
224 * Reads a line of data from the reader.
225 */
226 DOMString BasicReader::readLine()
227 {
228 DOMString str;
229 while (available() > 0)
230 {
231 XMLCh ch = get();
232 if (ch == '\n')
233 break;
234 str.push_back(ch);
235 }
236 return str;
237 }
239 /**
240 * Reads a line of data from the reader.
241 */
242 DOMString BasicReader::readWord()
243 {
244 DOMString str;
245 while (available() > 0)
246 {
247 XMLCh ch = get();
248 if (!isprint(ch))
249 break;
250 str.push_back(ch);
251 }
252 return str;
253 }
256 static bool getLong(DOMString &str, long *val)
257 {
258 const char *begin = str.c_str();
259 char *end;
260 long ival = strtol(begin, &end, 10);
261 if (str == end)
262 return false;
263 *val = ival;
264 return true;
265 }
267 static bool getULong(const DOMString &str, unsigned long *val)
268 {
269 DOMString tmp = str;
270 char *begin = (char *)tmp.c_str();
271 char *end;
272 unsigned long ival = strtoul(begin, &end, 10);
273 if (begin == end)
274 return false;
275 *val = ival;
276 return true;
277 }
279 static bool getDouble(const DOMString &str, double *val)
280 {
281 DOMString tmp = str;
282 const char *begin = tmp.c_str();
283 char *end;
284 double ival = strtod(begin, &end);
285 if (begin == end)
286 return false;
287 *val = ival;
288 return true;
289 }
294 /**
295 *
296 */
297 Reader &BasicReader::readBool (bool& val )
298 {
299 DOMString buf = readWord();
300 if (buf == "true")
301 val = true;
302 else
303 val = false;
304 return *this;
305 }
307 /**
308 *
309 */
310 Reader &BasicReader::readShort (short& val )
311 {
312 DOMString buf = readWord();
313 long ival;
314 if (getLong(buf, &ival))
315 val = (short) ival;
316 return *this;
317 }
319 /**
320 *
321 */
322 Reader &BasicReader::readUnsignedShort (unsigned short& val )
323 {
324 DOMString buf = readWord();
325 unsigned long ival;
326 if (getULong(buf, &ival))
327 val = (unsigned short) ival;
328 return *this;
329 }
331 /**
332 *
333 */
334 Reader &BasicReader::readInt (int& val )
335 {
336 DOMString buf = readWord();
337 long ival;
338 if (getLong(buf, &ival))
339 val = (int) ival;
340 return *this;
341 }
343 /**
344 *
345 */
346 Reader &BasicReader::readUnsignedInt (unsigned int& val )
347 {
348 DOMString buf = readWord();
349 unsigned long ival;
350 if (getULong(buf, &ival))
351 val = (unsigned int) ival;
352 return *this;
353 }
355 /**
356 *
357 */
358 Reader &BasicReader::readLong (long& val )
359 {
360 DOMString buf = readWord();
361 long ival;
362 if (getLong(buf, &ival))
363 val = ival;
364 return *this;
365 }
367 /**
368 *
369 */
370 Reader &BasicReader::readUnsignedLong (unsigned long& val )
371 {
372 DOMString buf = readWord();
373 unsigned long ival;
374 if (getULong(buf, &ival))
375 val = ival;
376 return *this;
377 }
379 /**
380 *
381 */
382 Reader &BasicReader::readFloat (float& val )
383 {
384 DOMString buf = readWord();
385 double ival;
386 if (getDouble(buf, &ival))
387 val = (float)ival;
388 return *this;
389 }
391 /**
392 *
393 */
394 Reader &BasicReader::readDouble (double& val )
395 {
396 DOMString buf = readWord();
397 double ival;
398 if (getDouble(buf, &ival))
399 val = ival;
400 return *this;
401 }
405 //#########################################################################
406 //# I N P U T S T R E A M R E A D E R
407 //#########################################################################
410 InputStreamReader::InputStreamReader(const InputStream &inputStreamSource)
411 : inputStream((InputStream &)inputStreamSource)
412 {
413 }
417 /**
418 * Close the underlying OutputStream
419 */
420 void InputStreamReader::close()
421 {
422 inputStream.close();
423 }
425 /**
426 * Flush the underlying OutputStream
427 */
428 int InputStreamReader::available()
429 {
430 return inputStream.available();
431 }
433 /**
434 * Overloaded to receive its bytes from an InputStream
435 * rather than a Reader
436 */
437 int InputStreamReader::get()
438 {
439 //Do we need conversions here?
440 int ch = (XMLCh)inputStream.get();
441 return ch;
442 }
446 //#########################################################################
447 //# S T D R E A D E R
448 //#########################################################################
451 /**
452 *
453 */
454 StdReader::StdReader()
455 {
456 inputStream = new StdInputStream();
457 }
459 /**
460 *
461 */
462 StdReader::~StdReader()
463 {
464 delete inputStream;
465 }
469 /**
470 * Close the underlying OutputStream
471 */
472 void StdReader::close()
473 {
474 inputStream->close();
475 }
477 /**
478 * Flush the underlying OutputStream
479 */
480 int StdReader::available()
481 {
482 return inputStream->available();
483 }
485 /**
486 * Overloaded to receive its bytes from an InputStream
487 * rather than a Reader
488 */
489 int StdReader::get()
490 {
491 //Do we need conversions here?
492 XMLCh ch = (XMLCh)inputStream->get();
493 return ch;
494 }
500 //#########################################################################
501 //# B A S I C W R I T E R
502 //#########################################################################
504 /**
505 *
506 */
507 BasicWriter::BasicWriter(const Writer &destinationWriter)
508 {
509 destination = (Writer *)&destinationWriter;
510 }
512 /**
513 * Closes this writer and releases any system resources
514 * associated with this writer.
515 */
516 void BasicWriter::close()
517 {
518 if (destination)
519 destination->close();
520 }
522 /**
523 * Flushes this output stream and forces any buffered output
524 * bytes to be written out.
525 */
526 void BasicWriter::flush()
527 {
528 if (destination)
529 destination->flush();
530 }
532 /**
533 * Writes the specified byte to this output writer.
534 */
535 void BasicWriter::put(XMLCh ch)
536 {
537 if (destination)
538 destination->put(ch);
539 }
541 /**
542 * Provide printf()-like formatting
543 */
544 Writer &BasicWriter::printf(char *fmt, ...)
545 {
546 va_list args;
547 va_start(args, fmt);
548 //replace this wish vsnprintf()
549 char buf[256];
550 vsnprintf(buf, 255, fmt, args);
551 va_end(args);
552 if (buf) {
553 writeString(buf);
554 //free(buf);
555 }
556 return *this;
557 }
558 /**
559 * Writes the specified character to this output writer.
560 */
561 Writer &BasicWriter::writeChar(char ch)
562 {
563 XMLCh uch = ch;
564 put(uch);
565 return *this;
566 }
569 /**
570 * Writes the specified standard string to this output writer.
571 */
572 Writer &BasicWriter::writeString(const DOMString &str)
573 {
574 for (int i=0; i< (int)str.size(); i++)
575 put(str[i]);
576 return *this;
577 }
580 /**
581 *
582 */
583 Writer &BasicWriter::writeBool (bool val )
584 {
585 if (val)
586 writeString("true");
587 else
588 writeString("false");
589 return *this;
590 }
593 /**
594 *
595 */
596 Writer &BasicWriter::writeShort (short val )
597 {
598 char buf[32];
599 snprintf(buf, 31, "%d", val);
600 writeString(buf);
601 return *this;
602 }
606 /**
607 *
608 */
609 Writer &BasicWriter::writeUnsignedShort (unsigned short val )
610 {
611 char buf[32];
612 snprintf(buf, 31, "%u", val);
613 writeString(buf);
614 return *this;
615 }
617 /**
618 *
619 */
620 Writer &BasicWriter::writeInt (int val)
621 {
622 char buf[32];
623 snprintf(buf, 31, "%d", val);
624 writeString(buf);
625 return *this;
626 }
628 /**
629 *
630 */
631 Writer &BasicWriter::writeUnsignedInt (unsigned int val)
632 {
633 char buf[32];
634 snprintf(buf, 31, "%u", val);
635 writeString(buf);
636 return *this;
637 }
639 /**
640 *
641 */
642 Writer &BasicWriter::writeLong (long val)
643 {
644 char buf[32];
645 snprintf(buf, 31, "%ld", val);
646 writeString(buf);
647 return *this;
648 }
650 /**
651 *
652 */
653 Writer &BasicWriter::writeUnsignedLong(unsigned long val)
654 {
655 char buf[32];
656 snprintf(buf, 31, "%lu", val);
657 writeString(buf);
658 return *this;
659 }
661 /**
662 *
663 */
664 Writer &BasicWriter::writeFloat(float val)
665 {
666 char buf[32];
667 snprintf(buf, 31, "%8.3f", val);
668 writeString(buf);
669 return *this;
670 }
672 /**
673 *
674 */
675 Writer &BasicWriter::writeDouble(double val)
676 {
677 char buf[32];
678 snprintf(buf, 31, "%8.3f", val);
679 writeString(buf);
680 return *this;
681 }
686 //#########################################################################
687 //# O U T P U T S T R E A M W R I T E R
688 //#########################################################################
691 OutputStreamWriter::OutputStreamWriter(OutputStream &outputStreamDest)
692 : outputStream(outputStreamDest)
693 {
694 }
698 /**
699 * Close the underlying OutputStream
700 */
701 void OutputStreamWriter::close()
702 {
703 flush();
704 outputStream.close();
705 }
707 /**
708 * Flush the underlying OutputStream
709 */
710 void OutputStreamWriter::flush()
711 {
712 outputStream.flush();
713 }
715 /**
716 * Overloaded to redirect the output chars from the next Writer
717 * in the chain to an OutputStream instead.
718 */
719 void OutputStreamWriter::put(XMLCh ch)
720 {
721 //Do we need conversions here?
722 int intCh = (int) ch;
723 outputStream.put(intCh);
724 }
726 //#########################################################################
727 //# S T D W R I T E R
728 //#########################################################################
731 /**
732 *
733 */
734 StdWriter::StdWriter()
735 {
736 outputStream = new StdOutputStream();
737 }
740 /**
741 *
742 */
743 StdWriter::~StdWriter()
744 {
745 delete outputStream;
746 }
750 /**
751 * Close the underlying OutputStream
752 */
753 void StdWriter::close()
754 {
755 flush();
756 outputStream->close();
757 }
759 /**
760 * Flush the underlying OutputStream
761 */
762 void StdWriter::flush()
763 {
764 outputStream->flush();
765 }
767 /**
768 * Overloaded to redirect the output chars from the next Writer
769 * in the chain to an OutputStream instead.
770 */
771 void StdWriter::put(XMLCh ch)
772 {
773 //Do we need conversions here?
774 int intCh = (int) ch;
775 outputStream->put(intCh);
776 }
789 //###############################################
790 //# O P E R A T O R S
791 //###############################################
792 //# Normally these would be in the .h, but we
793 //# just want to be absolutely certain that these
794 //# are never multiply defined. Easy to maintain,
795 //# though. Just occasionally copy/paste these
796 //# into the .h , and replace the {} with a ;
797 //###############################################
802 Reader& operator>> (Reader &reader, bool& val )
803 { return reader.readBool(val); }
805 Reader& operator>> (Reader &reader, short &val)
806 { return reader.readShort(val); }
808 Reader& operator>> (Reader &reader, unsigned short &val)
809 { return reader.readUnsignedShort(val); }
811 Reader& operator>> (Reader &reader, int &val)
812 { return reader.readInt(val); }
814 Reader& operator>> (Reader &reader, unsigned int &val)
815 { return reader.readUnsignedInt(val); }
817 Reader& operator>> (Reader &reader, long &val)
818 { return reader.readLong(val); }
820 Reader& operator>> (Reader &reader, unsigned long &val)
821 { return reader.readUnsignedLong(val); }
823 Reader& operator>> (Reader &reader, float &val)
824 { return reader.readFloat(val); }
826 Reader& operator>> (Reader &reader, double &val)
827 { return reader.readDouble(val); }
832 Writer& operator<< (Writer &writer, char val)
833 { return writer.writeChar(val); }
835 Writer& operator<< (Writer &writer, const DOMString &val)
836 { return writer.writeString(val); }
838 Writer& operator<< (Writer &writer, bool val)
839 { return writer.writeBool(val); }
841 Writer& operator<< (Writer &writer, short val)
842 { return writer.writeShort(val); }
844 Writer& operator<< (Writer &writer, unsigned short val)
845 { return writer.writeUnsignedShort(val); }
847 Writer& operator<< (Writer &writer, int val)
848 { return writer.writeInt(val); }
850 Writer& operator<< (Writer &writer, unsigned int val)
851 { return writer.writeUnsignedInt(val); }
853 Writer& operator<< (Writer &writer, long val)
854 { return writer.writeLong(val); }
856 Writer& operator<< (Writer &writer, unsigned long val)
857 { return writer.writeUnsignedLong(val); }
859 Writer& operator<< (Writer &writer, float val)
860 { return writer.writeFloat(val); }
862 Writer& operator<< (Writer &writer, double val)
863 { return writer.writeDouble(val); }
867 } //namespace dom
868 } //namespace w3c
869 } //namespace org
872 //#########################################################################
873 //# E N D O F F I L E
874 //#########################################################################