63257062f381a2f110ee54002138b470fd22540e
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 {
54 namespace io
55 {
58 //#########################################################################
59 //# U T I L I T Y
60 //#########################################################################
62 void pipeStream(InputStream &source, OutputStream &dest)
63 {
64 for (;;)
65 {
66 int ch = source.get();
67 if (ch<0)
68 break;
69 dest.put(ch);
70 }
71 dest.flush();
72 }
74 //#########################################################################
75 //# B A S I C I N P U T S T R E A M
76 //#########################################################################
79 /**
80 *
81 */
82 BasicInputStream::BasicInputStream(const InputStream &sourceStream)
83 : source((InputStream &)sourceStream)
84 {
85 closed = false;
86 }
88 /**
89 * Returns the number of bytes that can be read (or skipped over) from
90 * this input stream without blocking by the next caller of a method for
91 * this input stream.
92 */
93 int BasicInputStream::available()
94 {
95 if (closed)
96 return 0;
97 return source.available();
98 }
101 /**
102 * Closes this input stream and releases any system resources
103 * associated with the stream.
104 */
105 void BasicInputStream::close()
106 {
107 if (closed)
108 return;
109 source.close();
110 closed = true;
111 }
113 /**
114 * Reads the next byte of data from the input stream. -1 if EOF
115 */
116 int BasicInputStream::get()
117 {
118 if (closed)
119 return -1;
120 return source.get();
121 }
125 //#########################################################################
126 //# B A S I C O U T P U T S T R E A M
127 //#########################################################################
129 /**
130 *
131 */
132 BasicOutputStream::BasicOutputStream(const OutputStream &destinationStream)
133 : destination((OutputStream &)destinationStream)
134 {
135 closed = false;
136 }
138 /**
139 * Closes this output stream and releases any system resources
140 * associated with this stream.
141 */
142 void BasicOutputStream::close()
143 {
144 if (closed)
145 return;
146 destination.close();
147 closed = true;
148 }
150 /**
151 * Flushes this output stream and forces any buffered output
152 * bytes to be written out.
153 */
154 void BasicOutputStream::flush()
155 {
156 if (closed)
157 return;
158 destination.flush();
159 }
161 /**
162 * Writes the specified byte to this output stream.
163 */
164 void BasicOutputStream::put(XMLCh ch)
165 {
166 if (closed)
167 return;
168 destination.put(ch);
169 }
173 //#########################################################################
174 //# B A S I C R E A D E R
175 //#########################################################################
178 /**
179 *
180 */
181 BasicReader::BasicReader(Reader &sourceReader)
182 {
183 source = &sourceReader;
184 }
186 /**
187 * Returns the number of bytes that can be read (or skipped over) from
188 * this reader without blocking by the next caller of a method for
189 * this reader.
190 */
191 int BasicReader::available()
192 {
193 if (source)
194 return source->available();
195 else
196 return 0;
197 }
200 /**
201 * Closes this reader and releases any system resources
202 * associated with the reader.
203 */
204 void BasicReader::close()
205 {
206 if (source)
207 source->close();
208 }
210 /**
211 * Reads the next byte of data from the reader.
212 */
213 int BasicReader::get()
214 {
215 if (source)
216 return source->get();
217 else
218 return -1;
219 }
226 /**
227 * Reads a line of data from the reader.
228 */
229 DOMString BasicReader::readLine()
230 {
231 DOMString str;
232 while (available() > 0)
233 {
234 XMLCh ch = get();
235 if (ch == '\n')
236 break;
237 str.push_back(ch);
238 }
239 return str;
240 }
242 /**
243 * Reads a line of data from the reader.
244 */
245 DOMString BasicReader::readWord()
246 {
247 DOMString str;
248 while (available() > 0)
249 {
250 XMLCh ch = get();
251 if (isWhitespace(ch))
252 break;
253 str.push_back(ch);
254 }
255 return str;
256 }
259 static bool getLong(DOMString &str, long *val)
260 {
261 const char *begin = str.c_str();
262 char *end;
263 long ival = strtol(begin, &end, 10);
264 if (str == end)
265 return false;
266 *val = ival;
267 return true;
268 }
270 static bool getULong(const DOMString &str, unsigned long *val)
271 {
272 DOMString tmp = str;
273 char *begin = (char *)tmp.c_str();
274 char *end;
275 unsigned long ival = strtoul(begin, &end, 10);
276 if (begin == end)
277 return false;
278 *val = ival;
279 return true;
280 }
282 static bool getDouble(const DOMString &str, double *val)
283 {
284 DOMString tmp = str;
285 const char *begin = tmp.c_str();
286 char *end;
287 double ival = strtod(begin, &end);
288 if (begin == end)
289 return false;
290 *val = ival;
291 return true;
292 }
297 /**
298 *
299 */
300 Reader &BasicReader::readBool (bool& val )
301 {
302 DOMString buf = readWord();
303 if (buf == "true")
304 val = true;
305 else
306 val = false;
307 return *this;
308 }
310 /**
311 *
312 */
313 Reader &BasicReader::readShort (short& val )
314 {
315 DOMString buf = readWord();
316 long ival;
317 if (getLong(buf, &ival))
318 val = (short) ival;
319 return *this;
320 }
322 /**
323 *
324 */
325 Reader &BasicReader::readUnsignedShort (unsigned short& val )
326 {
327 DOMString buf = readWord();
328 unsigned long ival;
329 if (getULong(buf, &ival))
330 val = (unsigned short) ival;
331 return *this;
332 }
334 /**
335 *
336 */
337 Reader &BasicReader::readInt (int& val )
338 {
339 DOMString buf = readWord();
340 long ival;
341 if (getLong(buf, &ival))
342 val = (int) ival;
343 return *this;
344 }
346 /**
347 *
348 */
349 Reader &BasicReader::readUnsignedInt (unsigned int& val )
350 {
351 DOMString buf = readWord();
352 unsigned long ival;
353 if (getULong(buf, &ival))
354 val = (unsigned int) ival;
355 return *this;
356 }
358 /**
359 *
360 */
361 Reader &BasicReader::readLong (long& val )
362 {
363 DOMString buf = readWord();
364 long ival;
365 if (getLong(buf, &ival))
366 val = ival;
367 return *this;
368 }
370 /**
371 *
372 */
373 Reader &BasicReader::readUnsignedLong (unsigned long& val )
374 {
375 DOMString buf = readWord();
376 unsigned long ival;
377 if (getULong(buf, &ival))
378 val = ival;
379 return *this;
380 }
382 /**
383 *
384 */
385 Reader &BasicReader::readFloat (float& val )
386 {
387 DOMString buf = readWord();
388 double ival;
389 if (getDouble(buf, &ival))
390 val = (float)ival;
391 return *this;
392 }
394 /**
395 *
396 */
397 Reader &BasicReader::readDouble (double& val )
398 {
399 DOMString buf = readWord();
400 double ival;
401 if (getDouble(buf, &ival))
402 val = ival;
403 return *this;
404 }
408 //#########################################################################
409 //# I N P U T S T R E A M R E A D E R
410 //#########################################################################
413 InputStreamReader::InputStreamReader(const InputStream &inputStreamSource)
414 : inputStream((InputStream &)inputStreamSource)
415 {
416 }
420 /**
421 * Close the underlying OutputStream
422 */
423 void InputStreamReader::close()
424 {
425 inputStream.close();
426 }
428 /**
429 * Flush the underlying OutputStream
430 */
431 int InputStreamReader::available()
432 {
433 return inputStream.available();
434 }
436 /**
437 * Overloaded to receive its bytes from an InputStream
438 * rather than a Reader
439 */
440 int InputStreamReader::get()
441 {
442 //Do we need conversions here?
443 int ch = (XMLCh)inputStream.get();
444 return ch;
445 }
449 //#########################################################################
450 //# S T D R E A D E R
451 //#########################################################################
454 /**
455 *
456 */
457 StdReader::StdReader()
458 {
459 inputStream = new StdInputStream();
460 }
462 /**
463 *
464 */
465 StdReader::~StdReader()
466 {
467 delete inputStream;
468 }
472 /**
473 * Close the underlying OutputStream
474 */
475 void StdReader::close()
476 {
477 inputStream->close();
478 }
480 /**
481 * Flush the underlying OutputStream
482 */
483 int StdReader::available()
484 {
485 return inputStream->available();
486 }
488 /**
489 * Overloaded to receive its bytes from an InputStream
490 * rather than a Reader
491 */
492 int StdReader::get()
493 {
494 //Do we need conversions here?
495 XMLCh ch = (XMLCh)inputStream->get();
496 return ch;
497 }
503 //#########################################################################
504 //# B A S I C W R I T E R
505 //#########################################################################
507 /**
508 *
509 */
510 BasicWriter::BasicWriter(const Writer &destinationWriter)
511 {
512 destination = (Writer *)&destinationWriter;
513 }
515 /**
516 * Closes this writer and releases any system resources
517 * associated with this writer.
518 */
519 void BasicWriter::close()
520 {
521 if (destination)
522 destination->close();
523 }
525 /**
526 * Flushes this output stream and forces any buffered output
527 * bytes to be written out.
528 */
529 void BasicWriter::flush()
530 {
531 if (destination)
532 destination->flush();
533 }
535 /**
536 * Writes the specified byte to this output writer.
537 */
538 void BasicWriter::put(XMLCh ch)
539 {
540 if (destination)
541 destination->put(ch);
542 }
544 /**
545 * Provide printf()-like formatting
546 */
547 Writer &BasicWriter::printf(char *fmt, ...)
548 {
549 va_list args;
550 va_start(args, fmt);
551 //replace this wish vsnprintf()
552 char buf[256];
553 vsnprintf(buf, 255, fmt, args);
554 va_end(args);
555 if (buf) {
556 writeString(buf);
557 //free(buf);
558 }
559 return *this;
560 }
561 /**
562 * Writes the specified character to this output writer.
563 */
564 Writer &BasicWriter::writeChar(char ch)
565 {
566 XMLCh uch = ch;
567 put(uch);
568 return *this;
569 }
572 /**
573 * Writes the specified standard string to this output writer.
574 */
575 Writer &BasicWriter::writeString(const DOMString &str)
576 {
577 for (int i=0; i< (int)str.size(); i++)
578 put(str[i]);
579 return *this;
580 }
583 /**
584 *
585 */
586 Writer &BasicWriter::writeBool (bool val )
587 {
588 if (val)
589 writeString("true");
590 else
591 writeString("false");
592 return *this;
593 }
596 /**
597 *
598 */
599 Writer &BasicWriter::writeShort (short val )
600 {
601 char buf[32];
602 snprintf(buf, 31, "%d", val);
603 writeString(buf);
604 return *this;
605 }
609 /**
610 *
611 */
612 Writer &BasicWriter::writeUnsignedShort (unsigned short val )
613 {
614 char buf[32];
615 snprintf(buf, 31, "%u", val);
616 writeString(buf);
617 return *this;
618 }
620 /**
621 *
622 */
623 Writer &BasicWriter::writeInt (int val)
624 {
625 char buf[32];
626 snprintf(buf, 31, "%d", val);
627 writeString(buf);
628 return *this;
629 }
631 /**
632 *
633 */
634 Writer &BasicWriter::writeUnsignedInt (unsigned int val)
635 {
636 char buf[32];
637 snprintf(buf, 31, "%u", val);
638 writeString(buf);
639 return *this;
640 }
642 /**
643 *
644 */
645 Writer &BasicWriter::writeLong (long val)
646 {
647 char buf[32];
648 snprintf(buf, 31, "%ld", val);
649 writeString(buf);
650 return *this;
651 }
653 /**
654 *
655 */
656 Writer &BasicWriter::writeUnsignedLong(unsigned long val)
657 {
658 char buf[32];
659 snprintf(buf, 31, "%lu", val);
660 writeString(buf);
661 return *this;
662 }
664 /**
665 *
666 */
667 Writer &BasicWriter::writeFloat(float val)
668 {
669 char buf[32];
670 snprintf(buf, 31, "%8.3f", val);
671 writeString(buf);
672 return *this;
673 }
675 /**
676 *
677 */
678 Writer &BasicWriter::writeDouble(double val)
679 {
680 char buf[32];
681 snprintf(buf, 31, "%8.3f", val);
682 writeString(buf);
683 return *this;
684 }
689 //#########################################################################
690 //# O U T P U T S T R E A M W R I T E R
691 //#########################################################################
694 OutputStreamWriter::OutputStreamWriter(OutputStream &outputStreamDest)
695 : outputStream(outputStreamDest)
696 {
697 }
701 /**
702 * Close the underlying OutputStream
703 */
704 void OutputStreamWriter::close()
705 {
706 flush();
707 outputStream.close();
708 }
710 /**
711 * Flush the underlying OutputStream
712 */
713 void OutputStreamWriter::flush()
714 {
715 outputStream.flush();
716 }
718 /**
719 * Overloaded to redirect the output chars from the next Writer
720 * in the chain to an OutputStream instead.
721 */
722 void OutputStreamWriter::put(XMLCh ch)
723 {
724 //Do we need conversions here?
725 int intCh = (int) ch;
726 outputStream.put(intCh);
727 }
729 //#########################################################################
730 //# S T D W R I T E R
731 //#########################################################################
734 /**
735 *
736 */
737 StdWriter::StdWriter()
738 {
739 outputStream = new StdOutputStream();
740 }
743 /**
744 *
745 */
746 StdWriter::~StdWriter()
747 {
748 delete outputStream;
749 }
753 /**
754 * Close the underlying OutputStream
755 */
756 void StdWriter::close()
757 {
758 flush();
759 outputStream->close();
760 }
762 /**
763 * Flush the underlying OutputStream
764 */
765 void StdWriter::flush()
766 {
767 outputStream->flush();
768 }
770 /**
771 * Overloaded to redirect the output chars from the next Writer
772 * in the chain to an OutputStream instead.
773 */
774 void StdWriter::put(XMLCh ch)
775 {
776 //Do we need conversions here?
777 int intCh = (int) ch;
778 outputStream->put(intCh);
779 }
792 //###############################################
793 //# O P E R A T O R S
794 //###############################################
795 //# Normally these would be in the .h, but we
796 //# just want to be absolutely certain that these
797 //# are never multiply defined. Easy to maintain,
798 //# though. Just occasionally copy/paste these
799 //# into the .h , and replace the {} with a ;
800 //###############################################
805 Reader& operator>> (Reader &reader, bool& val )
806 { return reader.readBool(val); }
808 Reader& operator>> (Reader &reader, short &val)
809 { return reader.readShort(val); }
811 Reader& operator>> (Reader &reader, unsigned short &val)
812 { return reader.readUnsignedShort(val); }
814 Reader& operator>> (Reader &reader, int &val)
815 { return reader.readInt(val); }
817 Reader& operator>> (Reader &reader, unsigned int &val)
818 { return reader.readUnsignedInt(val); }
820 Reader& operator>> (Reader &reader, long &val)
821 { return reader.readLong(val); }
823 Reader& operator>> (Reader &reader, unsigned long &val)
824 { return reader.readUnsignedLong(val); }
826 Reader& operator>> (Reader &reader, float &val)
827 { return reader.readFloat(val); }
829 Reader& operator>> (Reader &reader, double &val)
830 { return reader.readDouble(val); }
835 Writer& operator<< (Writer &writer, char val)
836 { return writer.writeChar(val); }
838 Writer& operator<< (Writer &writer, const DOMString &val)
839 { return writer.writeString(val); }
841 Writer& operator<< (Writer &writer, bool val)
842 { return writer.writeBool(val); }
844 Writer& operator<< (Writer &writer, short val)
845 { return writer.writeShort(val); }
847 Writer& operator<< (Writer &writer, unsigned short val)
848 { return writer.writeUnsignedShort(val); }
850 Writer& operator<< (Writer &writer, int val)
851 { return writer.writeInt(val); }
853 Writer& operator<< (Writer &writer, unsigned int val)
854 { return writer.writeUnsignedInt(val); }
856 Writer& operator<< (Writer &writer, long val)
857 { return writer.writeLong(val); }
859 Writer& operator<< (Writer &writer, unsigned long val)
860 { return writer.writeUnsignedLong(val); }
862 Writer& operator<< (Writer &writer, float val)
863 { return writer.writeFloat(val); }
865 Writer& operator<< (Writer &writer, double val)
866 { return writer.writeDouble(val); }
870 } //namespace io
871 } //namespace dom
872 } //namespace w3c
873 } //namespace org
876 //#########################################################################
877 //# E N D O F F I L E
878 //#########################################################################