Elementa v8.0.0
Minimalistic library for any C++ application (C++11 and up)
Loading...
Searching...
No Matches
channels.h
Go to the documentation of this file.
1
3#include "elementa/license.inc"
4#include "elementa/checks.inc"
5
6#ifndef ELEMENTA_BASE_SERIALCHANNELS_CHANNELS_H
7#define ELEMENTA_BASE_SERIALCHANNELS_CHANNELS_H
8
9
10#include <streambuf>
11#include <vector>
12#include <array>
13#include <string>
15
16
17namespace elementa
18{
19
20namespace base
21{
22
23
64/* ***************************************************************************
65
66 Class: SerChO_Null
67
68*****************************************************************************/
69
71
80class SerChO_Null: public OutSerCh
81{
82 public:
83
84 SerChO_Null(void): sbuf_{}, // first create buffer
85 OutSerCh{&sbuf_} // then use it in base ctror
86 {}
87
88 private:
89
90 class NullOutStreamBuf: public std::streambuf
91 {
92 using BaseStreamBuf = std::streambuf;
93
94 public:
95
96 // all constructors/destructors by default (by default writing cursors
97 // are all null, thus forcing overflow)
98
99 private:
100
101 SerChDatum overflow(SerChDatum c = kSerChEOF) override;
102 };
103
104 NullOutStreamBuf sbuf_;
105};
106
107
108/* ***************************************************************************
109
110 Class: SerChO_NullCoBuf
111
112*****************************************************************************/
113
115
127{
128 public:
129
132 OutSerCh{&sbuf_}
133 {}
134
136 SerChSize size(void) const { return(sbuf_.size()); }
137
139 void reset(void) { sbuf_.reset(); }
140
142 SerChSize count(void) const { return(sbuf_.count()); }
143
145 const char * buffer(void) const { return(sbuf_.buffer()); }
146
147 private:
148
149 class NullOutStreamBuf: public std::streambuf
150 {
151 using BaseStreamBuf = std::streambuf;
152
153 public:
154
155 NullOutStreamBuf(SerChSize buffer);
156 ~NullOutStreamBuf(void);
157
158 SerChSize size(void) const { return(size_); }
159 void reset(void) { count_ = 0; }
160 SerChSize count(void) const { return(count_); }
161 const char * buffer(void) const { return(buffer_); }
162
163 private:
164
165 SerChDatum overflow(SerChDatum c = kSerChEOF) override;
166
167 SerChSize count_,size_;
168 char * buffer_;
169 };
170
171 NullOutStreamBuf sbuf_;
172};
173
174
175/* ***************************************************************************
176
177 Template class: SerChO_AppCont
178
179*****************************************************************************/
180
182
195template <class Cont>
197{
198 public:
199
201
203 SerChO_AppCont(Cont & cont):sbuf_{cont},OutSerCh{&sbuf_}
204 {}
205
207 Cont & container(void) noexcept { return(sbuf_.container()); }
208
209
210 private:
211
212 class AppContOutStreamBuf: public std::streambuf
213 {
214 using BaseStreamBuf = std::streambuf;
215
216 public:
217
218 AppContOutStreamBuf(Cont & cont):cont_{cont} {}
219 ~AppContOutStreamBuf(void) = default;
220
221 Cont & container(void) noexcept { return(cont_); }
222
223 private:
224
225 SerChDatum overflow(SerChDatum c = kSerChEOF) override
226 {
227 cont_.push_back(c);
228 // keep cursors in overflow
229 return(c == kSerChEOF ? 0 : c);
230 }
231
232 Cont & cont_;
233 };
234
235 AppContOutStreamBuf sbuf_;
236};
237
238
239/* ***************************************************************************
240
241 Class: SerChI_Constant
242 Object: serchI_dummy
243
244*****************************************************************************/
245
247
252{
253 public:
254
255 SerChI_Constant(char c): sbuf_{c}, // first create buffer
256 InSerCh{&sbuf_} // then use it in base ctror
257 {}
258
259 private:
260
261 class ConstInStreamBuf: public std::streambuf
262 {
263 using BaseStreamBuf = std::streambuf;
264
265 public:
266
267 ConstInStreamBuf(char c):c_{c} // pointers null to force uflow()
268 {}
269
270 private:
271
272 char c_;
273
274 SerChDatum uflow(void) override;
275 SerChDatum underflow(void) override;
276 SerChDatum pbackfail (SerChDatum c = kSerChEOF) override;
277 };
278
279 ConstInStreamBuf sbuf_;
280};
281
282
285
286
287/* ***************************************************************************
288
289 Class: SerChI_Procedural
290
291*****************************************************************************/
292
294
300{
301 public:
302
304
306 using Procedure = std::function< SerChDatum(void) >;
307
309 SerChI_Procedural(Procedure & p): sbuf_{p}, // first create buffer
310 InSerCh{&sbuf_} // then use it
311 {}
312
313 private:
314
315 class ProcInStreamBuf: public std::streambuf
316 {
317 using BaseStreamBuf = std::streambuf;
318
319 public:
320
321 ProcInStreamBuf(Procedure & p):p_{p},lastc_{kSerChEOF},
322 alreadyread_{false}
323 {} // pointers null to force uflow()
324
325 private:
326
327 Procedure & p_;
328 SerChDatum lastc_;
329 bool alreadyread_;
330
331 SerChDatum uflow(void) override;
332 SerChDatum underflow(void) override;
333 SerChDatum pbackfail(SerChDatum c = kSerChEOF) override;
334 };
335
336 ProcInStreamBuf sbuf_;
337};
338
339
340
341/* ======================================================================
342
343 MEMORY CHANNELS
344
345========================================================================= */
346
347
348/* ***************************************************************************
349
350 Non-usable classes: InOutStreamBuf_MemoryPriv, InStreamBuf_MemoryPriv
351
352*****************************************************************************/
353
355class SerChI_Memory;
356
357
359class InOutStreamBuf_MemoryPriv;
360
361
363class InStreamBuf_MemoryPriv: public std::streambuf
364{
365 public:
366
367 void reset(const char * begin, const char * end);
368 SerChSize transfer(InOutStreamBuf_MemoryPriv & other, SerChSize count);
369
370 private:
371
372 const char * begin_;
373 const char * end_;
374
375 std::streamsize xsgetn(char *s, std::streamsize n) override;
376 SerChDatum pbackfail (SerChDatum c = kSerChEOF) override;
377 SerChSize copyTo(const char * itorg, char * dest, SerChSize n) noexcept;
378 SerChSize copyFrom(const char * org, char * itdest,SerChSize n)noexcept;
379};
380
382class InOutStreamBuf_MemoryPriv: public std::streambuf
383{
384 friend InStreamBuf_MemoryPriv; // for InStreamBuf_MemoryPriv to access my ptrs
385 // during transfers from there
386
387 public:
388
389 void reset(char * begin, char * end);
390 SerChSize transfer(InOutStreamBuf_MemoryPriv & other, SerChSize count);
391
392 private:
393
394 char * begin_;
395 char * end_;
396
397 std::streamsize xsgetn(char *s, std::streamsize n) override;
398 std::streamsize xsputn(const char* s, std::streamsize n) override;
399 SerChDatum pbackfail (SerChDatum c = kSerChEOF) override;
400 SerChSize copyTo(const char * itorg, char * dest, SerChSize n) noexcept;
401 SerChSize copyFrom(const char * org, char * itdest,SerChSize n)noexcept;
402};
403
404
405/* ***************************************************************************
406
407 Class: SerChIO_Memory
408
409*****************************************************************************/
410
412
421{
422 friend SerChI_Memory;
423
424 public:
425
427
430 template <typename T>
431 SerChIO_Memory(void * begin, T n) noexcept;
432
434
438 SerChIO_Memory(std::string & str,
439 std::string::size_type offbegin = 0,
440 std::string::size_type offend = 0);
441
443
449 template <typename T>
450 SerChIO_Memory(std::vector<T> & v,
451 typename std::vector<T>::size_type offbegin = 0,
452 typename std::vector<T>::size_type offend = 0);
453
455
461 template <typename T, std::size_t N>
462 SerChIO_Memory(std::array<T,N> & a,
463 typename std::array<T,N>::size_type offbegin = 0,
464 typename std::array<T,N>::size_type offend = 0);
465
466
467 SerChIO_Memory(const SerChIO_Memory &) = delete;
468 SerChIO_Memory(SerChIO_Memory &&) = delete;
469 SerChIO_Memory & operator=(SerChIO_Memory &) = delete;
470 SerChIO_Memory & operator=(SerChIO_Memory &&) = delete;
471
473 void reset(void);
474
476
479 { if (good() && chout.good()) return(sbuf_.transfer(chout.sbuf_,count));
480 return(0); }
481
482 private:
483
484 char * begin_;
485 char * end_;
487};
488
489
491
493template <>
494inline
496 SerChIO_Memory & chout,
497 SerChSize count)
498{
500
501 ELE_CODE_TRACE({},"both containers case of serch_transfer (chin state={"<<
502 serch_st_to_string(chin) <<
503 "}, chout state={" <<
504 serch_st_to_string(chout) <<
505 "}, count = " << count);
506 return(chin.transfer(chout,count));
507}
508
509
510/* ***************************************************************************
511
512 Class: SerChI_Memory
513
514*****************************************************************************/
515
517
526{
527 public:
528
530
533 template <typename T>
534 SerChI_Memory(const void * begin, T n) noexcept;
535
537
539 SerChI_Memory(const std::string & str,
540 std::string::size_type offbegin = 0,
541 std::string::size_type offend = 0);
542
544
549 template <typename T>
550 SerChI_Memory(const std::vector<T> & v,
551 typename std::vector<T>::size_type offbegin = 0,
552 typename std::vector<T>::size_type offend = 0);
553
555
560 template <typename T, std::size_t N>
561 SerChI_Memory(const std::array<T,N> & a,
562 typename std::array<T,N>::size_type offbegin = 0,
563 typename std::array<T,N>::size_type offend = 0);
564
565 SerChI_Memory(const SerChI_Memory &) = delete;
566 SerChI_Memory(SerChI_Memory &&) = delete;
567 SerChI_Memory & operator=(SerChI_Memory &) = delete;
568 SerChI_Memory & operator=(SerChI_Memory &&) = delete;
569
571 void reset(void);
572
574
577 { if (good() && chout.good()) return(sbuf_.transfer(chout.sbuf_,count));
578 return(0); }
579
580 private:
581
582 const char * begin_;
583 const char * end_;
585};
586
587
589
591template <>
592inline
594 SerChIO_Memory & chout,
595 SerChSize count)
596{
598
599 ELE_CODE_TRACE({},"both containers case of serch_transfer (chin state={"<<
600 serch_st_to_string(chin) <<
601 "}, chout state={" <<
602 serch_st_to_string(chout) <<
603 "}, count = " << count);
604 return(chin.transfer(chout,count));
605}
606
607
608
609/* ======================================================================
610
611 TEMPLATE IMPLEMENTATIONS
612
613========================================================================= */
614
615/* ***************************************************************************
616
617 Class: SerChIO_Memory
618
619*****************************************************************************/
620
621template <typename T>
622SerChIO_Memory::SerChIO_Memory(void * begin, T n) noexcept:
623 begin_{reinterpret_cast<char *>(begin)},
624 end_{reinterpret_cast<char *>(begin) + n},
625 sbuf_{},
626 InOutSerCh{&sbuf_}
627{
628 reset();
629 static_assert(std::is_integral<T>::value,
630 "The size type must be integral in the "
631 "SerChIO_Memory constructor");
632}
633
634template <typename T>
636 typename std::vector<T>::size_type offbegin,
637 typename std::vector<T>::size_type offend):
638 sbuf_{},
639 InOutSerCh{&sbuf_}
640{
641 if ( (v.size() > 0) && (offbegin < v.size()) &&
642 (offend < v.size()) && (offbegin + offend < v.size()) )
643 {
644 begin_ = reinterpret_cast<char *>(v.data() + offbegin);
645 end_ = reinterpret_cast<char *>(v.data() + (v.size() - offend));
646 reset();
647 }
648 else ELE_CODE_INVARG("Empty vector or invalid offsets");
649}
650
651template <typename T, std::size_t N>
653 typename std::array<T,N>::size_type offbegin,
654 typename std::array<T,N>::size_type offend):
655 sbuf_{},
656 InOutSerCh{&sbuf_}
657{
658 if ( (a.size() > 0) && (offbegin < a.size()) &&
659 (offend < a.size()) && (offbegin + offend < a.size()) )
660 {
661 begin_ = reinterpret_cast<char *>(a.data() + offbegin);
662 end_ = reinterpret_cast<char *>(a.data() + (a.size() - offend));
663 reset();
664 }
665 else ELE_CODE_INVARG("Empty vector or invalid offsets");
666}
667
668
669/* ***************************************************************************
670
671 Class: SerChI_Memory
672
673*****************************************************************************/
674
675template <typename T>
676SerChI_Memory::SerChI_Memory(const void * begin, T n) noexcept:
677 begin_{reinterpret_cast<const char *>(begin)},
678 end_{reinterpret_cast<const char *>(begin) + n},
679 sbuf_{},
680 InSerCh{&sbuf_}
681{
682 reset();
683 static_assert(std::is_integral<T>::value,
684 "The size type must be integral in the "
685 "SerChI_Memory constructor");
686}
687
688template <typename T>
689SerChI_Memory::SerChI_Memory(const std::vector<T> & v,
690 typename std::vector<T>::size_type offbegin,
691 typename std::vector<T>::size_type offend):
692 sbuf_{},
693 InOutSerCh{&sbuf_}
694{
695 if ( (v.size() > 0) && (offbegin < v.size()) &&
696 (offend < v.size()) && (offbegin + offend < v.size()) )
697 {
698 begin_ = reinterpret_cast<const char *>(v.data() + offbegin);
699 end_ = reinterpret_cast<const char *>(v.data() +
700 (v.size() - offend));
701 reset();
702 }
703 else ELE_CODE_INVARG("Empty vector or invalid offsets");
704}
705
706template <typename T, std::size_t N>
707SerChI_Memory::SerChI_Memory(const std::array<T,N> & a,
708 typename std::array<T,N>::size_type offbegin,
709 typename std::array<T,N>::size_type offend):
710 sbuf_{},
711 InOutSerCh{&sbuf_}
712{
713 if ( (a.size() > 0) && (offbegin < a.size()) &&
714 (offend < a.size()) && (offbegin + offend < a.size()) )
715 {
716 begin_ = reinterpret_cast<const char *>(a.data() + offbegin);
717 end_ = reinterpret_cast<const char *>(a.data() +
718 (a.size() - offend));
719 reset();
720 }
721 else ELE_CODE_INVARG("Empty vector or invalid offsets");
722}
723
724
725
726 // SerCh_channels
728
729
730} // end namespace base
731
732} // end namespace elementa
733
734#endif
735
#define ELE_CODE_TRACE_OFF
Place this inside local scope (e.g., routine) to deactivate traces there.
Definition: debugging.h:283
#define ELE_CODE_INVARG(expl)
To throw an invalid-argument exception with an explanation.
Definition: exceptions.h:310
std::istream InSerCh
"Base class" that represents any input serial channel in Elementa.
Definition: basics.h:334
std::streambuf::int_type SerChDatum
Type that can hold either a char or eof.
Definition: basics.h:181
std::iostream InOutSerCh
"Base class" that represents any input + output serial channel in Elementa.
Definition: basics.h:356
std::streamsize SerChSize
Type of the size of any channel.
Definition: basics.h:178
std::ostream OutSerCh
"Base class" that represents any output serial channel in Elementa.
Definition: basics.h:247
constexpr SerChDatum kSerChEOF
Const that holds the eof value.
Definition: basics.h:189
std::string serch_st_to_string(std::ios_base::iostate st) noexcept
Converts an io state into a string.
SerChSize transfer(SerChIO_Memory &chout, SerChSize count=0)
Specialized version of serch_transfer when both channels are of memory.
Definition: channels.h:576
SerChO_NullCoBuf(SerChSize buffer=0)
Create a serial channel able to count and with a buffer of BUFFER chars.
Definition: channels.h:131
const char * buffer(void) const
Return nullptr if the buffer has size 0, or the buffer otherwise.
Definition: channels.h:145
SerChSize size(void) const
Return the buffer size defined in the constructor.
Definition: channels.h:136
SerChIO_Memory(std::string &str, std::string::size_type offbegin=0, std::string::size_type offend=0)
Constructor for a region within a string.
Cont & container(void) noexcept
Return a reference to the container.
Definition: channels.h:207
SerChI_Memory(const std::string &str, std::string::size_type offbegin=0, std::string::size_type offend=0)
Constructor for a region within a string.
void reset(void)
Reset the count of the channel and, if any, clear the buffer.
Definition: channels.h:139
SerChI_Procedural(Procedure &p)
Constructor. P must outlive this channel: only a reference is taken.
Definition: channels.h:309
SerChO_AppCont(Cont &cont)
Create a serial channel to append chars at the end of CONT.
Definition: channels.h:203
void reset(void)
Reset the channel to its initial position and state.
SerChSize transfer(SerChIO_Memory &chout, SerChSize count=0)
Specialized version of serch_transfer when both channels are of memory.
Definition: channels.h:478
void reset(void)
Reset the channel to its initial position and state.
std::function< SerChDatum(void) > Procedure
A procedure that generates the characters.
Definition: channels.h:306
SerChSize count(void) const
Return the current number of chars already serialized.
Definition: channels.h:142
Private class that needs to be here for the following channels to work.
Definition: channels.h:383
Private class that needs to be here for the following channels to work.
Definition: channels.h:364
Input serial channel that provides a pre-defined char value endlessly.
Definition: channels.h:252
Input + output ser. chan. associated to a pre-allocated region of memory.
Definition: channels.h:526
Input serial channel that provides values based on some procedure.
Definition: channels.h:300
Input + output ser. chan. associated to a pre-allocated region of memory.
Definition: channels.h:421
Output ser. chan. that appends to a container without pre-allocated storage.
Definition: channels.h:197
Null output serial channel to discard anything written to it.
Definition: channels.h:81
Null output serial channel that can count what is written and also buffer it.
Definition: channels.h:127
SerChSize serch_transfer< SerChIO_Memory, SerChIO_Memory >(SerChIO_Memory &chin, SerChIO_Memory &chout, SerChSize count)
Full specialization of serch_transfer for both channels being Memory.
Definition: channels.h:495
SerChIO_Memory(void *begin, T n) noexcept
Template constructor.
Definition: channels.h:622
SerChSize serch_transfer< SerChI_Memory, SerChIO_Memory >(SerChI_Memory &chin, SerChIO_Memory &chout, SerChSize count)
Full specialization of serch_transfer for both channels being Memory.
Definition: channels.h:593
SerChI_Memory(const void *begin, T n) noexcept
Template constructor.
Definition: channels.h:676
SerChI_Constant serchI_dummy
A singleton, dummy input channel that always produces space characters.