Mstdlib-1.24.0
m_buf.h
1/* The MIT License (MIT)
2 *
3 * Copyright (c) 2015 Monetra Technologies, LLC.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#ifndef __M_BUF_H__
25#define __M_BUF_H__
26
27/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
28
29#include <mstdlib/base/m_defs.h>
30#include <mstdlib/base/m_types.h>
31#include <mstdlib/base/m_str.h>
32#include <mstdlib/base/m_decimal.h>
33#include <mstdlib/base/m_endian.h>
34
35/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
36
37__BEGIN_DECLS
38
39/*! \addtogroup m_buf Buffered Data Builder
40 * \ingroup mstdlib_base
41 *
42 * Allows for buffered writing of string and binary data.
43 * It is a safe and efficient way to append and manipulate buffered data.
44 *
45 * Handles resizing of the buffer, location tracking, and has various
46 * helpers to modify the data being written into the buffer.
47 *
48 * When done adding data the contents of the buffer can be output
49 * as a continuous array. Such as unsigned char * or char *.
50 *
51 * Example (creating a buffer, adding data, finishing the buffer):
52 *
53 * \code{.c}
54 * M_buf_t *buf;
55 * char *out;
56 *
57 * buf = M_buf_create();
58 * M_buf_add_byte(buf, '^');
59 * M_buf_add_str(buf, "ABC");
60 * M_buf_add_int(buf, 123);
61 * out = M_buf_finish_str(buf, NULL);
62 *
63 * M_printf("out='%s'\n", out);
64 * M_free(out);
65 * \endcode
66 *
67 * Example output:
68 *
69 * \code
70 * out='^ABC123'
71 * \endcode
72 *
73 * @{
74 */
75
76struct M_buf;
77typedef struct M_buf M_buf_t;
78
79/*! Enumeration for transformation types, bitmapped type to allow multiple transformations to be run */
81 M_BUF_TRANSFORM_NONE = 0, /*!< Perform no transformation */
82 M_BUF_TRANSFORM_UPPER = 1 << 0, /*!< Transform into upper-case (cannot be used with M_BUF_TRANSFORM_LOWER) */
83 M_BUF_TRANSFORM_LOWER = 1 << 1, /*!< Transform into lower-case (cannot be used with M_BUF_TRANSFORM_UPPER) */
84 M_BUF_TRANSFORM_LTRIM = 1 << 2, /*!< Trim whitespace from left of the data */
85 M_BUF_TRANSFORM_RTRIM = 1 << 3, /*!< Trim whitespace from right of the data */
86 M_BUF_TRANSFORM_TRIM = M_BUF_TRANSFORM_LTRIM|M_BUF_TRANSFORM_RTRIM /*!< Trim whitespace from left and right of data */
87};
88
89
90/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
91
92/*! Create a new buffer.
93 *
94 * \return allocated buffer.
95 *
96 * \see M_buf_cancel
97 * \see M_buf_finish
98 * \see M_buf_finish_str
99 */
100M_API M_buf_t *M_buf_create(void) M_WARN_UNUSED_RESULT M_MALLOC;
101
102
103/*! Free a buffer, discarding its data.
104 *
105 * \param[in] buf Buffer.
106 */
107M_API void M_buf_cancel(M_buf_t *buf) M_FREE(1);
108
109
110/*! Free a buffer, saving its data.
111 *
112 * The caller is responsible for freeing the data.
113 *
114 * \param[in] buf Buffer
115 * \param[out] out_length Data length
116 *
117 * \return The buffered data.
118 *
119 * \see M_free
120 */
121M_API unsigned char *M_buf_finish(M_buf_t *buf, size_t *out_length) M_FREE(1) M_WARN_UNUSED_RESULT M_MALLOC M_WARN_NONNULL(2);
122
123
124/*! Free a buffer, saving its data as a C-string.
125 *
126 * The caller is responsible for freeing the data.
127 *
128 * \param[in] buf Buffer.
129 * \param[out] out_length Data length. Optional, pass NULL if length not needed.
130 *
131 * \return The buffered data.
132 *
133 * \see M_free
134 */
135M_API char *M_buf_finish_str(M_buf_t *buf, size_t *out_length) M_FREE(1) M_WARN_UNUSED_RESULT M_MALLOC;
136
137
138/*! Return the length of the data held by a buffer.
139 *
140 * \param[in] buf Buffer.
141 *
142 * \return Data length.
143 */
144M_API size_t M_buf_len(const M_buf_t *buf);
145
146
147/*! Return overall data allocation size for the buffer.
148 *
149 * \param[in] buf Buffer.
150 *
151 * \return Allocation size.
152 */
153M_API size_t M_buf_alloc_size(const M_buf_t *buf);
154
155
156/*! Take a sneak peek at the buffer.
157 *
158 * \param[in] buf Buffer.
159 *
160 * \return Current beginning of the data in the buffer.
161 */
162M_API const char *M_buf_peek(const M_buf_t *buf);
163
164
165/*! Truncate the length of the data to the specified size.
166 *
167 * Removes data from the end of the buffer.
168 *
169 * \param[in,out] buf Buffer.
170 * \param[in] length Length to truncate buffer to.
171 */
172M_API void M_buf_truncate(M_buf_t *buf, size_t length);
173
174
175/*! Drop the specified number of bytes from the beginning of the buffer.
176 *
177 * \param[in,out] buf Buffer.
178 * \param[in] num Number of bytes to drop.
179 */
180M_API void M_buf_drop(M_buf_t *buf, size_t num);
181
182
183/*! Begin a direct write operation. In general, this function should not be used,
184 * it is meant as an optimization to prevent double buffering when reading I/O.
185 * A writable buffer will be returned of at least the length requested, often it
186 * will be much larger. To end the direct write process, M_buf_direct_write_end()
187 * must be called with the length actually written. It is not valid to call any
188 * other M_buf_*() functions between start and end.
189 *
190 * \param[in,out] buf Buffer
191 * \param[in,out] len Pass in the minimum requested buffer size, outputs the maximum
192 * writable buffer size.
193 * \return Writable buffer or NULL on failure */
194M_API unsigned char *M_buf_direct_write_start(M_buf_t *buf, size_t *len);
195
196
197/*! End a direct write operation. Please see M_buf_direct_write_start() for more
198 * information. This terminates a direct write sequence regardless of if data was
199 * written or not (len = 0 is acceptable).
200 *
201 * \param[in,out] buf Buffer
202 * \param[in] len Length of data written.
203 */
204M_API void M_buf_direct_write_end(M_buf_t *buf, size_t len);
205
206/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
207
208/*! Merge two buffers.
209 *
210 * The data in the source buffer is appended to the destination buffer.
211 * The source buffer is freed.
212 *
213 * \param[in,out] dest Buffer.
214 * \param[in] source Buffer.
215 */
216M_API void M_buf_merge(M_buf_t *dest, M_buf_t *source) M_FREE(2);
217
218
219/*! Join an array of buffers.
220 *
221 * The data in the buffer array is appended to the destination buffer with sep placed between the data in each buffer.
222 * The buffers in the buffer array is freed. The array itself is not freed.
223 *
224 * \param[in,out] dest Buffer.
225 * \param[in] sep String to insert between element in the buffer array.
226 * \param[in] bufs Array of buffers.
227 * \param[in] cnt Number of elements in the buffer array.
228 */
229M_API void M_buf_bjoin_buf(M_buf_t *dest, unsigned char sep, M_buf_t **bufs, size_t cnt);
230
231
232/*! Join an array of strings.
233 *
234 * The data in the string array is appended to the destination buffer with sep placed between the data in each buffer.
235 *
236 * \param[in,out] dest Buffer.
237 * \param[in] sep String to insert between element in the string array.
238 * \param[in] strs Array of strings.
239 * \param[in] cnt Number of elements in the buffer array.
240 */
241M_API void M_buf_bjoin_str(M_buf_t *dest, unsigned char sep, const char **strs, size_t cnt);
242
243
244/*! Join an array of buffers.
245 *
246 * The data in the buffer array is appended to the destination buffer with sep placed between the data in each buffer.
247 * The buffers in the buffer array is freed. The array itself is not freed.
248 *
249 * \param[in,out] dest Buffer.
250 * \param[in] sep String to insert between element in the buffer array.
251 * \param[in] bufs Array of buffers.
252 * \param[in] cnt Number of elements in the buffer array.
253 */
254M_API void M_buf_sjoin_buf(M_buf_t *dest, const char *sep, M_buf_t **bufs, size_t cnt);
255
256
257/*! Join an array of strings.
258 *
259 * The data in the string array is appended to the destination buffer with sep placed between the data in each buffer.
260 *
261 * \param[in,out] dest Buffer.
262 * \param[in] sep String to insert between element in the string array.
263 * \param[in] strs Array of strings.
264 * \param[in] cnt Number of elements in the buffer array.
265 */
266M_API void M_buf_sjoin_str(M_buf_t *dest, const char *sep, const char **strs, size_t cnt);
267
268
269/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
270
271/*! Append one byte to a buffer.
272 *
273 * \param[in,out] buf Buffer.
274 * \param[in] byte Byte to append.
275 */
276M_API void M_buf_add_byte(M_buf_t *buf, unsigned char byte);
277
278
279/*! Append zero or more bytes to a buffer.
280 *
281 * \param[in,out] buf Buffer.
282 * \param[in] bytes Bytes to append.
283 * \param[in] bytes_length Number of bytes to append.
284 */
285M_API void M_buf_add_bytes(M_buf_t *buf, const void *bytes, size_t bytes_length);
286
287
288/*! Append zero or more bytes to a buffer (given as hex string).
289 *
290 * \warning
291 * This function is deprecated, M_buf_add_decode() or M_buf_decode() should be used instead.
292 *
293 * Same as M_buf_add_bytes(), but accepts binary data encoded as a hex string.
294 * The data is decoded into raw binary form before it's added to the buffer.
295 *
296 * \param[in,out] buf Buffer.
297 * \param[in] hex_bytes Hex string that encodes the bytes to append.
298 * \return M_TRUE if successful, M_FALSE if error during hex decode
299 */
300M_API M_bool M_buf_add_bytes_hex(M_buf_t *buf, const char *hex_bytes);
301
302
303/*! Append one char to a buffer.
304 *
305 * \param[in,out] buf Buffer.
306 * \param[in] c Char to append.
307 */
308M_API void M_buf_add_char(M_buf_t *buf, char c);
309
310
311/*! Append a C string (zero or more bytes terminated with a NULL) to a buffer.
312 *
313 * The NUL is not appended.
314 *
315 * \param[in,out] buf Buffer.
316 * \param[in] str String to append.
317 */
318M_API void M_buf_add_str(M_buf_t *buf, const char *str);
319
320
321/*! Append a C string up to the NUL terminator or max bytes (which ever is smaller) to a buffer.
322 *
323 * The NUL is not appended.
324 *
325 * \param[in,out] buf Buffer.
326 * \param[in] str String to append.
327 * \param[in] max Maximum number of bytes to add.
328 */
329M_API void M_buf_add_str_max(M_buf_t *buf, const char *str, size_t max);
330
331
332/*! Append the given bytes to the buffer as a hex-encoded string.
333 *
334 * \warning
335 * This function is deprecated, M_buf_add_encode() or M_buf_encode() should be used instead.
336 *
337 * The given binary data is converted to a hex-encoded string before being
338 * added to the buffer.
339 *
340 * \param[in,out] buf Buffer.
341 * \param[in] bytes Bytes to append as hex.
342 * \param[in] len Number of bytes to use as input.
343 */
344M_API void M_buf_add_str_hex(M_buf_t *buf, const void *bytes, size_t len);
345
346
347/*! Split string into lines while keeping words intact, then append to buffer.
348 *
349 * Words in this context are defined as contiguous blocks of non-whitespace characters. For each line,
350 * leading and trailing whitespace will be trimmed, but internal whitespace will be left alone.
351 *
352 * The given newline sequence is added at the end of each line.
353 *
354 * An example use case is breaking up strings for display on small LCD screens.
355 *
356 * \see M_str_explode_lines
357 *
358 * \param[in,out] buf Buffer to add output to.
359 * \param[in] str Source string.
360 * \param[in] max_lines Maximum number of lines to output.
361 * \param[in] max_chars Maximum characters per line.
362 * \param[in] truncate If true, truncation is allowed. If false, NULL will be returned if the string won't fit.
363 * \param[in] newline Newline sequence to add to end of each line.
364 * \return number of lines added to buffer (zero if the input string was empty or there's an error).
365 */
366M_API size_t M_buf_add_str_lines(M_buf_t *buf, const char *str, size_t max_lines, size_t max_chars, M_bool truncate,
367 const char *newline);
368
369
370/*! Append a C string (zero or more bytes terminated with a NUL) to a buffer, transform
371 * the data as specified.
372 *
373 * The NUL is not appended.
374 *
375 * \param[in,out] buf Buffer.
376 * \param[in] transform_type Type of transformation to perform, bitmap field of enum M_BUF_TRANSFORM_TYPE
377 * \param[in] str String to append.
378 */
379M_API void M_buf_add_str_transform(M_buf_t *buf, M_uint32 transform_type, const char *str);
380
381
382/*! Append a C string (zero or more bytes terminated with a NUL) to a buffer up to
383 * max size, transform the data as specified.
384 *
385 * The NUL is not appended.
386 *
387 * \param[in,out] buf Buffer.
388 * \param[in] transform_type Type of transformation to perform, bitmap field of enum M_BUF_TRANSFORM_TYPE
389 * \param[in] str String to append.
390 * \param[in] max Max length to append.
391 */
392M_API void M_buf_add_str_max_transform(M_buf_t *buf, M_uint32 transform_type, const char *str, size_t max);
393
394
395/*! Append a C string (zero or more bytes terminated with a NUL) to a buffer, ensuring all characters of the string
396 * are in uppercase.
397 *
398 * The NUL is not appended.
399 *
400 * \param[in,out] buf Buffer.
401 * \param[in] str String to append.
402 */
403M_API void M_buf_add_str_upper(M_buf_t *buf, const char *str);
404
405
406/*! Append a C string (zero or more bytes terminated with a NUL) to a buffer, ensuring all characters of the string
407 * are in lowercase.
408 *
409 * The NUL is not appended.
410 *
411 * \param[in,out] buf Buffer.
412 * \param[in] str String to append.
413 */
414M_API void M_buf_add_str_lower(M_buf_t *buf, const char *str);
415
416
417/*! Append a fill character to a buffer zero or more times.
418 *
419 * \param[in,out] buf Buffer
420 * \param[in] fill_char Character/byte to append.
421 * \param[in] width Number of times to add character/byte.
422 */
423M_API void M_buf_add_fill(M_buf_t *buf, unsigned char fill_char, size_t width);
424
425
426/*! Append the character decimal representation ("%llu") of an unsigned integer
427 * to a buffer.
428 *
429 * \param[in,out] buf Buffer.
430 * \param[in] n Unsigned integer to append.
431 */
432M_API void M_buf_add_uint(M_buf_t *buf, M_uint64 n);
433
434
435/*! Append the character decimal representation ("%lld") of a signed integer
436 * to a buffer.
437 *
438 * \param[in,out] buf Buffer.
439 * \param[in] n Unsigned integer to append.
440 */
441M_API void M_buf_add_int(M_buf_t *buf, M_int64 n);
442
443
444/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
445
446/*! Encode binary data using the given codec, then append the result to this buffer.
447 *
448 * The results are only added to the end of the given buffer on success - if there's an error, the buffer's existing
449 * contents are not modified.
450 *
451 * Passing input data with a length of zero will always succeed (contents of the buffer won't be modified).
452 *
453 * \see M_buf_encode
454 * \see M_buf_add_decode
455 * \see M_bincodec_encode
456 *
457 * \param[in,out] buf buffer to append encoded data to.
458 * \param[in] bytes binary data we want to encode into a string.
459 * \param[in] bytes_len length (in bytes) of binary data we want to encode.
460 * \param[in] wrap max length of a given line. Longer lines will be split with a newline char.
461 * Pass 0 if line splitting is not desired.
462 * \param[in] codec binary codec to encode the binary data with.
463 * \return M_TRUE on success, M_FALSE if there was some error during encoding.
464 */
465M_API M_bool M_buf_add_encode(M_buf_t *buf, const void *bytes, size_t bytes_len, size_t wrap, M_bincodec_codec_t codec);
466
467
468/*! Encode contents of buffer in-place using the given codec.
469 *
470 * If successful, the entire contents of the buffer will be replaced with their encoded version.
471 * If there's an error, the buffer's contents are not modified.
472 *
473 * Calling this function on an empty buffer will always succeed.
474 *
475 * \see M_buf_add_encode
476 * \see M_buf_decode
477 * \see M_bincodec_encode
478 *
479 * \param[in,out] buf buffer whose contents we want to encode
480 * \param[in] wrap max length of a given line. Longer lines will be split with a newline char.
481 * Pass 0 if line splitting is not desired.
482 * \param[in] codec binary codec to use on the contents of the buffer.
483 * \return M_TRUE on success, M_FALSE if there was some error during encoding.
484 */
485M_API M_bool M_buf_encode(M_buf_t *buf, size_t wrap, M_bincodec_codec_t codec);
486
487
488/*! Decode string to raw binary using the given codec, then append the result to this buffer.
489 *
490 * The results are only added to the end of the given buffer on success - if there's an error, the buffer's existing
491 * contents are not modified.
492 *
493 * Passing an empty input string will always succeed (contents of the buffer won't be modified).
494 *
495 * \see M_buf_decode
496 * \see M_buf_add_encode
497 * \see M_bincodec_decode
498 *
499 * \param[in,out] buf buffer to append decoded data to.
500 * \param[in] encoded string we want to decode into raw binary data.
501 * \param[in] encoded_len number of chars from string that we want to decode.
502 * \param[in] codec binary codec to decode the string with.
503 * \return M_TRUE on success, M_FALSE if there was some error during decoding.
504 */
505M_API M_bool M_buf_add_decode(M_buf_t *buf, const char *encoded, size_t encoded_len, M_bincodec_codec_t codec);
506
507
508/*! Decode contents of buffer in-place using the given codec.
509 *
510 * If successful, the entire contents of the buffer will be replaced with their decoded version.
511 * If there's an error, the buffer's contents are not modified.
512 *
513 * Calling this function on an empty buffer will always succeed.
514 *
515 * \see M_buf_add_decode
516 * \see M_buf_encode
517 * \see M_bincodec_decode
518 *
519 * \param[in,out] buf buffer whose contents we want to decode
520 * \param[in] codec binary codec to use when decoding the contents of the buffer.
521 * \return M_TRUE on success, M_FALSE if there was some error during decoding.
522 */
523M_API M_bool M_buf_decode(M_buf_t *buf, M_bincodec_codec_t codec);
524
525
526/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
527
528/*! Append zero or more bytes to a buffer, with justification.
529 *
530 * \param[in,out] buf Buffer.
531 * \param[in] bytes Bytes to append.
532 * \param[in] bytes_length Number of bytes to append.
533 * \param[in] justify_type Type of justification (left, right, etc.).
534 * \param[in] fill_char Character to use for padding.
535 * \param[in] width Width of field, including padding.
536 */
537M_API void M_buf_add_bytes_just(M_buf_t *buf, const void *bytes, size_t bytes_length, M_str_justify_type_t justify_type, unsigned char fill_char, size_t width);
538
539
540/*! Append a C string (zero or more bytes terminated with a NUL) to a buffer,
541 * with justification and transformation.
542 *
543 * The NUL is not appended.
544 *
545 * \param[in,out] buf Buffer.
546 * \param[in] transform_type bitmap of transformations (enum M_BUF_TRANSFORM_TYPE) to perform.
547 * \param[in] str String to append.
548 * \param[in] justify_type Type of justification (left, right, etc.).
549 * \param[in] fill_char Character to use for padding.
550 * \param[in] width Width of field, including padding.
551 */
552M_API void M_buf_add_str_just_transform(M_buf_t *buf, M_uint32 transform_type, const char *str, M_str_justify_type_t justify_type, unsigned char fill_char, size_t width);
553
554
555/*! Append a C string (zero or more bytes terminated with a NUL) to a buffer,
556 * with justification.
557 *
558 * The NUL is not appended.
559 *
560 * \param[in,out] buf Buffer.
561 * \param[in] str String to append.
562 * \param[in] justify_type Type of justification (left, right, etc.).
563 * \param[in] fill_char Character to use for padding.
564 * \param[in] width Width of field, including padding.
565 */
566M_API void M_buf_add_str_just(M_buf_t *buf, const char *str, M_str_justify_type_t justify_type, unsigned char fill_char, size_t width);
567
568
569/*! Append the character decimal representation ("%llu") of an unsigned integer
570 * to a buffer, with right justification, zero padded.
571 *
572 * Bytes on the left will be truncated from the integer if there is insufficient width.
573 *
574 * \param[in,out] buf Buffer.
575 * \param[in] n Unsigned integer to append.
576 * \param[in] width Width of field, including padding.
577 *
578 * \return M_FALSE if input was truncated, otherwise M_TRUE.
579 */
580M_API M_bool M_buf_add_uint_just(M_buf_t *buf, M_uint64 n, size_t width);
581
582
583/*! Append the character decimal representation ("%lld") of a signed integer
584 * to a buffer, with right justification, zero padded.
585 *
586 * Bytes on the left will be truncated from the integer if there is insufficient width.
587 *
588 * \param[in,out] buf Buffer.
589 * \param[in] n Unsigned integer to append.
590 * \param[in] width Width of field, including padding.
591 *
592 * \return M_FALSE if input was truncated, otherwise M_TRUE.
593 */
594M_API M_bool M_buf_add_int_just(M_buf_t *buf, M_int64 n, size_t width);
595
596
597/*! Append an integer converted to binary form based on endianness.
598 *
599 * \param[in,out] buf Buffer.
600 * \param[in] n Unsigned integer to append.
601 * \param[in] width Exact field length, must be [1:8]
602 * \param[in] endianness Endianness the integer should be written using.
603 *
604 * return M_TRUE if integer could be written. Otherwise M_FALSE.
605 */
606M_API M_bool M_buf_add_uintbin(M_buf_t *buf, M_uint64 n, size_t width, M_endian_t endianness);
607
608
609/*! Append an integer in string form to binary data based on endianness.
610 *
611 * The string representing a big endian number. Hex especially must be ordered as big endian.
612 *
613 * \param[in,out] buf Buffer.
614 * \param[in] s Numeric string form.
615 * \param[in] base Valid range 2 - 36. 0 to autodetect based on input (0x = hex, 0 = octal, anything else is decimal).
616 * \param[in] width Width of the field [1:8].
617 * \param[in] endianness Endianness the integer should be written using.
618 *
619 * return M_TRUE if integer could be written for number of bytes requested. Otherwise M_FALSE.
620 */
621M_API M_bool M_buf_add_uintstrbin(M_buf_t *buf, const char *s, unsigned char base, size_t width, M_endian_t endianness);
622
623
624/*! Append an integer converted to Binary Coded Decimal.
625 *
626 * Packed BCD with 4 bit numbers representing a single number. Two numbers packed into one byte.
627 *
628 * dec | just | bcd | hex
629 * -----|------|------------------------------:|----
630 * 1 | 2 | 0000 0001 | 0x01
631 * 2 | 3 | 0000 0000 0000 0000 0000 0010 | 0x000002
632 * 100 | 3 | 0000 0000 0000 0001 0000 0000 | 0x000100
633 *
634 * \param[in,out] buf Buffer.
635 * \param[in] n Unsigned integer to append.
636 * \param[in] width Width of field, including padding. This is the total number of bytes that should
637 * be written. A width of 3 means 3 bytes not 3 BCD segments.
638 *
639 * \return M_FALSE if input would be truncated (length greater than width), otherwise M_TRUE.
640 */
641M_API M_bool M_buf_add_uintbcd(M_buf_t *buf, M_uint64 n, size_t width);
642
643
644/*! Append an integer in string form to Binary Coded Decimal.
645 *
646 * Packed BCD with 4 bit numbers representing a single number. Two numbers packed into one byte.
647 *
648 * \param[in,out] buf Buffer.
649 * \param[in] s Numeric string form.
650 * \param[in] base Valid range 2 - 36. 0 to autodetect based on input (0x = hex, 0 = octal, anything else is decimal).
651 * \param[in] width Width of the field [1:8].
652 *
653 * return M_TRUE if integer could be written for number of bytes requested. Otherwise M_FALSE.
654 */
655M_API M_bool M_buf_add_uintstrbcd(M_buf_t *buf, const char *s, unsigned char base, size_t width);
656
657
658/*! Append an integer converted to Hex-ASCII.
659 *
660 * \param[in,out] buf Buffer.
661 * \param[in] n Unsigned integer to append.
662 * \param[in] is_upper Should data be added uppercase.
663 * \param[in] width Number of hex bytes to write to buffer, including padding.
664 *
665 * return M_TRUE if integer could be written for number of bytes requested. Otherwise M_FALSE.
666 */
667M_API M_bool M_buf_add_uinthex(M_buf_t *buf, M_uint64 n, M_bool is_upper, size_t width);
668
669
670
671/*! Append a byte converted to Hex-ASCII.
672 *
673 * \param[in,out] buf Buffer.
674 * \param[in] byte Byte to append.
675 * \param[in] is_upper Should data be added uppercase.
676 *
677 * return M_TRUE if byte could be written. Otherwise M_FALSE.
678 */
679M_API void M_buf_add_bytehex(M_buf_t *buf, unsigned char byte, M_bool is_upper);
680
681
682/*! Append a pointer
683 *
684 * \param[in,out] buf Buffer.
685 * \param[in] ptr Pointer (address) to append.
686 */
687M_API void M_buf_add_ptr(M_buf_t *buf, void *ptr);
688
689/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
690
691/*! Append a monetary amount to a buffer.
692 *
693 * Input is a dollar amount with a 2 digit decimal value using '.' to separate dollar
694 * and cents. A '.' is used for the decimal portion. The input is _not_ implied decimal.
695 * Only the first two decimal digits are evaluated. Everything after is truncated.
696 * The amount will be added as implied decimal. Negative symbol will be added if value is negative.
697 *
698 * E.g.
699 *
700 * in -> "12.00"
701 * out -> 1200
702 * in -> "12.1001"
703 * out -> 1210
704 * in -> "-12.0"
705 * out -> -1200
706 * in -> "-12."
707 * out -> -1200
708 * in -> "12"
709 * out -> 1200
710 *
711 * \param[in,out] buf Buffer.
712 * \param[in] amount Monetary amount to append. Not implied decimal.
713 * \param[in] max_width Maximum width of field. Number of digits output.
714 *
715 * \return M_FALSE on error (probably truncation), M_TRUE otherwise.
716 */
717M_API M_bool M_buf_add_money(M_buf_t *buf, const char *amount, size_t max_width) M_WARN_UNUSED_RESULT;
718
719
720/*! Append a monetary amount to a buffer, adding a decimal point.
721 *
722 * Input is a dollar amount with a 2 digit decimal value using '.' to separate dollar
723 * and cents. A '.' is used for the decimal portion. The input is _not_ implied decimal.
724 * Only the first two decimal digits are evaluated. Everything after is truncated.
725 * The amount will be added with a decimal. Negative symbol will be added if value is negative.
726 *
727 * This function is used to ensure a properly formatted monetary value.
728 *
729 * E.g.
730 *
731 * in -> "12.00"
732 * out -> 12.00
733 * in -> "12.1001"
734 * out -> 12.10
735 * in -> "-12.0"
736 * out -> -12.00
737 * in -> "-12."
738 * out -> -12.00
739 * in -> "12"
740 * out -> 12.00
741 *
742 * \param[in,out] buf Buffer.
743 * \param[in] amount Monetary amount to append.
744 * \param[in] max_width Maximum width of field.
745 *
746 * \return M_FALSE on error (probably truncation), Otherewise M_TRUE.
747 */
748M_API M_bool M_buf_add_money_dot(M_buf_t *buf, const char *amount, size_t max_width) M_WARN_UNUSED_RESULT;
749
750
751/*! Append a monetary amount to a buffer, with right justification, zero padded.
752 *
753 * \param[in,out] buf Buffer.
754 * \param[in] amount Monetary amount to append.
755 * \param[in] max_width Maximum width of field.
756 *
757 * \return M_FALSE on error (probably truncation), otherwise M_TRUE.
758 *
759 * \see M_buf_add_money
760 */
761M_API M_bool M_buf_add_money_just(M_buf_t *buf, const char *amount, size_t max_width) M_WARN_UNUSED_RESULT;
762
763
764/*! Append a monetary amount to a buffer, adding a decimal point, with right
765 * justification, zero padded.
766 *
767 * \param[in,out] buf Buffer.
768 * \param[in] amount Monetary amount to append.
769 * \param[in] max_width Maximum width of field.
770 *
771 * \return M_FALSE on error (probably truncation), otherwise M_TRUE.
772 *
773 * \see M_buf_add_money_dot
774 */
775M_API M_bool M_buf_add_money_dot_just(M_buf_t *buf, const char *amount, size_t max_width) M_WARN_UNUSED_RESULT;
776
777
778/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
779
780/*! Append a monetary amount to a buffer.
781 *
782 * \param[in,out] buf Buffer.
783 * \param[in] amount Monetary amount to append.
784 * \param[in] max_width Maximum width of field.
785 *
786 * \return M_FALSE on error (probably truncation), otherwise M_TRUE.
787 */
788M_API M_bool M_buf_add_int_money(M_buf_t *buf, M_int64 amount, size_t max_width) M_WARN_UNUSED_RESULT;
789#define M_buf_add_uint_money(buf, amount, max_width) M_buf_add_int_money(buf, M_ABS(amount), max_width)
790
791
792/*! Append a monetary amount to a buffer, adding a decimal point.
793 *
794 * \param[in,out] buf Buffer.
795 * \param[in] amount Monetary amount to append.
796 * \param[in] max_width Maximum width of field.
797 *
798 * \return M_FALSE on error (probably truncation), otherwise M_TRUE.
799 */
800M_API M_bool M_buf_add_int_money_dot(M_buf_t *buf, M_int64 amount, size_t max_width) M_WARN_UNUSED_RESULT;
801#define M_buf_add_uint_money_dot(buf, amount, max_width) M_buf_add_int_money_dot(buf, M_ABS(amount), max_width)
802
803
804/*! Append a monetary amount to a buffer, with right justification, zero padded.
805 *
806 * \param[in,out] buf Buffer.
807 * \param[in] amount Monetary amount to append.
808 * \param[in] max_width Maximum width of field.
809 *
810 * \return M_FALSE on error (probably truncation), otherwise M_TRUE.
811 */
812M_API M_bool M_buf_add_int_money_just(M_buf_t *buf, M_int64 amount, size_t max_width) M_WARN_UNUSED_RESULT;
813# define M_buf_add_uint_money_just(buf, amount, max_width) M_buf_add_int_money_just(buf, M_ABS(amount), max_width)
814
815
816/*! Append a monetary amount to a buffer, adding a decimal point, with right
817 * justification, zero padded.
818 *
819 * \param[in,out] buf Buffer.
820 * \param[in] amount Monetary amount to append.
821 * \param[in] max_width Maximum width of field.
822 *
823 * \return M_FALSE on error (probably truncation), otherwise M_TRUE.
824 */
825M_API M_bool M_buf_add_int_money_dot_just(M_buf_t *buf, M_int64 amount, size_t max_width) M_WARN_UNUSED_RESULT;
826#define M_buf_add_uint_money_dot_just(buf, amount, max_width) M_buf_add_int_money_dot_just(buf, M_ABS(amount), max_width)
827
828
829/*! Appends a decimal number to a buffer.
830 *
831 * The number of decimal places may be specified and whether or not the number should have an 'implied' decimal
832 * but not actually output the decimal character.
833 *
834 * \param[in,out] buf Buffer.
835 * \param[in] decimal Decimal number to represent.
836 * \param[in] implied_decimal The decimal place is implied (e.g. not actually present in the output).
837 * \param[in] num_decimals Number of digits after the decimal that should be printed.
838 * Pass as -1 if it should output whatever is currently
839 * in the decimal. Required to be something other than
840 * -1 if using implied decimal.
841 * \param[in] max_width Maximum width of the output, if this is exceeded it is an
842 * error condition. A value of 0 means there is no maximum.
843 *
844 * \return M_FALSE on error (e.g. truncation or misuse), otherwise M_TRUE.
845 */
846M_API M_bool M_buf_add_decimal(M_buf_t *buf, const M_decimal_t *decimal, M_bool implied_decimal, M_int8 num_decimals, size_t max_width) M_WARN_UNUSED_RESULT;
847
848
849/*! Appends a decimal number to a buffer justifying it on the left with zeros.
850 *
851 * The number of decimal places may be specified and whether or not the number should have an 'implied' decimal
852 * but not actually output the decimal character.
853 *
854 * \param[in,out] buf Buffer.
855 * \param[in] decimal Decimal number to represent.
856 * \param[in] implied_decimal The decimal place is implied (e.g. not actually present in the output).
857 * \param[in] num_decimals Number of digits after the decimal that should be printed.
858 * Pass as -1 if it should output whatever is currently
859 * in the decimal. Required to be something other than
860 * -1 if using implied decimal.
861 * \param[in] max_width Justification width of the output.
862 *
863 * \return M_FALSE on error (e.g. truncation or misuse), otherwise M_TRUE.
864 */
865M_API M_bool M_buf_add_decimal_just(M_buf_t *buf, const M_decimal_t *decimal, M_bool implied_decimal, M_int8 num_decimals, size_t max_width) M_WARN_UNUSED_RESULT;
866
867
868/*! Add given bytes to destination buffer, replace all instances of a byte sequence during the add.
869 *
870 * The source pointer must not point to the destination buffer's memory (no aliasing allowed).
871 *
872 * \param[out] dest_buf buffer to write data to
873 * \param[in] src bytes to add
874 * \param[in] src_len number of bytes to add
875 * \param[in] search_bytes sequence of bytes to look for
876 * \param[in] search_len length of search sequence
877 * \param[in] replace_bytes sequence of bytes to replace \a search_bytes with
878 * \param[in] replace_len length of replace sequence
879 * \return M_TRUE on success, M_FALSE on error
880 */
881M_API M_bool M_buf_add_bytes_replace(M_buf_t *dest_buf, const M_uint8 *src, size_t src_len,
882 const M_uint8 *search_bytes, size_t search_len, const M_uint8 *replace_bytes, size_t replace_len);
883
884
885/*! Add given string to destination buffer, replace all instances of a string during the add.
886 *
887 * The source pointer must not point to the destination buffer's memory (no aliasing allowed).
888 *
889 * \param[out] dest_buf buffer to write data to
890 * \param[in] src_str string to add
891 * \param[in] search_str string we're looking for
892 * \param[in] replace_str string we're going to replace \a search_str with
893 * \return M_TRUE on success, M_FALSE on error
894 */
895M_API M_bool M_buf_add_str_replace(M_buf_t *dest_buf, const char *src_str,
896 const char *search_str, const char *replace_str);
897
898
899/*! Add the given string to the buffer, quoting if necessary.
900 *
901 * This is useful for outputting delimited data like CSV.
902 *
903 * If the input string is NULL, it will not output anything even if always_quoted
904 * is specified. However, an empty string will always be output as quoted as
905 * that is what differentiates between an empty string an NULL.
906 *
907 * \param[out] buf Buffer to write quoted string to.
908 * \param[in] quote_char Quote character to use (often a double quote)
909 * \param[in] escape_char Escape character to use if either an embedded quote is found or another escape character.
910 * For CSV this is often the same value as the quote character as per RFC4180.
911 * \param[in] quote_req_chars NULL-terminated list of characters that would force
912 * quoting the string. Often ",\\r\\n" are used.
913 * \param[in] always_quote If set to M_TRUE, will always quote the output, M_FALSE
914 * it will decide based on quote_req_chars.
915 * \param[in] src Data to be quoted/escaped and appended to the buffer
916 */
917M_API void M_buf_add_str_quoted(M_buf_t *buf, char quote_char, char escape_char, const char *quote_req_chars, M_bool always_quote, const char *src);
918
919
920/*! Trim whitespace from beginning and end of buffer, in-place.
921 *
922 * \param[in,out] buf buffer to trim
923 */
924M_API void M_buf_trim(M_buf_t *buf);
925
926/*! @} */
927
928__END_DECLS
929
930#endif /* __M_BUF_H__ */
M_bincodec_codec_t
Definition: m_bincodec.h:67
void M_buf_add_str_just(M_buf_t *buf, const char *str, M_str_justify_type_t justify_type, unsigned char fill_char, size_t width)
M_bool M_buf_add_encode(M_buf_t *buf, const void *bytes, size_t bytes_len, size_t wrap, M_bincodec_codec_t codec)
M_bool M_buf_add_str_replace(M_buf_t *dest_buf, const char *src_str, const char *search_str, const char *replace_str)
void M_buf_add_byte(M_buf_t *buf, unsigned char byte)
void M_buf_add_char(M_buf_t *buf, char c)
M_bool M_buf_add_bytes_replace(M_buf_t *dest_buf, const M_uint8 *src, size_t src_len, const M_uint8 *search_bytes, size_t search_len, const M_uint8 *replace_bytes, size_t replace_len)
M_bool M_buf_add_int_money_dot(M_buf_t *buf, M_int64 amount, size_t max_width) M_WARN_UNUSED_RESULT
M_bool M_buf_add_money_dot(M_buf_t *buf, const char *amount, size_t max_width) M_WARN_UNUSED_RESULT
size_t M_buf_alloc_size(const M_buf_t *buf)
M_bool M_buf_add_uintbcd(M_buf_t *buf, M_uint64 n, size_t width)
M_bool M_buf_add_decimal(M_buf_t *buf, const M_decimal_t *decimal, M_bool implied_decimal, M_int8 num_decimals, size_t max_width) M_WARN_UNUSED_RESULT
void M_buf_add_bytes(M_buf_t *buf, const void *bytes, size_t bytes_length)
M_bool M_buf_decode(M_buf_t *buf, M_bincodec_codec_t codec)
M_bool M_buf_add_uintstrbin(M_buf_t *buf, const char *s, unsigned char base, size_t width, M_endian_t endianness)
unsigned char * M_buf_finish(M_buf_t *buf, size_t *out_length) M_FREE(1) M_WARN_UNUSED_RESULT M_MALLOC
void M_buf_truncate(M_buf_t *buf, size_t length)
void M_buf_add_bytes_just(M_buf_t *buf, const void *bytes, size_t bytes_length, M_str_justify_type_t justify_type, unsigned char fill_char, size_t width)
M_bool M_buf_add_bytes_hex(M_buf_t *buf, const char *hex_bytes)
void M_buf_bjoin_buf(M_buf_t *dest, unsigned char sep, M_buf_t **bufs, size_t cnt)
M_bool M_buf_add_decimal_just(M_buf_t *buf, const M_decimal_t *decimal, M_bool implied_decimal, M_int8 num_decimals, size_t max_width) M_WARN_UNUSED_RESULT
void M_buf_drop(M_buf_t *buf, size_t num)
unsigned char * M_buf_direct_write_start(M_buf_t *buf, size_t *len)
M_bool M_buf_add_uint_just(M_buf_t *buf, M_uint64 n, size_t width)
M_bool M_buf_add_decode(M_buf_t *buf, const char *encoded, size_t encoded_len, M_bincodec_codec_t codec)
void M_buf_add_int(M_buf_t *buf, M_int64 n)
void M_buf_add_fill(M_buf_t *buf, unsigned char fill_char, size_t width)
struct M_buf M_buf_t
Definition: m_buf.h:77
void M_buf_add_ptr(M_buf_t *buf, void *ptr)
void M_buf_add_uint(M_buf_t *buf, M_uint64 n)
void M_buf_add_bytehex(M_buf_t *buf, unsigned char byte, M_bool is_upper)
void M_buf_add_str_transform(M_buf_t *buf, M_uint32 transform_type, const char *str)
void M_buf_direct_write_end(M_buf_t *buf, size_t len)
const char * M_buf_peek(const M_buf_t *buf)
M_bool M_buf_add_int_money(M_buf_t *buf, M_int64 amount, size_t max_width) M_WARN_UNUSED_RESULT
M_BUF_TRANSFORM_TYPE
Definition: m_buf.h:80
void M_buf_add_str_hex(M_buf_t *buf, const void *bytes, size_t len)
void M_buf_add_str_upper(M_buf_t *buf, const char *str)
M_bool M_buf_add_int_money_dot_just(M_buf_t *buf, M_int64 amount, size_t max_width) M_WARN_UNUSED_RESULT
void M_buf_add_str_quoted(M_buf_t *buf, char quote_char, char escape_char, const char *quote_req_chars, M_bool always_quote, const char *src)
M_bool M_buf_add_uinthex(M_buf_t *buf, M_uint64 n, M_bool is_upper, size_t width)
size_t M_buf_len(const M_buf_t *buf)
M_bool M_buf_add_money_dot_just(M_buf_t *buf, const char *amount, size_t max_width) M_WARN_UNUSED_RESULT
M_bool M_buf_add_uintbin(M_buf_t *buf, M_uint64 n, size_t width, M_endian_t endianness)
M_buf_t * M_buf_create(void) M_WARN_UNUSED_RESULT M_MALLOC
void M_buf_sjoin_str(M_buf_t *dest, const char *sep, const char **strs, size_t cnt)
void M_buf_add_str_lower(M_buf_t *buf, const char *str)
size_t M_buf_add_str_lines(M_buf_t *buf, const char *str, size_t max_lines, size_t max_chars, M_bool truncate, const char *newline)
void M_buf_merge(M_buf_t *dest, M_buf_t *source) M_FREE(2)
M_bool M_buf_add_money(M_buf_t *buf, const char *amount, size_t max_width) M_WARN_UNUSED_RESULT
void M_buf_sjoin_buf(M_buf_t *dest, const char *sep, M_buf_t **bufs, size_t cnt)
M_bool M_buf_add_int_just(M_buf_t *buf, M_int64 n, size_t width)
char * M_buf_finish_str(M_buf_t *buf, size_t *out_length) M_FREE(1) M_WARN_UNUSED_RESULT M_MALLOC
void M_buf_add_str(M_buf_t *buf, const char *str)
void M_buf_bjoin_str(M_buf_t *dest, unsigned char sep, const char **strs, size_t cnt)
void M_buf_cancel(M_buf_t *buf) M_FREE(1)
void M_buf_add_str_just_transform(M_buf_t *buf, M_uint32 transform_type, const char *str, M_str_justify_type_t justify_type, unsigned char fill_char, size_t width)
void M_buf_trim(M_buf_t *buf)
M_bool M_buf_add_uintstrbcd(M_buf_t *buf, const char *s, unsigned char base, size_t width)
void M_buf_add_str_max(M_buf_t *buf, const char *str, size_t max)
M_bool M_buf_add_money_just(M_buf_t *buf, const char *amount, size_t max_width) M_WARN_UNUSED_RESULT
M_bool M_buf_encode(M_buf_t *buf, size_t wrap, M_bincodec_codec_t codec)
void M_buf_add_str_max_transform(M_buf_t *buf, M_uint32 transform_type, const char *str, size_t max)
M_bool M_buf_add_int_money_just(M_buf_t *buf, M_int64 amount, size_t max_width) M_WARN_UNUSED_RESULT
@ M_BUF_TRANSFORM_LTRIM
Definition: m_buf.h:84
@ M_BUF_TRANSFORM_TRIM
Definition: m_buf.h:86
@ M_BUF_TRANSFORM_UPPER
Definition: m_buf.h:82
@ M_BUF_TRANSFORM_RTRIM
Definition: m_buf.h:85
@ M_BUF_TRANSFORM_LOWER
Definition: m_buf.h:83
@ M_BUF_TRANSFORM_NONE
Definition: m_buf.h:81
Definition: m_decimal.h:78
M_endian_t
Definition: m_endian.h:76
M_str_justify_type_t
Definition: m_str.h:714