Moved string handling functions from version header into its own TU.

Fix bug involving _mixin producing conflicting symbols: now using `gnu_inilne` (macro"d to `force_inline`), instead of `always_inline`

Fortune for naka's current commit: Blessing − 吉
generic-project-skeleton
Avril 3 years ago
parent fb2fa5801e
commit 672502449b
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -23,11 +23,12 @@
#define noinline __attribute__((noinline))
#define always_inline __attribute__((always_inline))
#define force_inline __attribute__((gnu_inline))
#ifdef DEBUG
#define _mixin static inline always_inline
#define _mixin static inline force_inline
#else
#define _mixin extern inline always_inline
#define _mixin extern inline force_inline
#endif
#define unrestrict __attribute__((may_alias))

@ -41,39 +41,23 @@ _mixin uint32_t v_ctoraw(version_t ver)
#define VERSION_STRING_MAX AS(3 + 3 + 3 + 3 + 3, usize) // maj + min + bf + rev + (..r)
//TODO: Move the below functions to `version.c` and have them prototyped, not mixins.
/// Print a version to a string buffer `out`. Return the number of bytes written.
///
/// Has the same semantics as `snprintf`; to calculate the length of the string needed to allocate, invoke like: `size_t sz = v_ctosn(vers, 0, NULL)`. The buffer should be allocated as `sz + 1`, and then the next call to `v_ctosn` should be like: `v_ctosn(vers, sz+1, buffer);
_mixin usize v_ctosn(version_t ver, usize max, char out[static pOUT max])
//XXX: Specifying `str[static ...` tells the compiler this function expects a non-null pointer. When in reality, a `NULL` pointer is used here as a sentinel value to not print... The mixin below is a hack around this, but this might introduce invalid optimisations. We should either: split the size getting function into its own thing (`v_ctosn_sz` would become a real function) that does the exact same thing as `v_ctosn(_,0,NULL)`, and not pass `NULL` to str here ever. OR, change str to regular `char *pOUT str`. The latter would be easier, but we might potentially lose out on some obscure non-NULL snprintf optimisation? For now, just use the `v_ctosn_sz` hack below. If we go with the latter, we can #define it to be just `v_ctosn(v, 0, NULL)`, otherwise move it to version.c and implement it with `snprintf(NULL, 0, ...)`.
usize v_ctosn(version_t ver, usize max, char str[static pOUT max]);
_mixin usize v_ctosn_sz(version_t ver)
{
struct v_comp comp = ver.comp;
const char* const fmt = comp.revision ? "%hhu.%hhu.%hhur%hhu" : "%hhu.%hhu.%hhu";
return snprintf(out, max, fmt,
comp.major,
comp.minor,
comp.bugfix,
comp.revision);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull"
return v_ctosn(ver, 0, NULL);
#pragma GCC diagnostic pop
}
/// Print a version to a static string buffer. The string buffer is thread local. The next call to this function on the same thread will overwrite the returned buffer.
_mixin const char* v_ctoss(version_t ver)
{
_Thread_local static char buffer[VERSION_STRING_MAX+1];
buffer[v_ctosn(ver, VERSION_STRING_MAX+1, buffer)] = 0;
return buffer;
}
const char* v_ctoss(version_t ver);
/// Print a version to a `malloc()`d string buffer. The buffer is unique and owned by the callee. The buffer must be `free()`d.
_mixin char* v_ctos(version_t ver)
{
usize sz = v_ctosn(ver, 0, NULL);
char* buf = malloc(sz+1);
v_ctosn(ver, sz+1, buf);
return buf;
}
char* v_ctos(version_t ver);
#endif /* _VERSION_H */

@ -13,10 +13,10 @@ int main(int argc, char** argv)
IGNORE(argc);
IGNORE(argv);
const u32 vraw = VERSION(1,2,3,240);
const u32 vraw = VERSION(100,200,101,255);
version_t vers = v_rawtoc(vraw);
usize sz = v_ctosn(vers, 0, NULL);
usize sz = v_ctosn_sz(vers);
char verstr[sz+1];
v_ctosn(vers, sz+1, verstr);

@ -0,0 +1,34 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <version.h>
usize v_ctosn(version_t ver, usize max, char out[static pOUT max])
{
struct v_comp comp = ver.comp;
const char* const fmt = comp.revision ? "%hhu.%hhu.%hhur%hhu" : "%hhu.%hhu.%hhu";
return snprintf(out, max, fmt,
comp.major,
comp.minor,
comp.bugfix,
comp.revision);
}
const char* v_ctoss(version_t ver)
{
_Thread_local static char buffer[VERSION_STRING_MAX+1];
buffer[v_ctosn(ver, VERSION_STRING_MAX+1, buffer)] = 0;
return buffer;
}
char* v_ctos(version_t ver)
{
usize sz = v_ctosn_sz(ver);
char* buf = malloc(sz+1);
v_ctosn(ver, sz+1, buf);
return buf;
}
Loading…
Cancel
Save