#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; // argument name, must start with an alphabet } 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));