Evo C++ Library v0.5.1
io.h
Go to the documentation of this file.
1 // Evo C++ Library
2 /* Copyright 2019 Justin Crowell
3 Distributed under the BSD 2-Clause License -- see included file LICENSE.txt for details.
4 */
6 
7 #pragma once
8 #ifndef INCL_evo_io_h
9 #define INCL_evo_io_h
10 
11 #include "iobase.h"
12 #include "thread_inert.h"
13 
15 
44 #define EVO_CONSOLE static evo::Console& c = evo::con()
45 
66 #if EVO_CATCH_DEBUG == 0
67  #define EVO_CATCH(CODE) catch (const evo::Exception& e) { \
68  evo::Console& c = evo::con(); \
69  c.err << evo::NL << e.msg() << evo::SubString(" -- ", 4); \
70  evo::errormsg_out(c.err, e.error()); \
71  c.err << evo::NL; \
72  CODE; \
73  }
74 #else
75  #define EVO_CATCH(CODE) catch (const evo::Exception& e) { \
76  evo::Console& c = evo::con(); \
77  c.err << evo::NL; \
78  if (e.file()) \
79  c.err << e.file() << '(' << e.line() << evo::SubString("): ", 3); \
80  c.err << e.msg() << evo::SubString(" -- ", 4); \
81  evo::errormsg_out(c.err, e.error()); \
82  c.err << evo::NL; \
83  CODE; \
84  }
85 #endif
86 
88 
89 // Namespace: evo
90 namespace evo {
91 
96 
98 
119 template<class T>
120 class StreamIn : public StreamBase {
121 public:
122  typedef typename T::Handle Handle;
123  typedef StreamIn<T> This;
124 
125  typedef typename T::ExceptionInT ExceptionInT;
126 
130  StreamIn(Newline newlines=NL_SYS) :
131  owned_(false),
132  bufrd_(0, newlines)
133  { }
134 
136  Handle handle() const
137  { return device_.handle; }
138 
141  { return bufrd_.readbuf; }
142 
147  void attach(Handle handle, bool owned=true) {
148  close();
149  device_.handle = handle;
150  if (device_.isopen()) {
151  owned_ = owned;
152  init();
153  }
154  }
155 
161  Handle detach() {
162  if (device_.isopen()) {
163  bufrd_.close();
164  owned_ = false;
165  }
166  return device_.detach();
167  }
168 
174  bool close() {
175  if (device_.isopen()) {
176  bufrd_.close();
177  if (owned_) {
178  device_.close();
179  owned_ = false;
180  } else
181  device_.detach();
182  }
183  return true;
184  }
185 
186  bool isopen() const {
187  return device_.isopen();
188  }
189 
190  // Read methods copied from Stream, with some modifications -- it's done this way to avoid more virtual method overhead
191 
192  ulong readbin(void* buf, ulong size) {
193  size = bufrd_.readbin(error_, device_, buf, size);
194  EVO_THROW_ERR_CHECK(ExceptionInT, "Stream binary read failed", error_, (excep_ && size == 0 && error_ != ENone && error_ != EEnd));
195  return size;
196  }
197 
198  ulong readtext(char* buf, ulong size) {
199  size = bufrd_.readtext(error_, device_, buf, size);
200  EVO_THROW_ERR_CHECK(ExceptionInT, "Stream text read failed", error_, (excep_ && size == 0 && error_ != ENone && error_ != EEnd));
201  return size;
202  }
203 
204  bool readline(String& str, ulong maxlen=0) {
205  error_ = bufrd_.readline(str, device_, maxlen);
206  if (error_ != ENone && error_ != EEnd) {
207  EVO_THROW_ERR_CHECK(ExceptionInT, "Stream text line read failed", error_, excep_);
208  return false;
209  }
210  return true;
211  }
212 
213 protected:
215  bool owned_;
217 
219  void init() {
220  bufrd_.open();
221  }
222 
223 private:
224  StreamIn(const This&);
225  This& operator=(const This&);
226 };
227 
229 
260 template<class T>
261 class StreamOut : public StreamBase {
262 public:
263  typedef typename T::Handle Handle;
264  typedef StreamOut<T> This;
265  typedef This Out;
266 
268 
269  typedef typename T::ExceptionOutT ExceptionOutT;
270 
275  owned_(false),
276  bufwr_(0, newlines)
277  { }
278 
281  { close(); }
282 
284  Handle handle() const
285  { return device_.handle; }
286 
289  { return bufwr_; }
290 
296  void attach(Handle handle, bool owned=true, bool flushlines=false) {
297  close();
298  device_.handle = handle;
299  if (device_.isopen()) {
300  owned_ = owned;
301  init(flushlines);
302  }
303  }
304 
311  Handle detach() {
312  if (device_.isopen()) {
313  if (bufwr_.used > 0)
314  bufwr_.flush(device_);
315  bufwr_.close();
316  owned_ = false;
317  }
318  return device_.detach();
319  }
320 
327  bool close() {
328  if (device_.isopen()) {
329  if (bufwr_.used > 0)
330  error_ = bufwr_.flush(device_);
331  else
332  error_ = ENone;
333  bufwr_.close();
334  if (owned_) {
335  device_.close();
336  owned_ = false;
337  } else
338  device_.detach();
339  return (error_ == ENone);
340  }
341  return true;
342  }
343 
344  bool isopen() const
345  { return device_.isopen(); }
346 
347  // Write methods copied from Stream, with some modifications -- it's done this way to avoid more virtual method overhead
348 
349  bool flush() {
350  error_ = bufwr_.flush(device_);
351  if (error_ != ENone) {
352  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream flush failed", error_, (excep_ && error_ != ENone));
353  return false;
354  }
355  return true;
356  }
357 
358  ulong writebin(const void* buf, ulong size) {
359  size = bufwr_.writebin(error_, device_, buf, size);
360  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream binary write failed", error_, (excep_ && size == 0 && error_ != ENone));
361  return size;
362  }
363 
364  ulong writechar(char ch, ulong count=1) {
365  count = bufwr_.writetext_char(error_, device_, ch, count);
366  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write failed", error_, (excep_ && count == 0 && error_ != ENone));
367  return count;
368  }
369 
370  ulong writetext(const char* buf, ulong size) {
371  size = bufwr_.writetext(error_, device_, buf, size);
372  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write failed", error_, (excep_ && size == 0 && error_ != ENone));
373  return size;
374  }
375 
376  Size writequoted(const char* buf, Size size, char delim, bool optional=false) {
377  bool quote_optional = false;
378  const StrQuoting::Type type = StrQuoting::get(quote_optional, buf, size, delim);
379  switch (type) {
380  case StrQuoting::tSINGLE:
381  if (quote_optional && optional)
382  return writebin(buf, size);
383  case StrQuoting::tDOUBLE:
384  case StrQuoting::tBACKTICK: {
385  const char ch = "'\"`"[(uint)type];
386  const Size result = size + 2;
387  if (writebin(&ch, 1) == 1 && writebin(buf, size) == size && writebin(&ch, 1) == 1)
388  return result;
389  break;
390  }
393  case StrQuoting::tBACKTICK3: {
394  const char* str = &"'''\"\"\"```"[(uint(type) - 3) * 3];
395  const Size result = size + 6;
396  if (writebin(str, 3) == 3 && writebin(buf, size) == size && writebin(str, 3) == 3)
397  return result;
398  break;
399  }
401  const char* str = "`\x7F";
402  const Size result = size + 4;
403  if (writebin(str, 2) != 2 || writebin(buf, size) != size || writebin(str, 2) != 2)
404  return result;
405  break;
406  }
407  case StrQuoting::tERROR:
408  error_ = EInval;
409  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write failed on unquotable text", error_, excep_);
410  break;
411  }
412  return 0;
413  }
414 
415  ulong writeline(const char* buf, ulong size) {
416  ulong writtensize = bufwr_.writetext(error_, device_, buf, size);
417  bufwr_.partnl = 0;
418  if (writtensize == 0 || !bufwr_.writebin(error_, device_, bufwr_.newline, bufwr_.newlinesize) ) {
419  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text line write failed", error_, excep_);
420  return 0;
421  }
422  return writtensize + bufwr_.newlinesize;
423  }
424 
425  Out& write_out()
426  { return *this; }
427 
428  char* write_direct(Size size) {
429  if (size > bufwr_.size) {
430  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream not large enough for write_direct()", error_, excep_);
431  return NULL;
432  }
433  if (bufwr_.avail() < size) {
434  error_ = bufwr_.flush(device_);
435  if (error_ != ENone) {
436  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream flush failed", error_, excep_);
437  return NULL;
438  }
439  }
440  bufwr_.partnl = 0;
441  return bufwr_.data + bufwr_.used;
442  }
443 
444  char* write_direct_multi(Size& available, Size reserve_size) {
445  if (reserve_size > bufwr_.avail()) {
446  error_ = bufwr_.flush(device_);
447  if (error_ != ENone) {
448  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream flush failed", error_, excep_);
449  return NULL;
450  }
451  if (reserve_size > bufwr_.size)
452  available = (Size)bufwr_.size;
453  else
454  available = reserve_size;
455  } else {
456  available = reserve_size;
457  if (reserve_size == 0)
458  return (char*)1; // finished
459  }
460  bufwr_.partnl = 0;
461  return bufwr_.data + bufwr_.used;
462  }
463 
464  char* write_direct_flush(Size& available, Size written_size, Size reserve_size) {
465  bufwr_.used += written_size;
466  assert( bufwr_.used <= bufwr_.size );
467 
468  error_ = bufwr_.flush(device_);
469  if (error_ != ENone) {
470  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream flush failed", error_, excep_);
471  return NULL;
472  }
473 
474  if (reserve_size > bufwr_.size) {
475  available = (Size)bufwr_.size;
476  } else {
477  available = reserve_size;
478  if (reserve_size == 0)
479  return (char*)1; // finished
480  }
481 
482  return bufwr_.data;
483  }
484 
486  bufwr_.used += size;
487  assert( bufwr_.used <= bufwr_.size );
488  return true;
489  }
490 
492  template<class TNum>
493  bool writenum(TNum num, int base=fDEC) {
494  if (error_ == ENone) {
495  error_ = bufwr_.writenum(device_, num, base);
496  if (error_ != ENone) {
497  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write number failed", error_, excep_);
498  return false;
499  }
500  return true;
501  }
502  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write number blocked by previous error", error_, excep_);
503  return false;
504  }
505 
507  template<class TNum>
508  bool writenumu(TNum num, int base=fDEC) {
509  if (error_ == ENone) {
510  error_ = bufwr_.writenumu(device_, num, base);
511  if (error_ != ENone) {
512  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write number failed", error_, excep_);
513  return false;
514  }
515  return true;
516  }
517  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write number blocked by previous error", error_, excep_);
518  return false;
519  }
520 
522  template<class TNum>
523  bool writenumf(TNum num, int precision=fPREC_AUTO) {
524  if (error_ == ENone) {
525  error_ = bufwr_.writenumf(device_, num, precision);
526  if (error_ != ENone) {
527  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write number failed", error_, excep_);
528  return false;
529  }
530  return true;
531  }
532  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write number blocked by previous error", error_, excep_);
533  return false;
534  }
535 
537  bool writefmtchar(char ch, ulong count, const FmtSetField& field) {
538  if (error_ == ENone) {
539  error_ = bufwr_.writefmtchar(device_, ch, count, field);
540  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text formatted write char failed", error_, (excep_ && error_ != ENone));
541  return true;
542  }
543  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write formatted char blocked by previous error", error_, excep_);
544  return false;
545  }
546 
548  bool writefmtstr(const char* buf, ulong size, const FmtSetField& field) {
549  if (error_ == ENone) {
550  error_ = bufwr_.writefmtstr(device_, buf, size, field);
551  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text formatted write failed", error_, (excep_ && error_ != ENone));
552  return true;
553  }
554  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text formatted write blocked by previous error", error_, excep_);
555  return false;
556  }
557 
559  template<class TNum>
560  bool writefmtnum(TNum num, const FmtSetInt& fmt, const FmtSetField* field=NULL) {
561  if (error_ == ENone) {
562  error_ = bufwr_.writefmtnum(device_, num, fmt, field);
563  if (error_ != ENone) {
564  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write formatted number failed", error_, excep_);
565  return false;
566  }
567  return true;
568  }
569  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write formatted number blocked by previous error", error_, excep_);
570  return false;
571  }
572 
574  template<class TNum>
575  bool writefmtnumu(TNum num, const FmtSetInt& fmt, const FmtSetField* field=NULL) {
576  if (error_ == ENone) {
577  error_ = bufwr_.writefmtnumu(device_, num, fmt, field);
578  if (error_ != ENone) {
579  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write formatted number failed", error_, excep_);
580  return false;
581  }
582  return true;
583  }
584  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write formatted number blocked by previous error", error_, excep_);
585  return false;
586  }
587 
589  template<class TNum>
590  bool writefmtnumf(TNum num, const FmtSetFloat& fmt, const FmtSetField* field=NULL) {
591  if (error_ == ENone) {
592  error_ = bufwr_.writefmtnumf(device_, num, fmt, field);
593  if (error_ != ENone) {
594  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write formatted number failed", error_, excep_);
595  return false;
596  }
597  return true;
598  }
599  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write formatted number blocked by previous error", error_, excep_);
600  return false;
601  }
602 
604  bool writefmtdump(const FmtDump& fmt) {
605  if (error_ == ENone) {
606  error_ = bufwr_.writefmtdump(device_, fmt, bufwr_.newline, bufwr_.newlinesize);
607  if (error_ != ENone) {
608  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write hex dump failed", error_, excep_);
609  return false;
610  }
611  return true;
612  }
613  EVO_THROW_ERR_CHECK(ExceptionOutT, "Stream text write hex dump blocked by previous error", error_, excep_);
614  return false;
615  }
616 
617  // operator<<() overloads copied from Stream
618 
620  This& operator<<(This&)
621  { return *this; }
622 
624  This& operator<<(Newline nl) {
625  if (error_ == ENone) {
627  flush();
628  }
629  return *this;
630  }
631 
634  EVO_PARAM_UNUSED(nl);
635  if (error_ == ENone) {
636  writebin(bufwr_.newline, bufwr_.newlinesize);
637  flush();
638  }
639  return *this;
640  }
641 
643  This& operator<<(const NewlineValue& nl) {
644  if (error_ == ENone) {
645  uint nl_size;
646  const char* nl_str = nl.getnewline(nl_size, bufwr_.newline, bufwr_.newlinesize);
647  writebin(nl_str, nl_size);
648  flush();
649  }
650  return *this;
651  }
652 
654  This& operator<<(Flush) {
655  if (error_ == ENone)
656  flush();
657  return *this;
658  }
659 
661  This& operator<<(bool val) {
662  if (error_ == ENone) {
663  if (val)
664  bufwr_.writetext(error_, device_, "true", 4);
665  else
666  bufwr_.writetext(error_, device_, "false", 5);
667  }
668  return *this;
669  }
670 
672  This& operator<<(char ch) {
673  if (error_ == ENone)
674  writechar(ch);
675  return *this;
676  }
677 
679  This& operator<<(const char* str) {
680  if (error_ == ENone && str != NULL)
681  bufwr_.writetext(error_, device_, str, (ulong)strlen(str));
682  return *this;
683  }
684 
686  This& operator<<(const SubString& str) {
687  if (error_ == ENone)
688  bufwr_.writetext(error_, device_, str.data_, str.size_);
689  return *this;
690  }
691 
693  template<class TSize>
694  This& operator<<(const ListBase<char,TSize>& str) {
695  if (error_ == ENone) {
696  bufwr_.writetext(error_, device_, str.data_, str.size_);
697  EVO_THROW_ERR_CHECK(evo::ExceptionStreamOut, "Stream text write (ListBase) failed", error_, (excep_ && error_ != ENone));
698  }
699  return *this;
700  }
701 
703  This& operator<<(int num)
704  { writenum(num); return *this; }
705 
707  This& operator<<(long num)
708  { writenum(num); return *this; }
709 
711  This& operator<<(longl num)
712  { writenum(num); return *this; }
713 
715  This& operator<<(uint num)
716  { writenumu(num); return *this; }
717 
719  This& operator<<(ulong num)
720  { writenumu(num); return *this; }
721 
723  This& operator<<(ulongl num)
724  { writenumu(num); return *this; }
725 
727  template<class U>
728  This& operator<<(const IntegerT<U>& num) {
729  if (!num.null()) {
730  if (IntegerT<U>::SIGN)
731  writenum(num.value());
732  else
733  writenumu(num.value());
734  }
735  return *this;
736  }
737 
739  This& operator<<(float num)
740  { writenumf(num); return *this; }
741 
743  This& operator<<(double num)
744  { writenumf(num); return *this; }
745 
747  This& operator<<(ldouble num)
748  { writenumf(num); return *this; }
749 
751  template<class U>
752  This& operator<<(const FloatT<U>& num) {
753  if (!num.null())
754  writenumf(num);
755  return *this;
756  }
757 
759  This& operator<<(const FmtChar& fmt)
760  { writechar(fmt.ch, fmt.count); return *this; }
761 
763  This& operator<<(const FmtString& fmt)
764  { writefmtstr(fmt.str.data_, fmt.str.size_, fmt.fmt); return *this; }
765 
766  This& operator<<(const FmtStringWrap& fmt) {
767  uint newline_size;
768  const char* newline_str = fmt.newline.getnewline(newline_size, bufwr_.newline, bufwr_.newlinesize);
769 
770  SubString str(fmt.str), line, substr;
771  for (uint notfirst=0; str.token_line(line); ) {
772  for (;;) {
773  if (line.empty()) {
774  if (writebin(newline_str, newline_size) == 0)
775  return *this;
776  } else {
777  if (notfirst == 0)
778  ++notfirst;
779  else if (fmt.indent > 0 && writechar(' ', fmt.indent) == 0)
780  return *this;
781  if (fmt.width > 1 && line.size() > (Size)fmt.width) {
782  // line too long, try to find a word break
783  Size i = line.findnonwordr(0, (Size)fmt.width + 1);
784  if (i == NONE) {
785  i = (Size)fmt.width;
786  } else {
787  while (i > 0 && ascii_breaktype(line[i]) == cbtBEGIN)
788  --i;
789  if (i < (Size)fmt.width)
790  ++i;
791  }
792 
793  substr.set(line.data(), i).stripr();
794  if (!substr.empty() && (writebin(substr.data(), substr.size()) == 0 || writebin(newline_str, newline_size) == 0))
795  return *this;
796 
797  line.triml(i).stripl();
798  continue;
799  }
800  if (writebin(line.data(), line.size()) == 0 || writebin(newline_str, newline_size) == 0)
801  return *this;
802  }
803  break;
804  }
805  }
806  return *this;
807  }
808 
810  This& operator<<(const FmtShort& fmt)
811  { writefmtnum(fmt.num, fmt.fmt); return *this; }
812 
814  This& operator<<(const FmtInt& fmt)
815  { writefmtnum(fmt.num, fmt.fmt); return *this; }
816 
818  This& operator<<(const FmtLong& fmt)
819  { writefmtnum(fmt.num, fmt.fmt); return *this; }
820 
822  This& operator<<(const FmtLongL& fmt)
823  { writefmtnum(fmt.num, fmt.fmt); return *this; }
824 
826  This& operator<<(const FmtUShort& fmt)
827  { writefmtnumu(fmt.num, fmt.fmt); return *this; }
828 
830  This& operator<<(const FmtUInt& fmt)
831  { writefmtnumu(fmt.num, fmt.fmt); return *this; }
832 
834  This& operator<<(const FmtULong& fmt)
835  { writefmtnumu(fmt.num, fmt.fmt); return *this; }
836 
838  This& operator<<(const FmtULongL& fmt)
839  { writefmtnumu(fmt.num, fmt.fmt); return *this; }
840 
842  This& operator<<(const FmtFloat& fmt)
843  { writefmtnumf(fmt.num, fmt.fmt); return *this; }
844 
846  This& operator<<(const FmtFloatD& fmt)
847  { writefmtnumf(fmt.num, fmt.fmt); return *this; }
848 
850  This& operator<<(const FmtFloatL& fmt)
851  { writefmtnumf(fmt.num, fmt.fmt); return *this; }
852 
854  template<class U>
855  This& operator<<(const FmtFieldNum<U>& fmt) {
856  if (IntegerT<U>::SIGN)
857  writefmtnum(fmt.num.num, fmt.num.fmt, &fmt.field);
858  else
859  writefmtnumu(fmt.num.num, fmt.num.fmt, &fmt.field);
860  return *this;
861  }
862 
864  template<class U>
865  This& operator<<(const FmtFieldFloat<U>& fmt)
866  { writefmtnumf(fmt.num.num, fmt.num.fmt, &fmt.field); return *this; }
867 
869  This& operator<<(const FmtPtr& fmtptr)
870  { writefmtnumu((ulong)fmtptr.ptr, fmtptr.fmt); return *this; }
871 
873  This& operator<<(const FmtDump& fmt)
874  { writefmtdump(fmt); return *this; }
875 
876 protected:
878  bool owned_;
880 
882  void init(bool flushlines=false) {
883  bufwr_.open(flushlines);
884  }
885 
886 private:
887  StreamOut(const This&);
888  This& operator=(const This&);
889 };
890 
892 
895 class PipeIn : public StreamIn<IoFile> {
896 public:
898 
902  PipeIn(bool exceptions=EVO_EXCEPTIONS) {
903  excep(exceptions);
904  }
905 
906 private:
907  PipeIn(const PipeIn&);
908  PipeIn& operator=(const PipeIn&);
909 };
910 
912 
915 class PipeOut : public StreamOut<IoFile> {
916 public:
918 
922  PipeOut(bool exceptions=EVO_EXCEPTIONS) {
923  excep(exceptions);
924  }
925 
926 private:
927  PipeOut(const PipeOut&);
928  PipeOut& operator=(const PipeOut&);
929 };
930 
932 
935 struct Pipe {
938 };
939 
941 
972 struct Console {
974  typedef PipeIn InT;
975  typedef PipeOut OutT;
976 
980 
984  static Console& get() {
985  static Console console;
986  return console;
987  }
988 
989 private:
990  static const PipeIn::Handle HIN = 0;
991  static const PipeOut::Handle HOUT = 1;
992  static const PipeOut::Handle HERR = 2;
993 
994  static const ulong IN_BUFSZ = 4096;
995  static const ulong OUT_BUFSZ = 4096;
996  static const ulong ERR_BUFSZ = 1024;
997 
998  Console() {
999  in.bufread().resize( IN_BUFSZ);
1000  out.bufwrite().resize(OUT_BUFSZ);
1001  err.bufwrite().resize(ERR_BUFSZ);
1002 
1003  in.attach( HIN, false);
1004  out.attach(HOUT, false, false);
1005  err.attach(HERR, false, true);
1006  }
1007 
1008  Console(const Console&);
1009  Console& operator=(const Console&);
1010 };
1011 
1015 inline Console& con() {
1016  return Console::get();
1017 }
1018 
1020 
1024 template<class T,class M>
1025 struct StreamExtMT {
1027 
1028  M mutex;
1029  T& stream;
1030 
1034  StreamExtMT(T& stream) : stream(stream)
1035  { }
1036 
1037 private:
1038  StreamExtMT(This&);
1039  This& operator=(This&);
1040 };
1041 
1043 
1055 
1056  InT in;
1057  OutT out;
1058  OutT err;
1059 
1063  static ConsoleNotMT& get()
1064  { static ConsoleNotMT console(con()); return console; }
1065 
1066 private:
1067  ConsoleNotMT(Console& c) : in(c.in), out(c.out), err(c.err)
1068  { }
1069 
1070  ConsoleNotMT(const ConsoleNotMT&);
1071  ConsoleNotMT& operator=(const ConsoleNotMT&);
1072 };
1073 
1075 
1076 }
1077 #endif
bool empty() const
Get whether empty.
Error readline(String &str, T &in, ulong maxlen=0)
Read a line from file using buffer.
Definition: sysio.h:947
void open(bool flushlines_val=false)
Initialize and open for output (writing).
Definition: sysio.h:1051
CharBreakType ascii_breaktype(char ch)
Get ASCII character word-break type.
Definition: str.h:91
bool flush()
Flush any pending output in stream write buffer, if buffered.
Definition: io.h:349
This & operator<<(ulong num)
Write formatted number to stream.
Definition: io.h:719
This & operator<<(char ch)
Write character to stream.
Definition: io.h:672
StreamExtMT< T, M > This
This type.
Definition: io.h:1026
const char * getnewline(Newline newline=NL)
Get newline string for given type.
Definition: sys.h:793
This & operator<<(int num)
Write formatted number to stream.
Definition: io.h:703
bool writenumu(TNum num, int base=fDEC)
Write formatted unsigned number.
Definition: io.h:508
SubString & triml(Size size)
Trim left (beginning) items.
Definition: substring.h:1307
This & operator<<(const FmtLongL &fmt)
Write formatted number field to stream.
Definition: io.h:822
Holds integer formatting attributes.
Definition: str.h:2589
This & operator<<(bool val)
Append a bool value to stream.
Definition: io.h:661
Output stream implementation.
Definition: io.h:261
This & operator<<(ulongl num)
Write formatted number to stream.
Definition: io.h:723
Holds a Newline value that can be null, which implicitly converts to NL_SYS (system default newline)...
Definition: sys.h:813
This & operator<<(const FmtDump &fmt)
Write formatted data dump to stream.
Definition: io.h:873
This & operator<<(uint num)
Write formatted number to stream.
Definition: io.h:715
This & operator<<(This &)
No-op used by formatting helpers.
Definition: io.h:620
StringBase str
Definition: str.h:3006
This & operator<<(const FmtString &fmt)
Write formatted string field to stream.
Definition: io.h:763
Invalid argument or data.
Definition: sys.h:1123
bool readline(String &str, ulong maxlen=0)
Read text line input from stream.
Definition: io.h:204
bool excep() const
Get whether exceptions are enabled.
Definition: iobase.h:52
Extends an existing stream with mutex for multithreaded synchronization.
Definition: io.h:1025
Handle detach()
Detach current stream.
Definition: io.h:311
ulong readbin(Error &err, T &in, void *buf, ulong bufsize)
Read from file using buffer.
Definition: sysio.h:751
bool writenum(TNum num, int base=fDEC)
Write formatted signed number.
Definition: io.h:493
T::ExceptionInT ExceptionInT
Stream input exception type
Definition: io.h:125
Single-quotes: &#39;
Definition: strscan.h:1898
PipeOut(bool exceptions=1)
Constructor.
Definition: io.h:922
This & operator<<(double num)
Write formatted floating-point number to stream.
Definition: io.h:743
T::Handle Handle
Low-level handle type (OS dependent)
Definition: io.h:263
ulong readtext(Error &err, T &in, char *buf, ulong bufsize)
Read from file using buffer.
Definition: sysio.h:826
bool isopen() const
Get whether stream is open.
Definition: io.h:186
Console & con()
Shortcut for Console::get().
Definition: io.h:1015
bool write_direct_finish(Size size)
Finish writing directly to buffer.
Definition: io.h:485
PipeOut::Format Format
Stream output formatter with state.
Definition: io.h:1051
Console I/O.
Definition: io.h:972
Error error_
Last error code.
Definition: iobase.h:133
This & operator<<(Newline nl)
Write an explicit newline and flush stream.
Definition: io.h:624
Automatic floating point precision – either normal decimal notation or E notation, whichever is shorter (default)
Definition: str.h:2343
Single threaded console I/O.
Definition: io.h:1050
IoWriter & bufwrite()
Advanced: Access primary write buffer.
Definition: io.h:288
Backtick: `
Definition: strscan.h:1900
Triple backtick: ```
Definition: strscan.h:1903
Triple single-quotes: &#39;&#39;&#39;
Definition: strscan.h:1901
bool writefmtchar(char ch, ulong count, const FmtSetField &field)
Write formatted and/or repeated character.
Definition: io.h:537
virtual bool flush()
Flush any pending output in stream write buffer, if buffered.
Definition: iobase.h:127
bool isopen() const
Get whether stream is open.
Definition: io.h:344
This & operator<<(const FmtInt &fmt)
Write formatted number field to stream.
Definition: io.h:814
uint count
Character repeat count.
Definition: str.h:2916
bool excep_
Whether to throw exceptions.
Definition: iobase.h:134
Base text and binary stream interface.
Definition: iobase.h:145
Output stream exception for stream write errors, see Exception.
Definition: sys.h:1401
OutT err
Write to console, error output.
Definition: io.h:1058
Newline
Newline type.
Definition: sys.h:748
#define EVO_THROW_ERR_CHECK(TYPE, MSG, ERROR, COND)
Throw an Evo exception with error code if COND is true.
Definition: sys.h:1513
virtual ulong writechar(char ch, ulong count=1)
Write repeat character as text output to stream.
Definition: iobase.h:219
PipeIn(bool exceptions=1)
Constructor.
Definition: io.h:902
void open()
Initialize and open for input (reading).
Definition: sysio.h:690
PipeIn InT
Input type.
Definition: io.h:974
This & operator<<(const FmtULong &fmt)
Write formatted number field to stream.
Definition: io.h:834
StreamOut(Newline newlines=NL_SYS)
Constructor.
Definition: io.h:274
PipeOut err
Write to console, error output.
Definition: io.h:979
ulong writeline(const char *buf, ulong size)
Write text line output to stream.
Definition: io.h:415
Basic integer type.
Definition: type.h:980
char * write_direct(Size size)
Get pointer for writing directly to buffer to append data.
Definition: io.h:428
FmtSetFloat fmt
Definition: str.h:3156
bool writefmtnumf(TNum num, const FmtSetFloat &fmt, const FmtSetField *field=NULL)
Write formatted floating point number with field alignment.
Definition: io.h:590
int width
Definition: str.h:3007
Size size() const
Get size.
This & operator<<(const FmtUInt &fmt)
Write formatted number field to stream.
Definition: io.h:830
PipeOut OutT
Output type.
Definition: io.h:975
No error.
Definition: sys.h:1115
Reached end of resource (not an error)
Definition: sys.h:1116
Evo inert synchronization implementation.
#define EVO_EXCEPTIONS
Whether to throw exceptions on error by default.
Definition: evo_config.h:35
StreamExtMT< PipeOut, MutexInert > OutT
Output type.
Definition: io.h:1053
virtual ulong writebin(const void *buf, ulong size)
Write binary output to stream.
Definition: iobase.h:113
uint getnewlinesize(Newline newline=NL)
Get newline string size for given type.
Definition: sys.h:804
Base 10: decimal (default)
Definition: str.h:2323
ulong writechar(char ch, ulong count=1)
Write repeat character as text output to stream.
Definition: io.h:364
String container.
Definition: string.h:674
char * write_direct_multi(Size &available, Size reserve_size)
Definition: io.h:444
Evo base I/O stream classes.
Pipe stream access.
Definition: io.h:935
This & operator<<(const NewlineValue &nl)
Write newline value and flush stream.
Definition: io.h:643
Buffered reader for IoDevice (used internally).
Definition: sysio.h:658
Key findnonwordr(Key start=0, Key end=END) const
Find last non-word character with reverse search.
Definition: substring.h:949
T::ExceptionOutT ExceptionOutT
Stream output exception type
Definition: io.h:269
IoWriter bufwr_
Write buffer.
Definition: io.h:879
Definition: str.h:3003
InT in
Read console input.
Definition: io.h:1056
Input stream implementation.
Definition: io.h:120
Flush
Signals an output stream to flush pending data.
Definition: sys.h:739
ulong writebin(const void *buf, ulong size)
Write binary output to stream.
Definition: io.h:358
SubString & stripl()
Strip left (beginning) whitespace (spaces and tabs).
Definition: substring.h:1090
void init()
Initialize and reset buffers for a new stream.
Definition: io.h:219
bool writefmtnumu(TNum num, const FmtSetInt &fmt, const FmtSetField *field=NULL)
Write formatted unsigned number with field alignment.
Definition: io.h:575
This & operator<<(const FmtULongL &fmt)
Write formatted number field to stream.
Definition: io.h:838
OutT out
Write to console, normal output.
Definition: io.h:1057
This & operator<<(NewlineDefault nl)
Write default newline and flush stream.
Definition: io.h:633
StreamIn< T > This
This stream type.
Definition: io.h:123
This & operator<<(const FmtUShort &fmt)
Write formatted number field to stream.
Definition: io.h:826
Stream output formatter with state.
Definition: iobase.h:406
RawBuffer readbuf
Primary read buffer – filtering may involve additional buffers.
Definition: sysio.h:661
Explicitly format an integer.
Definition: str.h:3065
Inert lock that doesn&#39;t do anything.
Definition: thread_inert.h:27
StreamOut< T > This
This stream type.
Definition: io.h:264
const char * getnewline() const
Get newline string pointer for current value.
Definition: sys.h:885
This & operator<<(long num)
Write formatted number to stream.
Definition: io.h:707
bool writenumf(TNum num, int precision=fPREC_AUTO)
Write formatted floating-point number.
Definition: io.h:523
bool writefmtdump(const FmtDump &fmt)
Write formatted data dump.
Definition: io.h:604
This & operator<<(const FmtPtr &fmtptr)
Writer formatted pointer field to stream.
Definition: io.h:869
void attach(Handle handle, bool owned=true)
Attach existing input stream.
Definition: io.h:147
This & operator<<(const FmtFloatL &fmt)
Write formatted number field to stream.
Definition: io.h:850
Handle handle() const
Get stream handle for low-level calls.
Definition: io.h:284
This & operator<<(const FmtStringWrap &fmt)
Definition: io.h:766
This & operator<<(const FmtFloatD &fmt)
Write formatted number field to stream.
Definition: io.h:846
PipeIn in
Read console input.
Definition: io.h:977
FmtSetInt fmt
Formatting attributes.
Definition: str.h:3266
ulong Size
Data size type (ulong)
Definition: iobase.h:146
RawBuffer & bufread()
Advanced: Access primary read buffer.
Definition: io.h:140
Double-quotes: "
Definition: strscan.h:1899
RawBuffer & resize(ulong newsize)
Resize buffer.
Definition: rawbuffer.h:116
This & operator<<(const SubString &str)
Write substring to stream.
Definition: io.h:686
Triple double-quotes: """
Definition: strscan.h:1902
This & operator<<(Flush)
Flush buffer by writing to stream.
Definition: io.h:654
Evo C++ Library namespace.
Definition: alg.h:11
Out & write_out()
Definition: io.h:425
static const EndT NONE
Special integer value for indicating no item or unknown item.
Definition: type.h:1832
StreamExtMT< PipeIn, MutexInert > InT
Input type.
Definition: io.h:1052
bool writefmtstr(const char *buf, ulong size, const FmtSetField &field)
Write text with field alignment.
Definition: io.h:548
Holds floating point formatting attributes.
Definition: str.h:2775
Explicitly format a string.
Definition: str.h:2931
ulong readtext(char *buf, ulong size)
Read text input from stream.
Definition: io.h:198
~StreamOut()
Destructor.
Definition: io.h:280
PipeOut out
Write to console, normal output.
Definition: io.h:978
bool owned_
Whether handle is owned (to be closed here)
Definition: io.h:878
StreamExtMT(T &stream)
Constructor.
Definition: io.h:1034
M mutex
Stream mutex.
Definition: io.h:1028
bool owned_
Whether handle is owned (to be closed here)
Definition: io.h:215
T num
Definition: str.h:3155
This & operator<<(const FmtChar &fmt)
Write repeated character to stream.
Definition: io.h:759
bool close()
Close stream.
Definition: io.h:174
This Out
Type returned by write_out()
Definition: io.h:265
FmtSetInt fmt
Formatting attributes.
Definition: str.h:3072
This & operator<<(ldouble num)
Write formatted floating-point number to stream.
Definition: io.h:747
void attach(Handle handle, bool owned=true, bool flushlines=false)
Attach existing output stream.
Definition: io.h:296
bool writefmtnum(TNum num, const FmtSetInt &fmt, const FmtSetField *field=NULL)
Write formatted signed number with field alignment.
Definition: io.h:560
static const Newline NL_SYS
Current system newline type.
Definition: sys.h:763
Buffered writer for IoDevice (used internally).
Definition: sysio.h:1023
T * data_
Data pointer, NULL if null.
Definition: sys.h:979
Backtick followed by DEL char (7F) – last resort (rare)
Definition: strscan.h:1904
PipeOut::Format Format
Stream output formatter with state.
Definition: io.h:973
Explicitly format a repeated character.
Definition: str.h:2914
PipeIn in
Definition: io.h:936
This & operator<<(const FmtFloat &fmt)
Write formatted number field to stream.
Definition: io.h:842
Handle handle() const
Get stream handle for low-level calls.
Definition: io.h:136
char * write_direct_flush(Size &available, Size written_size, Size reserve_size)
Definition: io.h:464
Default newline type, implicitly converts to NL_SYS (system default newline).
Definition: sys.h:773
StreamFormatter< This > Format
Stream output formatter with state.
Definition: io.h:267
Explicitly format a pointer.
Definition: str.h:3264
Size writequoted(const char *buf, Size size, char delim, bool optional=false)
Write quoted text output to string.
Definition: io.h:376
StreamIn(Newline newlines=NL_SYS)
Constructor.
Definition: io.h:130
int indent
Definition: str.h:3008
static Type get(const char *data, ulong data_size)
Definition: strscan.h:1917
This & operator<<(float num)
Write formatted floating-point number to stream.
Definition: io.h:739
T::Handle Handle
Low-level handle type (OS dependent)
Definition: io.h:122
TSize size_
Data size as item count, 0 if empty or null.
Definition: sys.h:980
StringBase str
Definition: str.h:2936
ulong readbin(void *buf, ulong size)
Read binary input from stream.
Definition: io.h:192
Handle detach()
Detach current stream.
Definition: io.h:161
This & operator<<(const FmtLong &fmt)
Write formatted number field to stream.
Definition: io.h:818
const void * ptr
Pointer to format.
Definition: str.h:3265
PipeOut out
Definition: io.h:937
T & stream
Stream object.
Definition: io.h:1029
Punctuation used before a word begins, break words before this ( ([{< )
Definition: str.h:63
This & operator<<(const char *str)
Write terminated string to stream.
Definition: io.h:679
SubString & set(const char *data)
Set as reference to terminated string.
Definition: substring.h:353
Reference and access existing string data.
Definition: substring.h:229
IoReader bufrd_
Buffered reader.
Definition: io.h:216
char ch
Character to format.
Definition: str.h:2915
Input stream for reading from pipe.
Definition: io.h:895
FmtSetField fmt
Definition: str.h:2937
void close()
Close input.
Definition: sysio.h:699
ulong writetext(const char *buf, ulong size)
Write text output to stream.
Definition: io.h:370
Output stream for writing to pipe.
Definition: io.h:915
Explicitly format a floating pointer number.
Definition: str.h:3148
Simple raw memory buffer.
Definition: rawbuffer.h:34
Holds field and alignment formatting attributes.
Definition: str.h:2481
T num
Number to format.
Definition: str.h:3071
NewlineValue newline
Definition: str.h:3009
This & operator<<(longl num)
Write formatted number to stream.
Definition: io.h:711
void init(bool flushlines=false)
Initialize and reset buffers for a new stream.
Definition: io.h:882
bool close()
Close stream.
Definition: io.h:327
T device_
I/O handle.
Definition: io.h:214
Data not quotable (invalid text)
Definition: strscan.h:1905
Explicitly format a hex dump from buffer.
Definition: str.h:3294
#define EVO_PARAM_UNUSED(NAME)
Mark function parameter as unused to suppress "unreferenced parameter" compiler warnings on it...
Definition: sys.h:427
static Console & get()
Get console instance to use.
Definition: io.h:984
const char * data() const
Get data pointer.
MutexInert::Lock Lock
Mutex lock type.
Definition: io.h:1054
This & operator<<(const FmtShort &fmt)
Write formatted number field to stream.
Definition: io.h:810
Type
Quoting type.
Definition: strscan.h:1897
T device_
I/O handle.
Definition: io.h:877