Added `sprintf()`-like functions for `view_t` `sv_s[vn]?printf\(\)`

Fortune for sink's current commit: Curse − 凶
args
Avril 2 years ago
parent 2d5840da8d
commit 02c055f2c8
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -3,6 +3,7 @@
#include <string.h>
#include <stdbool.h>
#include <limits.h>
#include <stdarg.h>
#include "view.h"
@ -103,23 +104,29 @@ view_t s_get_str(str_info_t data)
};
}
__attribute__((cold))
static size_t _sv_copy_manual(size_t sz, char buffer[restrict static sz], view_t view)
__attribute__((__always_inline__, __gnu_inline__, artificial))
inline static size_t _sv_copy_manual(size_t sz, char buffer[restrict static sz], view_t view)
{
memcpy(buffer, view.ptr, sz = min((sz-1), view.len));
/*
size_t i=0;
for(;i< (sz-1) && i<view.len;i++)
{
buffer[i] = view.ptr[i];
}
buffer[i] = 0;
}*/
buffer[sz] = 0;
return view.len+1;
}
size_t sv_copy_to(size_t sz, char buffer[restrict static sz], view_t view)
inline size_t sv_copy_to(size_t sz, char buffer[restrict static sz], view_t view)
{
#ifdef _VIEW_USE_SNPRINTF_INTERNAL
if(__builtin_expect(view.len <= INT_MAX, true))
return (size_t)snprintf(buffer, sz, "%.*s", (int)view.len, view.ptr);
else {
else
#endif
{
// Manual implementation, for views longer than INT_MAX
//XXX: TODO: Ensure return value follows the same construct.
return _sv_copy_manual(sz, buffer, view);
@ -213,6 +220,65 @@ bool sv_eq(view_t a, view_t b)
return a.len == b.len && (__builtin_expect(a.ptr == b.ptr, false) || memcmp(a.ptr, b.ptr, a.len));
}
/* Not useful.
int sv_fprintf(FILE* out, view_t fmt, ...)
{
va_list va;
char rfmt[fmt.len+1];
va_start(va, fmt);
sv_copy_to(fmt.len+1, rfmt, fmt);
int r =vfprintf(out, rfmt, va);
va_end(va);
return r;
}*/
inline static size_t sv_vsnprintf(view_t* restrict out, size_t sz, const char* fmt, va_list args)
{
if(__builtin_expect(out!=NULL, true))
return vsnprintf(out->ptr, min(out->len, sz), fmt, args);
else return vsnprintf((char[]){}, 0, fmt, args);
}
size_t sv_vsvnprintf(view_t* restrict out, size_t sz, view_t fmt, va_list args)
{
char buffer[fmt.len+1];
sv_copy_to(fmt.len+1, buffer, fmt);
return sv_vsnprintf(out, sz, buffer, args);
}
size_t sv_snprintf(view_t* restrict out, size_t sz, const char* fmt, ...)
{
va_list va;
va_start(va, fmt);
size_t r = sv_vsnprintf(out, sz, fmt, va);
va_end(va);
return r;
}
size_t sv_sprintf(view_t* restrict out, const char* fmt, ...)
{
va_list va;
va_start(va, fmt);
size_t r = sv_vsnprintf(out, out ? out->len : 0, fmt, va);
va_end(va);
return r;
}
size_t sv_svnprintf(view_t* restrict out, size_t sz, view_t fmt, ...)
{
va_list va;
va_start(va, fmt);
size_t r = sv_vsvnprintf(out, sz, fmt, va);
va_end(va);
return r;
}
size_t sv_svprintf(view_t* restrict out, view_t fmt, ...)
{
va_list va;
va_start(va, fmt);
size_t r = sv_vsvnprintf(out, out ? out->len : fmt.len, fmt, va);
va_end(va);
return r;
}

@ -5,6 +5,11 @@
#include <stddef.h>
#include <stdbool.h>
/// Printf format string for `view_t`
#define SV_PRINT_FMT "%.*s"
/// Printf format arguments for `view_t` to match the position of `SV_PRINT_FMT`
#define SV_PRINT_ARG(view) (int)(view).len, (view).ptr
typedef struct string_view {
size_t len;
char* ptr;
@ -36,6 +41,12 @@ extern inline size_t sv_split_cstr(const char* p, char on, view_t* restrict firs
size_t sv_copy_to(size_t sz, char buffer[restrict static sz], view_t view);
char* sv_to_cstr(view_t view, char* restrict buffer, size_t n);
// sprintf-like
size_t sv_svnprintf(view_t* restrict out, size_t sz, view_t fmt, ...);
size_t sv_svprintf(view_t* restrict out, view_t fmt, ...);
size_t sv_sprintf(view_t* restrict out, const char* fmt, ...);
size_t sv_snprintf(view_t* restrict out, size_t sz, const char* fmt, ...);
__attribute__((__gnu_inline__, malloc))
extern inline char* sv_dupto_cstr(view_t view)
{ return sv_to_cstr(view, (char*)0, 0); }

Loading…
Cancel
Save