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"
46 #include "charclass.h"
48 namespace org
49 {
50 namespace w3c
51 {
52 namespace dom
53 {
56 //#########################################################################
57 //# U T I L I T Y
58 //#########################################################################
60 void pipeStream(InputStream &source, OutputStream &dest)
61 {
62 for (;;)
63 {
64 int ch = source.get();
65 if (ch<0)
66 break;
67 dest.put(ch);
68 }
69 dest.flush();
70 }
72 //#########################################################################
73 //# B A S I C I N P U T S T R E A M
74 //#########################################################################
77 /**
78 *
79 */
80 BasicInputStream::BasicInputStream(const InputStream &sourceStream)
81 : source((InputStream &)sourceStream)
82 {
83 closed = false;
84 }
86 /**
87 * Returns the number of bytes that can be read (or skipped over) from
88 * this input stream without blocking by the next caller of a method for
89 * this input stream.
90 */
91 int BasicInputStream::available()
92 {
93 if (closed)
94 return 0;
95 return source.available();
96 }
99 /**
100 * Closes this input stream and releases any system resources
101 * associated with the stream.
102 */
103 void BasicInputStream::close()
104 {
105 if (closed)
106 return;
107 source.close();
108 closed = true;
109 }
111 /**
112 * Reads the next byte of data from the input stream. -1 if EOF
113 */
114 int BasicInputStream::get()
115 {
116 if (closed)
117 return -1;
118 return source.get();
119 }
123 //#########################################################################
124 //# B A S I C O U T P U T S T R E A M
125 //#########################################################################
127 /**
128 *
129 */
130 BasicOutputStream::BasicOutputStream(const OutputStream &destinationStream)
131 : destination((OutputStream &)destinationStream)
132 {
133 closed = false;
134 }
136 /**
137 * Closes this output stream and releases any system resources
138 * associated with this stream.
139 */
140 void BasicOutputStream::close()
141 {
142 if (closed)
143 return;
144 destination.close();
145 closed = true;
146 }
148 /**
149 * Flushes this output stream and forces any buffered output
150 * bytes to be written out.
151 */
152 void BasicOutputStream::flush()
153 {
154 if (closed)
155 return;
156 destination.flush();
157 }
159 /**
160 * Writes the specified byte to this output stream.
161 */
162 void BasicOutputStream::put(XMLCh ch)
163 {
164 if (closed)
165 return;
166 destination.put(ch);
167 }
171 //#########################################################################
172 //# B A S I C R E A D E R
173 //#########################################################################
176 /**
177 *
178 */
179 BasicReader::BasicReader(Reader &sourceReader)
180 {
181 source = &sourceReader;
182 }
184 /**
185 * Returns the number of bytes that can be read (or skipped over) from
186 * this reader without blocking by the next caller of a method for
187 * this reader.
188 */
189 int BasicReader::available()
190 {
191 if (source)
192 return source->available();
193 else
194 return 0;
195 }
198 /**
199 * Closes this reader and releases any system resources
200 * associated with the reader.
201 */
202 void BasicReader::close()
203 {
204 if (source)
205 source->close();
206 }
208 /**
209 * Reads the next byte of data from the reader.
210 */
211 int BasicReader::get()
212 {
213 if (source)
214 return source->get();
215 else
216 return -1;
217 }
224 /**
225 * Reads a line of data from the reader.
226 */
227 DOMString BasicReader::readLine()
228 {
229 DOMString str;
230 while (available() > 0)
231 {
232 XMLCh ch = get();
233 if (ch == '\n')
234 break;
235 str.push_back(ch);
236 }
237 return str;
238 }
240 /**
241 * Reads a line of data from the reader.
242 */
243 DOMString BasicReader::readWord()
244 {
245 DOMString str;
246 while (available() > 0)
247 {
248 XMLCh ch = get();
249 if (isWhitespace(ch))
250 break;
251 str.push_back(ch);
252 }
253 return str;
254 }
257 static bool getLong(DOMString &str, long *val)
258 {
259 const char *begin = str.c_str();
260 char *end;
261 long ival = strtol(begin, &end, 10);
262 if (str == end)
263 return false;
264 *val = ival;
265 return true;
266 }
268 static bool getULong(const DOMString &str, unsigned long *val)
269 {
270 DOMString tmp = str;
271 char *begin = (char *)tmp.c_str();
272 char *end;
273 unsigned long ival = strtoul(begin, &end, 10);
274 if (begin == end)
275 return false;
276 *val = ival;
277 return true;
278 }
280 static bool getDouble(const DOMString &str, double *val)
281 {
282 DOMString tmp = str;
283 const char *begin = tmp.c_str();
284 char *end;
285 double ival = strtod(begin, &end);
286 if (begin == end)
287 return false;
288 *val = ival;
289 return true;
290 }
295 /**
296 *
297 */
298 Reader &BasicReader::readBool (bool& val )
299 {
300 DOMString buf = readWord();
301 if (buf == "true")
302 val = true;
303 else
304 val = false;
305 return *this;
306 }
308 /**
309 *
310 */
311 Reader &BasicReader::readShort (short& val )
312 {
313 DOMString buf = readWord();
314 long ival;
315 if (getLong(buf, &ival))
316 val = (short) ival;
317 return *this;
318 }
320 /**
321 *
322 */
323 Reader &BasicReader::readUnsignedShort (unsigned short& val )
324 {
325 DOMString buf = readWord();
326 unsigned long ival;
327 if (getULong(buf, &ival))
328 val = (unsigned short) ival;
329 return *this;
330 }
332 /**
333 *
334 */
335 Reader &BasicReader::readInt (int& val )
336 {
337 DOMString buf = readWord();
338 long ival;
339 if (getLong(buf, &ival))
340 val = (int) ival;
341 return *this;
342 }
344 /**
345 *
346 */
347 Reader &BasicReader::readUnsignedInt (unsigned int& val )
348 {
349 DOMString buf = readWord();
350 unsigned long ival;
351 if (getULong(buf, &ival))
352 val = (unsigned int) ival;
353 return *this;
354 }
356 /**
357 *
358 */
359 Reader &BasicReader::readLong (long& val )
360 {
361 DOMString buf = readWord();
362 long ival;
363 if (getLong(buf, &ival))
364 val = ival;
365 return *this;
366 }
368 /**
369 *
370 */
371 Reader &BasicReader::readUnsignedLong (unsigned long& val )
372 {
373 DOMString buf = readWord();
374 unsigned long ival;
375 if (getULong(buf, &ival))
376 val = ival;
377 return *this;
378 }
380 /**
381 *
382 */
383 Reader &BasicReader::readFloat (float& val )
384 {
385 DOMString buf = readWord();
386 double ival;
387 if (getDouble(buf, &ival))
388 val = (float)ival;
389 return *this;
390 }
392 /**
393 *
394 */
395 Reader &BasicReader::readDouble (double& val )
396 {
397 DOMString buf = readWord();
398 double ival;
399 if (getDouble(buf, &ival))
400 val = ival;
401 return *this;
402 }
406 //#########################################################################
407 //# I N P U T S T R E A M R E A D E R
408 //#########################################################################
411 InputStreamReader::InputStreamReader(const InputStream &inputStreamSource)
412 : inputStream((InputStream &)inputStreamSource)
413 {
414 }
418 /**
419 * Close the underlying OutputStream
420 */
421 void InputStreamReader::close()
422 {
423 inputStream.close();
424 }
426 /**
427 * Flush the underlying OutputStream
428 */
429 int InputStreamReader::available()
430 {
431 return inputStream.available();
432 }
434 /**
435 * Overloaded to receive its bytes from an InputStream
436 * rather than a Reader
437 */
438 int InputStreamReader::get()
439 {
440 //Do we need conversions here?
441 int ch = (XMLCh)inputStream.get();
442 return ch;
443 }
447 //#########################################################################
448 //# S T D R E A D E R
449 //#########################################################################
452 /**
453 *
454 */
455 StdReader::StdReader()
456 {
457 inputStream = new StdInputStream();
458 }
460 /**
461 *
462 */
463 StdReader::~StdReader()
464 {
465 delete inputStream;
466 }
470 /**
471 * Close the underlying OutputStream
472 */
473 void StdReader::close()
474 {
475 inputStream->close();
476 }
478 /**
479 * Flush the underlying OutputStream
480 */
481 int StdReader::available()
482 {
483 return inputStream->available();
484 }
486 /**
487 * Overloaded to receive its bytes from an InputStream
488 * rather than a Reader
489 */
490 int StdReader::get()
491 {
492 //Do we need conversions here?
493 XMLCh ch = (XMLCh)inputStream->get();
494 return ch;
495 }
501 //#########################################################################
502 //# B A S I C W R I T E R
503 //#########################################################################
505 /**
506 *
507 */
508 BasicWriter::BasicWriter(const Writer &destinationWriter)
509 {
510 destination = (Writer *)&destinationWriter;
511 }
513 /**
514 * Closes this writer and releases any system resources
515 * associated with this writer.
516 */
517 void BasicWriter::close()
518 {
519 if (destination)
520 destination->close();
521 }
523 /**
524 * Flushes this output stream and forces any buffered output
525 * bytes to be written out.
526 */
527 void BasicWriter::flush()
528 {
529 if (destination)
530 destination->flush();
531 }
533 /**
534 * Writes the specified byte to this output writer.
535 */
536 void BasicWriter::put(XMLCh ch)
537 {
538 if (destination)
539 destination->put(ch);
540 }
542 /**
543 * Provide printf()-like formatting
544 */
545 Writer &BasicWriter::printf(char *fmt, ...)
546 {
547 va_list args;
548 va_start(args, fmt);
549 //replace this wish vsnprintf()
550 char buf[256];
551 vsnprintf(buf, 255, fmt, args);
552 va_end(args);
553 if (buf) {
554 writeString(buf);
555 //free(buf);
556 }
557 return *this;
558 }
559 /**
560 * Writes the specified character to this output writer.
561 */
562 Writer &BasicWriter::writeChar(char ch)
563 {
564 XMLCh uch = ch;
565 put(uch);
566 return *this;
567 }
570 /**
571 * Writes the specified standard string to this output writer.
572 */
573 Writer &BasicWriter::writeString(const DOMString &str)
574 {
575 for (int i=0; i< (int)str.size(); i++)
576 put(str[i]);
577 return *this;
578 }
581 /**
582 *
583 */
584 Writer &BasicWriter::writeBool (bool val )
585 {
586 if (val)
587 writeString("true");
588 else
589 writeString("false");
590 return *this;
591 }
594 /**
595 *
596 */
597 Writer &BasicWriter::writeShort (short val )
598 {
599 char buf[32];
600 snprintf(buf, 31, "%d", val);
601 writeString(buf);
602 return *this;
603 }
607 /**
608 *
609 */
610 Writer &BasicWriter::writeUnsignedShort (unsigned short val )
611 {
612 char buf[32];
613 snprintf(buf, 31, "%u", val);
614 writeString(buf);
615 return *this;
616 }
618 /**
619 *
620 */
621 Writer &BasicWriter::writeInt (int val)
622 {
623 char buf[32];
624 snprintf(buf, 31, "%d", val);
625 writeString(buf);
626 return *this;
627 }
629 /**
630 *
631 */
632 Writer &BasicWriter::writeUnsignedInt (unsigned int val)
633 {
634 char buf[32];
635 snprintf(buf, 31, "%u", val);
636 writeString(buf);
637 return *this;
638 }
640 /**
641 *
642 */
643 Writer &BasicWriter::writeLong (long val)
644 {
645 char buf[32];
646 snprintf(buf, 31, "%ld", val);
647 writeString(buf);
648 return *this;
649 }
651 /**
652 *
653 */
654 Writer &BasicWriter::writeUnsignedLong(unsigned long val)
655 {
656 char buf[32];
657 snprintf(buf, 31, "%lu", val);
658 writeString(buf);
659 return *this;
660 }
662 /**
663 *
664 */
665 Writer &BasicWriter::writeFloat(float val)
666 {
667 char buf[32];
668 snprintf(buf, 31, "%8.3f", val);
669 writeString(buf);
670 return *this;
671 }
673 /**
674 *
675 */
676 Writer &BasicWriter::writeDouble(double val)
677 {
678 char buf[32];
679 snprintf(buf, 31, "%8.3f", val);
680 writeString(buf);
681 return *this;
682 }
687 //#########################################################################
688 //# O U T P U T S T R E A M W R I T E R
689 //#########################################################################
692 OutputStreamWriter::OutputStreamWriter(OutputStream &outputStreamDest)
693 : outputStream(outputStreamDest)
694 {
695 }
699 /**
700 * Close the underlying OutputStream
701 */
702 void OutputStreamWriter::close()
703 {
704 flush();
705 outputStream.close();
706 }
708 /**
709 * Flush the underlying OutputStream
710 */
711 void OutputStreamWriter::flush()
712 {
713 outputStream.flush();
714 }
716 /**
717 * Overloaded to redirect the output chars from the next Writer
718 * in the chain to an OutputStream instead.
719 */
720 void OutputStreamWriter::put(XMLCh ch)
721 {
722 //Do we need conversions here?
723 int intCh = (int) ch;
724 outputStream.put(intCh);
725 }
727 //#########################################################################
728 //# S T D W R I T E R
729 //#########################################################################
732 /**
733 *
734 */
735 StdWriter::StdWriter()
736 {
737 outputStream = new StdOutputStream();
738 }
741 /**
742 *
743 */
744 StdWriter::~StdWriter()
745 {
746 delete outputStream;
747 }
751 /**
752 * Close the underlying OutputStream
753 */
754 void StdWriter::close()
755 {
756 flush();
757 outputStream->close();
758 }
760 /**
761 * Flush the underlying OutputStream
762 */
763 void StdWriter::flush()
764 {
765 outputStream->flush();
766 }
768 /**
769 * Overloaded to redirect the output chars from the next Writer
770 * in the chain to an OutputStream instead.
771 */
772 void StdWriter::put(XMLCh ch)
773 {
774 //Do we need conversions here?
775 int intCh = (int) ch;
776 outputStream->put(intCh);
777 }
790 //###############################################
791 //# O P E R A T O R S
792 //###############################################
793 //# Normally these would be in the .h, but we
794 //# just want to be absolutely certain that these
795 //# are never multiply defined. Easy to maintain,
796 //# though. Just occasionally copy/paste these
797 //# into the .h , and replace the {} with a ;
798 //###############################################
803 Reader& operator>> (Reader &reader, bool& val )
804 { return reader.readBool(val); }
806 Reader& operator>> (Reader &reader, short &val)
807 { return reader.readShort(val); }
809 Reader& operator>> (Reader &reader, unsigned short &val)
810 { return reader.readUnsignedShort(val); }
812 Reader& operator>> (Reader &reader, int &val)
813 { return reader.readInt(val); }
815 Reader& operator>> (Reader &reader, unsigned int &val)
816 { return reader.readUnsignedInt(val); }
818 Reader& operator>> (Reader &reader, long &val)
819 { return reader.readLong(val); }
821 Reader& operator>> (Reader &reader, unsigned long &val)
822 { return reader.readUnsignedLong(val); }
824 Reader& operator>> (Reader &reader, float &val)
825 { return reader.readFloat(val); }
827 Reader& operator>> (Reader &reader, double &val)
828 { return reader.readDouble(val); }
833 Writer& operator<< (Writer &writer, char val)
834 { return writer.writeChar(val); }
836 Writer& operator<< (Writer &writer, const DOMString &val)
837 { return writer.writeString(val); }
839 Writer& operator<< (Writer &writer, bool val)
840 { return writer.writeBool(val); }
842 Writer& operator<< (Writer &writer, short val)
843 { return writer.writeShort(val); }
845 Writer& operator<< (Writer &writer, unsigned short val)
846 { return writer.writeUnsignedShort(val); }
848 Writer& operator<< (Writer &writer, int val)
849 { return writer.writeInt(val); }
851 Writer& operator<< (Writer &writer, unsigned int val)
852 { return writer.writeUnsignedInt(val); }
854 Writer& operator<< (Writer &writer, long val)
855 { return writer.writeLong(val); }
857 Writer& operator<< (Writer &writer, unsigned long val)
858 { return writer.writeUnsignedLong(val); }
860 Writer& operator<< (Writer &writer, float val)
861 { return writer.writeFloat(val); }
863 Writer& operator<< (Writer &writer, double val)
864 { return writer.writeDouble(val); }
868 } //namespace dom
869 } //namespace w3c
870 } //namespace org
873 //#########################################################################
874 //# E N D O F F I L E
875 //#########################################################################