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