1 /***********************************************************************************************************************************
2 IO Filter Interface Internal
3 
4 Two types of filters are implemented using this interface:  In and InOut.
5 
6 In filters accept input and produce a result, but do not modify the input.  An example is the IoSize filter which counts all bytes
7 that pass through it.
8 
9 InOut filters accept input and produce output (and perhaps a result).  Because the input/output buffers may not be the same size the
10 filter must be prepared to accept the same input again (by implementing IoFilterInputSame) if the output buffer is too small to
11 accept all processed data.  If the filter holds state even when inputSame is false then it may also implement IoFilterDone to
12 indicate that the filter should be flushed (by passing NULL inputs) after all input has been processed.  InOut filters should strive
13 to fill the output buffer as much as possible, i.e., if the output buffer is not full after processing then inputSame should be
14 false.  An example is the IoBuffer filter which buffers data between unequally sized input/output buffers.
15 
16 Each filter has a type that allows it to be identified in the filter list.
17 ***********************************************************************************************************************************/
18 #ifndef COMMON_IO_FILTER_FILTER_INTERN_H
19 #define COMMON_IO_FILTER_FILTER_INTERN_H
20 
21 #include "common/type/variantList.h"
22 
23 /***********************************************************************************************************************************
24 Constructors
25 ***********************************************************************************************************************************/
26 typedef struct IoFilterInterface
27 {
28     // Indicates that filter processing is done.  This is used for filters that have additional data to be flushed even after all
29     // input has been processed.  Compression and encryption filters will usually need to implement done.  If done is not
30     // implemented then it will always return true if all input has been consumed, i.e. if inputSame returns false.
31     bool (*done)(const void *driver);
32 
33     // Processing function for filters that do not produce output.  Note that result must be implemented in this case (or else what
34     // would be the point.
35     void (*in)(void *driver, const Buffer *);
36 
37     // Processing function for filters that produce output.  InOut filters will typically implement inputSame and may also implement
38     // done.
39     void (*inOut)(void *driver, const Buffer *, Buffer *);
40 
41     // InOut filters must be prepared for an output buffer that is too small to accept all the processed output.  In this case the
42     // filter must implement inputSame and set it to true when there is more output to be produced for a given input.  On the next
43     // call to inOut the same input will be passed along with a fresh output buffer with space for more processed output.
44     bool (*inputSame)(const void *driver);
45 
46     // If the filter produces a result then this function must be implemented to return the result.  A result can be anything that
47     // is not processed output, e.g. a count of total bytes or a cryptographic hash.
48     Variant *(*result)(void *driver);
49 } IoFilterInterface;
50 
51 #define ioFilterNewP(type, driver, paramList, ...)                                                                                 \
52     ioFilterNew(type, driver, paramList, (IoFilterInterface){__VA_ARGS__})
53 
54 IoFilter *ioFilterNew(const String *type, void *driver, VariantList *paramList, IoFilterInterface);
55 
56 /***********************************************************************************************************************************
57 Getters/Setters
58 ***********************************************************************************************************************************/
59 typedef struct IoFilterPub
60 {
61     MemContext *memContext;                                         // Mem context
62     const String *type;                                             // Filter type
63     IoFilterInterface interface;                                    // Filter interface
64     void *driver;                                                   // Filter driver
65     const VariantList *paramList;                                   // Filter parameters
66 } IoFilterPub;
67 
68 // Is the filter done?
69 bool ioFilterDone(const IoFilter *this);
70 
71 // Driver for the filter
72 __attribute__((always_inline)) static inline void *
ioFilterDriver(IoFilter * const this)73 ioFilterDriver(IoFilter *const this)
74 {
75     return THIS_PUB(IoFilter)->driver;
76 }
77 
78 // Does the filter need the same input again? If the filter cannot get all its output into the output buffer then it may need access
79 // to the same input again.
80 bool ioFilterInputSame(const IoFilter *this);
81 
82 // Interface for the filter
83 __attribute__((always_inline)) static inline const IoFilterInterface *
ioFilterInterface(const IoFilter * const this)84 ioFilterInterface(const IoFilter *const this)
85 {
86     return &THIS_PUB(IoFilter)->interface;
87 }
88 
89 // Does filter produce output? All In filters produce output.
90 __attribute__((always_inline)) static inline bool
ioFilterOutput(const IoFilter * const this)91 ioFilterOutput(const IoFilter *const this)
92 {
93     return THIS_PUB(IoFilter)->interface.inOut != NULL;
94 }
95 
96 // List of filter parameters
97 __attribute__((always_inline)) static inline const VariantList *
ioFilterParamList(const IoFilter * const this)98 ioFilterParamList(const IoFilter *const this)
99 {
100     return THIS_PUB(IoFilter)->paramList;
101 }
102 
103 /***********************************************************************************************************************************
104 Functions
105 ***********************************************************************************************************************************/
106 // Filter input only (a result is expected)
107 void ioFilterProcessIn(IoFilter *this, const Buffer *input);
108 
109 // Filter input and produce output
110 void ioFilterProcessInOut(IoFilter *this, const Buffer *input, Buffer *output);
111 
112 // Move filter to a new parent mem context
113 __attribute__((always_inline)) static inline IoFilter *
ioFilterMove(IoFilter * this,MemContext * parentNew)114 ioFilterMove(IoFilter *this, MemContext *parentNew)
115 {
116     return objMove(this, parentNew);
117 }
118 
119 /***********************************************************************************************************************************
120 Macros for function logging
121 ***********************************************************************************************************************************/
122 #define FUNCTION_LOG_IO_FILTER_INTERFACE_TYPE                                                                                      \
123     IoFilterInterface *
124 #define FUNCTION_LOG_IO_FILTER_INTERFACE_FORMAT(value, buffer, bufferSize)                                                         \
125     objToLog(&value, "IoFilterInterface", buffer, bufferSize)
126 
127 #endif
128