summaryrefslogtreecommitdiff
path: root/libmisc/include
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-05-18 08:57:29 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-05-30 14:07:17 -0600
commit222ee4838251a88bf23779b5c2b405a4c7dc619c (patch)
tree990a89da658a4196da122bd2a64ff20531fb97fa /libmisc/include
parent691d3fe7ff920e8113d174c2ce6c3126000a2f82 (diff)
libmisc: fmt.h: Add fmt_print2() and fmt_asprint()
Diffstat (limited to 'libmisc/include')
-rw-r--r--libmisc/include/libmisc/fmt.h31
1 files changed, 23 insertions, 8 deletions
diff --git a/libmisc/include/libmisc/fmt.h b/libmisc/include/libmisc/fmt.h
index c0743ff..6c04d99 100644
--- a/libmisc/include/libmisc/fmt.h
+++ b/libmisc/include/libmisc/fmt.h
@@ -9,6 +9,7 @@
#include <stddef.h> /* for size_t */
#include <stdint.h> /* for (u)int{n}_t */
+#include <stdlib.h> /* for realloc() */
#include <libmisc/macro.h>
#include <libmisc/obj.h>
@@ -99,6 +100,11 @@ void fmt_print_bool(lo_interface fmt_dest w, bool b);
const char * : fmt_print_str , \
bool : fmt_print_bool )(w, val)
+/** Same as fmt_print(), but usable from inside of fmt_print(). */
+#define fmt_print2(w, ...) do { LM_FOREACH_PARAM2_(_fmt_param2, (w), __VA_ARGS__) } while (0)
+#define _fmt_param2(...) _LM_DEFER2(_fmt_param_indirect)()(__VA_ARGS__)
+#define _fmt_param_indirect() _fmt_param
+
/* print-to-memory ************************************************************/
struct fmt_buf {
@@ -116,16 +122,25 @@ LO_IMPLEMENTATION_H(fmt_dest, struct fmt_buf, fmt_buf);
_w.len; \
})
-/* justify ********************************************************************/
+#define fmt_asprint(...) ({ \
+ struct fmt_buf _w = {}; \
+ lo_interface fmt_dest w = lo_box_fmt_buf_as_fmt_dest(&_w); \
+ fmt_print(w, __VA_ARGS__); \
+ while (_w.cap <= _w.len) { \
+ _w.cap = _w.len + 1; \
+ _w.len = 0; \
+ _w.dat = realloc(_w.dat, _w.cap); \
+ fmt_print(w, __VA_ARGS__); \
+ } \
+ ((char *)_w.dat)[_w.len] = '\0'; \
+ _w.dat; \
+})
-/* *grubles about not being allowed to nest things* */
-#define _fmt_param_indirect() _fmt_param
-#define _fmt_print2(w, ...) do { LM_FOREACH_PARAM2_(_fmt_param2, (w), __VA_ARGS__) } while (0)
-#define _fmt_param2(...) _LM_DEFER2(_fmt_param_indirect)()(__VA_ARGS__)
+/* justify ********************************************************************/
#define fmt_print_ljust(w, width, fillchar, ...) do { \
size_t beg = LO_CALL(w, tell); \
- _fmt_print2(w, __VA_ARGS__); \
+ fmt_print2(w, __VA_ARGS__); \
while ((LO_CALL(w, tell) - beg) < width) \
fmt_print_byte(w, fillchar); \
} while (0)
@@ -133,10 +148,10 @@ LO_IMPLEMENTATION_H(fmt_dest, struct fmt_buf, fmt_buf);
#define fmt_print_rjust(w, width, fillchar, ...) do { \
struct fmt_buf _discard = {}; \
lo_interface fmt_dest discard = lo_box_fmt_buf_as_fmt_dest(&_discard); \
- _fmt_print2(discard, __VA_ARGS__); \
+ fmt_print2(discard, __VA_ARGS__); \
while (_discard.len++ < width) \
fmt_print_byte(w, fillchar); \
- _fmt_print2(w, __VA_ARGS__); \
+ fmt_print2(w, __VA_ARGS__); \
} while (0)
void fmt_print_base16_u8_(lo_interface fmt_dest w, uint8_t x);