Elementa v8.0.0
Minimalistic library for any C++ application (C++11 and up)
Loading...
Searching...
No Matches
filters.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_FILTERS_H
7#define ELEMENTA_BASE_SERIALCHANNELS_FILTERS_H
8
9#include <functional>
10#include <type_traits>
12#include "elementa/base/enums.h"
14
15
16namespace elementa
17{
18
19namespace base
20{
21
22
47/* ======================================================================
48
49 BASIC DEFINITIONS
50
51========================================================================= */
52
53
54/* *************************************************************************
55
56 Enum: SerChBufOp
57
58*****************************************************************************/
59
61ELE_CLASS_ENUM(SerChBufOp,
62 kUFlow, // get()
63 kUnderflow, // peek()
64 kPBackFail, // unget() / putback()
65 kOverflow); // put()
66
67
68/* *************************************************************************
69
70 Template functions: filtered_uflow, filtered_underflow,
71 filtered_pbackfail, filtered_overflow
72
73*****************************************************************************/
74
76
80template <class F>
81SerChDatum serch_filtered_uflow(InSerCh & wrappingchin_, InSerCh & chin_,
82 F & filter_);
83
85
89template <class F>
90SerChDatum serch_filtered_underflow(InSerCh & wrappingchin_, InSerCh & chin_,
91 F & filter_);
92
94
98template <class F>
99SerChDatum serch_filtered_pbackfail(InSerCh & wrappingchin_, InSerCh & chin_,
100 F & filter_, SerChDatum c);
101
103
107template <class F>
108SerChDatum serch_filtered_overflow(OutSerCh & wrappingchout_,OutSerCh & chout_,
109 F & filter_, SerChDatum c);
110
111
112/* *************************************************************************
113
114 Template classes: SerChIFilter, SerChOFilter, SerChIOFilter
115
116*****************************************************************************/
117
119
123template <class F>
125{
126 public:
127
129
131 SerChIFilter(InSerCh & inch, const F & filter = F{}):
132 inch_{inch},
133 filter_{filter},
134 sbuf_{*this,inch_,filter_},
135 InSerCh{&sbuf_}
136 {}
137
139 SerChIFilter(SerChIFilter && oth): inch_{oth.inch_},
140 filter_{oth.filter_},
141 sbuf_{*this,inch_,filter_},
142 InSerCh{&sbuf_}
143 {}
144
146 InSerCh & channel(void) noexcept { return(inch_); }
147
149 F & filter(void) noexcept { return(filter_); }
150
151
152 private:
153
154 class StreambufSerChIFilter final: public std::streambuf
155 {
156 public:
157
158 StreambufSerChIFilter(InSerCh & wrappingch,
159 InSerCh & wrappedch,
160 F & filter): wrappingchin_{wrappingch},
161 chin_{wrappedch},
162 filter_{filter}
163 {}
164 // cursors are all null, thus forcing underflow
165
166 ~StreambufSerChIFilter(void) = default;
167
168 StreambufSerChIFilter(const StreambufSerChIFilter &) = delete;
169 StreambufSerChIFilter & operator=(const StreambufSerChIFilter &)=delete;
170 StreambufSerChIFilter(StreambufSerChIFilter &&) = delete;
171 StreambufSerChIFilter & operator=(StreambufSerChIFilter &&) = delete;
172
173 private:
174
175 InSerCh & wrappingchin_;
176 InSerCh & chin_;
177 F & filter_;
178
179 SerChDatum uflow(void) override
180 { return(serch_filtered_uflow(wrappingchin_,chin_,filter_)); }
181 SerChDatum underflow(void) override
182 { return(serch_filtered_underflow(wrappingchin_,chin_,filter_)); }
183 SerChDatum pbackfail (SerChDatum c = kSerChEOF) override
184 { return(serch_filtered_pbackfail(wrappingchin_,chin_,filter_,c)); }
185 };
186
187
188 InSerCh & inch_;
189 F filter_;
190 StreambufSerChIFilter sbuf_;
191
192 static_assert(std::is_copy_constructible<F>::value,
193 "The filter template argument in SerChIFilter must be"
194 " copy-constructible");
195};
196
197
199
203template <class F>
205{
206 public:
207
209
211 SerChOFilter(OutSerCh & chout, const F & filter = F{}):
212 chout_{chout},
213 filter_{filter},
214 sbuf_{*this,
215 chout_,
216 filter_},
217 OutSerCh{&sbuf_}
218 {}
219
221 SerChOFilter(SerChOFilter && oth): chout_{oth.chout_},
222 filter_{oth.filter_},
223 sbuf_{*this,chout_,filter_},
224 OutSerCh{&sbuf_}
225 {}
226
228 OutSerCh & channel(void) noexcept { return(chout_); }
229
231 F & filter(void) noexcept { return(filter_); }
232
233
234 private:
235
236 class StreambufSerChOFilter final: public std::streambuf
237 {
238 public:
239
240 StreambufSerChOFilter(OutSerCh & wrappingch,
241 OutSerCh & wrappedch,
242 F & filter): wrappingchout_{wrappingch},
243 chout_{wrappedch},
244 filter_{filter}
245
246 {}
247 // cursors are all null, thus forcing overflow
248
249 ~StreambufSerChOFilter(void) = default;
250
251 StreambufSerChOFilter(const StreambufSerChOFilter &) = delete;
252 StreambufSerChOFilter & operator=(const StreambufSerChOFilter &)=delete;
253 StreambufSerChOFilter(StreambufSerChOFilter &&) = delete;
254 StreambufSerChOFilter & operator=(StreambufSerChOFilter &&) = delete;
255
256 private:
257
258 OutSerCh & chout_;
259 OutSerCh & wrappingchout_;
260 F & filter_;
261
262 SerChDatum overflow(SerChDatum c = kSerChEOF) override
263 { return(serch_filtered_overflow(wrappingchout_,chout_,filter_,c));}
264 };
265
266 OutSerCh & chout_;
267 F filter_;
268 StreambufSerChOFilter sbuf_;
269
270 static_assert(std::is_copy_constructible<F>::value,
271 "The filter template argument in SerChOFilter must be"
272 " copy-constructible");
273};
274
275
277
281template <class FI, class FO>
283{
284 public:
285
287
290 const FI & filterin = FI{},
291 const FO & filterout = FO{}): chinout_{chinout},
292 filterin_{filterin},
293 filterout_{filterout},
294 sbuf_{*this,chinout_,
295 filterin_,filterout_},
296 InOutSerCh{&sbuf_}
297 {}
298
300 SerChIOFilter(SerChIOFilter && oth):chinout_{oth.chinout_},
301 filterin_{oth.filterin_},
302 filterout_{oth.filterout_},
303 sbuf_{*this,chinout_,
304 filterin_,filterout_},
305 InOutSerCh{&sbuf_}
306 {}
307
309 OutSerCh & channel(void) noexcept { return(chinout_); }
310
312 FI & filterIn(void) noexcept { return(filterin_); }
313
315 FO & filterOut(void) noexcept { return(filterout_);}
316
317
318 private:
319
320 class StreambufSerChIOFilter final: public std::streambuf
321 {
322 public:
323
324 StreambufSerChIOFilter(InOutSerCh & wrappingch,
325 InOutSerCh & wrappedch,
326 FI & filterin,
327 FO & filterout): wrappingchinout_{wrappingch},
328 chinout_{wrappedch},
329 filterin_{filterin},
330 filterout_{filterout}
331 {}
332 // cursors are all null, thus forcing overflow
333
334 ~StreambufSerChIOFilter(void) = default;
335
336 StreambufSerChIOFilter(const StreambufSerChIOFilter &) = delete;
337 StreambufSerChIOFilter & operator=(const StreambufSerChIOFilter &)
338 =delete;
339 StreambufSerChIOFilter(StreambufSerChIOFilter &&) = delete;
340 StreambufSerChIOFilter & operator=(StreambufSerChIOFilter &&) = delete;
341
342 private:
343
344 InOutSerCh & chinout_;
345 InOutSerCh & wrappingchinout_;
346 FI filterin_;
347 FO filterout_;
348
349 SerChDatum uflow(void) override
350 {return(serch_filtered_uflow(wrappingchinout_,chinout_,filterin_));}
351 SerChDatum underflow(void) override
352 { return(serch_filtered_underflow(wrappingchinout_,chinout_,
353 filterin_)); }
354 SerChDatum pbackfail (SerChDatum c = kSerChEOF) override
355 { return(serch_filtered_pbackfail(wrappingchinout_,chinout_,
356 filterin_,c)); }
357 SerChDatum overflow(SerChDatum c = kSerChEOF) override
358 { return(serch_filtered_overflow(wrappingchinout_,chinout_,
359 filterout_,c)); }
360 };
361
362 InOutSerCh & chinout_;
363 FI filterin_;
364 FO filterout_;
365 StreambufSerChIOFilter sbuf_;
366
367 static_assert(std::is_copy_constructible<FI>::value,
368 "The filter input template argument in SerChIOFilter must be"
369 " copy-constructible");
370 static_assert(std::is_copy_constructible<FO>::value,
371 "The filter output template argument in SerChIOFilter must be"
372 " copy-constructible");
373};
374
375
376/* *************************************************************************
377
378 Template functions: make_schfiltI, make_schfiltO, make_schfiltIO
379
380*****************************************************************************/
381
383template <class F>
385 { return(SerChIFilter<F>{sch,f}); }
386
388template <class F>
390 { return(SerChOFilter<F>{sch,f}); }
391
393template <class FI, class FO>
395 const FI & f1, const FO & f2)
396 { return(SerChIOFilter<FI,FO>{sch,f1,f2}); }
397
398
399
400
401/* ======================================================================
402
403 COMMON FILTERS
404
405========================================================================= */
406
407
408/* *************************************************************************
409
410 Functions: serchfilt_null, serchfilt_toupper, serchfilt_tolower
411
412*****************************************************************************/
413
415extern std::function< SerChDatum (RootSerCh &, SerChBufOp, SerChDatum) >
417
419extern std::function< SerChDatum (RootSerCh &, SerChBufOp, SerChDatum) >
421
423extern std::function< SerChDatum (RootSerCh &, SerChBufOp, SerChDatum) >
425
426
427/* *************************************************************************
428
429 Class: SerChFilt_Loc
430
431*****************************************************************************/
432
434
436{
437 public:
438
440 template <class L>
442 { return(SerChIFilter<SerChFilt_Loc>{isch,L{}}); }
443
445 template <class L>
447 { return(SerChOFilter<SerChFilt_Loc>{osch,L{}}); }
448
450 template <class L>
452 { return(dynamic_cast<L &>(*fch.filter().ploc)); }
453
455 template <class L>
457 { return(dynamic_cast<L &>(*fch.filter().ploc)); }
458
459
461
462
464
465 SerChFilt_Loc(const SerChLoc & loc = SerChLocText{}): ploc{loc.clone()} {}
466
468
469 SerChFilt_Loc(const SerChLoc::Ptr & pl): ploc{pl} {}
470
471
472 SerChDatum operator()(RootSerCh &, SerChBufOp op, SerChDatum c);
473
474};
475
476
477/* ***************************************************************************
478
479 Class: SerChFilt_Demux
480
481*****************************************************************************/
482
484
494{
495 public:
496
498
500 using SelPred = std::function< InSerCh & (void) >;
501
503
505 SerChFilt_Demux(SelPred pred): pred_{pred} {}
506
507
510
511 private:
512
513 SelPred pred_;
514
515};
516
517
518/* ***************************************************************************
519
520 Class: SerChFilt_Divert
521
522*****************************************************************************/
523
525
530{
531 public:
532
534
535 SerChFilt_Divert(OutSerCh & div): div_{div} {}
536
537
538 SerChDatum operator()(RootSerCh &, SerChBufOp op, SerChDatum c);
539
540 private:
541
542 OutSerCh & div_;
543
544};
545
546
547
548
549/* ======================================================================
550
551 TEMPLATE IMPLEMENTATIONS
552
553========================================================================= */
554
555/* *************************************************************************
556
557 Template functions: filtered_uflow, filtered_underflow,
558 filtered_pbackfail, filtered_overflow
559
560*****************************************************************************/
561
562template <class F>
564 F & filter_)
566
567 ELE_CODE_TRACE({},"State of wrapping: " <<
568 serch_st_to_string(wrappingchin_) <<
569 ", state of wrapped: " <<
570 serch_st_to_string(chin_));
571
572 SerChDatum res;
573 if (!chin_.good()) res = kSerChEOF;
574 else res = filter_(chin_,SerChBufOp::kUFlow,chin_.get());
575
576 serch_copy_st(chin_,wrappingchin_);
577 ELE_CODE_TRACE({},".... State of wrapping: " <<
578 serch_st_to_string(wrappingchin_) <<
579 ", state of wrapped: " <<
580 serch_st_to_string(chin_));
581 return(res);
582 // continue in underflow
583}
584
585template <class F>
587 F & filter_)
589
590 ELE_CODE_TRACE({}, "State of wrapping: " <<
591 serch_st_to_string(wrappingchin_) <<
592 ", state of wrapped: " <<
593 serch_st_to_string(chin_));
594
595 SerChDatum res;
596 if (!chin_.good()) res = kSerChEOF;
597 else res = filter_(chin_,SerChBufOp::kUnderflow,chin_.peek());
598
599 serch_copy_st(chin_,wrappingchin_);
600 ELE_CODE_TRACE({}, ".... State of wrapping: " <<
601 serch_st_to_string(wrappingchin_) <<
602 ", state of wrapped: " <<
603 serch_st_to_string(chin_));
604 return(res);
605 // continue in underflow
606}
607
608template <class F>
610 F & filter_, SerChDatum c)
612
613 ELE_CODE_TRACE({},"State of wrapping: " <<
614 serch_st_to_string(wrappingchin_) <<
615 ", state of wrapped: " <<
616 serch_st_to_string(chin_));
617
618 SerChDatum res;
619 if (!chin_.good()) res = kSerChEOF;
620 else
621 {
622 if (c == kSerChEOF) res = chin_.unget().peek();
623 else
624 {
625 chin_.putback(c);
626 res = c;
627 }
628 if (!chin_.good()) res = kSerChEOF;
629 else res = filter_(chin_,SerChBufOp::kPBackFail,res);
630 }
631
632 serch_copy_st(chin_,wrappingchin_);
633 ELE_CODE_TRACE({},".... State of wrapping: " <<
634 serch_st_to_string(wrappingchin_) <<
635 ", state of wrapped: " <<
636 serch_st_to_string(chin_));
637 return(res);
638}
639
640template <class F>
642 F & filter_, SerChDatum c)
643{
644 SerChDatum res;
645 if (!chout_.good()) res = kSerChEOF;
646 else
647 {
648 if (c != kSerChEOF)
649 chout_.put(filter_(chout_,SerChBufOp::kOverflow,c));
650 res = c == kSerChEOF ? 0 : c;
651 // 0 if c==eof, or c otherwise.
652 }
653
654 serch_copy_st(chout_,wrappingchout_);
655 return(res);
656 // keep cursors in overflow
657}
658
659
660 // SerCh_filters
662
663
664} // end namespace base
665
666} // end namespace elementa
667
668#endif
669
#define ELE_CODE_TRACE_OFF
Place this inside local scope (e.g., routine) to deactivate traces there.
Definition: debugging.h:283
#define ELE_CLASS_ENUM(NameEnumClass,...)
Define an extended enum type.
Definition: enums.h:502
std::shared_ptr< SerChLoc > Ptr
Safe pointer for polymorphic behaviours.
Definition: basics.h:776
Location in a channel, at least in linear form, either at reading or writing.
Definition: basics.h:769
A location into a text channel consisting of a row and a column.
Definition: basics.h:898
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::ios RootSerCh
Class that is at the root of any serial channel in Elementa.
Definition: basics.h:195
std::iostream InOutSerCh
"Base class" that represents any input + output serial channel in Elementa.
Definition: basics.h:356
std::ostream OutSerCh
"Base class" that represents any output serial channel in Elementa.
Definition: basics.h:247
std::ios_base::iostate serch_copy_st(RootSerCh &chorg, RootSerCh &chdest)
Copy the state of CHORG into DEST, returning that state.
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.
SerChOFilter(SerChOFilter &&oth)
Move constructor from another with same filters. Share same channel.
Definition: filters.h:221
static L & get_loc(SerChIFilter< SerChFilt_Loc > &fch)
Get the downcast location object of class L from the filtered channel.
Definition: filters.h:451
F & filter(void) noexcept
Getter for the internal filter function.
Definition: filters.h:149
OutSerCh & channel(void) noexcept
Getter for the referenced channel.
Definition: filters.h:228
OutSerCh & channel(void) noexcept
Getter for the referenced channel.
Definition: filters.h:309
SerChIFilter(SerChIFilter &&oth)
Move constructor from another with same filters. Share same channel.
Definition: filters.h:139
SerChFilt_Loc(const SerChLoc &loc=SerChLocText{})
Default constructor. By default, SerChLocText is used for locations.
Definition: filters.h:465
SerChOFilter(OutSerCh &chout, const F &filter=F{})
Constructor.
Definition: filters.h:211
static SerChOFilter< SerChFilt_Loc > make_filtch(OutSerCh &osch)
Return a SerChOFilter that uses a new location object of class L.
Definition: filters.h:446
FO & filterOut(void) noexcept
Getter for the internal output filter function.
Definition: filters.h:315
SerChDatum operator()(RootSerCh &, SerChBufOp op, SerChDatum c)
Each time this method is called, the predicate function is called.
FI & filterIn(void) noexcept
Getter for the internal input filter function.
Definition: filters.h:312
InSerCh & channel(void) noexcept
Getter for the referenced channel.
Definition: filters.h:146
static L & get_loc(SerChOFilter< SerChFilt_Loc > &fch)
Get the downcast location object of class L from the filtered channel.
Definition: filters.h:456
SerChFilt_Divert(OutSerCh &div)
Constructor.
Definition: filters.h:535
SerChFilt_Loc(const SerChLoc::Ptr &pl)
Constructor from an already existing location object.
Definition: filters.h:469
SerChLoc::Ptr ploc
Location object, updated by the () operator.
Definition: filters.h:460
SerChIFilter(InSerCh &inch, const F &filter=F{})
Constructor.
Definition: filters.h:131
F & filter(void) noexcept
Getter for the internal filter function.
Definition: filters.h:231
SerChIOFilter(SerChIOFilter &&oth)
Move constructor from another with same filters. Share same channel.
Definition: filters.h:300
SerChIOFilter(InOutSerCh &chinout, const FI &filterin=FI{}, const FO &filterout=FO{})
Constructor
Definition: filters.h:289
std::function< InSerCh &(void) > SelPred
Prototype of the predicate used for selecting a channel from the list.
Definition: filters.h:500
SerChFilt_Demux(SelPred pred)
Constructor: it admits the selection predicate.
Definition: filters.h:505
static SerChIFilter< SerChFilt_Loc > make_filtch(InSerCh &isch)
Return a SerChIFilter that uses a new location object of class L.
Definition: filters.h:441
A filter that serves data from multiple input channels.
Definition: filters.h:494
A filter that sends a copy of the readings of an InSerCh to another channel.
Definition: filters.h:530
A filter to keep a location on a channel.
Definition: filters.h:436
A filter for InSerCh. It filters their inputs after getting or putbacking'em.
Definition: filters.h:125
A double filter for input/output channels.
Definition: filters.h:283
A filter for output channels. It processes their outputs before writing them.
Definition: filters.h:205
SerChIOFilter< FI, FO > make_schfiltIO(InOutSerCh &sch, const FI &f1, const FO &f2)
Creator of a SerChIOFilter that deduces automatically the type of the filter.
Definition: filters.h:394
SerChDatum serch_filtered_overflow(OutSerCh &wrappingchout_, OutSerCh &chout_, F &filter_, SerChDatum c)
Intended to implement overflow() in output/inout chnnels filtered by FILTER_.
Definition: filters.h:641
SerChIFilter< F > make_schfiltI(InSerCh &sch, const F &f)
Creator of a SerChIFilter that deduces automatically the type of the filter.
Definition: filters.h:384
std::function< SerChDatum(RootSerCh &, SerChBufOp, SerChDatum) > serchfilt_null
Change nothing in the flow of the channel.
SerChDatum serch_filtered_uflow(InSerCh &wrappingchin_, InSerCh &chin_, F &filter_)
Intended to implement uflow() in input or inout channels filtered by FILTER_.
Definition: filters.h:563
SerChDatum serch_filtered_pbackfail(InSerCh &wrappingchin_, InSerCh &chin_, F &filter_, SerChDatum c)
Intended to implement pbackfail() in input/inout chnnels filtered by FILTER_.
Definition: filters.h:609
std::function< SerChDatum(RootSerCh &, SerChBufOp, SerChDatum) > serchfilt_tolower
Change to lowercase everything flowing through the channel.
SerChDatum serch_filtered_underflow(InSerCh &wrappingchin_, InSerCh &chin_, F &filter_)
Intended to implement underflow() in input/inout chnnels filtered by FILTER_.
Definition: filters.h:586
SerChOFilter< F > make_schfiltO(OutSerCh &sch, const F &f)
Creator of a SerChOFilter that deduces automatically the type of the filter.
Definition: filters.h:389
std::function< SerChDatum(RootSerCh &, SerChBufOp, SerChDatum) > serchfilt_toupper
Change to uppercase everything flowing through the channel.