1 /***********************************************************************************************************************************
2 Buffer Handler
3 ***********************************************************************************************************************************/
4 #ifndef COMMON_TYPE_BUFFER_H
5 #define COMMON_TYPE_BUFFER_H
6 
7 /***********************************************************************************************************************************
8 Buffer object
9 ***********************************************************************************************************************************/
10 typedef struct Buffer Buffer;
11 
12 #include "common/memContext.h"
13 #include "common/type/object.h"
14 #include "common/type/string.h"
15 
16 /***********************************************************************************************************************************
17 Constructors
18 ***********************************************************************************************************************************/
19 Buffer *bufNew(size_t size);
20 
21 // Create a new buffer from a C buffer
22 Buffer *bufNewC(const void *buffer, size_t size);
23 
24 // Create a new buffer from a string encoded with the specified type
25 Buffer *bufNewDecode(EncodeType type, const String *string);
26 
27 // Duplicate a buffer
28 Buffer *bufDup(const Buffer *buffer);
29 
30 /***********************************************************************************************************************************
31 Getters/Setters
32 ***********************************************************************************************************************************/
33 typedef struct BufferPub
34 {
35     MemContext *memContext;                                         // Mem context
36     size_t sizeAlloc;                                               // Allocated size of the buffer
37     size_t size;                                                    // Reported size of the buffer
38     bool sizeLimit;                                                 // Is the size limited to make the buffer appear smaller?
39     size_t used;                                                    // Amount of buffer used
40     unsigned char *buffer;                                          // Buffer
41 } BufferPub;
42 
43 // Amount of the buffer actually used. This will be updated automatically when possible but if the buffer is modified by using
44 // bufPtr() then the user is responsible for updating used.
45 __attribute__((always_inline)) static inline size_t
bufUsed(const Buffer * const this)46 bufUsed(const Buffer *const this)
47 {
48     return THIS_PUB(Buffer)->used;
49 }
50 
51 // Is the buffer empty?
52 __attribute__((always_inline)) static inline bool
bufEmpty(const Buffer * const this)53 bufEmpty(const Buffer *const this)
54 {
55     return bufUsed(this) == 0;
56 }
57 
58 // Buffer size
59 __attribute__((always_inline)) static inline size_t
bufSize(const Buffer * const this)60 bufSize(const Buffer *const this)
61 {
62     return THIS_PUB(Buffer)->size;
63 }
64 
65 // Is the buffer full?
66 __attribute__((always_inline)) static inline bool
bufFull(const Buffer * const this)67 bufFull(const Buffer *const this)
68 {
69     return bufUsed(this) == bufSize(this);
70 }
71 
72 // Buffer pointer
73 __attribute__((always_inline)) static inline unsigned char *
bufPtr(Buffer * const this)74 bufPtr(Buffer *const this)
75 {
76     return THIS_PUB(Buffer)->buffer;
77 }
78 
79 // Const buffer pointer
80 __attribute__((always_inline)) static inline const unsigned char *
bufPtrConst(const Buffer * const this)81 bufPtrConst(const Buffer *const this)
82 {
83     return THIS_PUB(Buffer)->buffer;
84 }
85 
86 // Remaining space in the buffer
87 __attribute__((always_inline)) static inline size_t
bufRemains(const Buffer * const this)88 bufRemains(const Buffer *const this)
89 {
90     return bufSize(this) - bufUsed(this);
91 }
92 
93 // Pointer to remaining buffer space (after used space)
94 __attribute__((always_inline)) static inline unsigned char *
bufRemainsPtr(Buffer * const this)95 bufRemainsPtr(Buffer *const this)
96 {
97     return bufPtr(this) + bufUsed(this);
98 }
99 
100 // Allocated buffer size. This may be different from bufSize() if a limit has been set.
101 __attribute__((always_inline)) static inline size_t
bufSizeAlloc(const Buffer * const this)102 bufSizeAlloc(const Buffer *const this)
103 {
104     return THIS_PUB(Buffer)->sizeAlloc;
105 }
106 
107 // Is the size limited to make the buffer appear smaller?
108 __attribute__((always_inline)) static inline bool
bufSizeLimit(const Buffer * const this)109 bufSizeLimit(const Buffer *const this)
110 {
111     return THIS_PUB(Buffer)->sizeLimit;
112 }
113 
114 /***********************************************************************************************************************************
115 Functions
116 ***********************************************************************************************************************************/
117 // Append the contents of another buffer
118 Buffer *bufCat(Buffer *this, const Buffer *cat);
119 
120 // Append a C buffer
121 Buffer *bufCatC(Buffer *this, const unsigned char *cat, size_t catOffset, size_t catSize);
122 
123 // Append a subset of another buffer
124 Buffer *bufCatSub(Buffer *this, const Buffer *cat, size_t catOffset, size_t catSize);
125 
126 // Are two buffers equal?
127 bool bufEq(const Buffer *this, const Buffer *compare);
128 
129 // Convert the buffer to a hex string
130 String *bufHex(const Buffer *this);
131 
132 // Move to a new parent mem context
133 __attribute__((always_inline)) static inline Buffer *
bufMove(Buffer * const this,MemContext * const parentNew)134 bufMove(Buffer *const this, MemContext *const parentNew)
135 {
136     return objMove(this, parentNew);
137 }
138 
139 // Resize the buffer
140 Buffer *bufResize(Buffer *this, size_t size);
141 
142 // Manage buffer limits
143 void bufLimitClear(Buffer *this);
144 void bufLimitSet(Buffer *this, size_t limit);
145 
146 void bufUsedInc(Buffer *this, size_t inc);
147 void bufUsedSet(Buffer *this, size_t used);
148 void bufUsedZero(Buffer *this);
149 
150 /***********************************************************************************************************************************
151 Destructor
152 ***********************************************************************************************************************************/
153 __attribute__((always_inline)) static inline void
bufFree(Buffer * const this)154 bufFree(Buffer *const this)
155 {
156     objFree(this);
157 }
158 
159 /***********************************************************************************************************************************
160 Macros for constant buffers
161 
162 Frequently used constant buffers can be declared with these macros at compile time rather than dynamically at run time.
163 
164 Note that buffers created in this way are declared as const so can't be modified or freed by the buf*() methods.  Casting to
165 Buffer * will result in a segfault.
166 
167 By convention all buffer constant identifiers are appended with _BUF.
168 ***********************************************************************************************************************************/
169 // Create a buffer constant inline from an unsigned char[]
170 #define BUF(bufferParam, sizeParam)                                                                                                \
171     ((const Buffer *)&(const BufferPub){.size = sizeParam, .used = sizeParam, .buffer = (unsigned char *)bufferParam})
172 
173 // Create a buffer constant inline from a non-constant zero-terminated string
174 #define BUFSTRZ(stringz)                                                                                                           \
175     BUF((unsigned char *)stringz, strlen(stringz))
176 
177 // Create a buffer constant inline from a String
178 #define BUFSTR(string)                                                                                                             \
179     BUF((unsigned char *)strZ(string), strSize(string))
180 
181 // Create a buffer constant inline from a constant zero-terminated string
182 #define BUFSTRDEF(stringdef)                                                                                                       \
183     BUF((unsigned char *)stringdef, (sizeof(stringdef) - 1))
184 
185 // Used to declare buffer constants that will be externed using BUFFER_DECLARE().  Must be used in a .c file.
186 #define BUFFER_STRDEF_EXTERN(name, string)                                                                                         \
187     const Buffer *const name = BUFSTRDEF(string)
188 
189 // Used to declare buffer constants that will be local to the .c file.  Must be used in a .c file.
190 #define BUFFER_STRDEF_STATIC(name, string)                                                                                         \
191     static BUFFER_STRDEF_EXTERN(name, string)
192 
193 // Used to extern buffer constants declared with BUFFER_STRDEF_EXTERN(.  Must be used in a .h file.
194 #define BUFFER_DECLARE(name)                                                                                                       \
195     extern const Buffer *const name
196 
197 /***********************************************************************************************************************************
198 Constant buffers that are generally useful
199 ***********************************************************************************************************************************/
200 BUFFER_DECLARE(BRACEL_BUF);
201 BUFFER_DECLARE(BRACER_BUF);
202 BUFFER_DECLARE(BRACKETL_BUF);
203 BUFFER_DECLARE(BRACKETR_BUF);
204 BUFFER_DECLARE(COMMA_BUF);
205 BUFFER_DECLARE(CR_BUF);
206 BUFFER_DECLARE(DOT_BUF);
207 BUFFER_DECLARE(EQ_BUF);
208 BUFFER_DECLARE(LF_BUF);
209 BUFFER_DECLARE(QUOTED_BUF);
210 
211 /***********************************************************************************************************************************
212 Macros for function logging
213 ***********************************************************************************************************************************/
214 String *bufToLog(const Buffer *this);
215 
216 #define FUNCTION_LOG_BUFFER_TYPE                                                                                                   \
217     Buffer *
218 #define FUNCTION_LOG_BUFFER_FORMAT(value, buffer, bufferSize)                                                                      \
219     FUNCTION_LOG_STRING_OBJECT_FORMAT(value, bufToLog, buffer, bufferSize)
220 
221 #endif
222