Derive-C
Loading...
Searching...
No Matches
dump.h
Go to the documentation of this file.
1
5
6#pragma once
7
8#include <stdio.h>
9#include <string.h>
13
14static const char* _dc_debug_trailing_space = "...";
15#define _DC_DEBUG_MAX_CAPACITY 4096
19
21 // JUSTIFY: Single static buffer
22 // - Thread local required for thread safety
23 // - The returned strings must outlive the function call (e.g. to be used in a printf)
24 // - Multiple prints are possible.
25 // A single thread local buffer suits this task well.
26
28 return NULL;
29 }
30
33 size_t writable = available + 1;
34
35 FILE* mem_stream = fmemopen(_dc_debug_dump_buf + _dc_debug_dump_start_pos, writable, "w");
36 return mem_stream;
37}
38
39DC_INTERNAL static char const* _dc_debug_dump_end(FILE* mem_stream) {
40 if (mem_stream == NULL) {
42 }
43
44 fflush(mem_stream);
45 long used_long = ftell(mem_stream);
46 fclose(mem_stream);
47
48 if (used_long < 0) {
50 }
51
52 size_t used = (size_t)used_long;
53
54 size_t start = _dc_debug_dump_start_pos;
55 size_t available = _DC_DEBUG_MAX_CAPACITY - start;
56 size_t trailing_len = strlen(_dc_debug_trailing_space);
57
58 if (used > available) {
59 size_t content_size = available - trailing_len;
60
61 for (size_t i = 0; i < trailing_len; i++) {
62 _dc_debug_dump_buf[start + content_size + i] = _dc_debug_trailing_space[i];
63 }
64 _dc_debug_dump_buf[start + content_size + trailing_len] = '\0';
65
66 _dc_debug_dump_head = start + content_size + trailing_len + 1;
67 return &_dc_debug_dump_buf[start];
68 }
69 _dc_debug_dump_buf[start + used] = '\0';
70 _dc_debug_dump_head = start + used + 1;
71 return &_dc_debug_dump_buf[start];
72}
73
74// JUSTIFY: Allowing the buffer to be reset, invalidating existing strings.
75// - Used for resetting the buffer for reuse (e.g. in unit tests)
76// - e.g. called in test constructor
77DC_PUBLIC static void dc_debug_dump_reset(void) {
80
81 // JUSTIFY: For easier debugging in coredumps from unit tests, clear the buffer.
82 memset(_dc_debug_dump_buf, 0, sizeof(_dc_debug_dump_buf));
83}
84
85// JUSTIFY: Using a macro, rather than a function
86// - We need the actual types for the debug pointer and function, we cannot convert them to
87// `void*` and `(*foo)(void*, dc_debug_fmt, FILE*)`.
88// - Additionally users are allowed to pass non-function pointers to the templates (e.g. using the
89// `DC_DEFAULT_DEBUG`, or just defining as say `#define ITEM_DEBUG(self, fmt, stream)
90// fprintf(stream, "foo")`). To avoid needing to wrap all of these in a function, we can just take
91// a macro here.
92#define DC_DEBUG(DEBUG_FN, DEBUG_PTR) \
93 ({ \
94 FILE* stream = _dc_debug_dump_start(); \
95 char const* result; \
96 if (stream == NULL) { \
97 result = _dc_debug_trailing_space; \
98 } else { \
99 DEBUG_FN(DEBUG_PTR, dc_debug_fmt_new(), stream); \
100 result = _dc_debug_dump_end(stream); \
101 } \
102 result; \
103 })
#define DC_THREAD_LOCAL
Definition attributes.h:31
#define _DC_DEBUG_MAX_CAPACITY
Definition dump.h:15
static DC_THREAD_LOCAL size_t _dc_debug_dump_head
Definition dump.h:17
static DC_THREAD_LOCAL char _dc_debug_dump_buf[_DC_DEBUG_MAX_CAPACITY+4]
Definition dump.h:16
static DC_INTERNAL char const * _dc_debug_dump_end(FILE *mem_stream)
Definition dump.h:39
static DC_INTERNAL FILE * _dc_debug_dump_start(void)
Definition dump.h:20
static const char * _dc_debug_trailing_space
A no-alloc, debug dump utility for use in asserts.
Definition dump.h:14
static DC_PUBLIC void dc_debug_dump_reset(void)
Definition dump.h:77
static DC_THREAD_LOCAL size_t _dc_debug_dump_start_pos
Definition dump.h:18
#define DC_PUBLIC
Definition namespace.h:25
#define DC_INTERNAL
Definition namespace.h:30