1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Our base input/output stream classes.  These are is directly
4  * inherited from iostreams, and includes any extra
5  * functionality that we might need.
6  *
7  * Authors:
8  *   Bob Jamison <rjamison@titan.com>
9  *
10  * Copyright (C) 2004 Inkscape.org
11  *
12  * Released under GNU GPL v2+, read the file 'COPYING' for more information.
13  */
14 
15 #include <cstdlib>
16 #include "inkscapestream.h"
17 
18 namespace Inkscape
19 {
20 namespace IO
21 {
22 
23 //#########################################################################
24 //# U T I L I T Y
25 //#########################################################################
26 
pipeStream(InputStream & source,OutputStream & dest)27 void pipeStream(InputStream &source, OutputStream &dest)
28 {
29     for (;;)
30         {
31         int ch = source.get();
32         if (ch<0)
33             break;
34         dest.put(ch);
35         }
36     dest.flush();
37 }
38 
39 //#########################################################################
40 //# B A S I C    I N P U T    S T R E A M
41 //#########################################################################
42 
43 
44 /**
45  *
46  */
BasicInputStream(InputStream & sourceStream)47 BasicInputStream::BasicInputStream(InputStream &sourceStream)
48                    : source(sourceStream)
49 {
50     closed = false;
51 }
52 
53 /**
54  * Returns the number of bytes that can be read (or skipped over) from
55  * this input stream without blocking by the next caller of a method for
56  * this input stream.
57  */
available()58 int BasicInputStream::available()
59 {
60     if (closed)
61         return 0;
62     return source.available();
63 }
64 
65 
66 /**
67  *  Closes this input stream and releases any system resources
68  *  associated with the stream.
69  */
close()70 void BasicInputStream::close()
71 {
72     if (closed)
73         return;
74     source.close();
75     closed = true;
76 }
77 
78 /**
79  * Reads the next byte of data from the input stream.  -1 if EOF
80  */
get()81 int BasicInputStream::get()
82 {
83     if (closed)
84         return -1;
85     return source.get();
86 }
87 
88 
89 
90 //#########################################################################
91 //# B A S I C    O U T P U T    S T R E A M
92 //#########################################################################
93 
94 /**
95  *
96  */
BasicOutputStream(OutputStream & destinationStream)97 BasicOutputStream::BasicOutputStream(OutputStream &destinationStream)
98                      : destination(destinationStream)
99 {
100     closed = false;
101 }
102 
103 /**
104  * Closes this output stream and releases any system resources
105  * associated with this stream.
106  */
close()107 void BasicOutputStream::close()
108 {
109     if (closed)
110         return;
111     destination.close();
112     closed = true;
113 }
114 
115 /**
116  *  Flushes this output stream and forces any buffered output
117  *  bytes to be written out.
118  */
flush()119 void BasicOutputStream::flush()
120 {
121     if (closed)
122         return;
123     destination.flush();
124 }
125 
126 /**
127  * Writes the specified byte to this output stream.
128  */
put(char ch)129 int BasicOutputStream::put(char ch)
130 {
131     if (closed)
132         return -1;
133     destination.put(ch);
134     return 1;
135 }
136 
137 
138 
139 //#########################################################################
140 //# B A S I C    R E A D E R
141 //#########################################################################
142 /**
143  *
144  */
BasicReader(Reader & sourceReader)145 BasicReader::BasicReader(Reader &sourceReader)
146 {
147     source = &sourceReader;
148 }
149 
150 /**
151  * Returns the number of bytes that can be read (or skipped over) from
152  * this reader without blocking by the next caller of a method for
153  * this reader.
154  */
available()155 int BasicReader::available()
156 {
157     if (source)
158         return source->available();
159     else
160         return 0;
161 }
162 
163 
164 /**
165  *  Closes this reader and releases any system resources
166  *  associated with the reader.
167  */
close()168 void BasicReader::close()
169 {
170     if (source)
171         source->close();
172 }
173 
174 /**
175  * Reads the next byte of data from the reader.
176  */
get()177 char BasicReader::get()
178 {
179     if (source)
180         return source->get();
181     else
182         return (char)-1;
183 }
184 
185 
186 /**
187  * Reads a line of data from the reader.
188  */
readLine()189 Glib::ustring BasicReader::readLine()
190 {
191     Glib::ustring str;
192     while (available() > 0)
193         {
194         char ch = get();
195         if (ch == '\n')
196             break;
197         str.push_back(ch);
198         }
199     return str;
200 }
201 
202 /**
203  * Reads a line of data from the reader.
204  */
readWord()205 Glib::ustring BasicReader::readWord()
206 {
207     Glib::ustring str;
208     while (available() > 0)
209         {
210         char ch = get();
211         if (!std::isprint(ch))
212             break;
213         str.push_back(ch);
214         }
215     return str;
216 }
217 
218 
getLong(Glib::ustring & str,long * val)219 static bool getLong(Glib::ustring &str, long *val)
220 {
221     const char *begin = str.raw().c_str();
222     char *end;
223     long ival = strtol(begin, &end, 10);
224     if (str == end)
225         return false;
226     *val = ival;
227     return true;
228 }
229 
getULong(Glib::ustring & str,unsigned long * val)230 static bool getULong(Glib::ustring &str, unsigned long *val)
231 {
232     const char *begin = str.raw().c_str();
233     char *end;
234     unsigned long ival = strtoul(begin, &end, 10);
235     if (str == end)
236         return false;
237     *val = ival;
238     return true;
239 }
240 
getDouble(Glib::ustring & str,double * val)241 static bool getDouble(Glib::ustring &str, double *val)
242 {
243     const char *begin = str.raw().c_str();
244     char *end;
245     double ival = strtod(begin, &end);
246     if (str == end)
247         return false;
248     *val = ival;
249     return true;
250 }
251 
252 
253 
readBool(bool & val)254 const Reader &BasicReader::readBool (bool& val )
255 {
256     Glib::ustring buf = readWord();
257     if (buf == "true")
258         val = true;
259     else
260         val = false;
261     return *this;
262 }
263 
readShort(short & val)264 const Reader &BasicReader::readShort (short& val )
265 {
266     Glib::ustring buf = readWord();
267     long ival;
268     if (getLong(buf, &ival))
269         val = (short) ival;
270     return *this;
271 }
272 
readUnsignedShort(unsigned short & val)273 const Reader &BasicReader::readUnsignedShort (unsigned short& val )
274 {
275     Glib::ustring buf = readWord();
276     unsigned long ival;
277     if (getULong(buf, &ival))
278         val = (unsigned short) ival;
279     return *this;
280 }
281 
readInt(int & val)282 const Reader &BasicReader::readInt (int& val )
283 {
284     Glib::ustring buf = readWord();
285     long ival;
286     if (getLong(buf, &ival))
287         val = (int) ival;
288     return *this;
289 }
290 
readUnsignedInt(unsigned int & val)291 const Reader &BasicReader::readUnsignedInt (unsigned int& val )
292 {
293     Glib::ustring buf = readWord();
294     unsigned long ival;
295     if (getULong(buf, &ival))
296         val = (unsigned int) ival;
297     return *this;
298 }
299 
readLong(long & val)300 const Reader &BasicReader::readLong (long& val )
301 {
302     Glib::ustring buf = readWord();
303     long ival;
304     if (getLong(buf, &ival))
305         val = ival;
306     return *this;
307 }
308 
readUnsignedLong(unsigned long & val)309 const Reader &BasicReader::readUnsignedLong (unsigned long& val )
310 {
311     Glib::ustring buf = readWord();
312     unsigned long ival;
313     if (getULong(buf, &ival))
314         val = ival;
315     return *this;
316 }
317 
readFloat(float & val)318 const Reader &BasicReader::readFloat (float& val )
319 {
320     Glib::ustring buf = readWord();
321     double ival;
322     if (getDouble(buf, &ival))
323         val = (float)ival;
324     return *this;
325 }
326 
readDouble(double & val)327 const Reader &BasicReader::readDouble (double& val )
328 {
329     Glib::ustring buf = readWord();
330     double ival;
331     if (getDouble(buf, &ival))
332         val = ival;
333     return *this;
334 }
335 
336 
337 
338 //#########################################################################
339 //# I N P U T    S T R E A M    R E A D E R
340 //#########################################################################
341 
342 
InputStreamReader(InputStream & inputStreamSource)343 InputStreamReader::InputStreamReader(InputStream &inputStreamSource)
344                      : inputStream(inputStreamSource)
345 {
346 }
347 
348 
349 
350 /**
351  *  Close the underlying OutputStream
352  */
close()353 void InputStreamReader::close()
354 {
355     inputStream.close();
356 }
357 
358 /**
359  *  Flush the underlying OutputStream
360  */
available()361 int InputStreamReader::available()
362 {
363     return inputStream.available();
364 }
365 
366 /**
367  *  Overloaded to receive its bytes from an InputStream
368  *  rather than a Reader
369  */
get()370 char InputStreamReader::get()
371 {
372     char ch = inputStream.get();
373     return ch;
374 }
375 
376 
377 
378 //#########################################################################
379 //# S T D    R E A D E R
380 //#########################################################################
381 
382 
383 /**
384  *
385  */
StdReader()386 StdReader::StdReader()
387 {
388     inputStream = new StdInputStream();
389 }
390 
391 /**
392  *
393  */
~StdReader()394 StdReader::~StdReader()
395 {
396     delete inputStream;
397 }
398 
399 
400 
401 /**
402  *  Close the underlying OutputStream
403  */
close()404 void StdReader::close()
405 {
406     inputStream->close();
407 }
408 
409 /**
410  *  Flush the underlying OutputStream
411  */
available()412 int StdReader::available()
413 {
414     return inputStream->available();
415 }
416 
417 /**
418  *  Overloaded to receive its bytes from an InputStream
419  *  rather than a Reader
420  */
get()421 char StdReader::get()
422 {
423     char ch = inputStream->get();
424     return ch;
425 }
426 
427 
428 
429 
430 
431 //#########################################################################
432 //# B A S I C    W R I T E R
433 //#########################################################################
434 
435 /**
436  *
437  */
BasicWriter(Writer & destinationWriter)438 BasicWriter::BasicWriter(Writer &destinationWriter)
439 {
440     destination = &destinationWriter;
441 }
442 
443 /**
444  * Closes this writer and releases any system resources
445  * associated with this writer.
446  */
close()447 void BasicWriter::close()
448 {
449     if (destination)
450         destination->close();
451 }
452 
453 /**
454  *  Flushes this output stream and forces any buffered output
455  *  bytes to be written out.
456  */
flush()457 void BasicWriter::flush()
458 {
459     if (destination)
460         destination->flush();
461 }
462 
463 /**
464  * Writes the specified byte to this output writer.
465  */
put(char ch)466 void BasicWriter::put(char ch)
467 {
468     if (destination)
469         destination->put(ch);
470 }
471 
472 /**
473  * Provide printf()-like formatting
474  */
printf(char const * fmt,...)475 Writer &BasicWriter::printf(char const *fmt, ...)
476 {
477     va_list args;
478     va_start(args, fmt);
479     gchar *buf = g_strdup_vprintf(fmt, args);
480     va_end(args);
481     if (buf) {
482         writeString(buf);
483         g_free(buf);
484     }
485     return *this;
486 }
487 /**
488  * Writes the specified character to this output writer.
489  */
writeChar(char ch)490 Writer &BasicWriter::writeChar(char ch)
491 {
492     put(ch);
493     return *this;
494 }
495 
496 
497 /**
498  * Writes the specified unicode string to this output writer.
499  */
writeUString(const Glib::ustring & str)500 Writer &BasicWriter::writeUString(const Glib::ustring &str)
501 {
502     writeStdString(str.raw());
503     return *this;
504 }
505 
506 /**
507  * Writes the specified standard string to this output writer.
508  */
writeStdString(const std::string & str)509 Writer &BasicWriter::writeStdString(const std::string &str)
510 {
511     for (char it : str) {
512         put(it);
513     }
514     return *this;
515 }
516 
517 /**
518  * Writes the specified character string to this output writer.
519  */
writeString(const char * str)520 Writer &BasicWriter::writeString(const char *str)
521 {
522     std::string tmp;
523     if (str)
524         tmp = str;
525     else
526         tmp = "null";
527     writeStdString(tmp);
528     return *this;
529 }
530 
531 
532 
533 
534 /**
535  *
536  */
writeBool(bool val)537 Writer &BasicWriter::writeBool (bool val )
538 {
539     if (val)
540         writeString("true");
541     else
542         writeString("false");
543     return *this;
544 }
545 
546 
547 /**
548  *
549  */
writeShort(short val)550 Writer &BasicWriter::writeShort (short val )
551 {
552     gchar *buf = g_strdup_printf("%d", val);
553     if (buf) {
554         writeString(buf);
555         g_free(buf);
556     }
557   return *this;
558 }
559 
560 
561 
562 /**
563  *
564  */
writeUnsignedShort(unsigned short val)565 Writer &BasicWriter::writeUnsignedShort (unsigned short val )
566 {
567     gchar *buf = g_strdup_printf("%u", val);
568     if (buf) {
569         writeString(buf);
570         g_free(buf);
571     }
572     return *this;
573 }
574 
575 /**
576  *
577  */
writeInt(int val)578 Writer &BasicWriter::writeInt (int val)
579 {
580     gchar *buf = g_strdup_printf("%d", val);
581     if (buf) {
582         writeString(buf);
583         g_free(buf);
584     }
585     return *this;
586 }
587 
588 /**
589  *
590  */
writeUnsignedInt(unsigned int val)591 Writer &BasicWriter::writeUnsignedInt (unsigned int val)
592 {
593     gchar *buf = g_strdup_printf("%u", val);
594     if (buf) {
595         writeString(buf);
596         g_free(buf);
597     }
598     return *this;
599 }
600 
601 /**
602  *
603  */
writeLong(long val)604 Writer &BasicWriter::writeLong (long val)
605 {
606     gchar *buf = g_strdup_printf("%ld", val);
607     if (buf) {
608         writeString(buf);
609         g_free(buf);
610     }
611     return *this;
612 }
613 
614 /**
615  *
616  */
writeUnsignedLong(unsigned long val)617 Writer &BasicWriter::writeUnsignedLong(unsigned long val)
618 {
619     gchar *buf = g_strdup_printf("%lu", val);
620     if (buf) {
621         writeString(buf);
622         g_free(buf);
623     }
624     return *this;
625 }
626 
627 /**
628  *
629  */
writeFloat(float val)630 Writer &BasicWriter::writeFloat(float val)
631 {
632 #if 1
633     gchar *buf = g_strdup_printf("%8.3f", val);
634     if (buf) {
635         writeString(buf);
636         g_free(buf);
637     }
638 #else
639     std::string tmp = ftos(val, 'g', 8, 3, 0);
640     writeStdString(tmp);
641 #endif
642     return *this;
643 }
644 
645 /**
646  *
647  */
writeDouble(double val)648 Writer &BasicWriter::writeDouble(double val)
649 {
650 #if 1
651     gchar *buf = g_strdup_printf("%8.3f", val);
652     if (buf) {
653         writeString(buf);
654         g_free(buf);
655     }
656 #else
657     std::string tmp = ftos(val, 'g', 8, 3, 0);
658     writeStdString(tmp);
659 #endif
660     return *this;
661 }
662 
663 
operator <<(Writer & writer,char val)664 Writer& operator<< (Writer &writer, char val)
665     { return writer.writeChar(val); }
666 
operator <<(Writer & writer,Glib::ustring & val)667 Writer& operator<< (Writer &writer, Glib::ustring &val)
668     { return writer.writeUString(val); }
669 
operator <<(Writer & writer,std::string & val)670 Writer& operator<< (Writer &writer, std::string &val)
671     { return writer.writeStdString(val); }
672 
operator <<(Writer & writer,char const * val)673 Writer& operator<< (Writer &writer, char const *val)
674     { return writer.writeString(val); }
675 
operator <<(Writer & writer,bool val)676 Writer& operator<< (Writer &writer, bool val)
677     { return writer.writeBool(val); }
678 
operator <<(Writer & writer,short val)679 Writer& operator<< (Writer &writer, short val)
680     { return writer.writeShort(val); }
681 
operator <<(Writer & writer,unsigned short val)682 Writer& operator<< (Writer &writer, unsigned short val)
683     { return writer.writeUnsignedShort(val); }
684 
operator <<(Writer & writer,int val)685 Writer& operator<< (Writer &writer, int val)
686     { return writer.writeInt(val); }
687 
operator <<(Writer & writer,unsigned int val)688 Writer& operator<< (Writer &writer, unsigned int val)
689     { return writer.writeUnsignedInt(val); }
690 
operator <<(Writer & writer,long val)691 Writer& operator<< (Writer &writer, long val)
692     { return writer.writeLong(val); }
693 
operator <<(Writer & writer,unsigned long val)694 Writer& operator<< (Writer &writer, unsigned long val)
695     { return writer.writeUnsignedLong(val); }
696 
operator <<(Writer & writer,float val)697 Writer& operator<< (Writer &writer, float val)
698     { return writer.writeFloat(val); }
699 
operator <<(Writer & writer,double val)700 Writer& operator<< (Writer &writer, double val)
701     { return writer.writeDouble(val); }
702 
703 
704 
705 //#########################################################################
706 //# O U T P U T    S T R E A M    W R I T E R
707 //#########################################################################
708 
709 
OutputStreamWriter(OutputStream & outputStreamDest)710 OutputStreamWriter::OutputStreamWriter(OutputStream &outputStreamDest)
711                      : outputStream(outputStreamDest)
712 {
713 }
714 
715 
716 
717 /**
718  *  Close the underlying OutputStream
719  */
close()720 void OutputStreamWriter::close()
721 {
722     flush();
723     outputStream.close();
724 }
725 
726 /**
727  *  Flush the underlying OutputStream
728  */
flush()729 void OutputStreamWriter::flush()
730 {
731       outputStream.flush();
732 }
733 
734 /**
735  *  Overloaded to redirect the output chars from the next Writer
736  *  in the chain to an OutputStream instead.
737  */
put(char ch)738 void OutputStreamWriter::put(char ch)
739 {
740     outputStream.put(ch);
741 }
742 
743 //#########################################################################
744 //# S T D    W R I T E R
745 //#########################################################################
746 
747 
748 /**
749  *
750  */
StdWriter()751 StdWriter::StdWriter()
752 {
753     outputStream = new StdOutputStream();
754 }
755 
756 
757 /**
758  *
759  */
~StdWriter()760 StdWriter::~StdWriter()
761 {
762     delete outputStream;
763 }
764 
765 
766 
767 /**
768  *  Close the underlying OutputStream
769  */
close()770 void StdWriter::close()
771 {
772     flush();
773     outputStream->close();
774 }
775 
776 /**
777  *  Flush the underlying OutputStream
778  */
flush()779 void StdWriter::flush()
780 {
781       outputStream->flush();
782 }
783 
784 /**
785  *  Overloaded to redirect the output chars from the next Writer
786  *  in the chain to an OutputStream instead.
787  */
put(char ch)788 void StdWriter::put(char ch)
789 {
790     outputStream->put(ch);
791 }
792 
793 
794 } // namespace IO
795 } // namespace Inkscape
796 
797 
798 //#########################################################################
799 //# E N D    O F    F I L E
800 //#########################################################################
801