#pragma once
#include "util/FFstrbuf.h"
typedef enum __attribute__((__packed__)) FFformatArgType
{
FF_FORMAT_ARG_TYPE_NULL = 0,
FF_FORMAT_ARG_TYPE_UINT,
FF_FORMAT_ARG_TYPE_UINT64,
FF_FORMAT_ARG_TYPE_UINT16,
FF_FORMAT_ARG_TYPE_UINT8,
FF_FORMAT_ARG_TYPE_INT,
FF_FORMAT_ARG_TYPE_STRING,
FF_FORMAT_ARG_TYPE_STRBUF,
FF_FORMAT_ARG_TYPE_FLOAT,
FF_FORMAT_ARG_TYPE_DOUBLE,
FF_FORMAT_ARG_TYPE_LIST,
FF_FORMAT_ARG_TYPE_BOOL
} FFformatArgType;
#define FF_FORMAT_ARG(variable, var_name) { _Generic((variable), \
uint32_t: FF_FORMAT_ARG_TYPE_UINT, \
uint64_t: FF_FORMAT_ARG_TYPE_UINT64, \
uint16_t: FF_FORMAT_ARG_TYPE_UINT16, \
uint8_t: FF_FORMAT_ARG_TYPE_UINT8, \
int32_t: FF_FORMAT_ARG_TYPE_INT, \
char*: FF_FORMAT_ARG_TYPE_STRING, \
const char*: FF_FORMAT_ARG_TYPE_STRING, \
FFstrbuf: FF_FORMAT_ARG_TYPE_STRBUF, \
float: FF_FORMAT_ARG_TYPE_FLOAT, \
double: FF_FORMAT_ARG_TYPE_DOUBLE, \
FFlist: FF_FORMAT_ARG_TYPE_LIST, \
bool: FF_FORMAT_ARG_TYPE_BOOL \
), _Generic((variable), char*: (variable), const char*: (variable), default: &(variable) ), (var_name) }
typedef struct FFformatarg
{
FFformatArgType type;
const void* value;
const char* name; } FFformatarg;
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg);
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments);
#define FF_PARSE_FORMAT_STRING_CHECKED(buffer, formatstr, arguments) \
ffParseFormatString((buffer), (formatstr), sizeof(arguments) / sizeof(*arguments), (arguments));