add: vendor directory
add: cli (argparse) add: test runner
This commit is contained in:
parent
25ba0ff723
commit
ec720e7617
15 changed files with 658 additions and 13 deletions
384
vendor/argparse.c
vendored
Normal file
384
vendor/argparse.c
vendored
Normal file
|
@ -0,0 +1,384 @@
|
|||
/**
|
||||
* Copyright (C) 2012-2015 Yecheng Fu <cofyc.jackson at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a MIT-style license that can be found
|
||||
* in the LICENSE file.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include "argparse.h"
|
||||
|
||||
#define OPT_UNSET 1
|
||||
#define OPT_LONG (1 << 1)
|
||||
|
||||
static const char *
|
||||
prefix_skip(const char *str, const char *prefix)
|
||||
{
|
||||
size_t len = strlen(prefix);
|
||||
return strncmp(str, prefix, len) ? NULL : str + len;
|
||||
}
|
||||
|
||||
static int
|
||||
prefix_cmp(const char *str, const char *prefix)
|
||||
{
|
||||
for (;; str++, prefix++)
|
||||
if (!*prefix) {
|
||||
return 0;
|
||||
} else if (*str != *prefix) {
|
||||
return (unsigned char)*prefix - (unsigned char)*str;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
argparse_error(struct argparse *self, const struct argparse_option *opt,
|
||||
const char *reason, int flags)
|
||||
{
|
||||
(void)self;
|
||||
if (flags & OPT_LONG) {
|
||||
fprintf(stderr, "error: option `--%s` %s\n", opt->long_name, reason);
|
||||
} else {
|
||||
fprintf(stderr, "error: option `-%c` %s\n", opt->short_name, reason);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
argparse_getvalue(struct argparse *self, const struct argparse_option *opt,
|
||||
int flags)
|
||||
{
|
||||
const char *s = NULL;
|
||||
if (!opt->value)
|
||||
goto skipped;
|
||||
switch (opt->type) {
|
||||
case ARGPARSE_OPT_BOOLEAN:
|
||||
if (flags & OPT_UNSET) {
|
||||
*(int *)opt->value = *(int *)opt->value - 1;
|
||||
} else {
|
||||
*(int *)opt->value = *(int *)opt->value + 1;
|
||||
}
|
||||
if (*(int *)opt->value < 0) {
|
||||
*(int *)opt->value = 0;
|
||||
}
|
||||
break;
|
||||
case ARGPARSE_OPT_BIT:
|
||||
if (flags & OPT_UNSET) {
|
||||
*(int *)opt->value &= ~opt->data;
|
||||
} else {
|
||||
*(int *)opt->value |= opt->data;
|
||||
}
|
||||
break;
|
||||
case ARGPARSE_OPT_STRING:
|
||||
if (self->optvalue) {
|
||||
*(const char **)opt->value = self->optvalue;
|
||||
self->optvalue = NULL;
|
||||
} else if (self->argc > 1) {
|
||||
self->argc--;
|
||||
*(const char **)opt->value = *++self->argv;
|
||||
} else {
|
||||
argparse_error(self, opt, "requires a value", flags);
|
||||
}
|
||||
break;
|
||||
case ARGPARSE_OPT_INTEGER:
|
||||
errno = 0;
|
||||
if (self->optvalue) {
|
||||
*(int *)opt->value = strtol(self->optvalue, (char **)&s, 0);
|
||||
self->optvalue = NULL;
|
||||
} else if (self->argc > 1) {
|
||||
self->argc--;
|
||||
*(int *)opt->value = strtol(*++self->argv, (char **)&s, 0);
|
||||
} else {
|
||||
argparse_error(self, opt, "requires a value", flags);
|
||||
}
|
||||
if (errno)
|
||||
argparse_error(self, opt, strerror(errno), flags);
|
||||
if (s[0] != '\0')
|
||||
argparse_error(self, opt, "expects an integer value", flags);
|
||||
break;
|
||||
case ARGPARSE_OPT_FLOAT:
|
||||
errno = 0;
|
||||
if (self->optvalue) {
|
||||
*(float *)opt->value = strtof(self->optvalue, (char **)&s);
|
||||
self->optvalue = NULL;
|
||||
} else if (self->argc > 1) {
|
||||
self->argc--;
|
||||
*(float *)opt->value = strtof(*++self->argv, (char **)&s);
|
||||
} else {
|
||||
argparse_error(self, opt, "requires a value", flags);
|
||||
}
|
||||
if (errno)
|
||||
argparse_error(self, opt, strerror(errno), flags);
|
||||
if (s[0] != '\0')
|
||||
argparse_error(self, opt, "expects a numerical value", flags);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
skipped:
|
||||
if (opt->callback) {
|
||||
return opt->callback(self, opt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
argparse_options_check(const struct argparse_option *options)
|
||||
{
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
switch (options->type) {
|
||||
case ARGPARSE_OPT_END:
|
||||
case ARGPARSE_OPT_BOOLEAN:
|
||||
case ARGPARSE_OPT_BIT:
|
||||
case ARGPARSE_OPT_INTEGER:
|
||||
case ARGPARSE_OPT_FLOAT:
|
||||
case ARGPARSE_OPT_STRING:
|
||||
case ARGPARSE_OPT_GROUP:
|
||||
continue;
|
||||
default:
|
||||
fprintf(stderr, "wrong option type: %d", options->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
argparse_short_opt(struct argparse *self, const struct argparse_option *options)
|
||||
{
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
if (options->short_name == *self->optvalue) {
|
||||
self->optvalue = self->optvalue[1] ? self->optvalue + 1 : NULL;
|
||||
return argparse_getvalue(self, options, 0);
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int
|
||||
argparse_long_opt(struct argparse *self, const struct argparse_option *options)
|
||||
{
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
const char *rest;
|
||||
int opt_flags = 0;
|
||||
if (!options->long_name)
|
||||
continue;
|
||||
|
||||
rest = prefix_skip(self->argv[0] + 2, options->long_name);
|
||||
if (!rest) {
|
||||
// negation disabled?
|
||||
if (options->flags & OPT_NONEG) {
|
||||
continue;
|
||||
}
|
||||
// only OPT_BOOLEAN/OPT_BIT supports negation
|
||||
if (options->type != ARGPARSE_OPT_BOOLEAN && options->type !=
|
||||
ARGPARSE_OPT_BIT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prefix_cmp(self->argv[0] + 2, "no-")) {
|
||||
continue;
|
||||
}
|
||||
rest = prefix_skip(self->argv[0] + 2 + 3, options->long_name);
|
||||
if (!rest)
|
||||
continue;
|
||||
opt_flags |= OPT_UNSET;
|
||||
}
|
||||
if (*rest) {
|
||||
if (*rest != '=')
|
||||
continue;
|
||||
self->optvalue = rest + 1;
|
||||
}
|
||||
return argparse_getvalue(self, options, opt_flags | OPT_LONG);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int
|
||||
argparse_init(struct argparse *self, struct argparse_option *options,
|
||||
const char *const *usages, int flags)
|
||||
{
|
||||
memset(self, 0, sizeof(*self));
|
||||
self->options = options;
|
||||
self->usages = usages;
|
||||
self->flags = flags;
|
||||
self->description = NULL;
|
||||
self->epilog = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
argparse_describe(struct argparse *self, const char *description,
|
||||
const char *epilog)
|
||||
{
|
||||
self->description = description;
|
||||
self->epilog = epilog;
|
||||
}
|
||||
|
||||
int
|
||||
argparse_parse(struct argparse *self, int argc, const char **argv)
|
||||
{
|
||||
self->argc = argc - 1;
|
||||
self->argv = argv + 1;
|
||||
self->out = argv;
|
||||
|
||||
argparse_options_check(self->options);
|
||||
|
||||
for (; self->argc; self->argc--, self->argv++) {
|
||||
const char *arg = self->argv[0];
|
||||
if (arg[0] != '-' || !arg[1]) {
|
||||
if (self->flags & ARGPARSE_STOP_AT_NON_OPTION) {
|
||||
goto end;
|
||||
}
|
||||
// if it's not option or is a single char '-', copy verbatim
|
||||
self->out[self->cpidx++] = self->argv[0];
|
||||
continue;
|
||||
}
|
||||
// short option
|
||||
if (arg[1] != '-') {
|
||||
self->optvalue = arg + 1;
|
||||
switch (argparse_short_opt(self, self->options)) {
|
||||
case -1:
|
||||
break;
|
||||
case -2:
|
||||
goto unknown;
|
||||
}
|
||||
while (self->optvalue) {
|
||||
switch (argparse_short_opt(self, self->options)) {
|
||||
case -1:
|
||||
break;
|
||||
case -2:
|
||||
goto unknown;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// if '--' presents
|
||||
if (!arg[2]) {
|
||||
self->argc--;
|
||||
self->argv++;
|
||||
break;
|
||||
}
|
||||
// long option
|
||||
switch (argparse_long_opt(self, self->options)) {
|
||||
case -1:
|
||||
break;
|
||||
case -2:
|
||||
goto unknown;
|
||||
}
|
||||
continue;
|
||||
|
||||
unknown:
|
||||
fprintf(stderr, "error: unknown option `%s`\n", self->argv[0]);
|
||||
argparse_usage(self);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
end:
|
||||
memmove(self->out + self->cpidx, self->argv,
|
||||
self->argc * sizeof(*self->out));
|
||||
self->out[self->cpidx + self->argc] = NULL;
|
||||
|
||||
return self->cpidx + self->argc;
|
||||
}
|
||||
|
||||
void
|
||||
argparse_usage(struct argparse *self)
|
||||
{
|
||||
if (self->usages) {
|
||||
fprintf(stdout, "Usage: %s\n", *self->usages++);
|
||||
while (*self->usages && **self->usages)
|
||||
fprintf(stdout, " or: %s\n", *self->usages++);
|
||||
} else {
|
||||
fprintf(stdout, "Usage:\n");
|
||||
}
|
||||
|
||||
// print description
|
||||
if (self->description)
|
||||
fprintf(stdout, "%s\n", self->description);
|
||||
|
||||
fputc('\n', stdout);
|
||||
|
||||
const struct argparse_option *options;
|
||||
|
||||
// figure out best width
|
||||
size_t usage_opts_width = 0;
|
||||
size_t len;
|
||||
options = self->options;
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
len = 0;
|
||||
if ((options)->short_name) {
|
||||
len += 2;
|
||||
}
|
||||
if ((options)->short_name && (options)->long_name) {
|
||||
len += 2; // separator ", "
|
||||
}
|
||||
if ((options)->long_name) {
|
||||
len += strlen((options)->long_name) + 2;
|
||||
}
|
||||
if (options->type == ARGPARSE_OPT_INTEGER) {
|
||||
len += strlen("=<int>");
|
||||
}
|
||||
if (options->type == ARGPARSE_OPT_FLOAT) {
|
||||
len += strlen("=<flt>");
|
||||
} else if (options->type == ARGPARSE_OPT_STRING) {
|
||||
len += strlen("=<str>");
|
||||
}
|
||||
len = (len + 3) - ((len + 3) & 3);
|
||||
if (usage_opts_width < len) {
|
||||
usage_opts_width = len;
|
||||
}
|
||||
}
|
||||
usage_opts_width += 4; // 4 spaces prefix
|
||||
|
||||
options = self->options;
|
||||
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||
size_t pos = 0;
|
||||
int pad = 0;
|
||||
if (options->type == ARGPARSE_OPT_GROUP) {
|
||||
fputc('\n', stdout);
|
||||
fprintf(stdout, "%s", options->help);
|
||||
fputc('\n', stdout);
|
||||
continue;
|
||||
}
|
||||
pos = fprintf(stdout, " ");
|
||||
if (options->short_name) {
|
||||
pos += fprintf(stdout, "-%c", options->short_name);
|
||||
}
|
||||
if (options->long_name && options->short_name) {
|
||||
pos += fprintf(stdout, ", ");
|
||||
}
|
||||
if (options->long_name) {
|
||||
pos += fprintf(stdout, "--%s", options->long_name);
|
||||
}
|
||||
if (options->type == ARGPARSE_OPT_INTEGER) {
|
||||
pos += fprintf(stdout, "=<int>");
|
||||
} else if (options->type == ARGPARSE_OPT_FLOAT) {
|
||||
pos += fprintf(stdout, "=<flt>");
|
||||
} else if (options->type == ARGPARSE_OPT_STRING) {
|
||||
pos += fprintf(stdout, "=<str>");
|
||||
}
|
||||
if (pos <= usage_opts_width) {
|
||||
pad = usage_opts_width - pos;
|
||||
} else {
|
||||
fputc('\n', stdout);
|
||||
pad = usage_opts_width;
|
||||
}
|
||||
fprintf(stdout, "%*s%s\n", pad + 2, "", options->help);
|
||||
}
|
||||
|
||||
// print epilog
|
||||
if (self->epilog)
|
||||
fprintf(stdout, "%s\n", self->epilog);
|
||||
}
|
||||
|
||||
int
|
||||
argparse_help_cb(struct argparse *self, const struct argparse_option *option)
|
||||
{
|
||||
(void)option;
|
||||
argparse_usage(self);
|
||||
exit(0);
|
||||
}
|
130
vendor/argparse.h
vendored
Normal file
130
vendor/argparse.h
vendored
Normal file
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* Copyright (C) 2012-2015 Yecheng Fu <cofyc.jackson at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a MIT-style license that can be found
|
||||
* in the LICENSE file.
|
||||
*/
|
||||
#ifndef ARGPARSE_H
|
||||
#define ARGPARSE_H
|
||||
|
||||
/* For c++ compatibility */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct argparse;
|
||||
struct argparse_option;
|
||||
|
||||
typedef int argparse_callback (struct argparse *self,
|
||||
const struct argparse_option *option);
|
||||
|
||||
enum argparse_flag {
|
||||
ARGPARSE_STOP_AT_NON_OPTION = 1,
|
||||
};
|
||||
|
||||
enum argparse_option_type {
|
||||
/* special */
|
||||
ARGPARSE_OPT_END,
|
||||
ARGPARSE_OPT_GROUP,
|
||||
/* options with no arguments */
|
||||
ARGPARSE_OPT_BOOLEAN,
|
||||
ARGPARSE_OPT_BIT,
|
||||
/* options with arguments (optional or required) */
|
||||
ARGPARSE_OPT_INTEGER,
|
||||
ARGPARSE_OPT_FLOAT,
|
||||
ARGPARSE_OPT_STRING,
|
||||
};
|
||||
|
||||
enum argparse_option_flags {
|
||||
OPT_NONEG = 1, /* disable negation */
|
||||
};
|
||||
|
||||
/**
|
||||
* argparse option
|
||||
*
|
||||
* `type`:
|
||||
* holds the type of the option, you must have an ARGPARSE_OPT_END last in your
|
||||
* array.
|
||||
*
|
||||
* `short_name`:
|
||||
* the character to use as a short option name, '\0' if none.
|
||||
*
|
||||
* `long_name`:
|
||||
* the long option name, without the leading dash, NULL if none.
|
||||
*
|
||||
* `value`:
|
||||
* stores pointer to the value to be filled.
|
||||
*
|
||||
* `help`:
|
||||
* the short help message associated to what the option does.
|
||||
* Must never be NULL (except for ARGPARSE_OPT_END).
|
||||
*
|
||||
* `callback`:
|
||||
* function is called when corresponding argument is parsed.
|
||||
*
|
||||
* `data`:
|
||||
* associated data. Callbacks can use it like they want.
|
||||
*
|
||||
* `flags`:
|
||||
* option flags.
|
||||
*/
|
||||
struct argparse_option {
|
||||
enum argparse_option_type type;
|
||||
const char short_name;
|
||||
const char *long_name;
|
||||
void *value;
|
||||
const char *help;
|
||||
argparse_callback *callback;
|
||||
intptr_t data;
|
||||
int flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* argpparse
|
||||
*/
|
||||
struct argparse {
|
||||
// user supplied
|
||||
const struct argparse_option *options;
|
||||
const char *const *usages;
|
||||
int flags;
|
||||
const char *description; // a description after usage
|
||||
const char *epilog; // a description at the end
|
||||
// internal context
|
||||
int argc;
|
||||
const char **argv;
|
||||
const char **out;
|
||||
int cpidx;
|
||||
const char *optvalue; // current option value
|
||||
};
|
||||
|
||||
// built-in callbacks
|
||||
int argparse_help_cb(struct argparse *self,
|
||||
const struct argparse_option *option);
|
||||
|
||||
// built-in option macros
|
||||
#define OPT_END() { ARGPARSE_OPT_END, 0, NULL, NULL, 0, NULL, 0, 0 }
|
||||
#define OPT_BOOLEAN(...) { ARGPARSE_OPT_BOOLEAN, __VA_ARGS__ }
|
||||
#define OPT_BIT(...) { ARGPARSE_OPT_BIT, __VA_ARGS__ }
|
||||
#define OPT_INTEGER(...) { ARGPARSE_OPT_INTEGER, __VA_ARGS__ }
|
||||
#define OPT_FLOAT(...) { ARGPARSE_OPT_FLOAT, __VA_ARGS__ }
|
||||
#define OPT_STRING(...) { ARGPARSE_OPT_STRING, __VA_ARGS__ }
|
||||
#define OPT_GROUP(h) { ARGPARSE_OPT_GROUP, 0, NULL, NULL, h, NULL, 0, 0 }
|
||||
#define OPT_HELP() OPT_BOOLEAN('h', "help", NULL, \
|
||||
"show this help message and exit", \
|
||||
argparse_help_cb, 0, OPT_NONEG)
|
||||
|
||||
int argparse_init(struct argparse *self, struct argparse_option *options,
|
||||
const char *const *usages, int flags);
|
||||
void argparse_describe(struct argparse *self, const char *description,
|
||||
const char *epilog);
|
||||
int argparse_parse(struct argparse *self, int argc, const char **argv);
|
||||
void argparse_usage(struct argparse *self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
3379
vendor/binn.c
vendored
Normal file
3379
vendor/binn.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
921
vendor/binn.h
vendored
Normal file
921
vendor/binn.h
vendored
Normal file
|
@ -0,0 +1,921 @@
|
|||
|
||||
// TO ENABLE INLINE FUNCTIONS:
|
||||
// ON MSVC: enable the 'Inline Function Expansion' (/Ob2) compiler option, and maybe the
|
||||
// 'Whole Program Optimitazion' (/GL), that requires the
|
||||
// 'Link Time Code Generation' (/LTCG) linker option to be enabled too
|
||||
|
||||
#ifndef BINN_H
|
||||
#define BINN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NULL
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef BOOL
|
||||
typedef int BOOL;
|
||||
#endif
|
||||
|
||||
#ifndef APIENTRY
|
||||
#ifdef _WIN32
|
||||
#define APIENTRY __stdcall
|
||||
#else
|
||||
//#define APIENTRY __attribute__((stdcall))
|
||||
#define APIENTRY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BINN_PRIVATE
|
||||
#ifdef DEBUG
|
||||
#define BINN_PRIVATE
|
||||
#else
|
||||
#define BINN_PRIVATE static
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define INLINE __inline
|
||||
#define ALWAYS_INLINE __forceinline
|
||||
#else
|
||||
// you can change to 'extern inline' if using the gcc option -flto
|
||||
#define INLINE static inline
|
||||
#define ALWAYS_INLINE static inline __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
#ifndef int64
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
#else
|
||||
typedef long long int int64;
|
||||
typedef unsigned long long int uint64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define INT64_FORMAT "I64i"
|
||||
#define UINT64_FORMAT "I64u"
|
||||
#define INT64_HEX_FORMAT "I64x"
|
||||
#else
|
||||
#define INT64_FORMAT "lli"
|
||||
#define UINT64_FORMAT "llu"
|
||||
#define INT64_HEX_FORMAT "llx"
|
||||
#endif
|
||||
|
||||
|
||||
// BINN CONSTANTS ----------------------------------------
|
||||
|
||||
#define INVALID_BINN 0
|
||||
|
||||
// Storage Data Types ------------------------------------
|
||||
|
||||
#define BINN_STORAGE_NOBYTES 0x00
|
||||
#define BINN_STORAGE_BYTE 0x20 // 8 bits
|
||||
#define BINN_STORAGE_WORD 0x40 // 16 bits -- the endianess (byte order) is automatically corrected
|
||||
#define BINN_STORAGE_DWORD 0x60 // 32 bits -- the endianess (byte order) is automatically corrected
|
||||
#define BINN_STORAGE_QWORD 0x80 // 64 bits -- the endianess (byte order) is automatically corrected
|
||||
#define BINN_STORAGE_STRING 0xA0 // Are stored with null termination
|
||||
#define BINN_STORAGE_BLOB 0xC0
|
||||
#define BINN_STORAGE_CONTAINER 0xE0
|
||||
#define BINN_STORAGE_VIRTUAL 0x80000
|
||||
|
||||
#define BINN_STORAGE_MIN BINN_STORAGE_NOBYTES
|
||||
#define BINN_STORAGE_MAX BINN_STORAGE_CONTAINER
|
||||
|
||||
#define BINN_STORAGE_MASK 0xE0
|
||||
#define BINN_STORAGE_MASK16 0xE000
|
||||
#define BINN_STORAGE_HAS_MORE 0x10
|
||||
#define BINN_TYPE_MASK 0x0F
|
||||
#define BINN_TYPE_MASK16 0x0FFF
|
||||
|
||||
#define BINN_MAX_VALUE_MASK 0xFFFFF
|
||||
|
||||
|
||||
// Data Formats ------------------------------------------
|
||||
|
||||
#define BINN_LIST 0xE0
|
||||
#define BINN_MAP 0xE1
|
||||
#define BINN_OBJECT 0xE2
|
||||
|
||||
#define BINN_NULL 0x00
|
||||
#define BINN_TRUE 0x01
|
||||
#define BINN_FALSE 0x02
|
||||
|
||||
#define BINN_UINT8 0x20 // (BYTE) (unsigned byte) Is the default format for the BYTE type
|
||||
#define BINN_INT8 0x21 // (BYTE) (signed byte, from -128 to +127. The 0x80 is the sign bit, so the range in hex is from 0x80 [-128] to 0x7F [127], being 0x00 = 0 and 0xFF = -1)
|
||||
#define BINN_UINT16 0x40 // (WORD) (unsigned integer) Is the default format for the WORD type
|
||||
#define BINN_INT16 0x41 // (WORD) (signed integer)
|
||||
#define BINN_UINT32 0x60 // (DWORD) (unsigned integer) Is the default format for the DWORD type
|
||||
#define BINN_INT32 0x61 // (DWORD) (signed integer)
|
||||
#define BINN_UINT64 0x80 // (QWORD) (unsigned integer) Is the default format for the QWORD type
|
||||
#define BINN_INT64 0x81 // (QWORD) (signed integer)
|
||||
|
||||
#define BINN_SCHAR BINN_INT8
|
||||
#define BINN_UCHAR BINN_UINT8
|
||||
|
||||
#define BINN_STRING 0xA0 // (STRING) Raw String
|
||||
#define BINN_DATETIME 0xA1 // (STRING) iso8601 format -- YYYY-MM-DD HH:MM:SS
|
||||
#define BINN_DATE 0xA2 // (STRING) iso8601 format -- YYYY-MM-DD
|
||||
#define BINN_TIME 0xA3 // (STRING) iso8601 format -- HH:MM:SS
|
||||
#define BINN_DECIMAL 0xA4 // (STRING) High precision number - used for generic decimal values and for those ones that cannot be represented in the float64 format.
|
||||
#define BINN_CURRENCYSTR 0xA5 // (STRING) With currency unit/symbol - check for some iso standard format
|
||||
#define BINN_SINGLE_STR 0xA6 // (STRING) Can be restored to float32
|
||||
#define BINN_DOUBLE_STR 0xA7 // (STRING) May be restored to float64
|
||||
|
||||
#define BINN_FLOAT32 0x62 // (DWORD)
|
||||
#define BINN_FLOAT64 0x82 // (QWORD)
|
||||
#define BINN_FLOAT BINN_FLOAT32
|
||||
#define BINN_SINGLE BINN_FLOAT32
|
||||
#define BINN_DOUBLE BINN_FLOAT64
|
||||
|
||||
#define BINN_CURRENCY 0x83 // (QWORD)
|
||||
|
||||
#define BINN_BLOB 0xC0 // (BLOB) Raw Blob
|
||||
|
||||
|
||||
// virtual types:
|
||||
|
||||
#define BINN_BOOL 0x80061 // (DWORD) The value may be 0 or 1
|
||||
|
||||
#ifdef BINN_EXTENDED
|
||||
//#define BINN_SINGLE 0x800A1 // (STRING) Can be restored to float32
|
||||
//#define BINN_DOUBLE 0x800A2 // (STRING) May be restored to float64
|
||||
#endif
|
||||
|
||||
//#define BINN_BINN 0x800E1 // (CONTAINER)
|
||||
//#define BINN_BINN_BUFFER 0x800C1 // (BLOB) user binn. it's not open by the parser
|
||||
|
||||
|
||||
// extended content types:
|
||||
|
||||
// strings:
|
||||
|
||||
#define BINN_HTML 0xB001
|
||||
#define BINN_XML 0xB002
|
||||
#define BINN_JSON 0xB003
|
||||
#define BINN_JAVASCRIPT 0xB004
|
||||
#define BINN_CSS 0xB005
|
||||
|
||||
// blobs:
|
||||
|
||||
#define BINN_JPEG 0xD001
|
||||
#define BINN_GIF 0xD002
|
||||
#define BINN_PNG 0xD003
|
||||
#define BINN_BMP 0xD004
|
||||
|
||||
|
||||
// type families
|
||||
#define BINN_FAMILY_NONE 0x00
|
||||
#define BINN_FAMILY_NULL 0xf1
|
||||
#define BINN_FAMILY_INT 0xf2
|
||||
#define BINN_FAMILY_FLOAT 0xf3
|
||||
#define BINN_FAMILY_STRING 0xf4
|
||||
#define BINN_FAMILY_BLOB 0xf5
|
||||
#define BINN_FAMILY_BOOL 0xf6
|
||||
#define BINN_FAMILY_BINN 0xf7
|
||||
|
||||
// integer types related to signal
|
||||
#define BINN_SIGNED_INT 11
|
||||
#define BINN_UNSIGNED_INT 22
|
||||
|
||||
|
||||
typedef void (*binn_mem_free)(void*);
|
||||
#define BINN_STATIC ((binn_mem_free)0)
|
||||
#define BINN_TRANSIENT ((binn_mem_free)-1)
|
||||
|
||||
|
||||
// --- BINN STRUCTURE --------------------------------------------------------------
|
||||
|
||||
|
||||
struct binn_struct {
|
||||
int header; // this struct header holds the magic number (BINN_MAGIC) that identifies this memory block as a binn structure
|
||||
BOOL allocated; // the struct can be allocated using malloc_fn() or can be on the stack
|
||||
BOOL writable; // did it was create for writing? it can use the pbuf if not unified with ptr
|
||||
BOOL dirty; // the container header is not written to the buffer
|
||||
//
|
||||
void *pbuf; // use *ptr below?
|
||||
BOOL pre_allocated;
|
||||
int alloc_size;
|
||||
int used_size;
|
||||
//
|
||||
int type;
|
||||
void *ptr;
|
||||
int size;
|
||||
int count;
|
||||
//
|
||||
binn_mem_free freefn; // used only when type == BINN_STRING or BINN_BLOB
|
||||
//
|
||||
union {
|
||||
signed char vint8;
|
||||
signed short vint16;
|
||||
signed int vint32;
|
||||
int64 vint64;
|
||||
unsigned char vuint8;
|
||||
unsigned short vuint16;
|
||||
unsigned int vuint32;
|
||||
uint64 vuint64;
|
||||
//
|
||||
signed char vchar;
|
||||
unsigned char vuchar;
|
||||
signed short vshort;
|
||||
unsigned short vushort;
|
||||
signed int vint;
|
||||
unsigned int vuint;
|
||||
//
|
||||
float vfloat;
|
||||
double vdouble;
|
||||
//
|
||||
BOOL vbool;
|
||||
};
|
||||
//
|
||||
BOOL disable_int_compression;
|
||||
};
|
||||
|
||||
typedef struct binn_struct binn;
|
||||
|
||||
|
||||
|
||||
// --- GENERAL FUNCTIONS ----------------------------------------------------------
|
||||
|
||||
|
||||
void APIENTRY binn_set_alloc_functions(void* (*new_malloc)(size_t), void* (*new_realloc)(void*,size_t), void (*new_free)(void*));
|
||||
|
||||
int APIENTRY binn_create_type(int storage_type, int data_type_index);
|
||||
BOOL APIENTRY binn_get_type_info(int long_type, int *pstorage_type, int *pextra_type);
|
||||
|
||||
int APIENTRY binn_get_write_storage(int type);
|
||||
int APIENTRY binn_get_read_storage(int type);
|
||||
|
||||
BOOL APIENTRY binn_is_container(binn *item);
|
||||
|
||||
|
||||
// --- WRITE FUNCTIONS ------------------------------------------------------------
|
||||
|
||||
// create a new binn allocating memory for the structure
|
||||
binn * APIENTRY binn_new(int type, int size, void *buffer);
|
||||
binn * APIENTRY binn_list();
|
||||
binn * APIENTRY binn_map();
|
||||
binn * APIENTRY binn_object();
|
||||
|
||||
// create a new binn storing the structure on the stack
|
||||
BOOL APIENTRY binn_create(binn *item, int type, int size, void *buffer);
|
||||
BOOL APIENTRY binn_create_list(binn *list);
|
||||
BOOL APIENTRY binn_create_map(binn *map);
|
||||
BOOL APIENTRY binn_create_object(binn *object);
|
||||
|
||||
// create a new binn as a copy from another
|
||||
binn * APIENTRY binn_copy(void *old);
|
||||
|
||||
|
||||
BOOL APIENTRY binn_list_add_new(binn *list, binn *value);
|
||||
BOOL APIENTRY binn_map_set_new(binn *map, int id, binn *value);
|
||||
BOOL APIENTRY binn_object_set_new(binn *obj, char *key, binn *value);
|
||||
|
||||
|
||||
// extended interface
|
||||
|
||||
BOOL APIENTRY binn_list_add(binn *list, int type, void *pvalue, int size);
|
||||
BOOL APIENTRY binn_map_set(binn *map, int id, int type, void *pvalue, int size);
|
||||
BOOL APIENTRY binn_object_set(binn *obj, char *key, int type, void *pvalue, int size);
|
||||
|
||||
|
||||
// release memory
|
||||
|
||||
void APIENTRY binn_free(binn *item);
|
||||
void * APIENTRY binn_release(binn *item); // free the binn structure but keeps the binn buffer allocated, returning a pointer to it. use the free function to release the buffer later
|
||||
|
||||
|
||||
// --- CREATING VALUES ---------------------------------------------------
|
||||
|
||||
binn * APIENTRY binn_value(int type, void *pvalue, int size, binn_mem_free freefn);
|
||||
|
||||
ALWAYS_INLINE binn * binn_int8(signed char value) {
|
||||
return binn_value(BINN_INT8, &value, 0, NULL);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_int16(short value) {
|
||||
return binn_value(BINN_INT16, &value, 0, NULL);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_int32(int value) {
|
||||
return binn_value(BINN_INT32, &value, 0, NULL);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_int64(int64 value) {
|
||||
return binn_value(BINN_INT64, &value, 0, NULL);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_uint8(unsigned char value) {
|
||||
return binn_value(BINN_UINT8, &value, 0, NULL);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_uint16(unsigned short value) {
|
||||
return binn_value(BINN_UINT16, &value, 0, NULL);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_uint32(unsigned int value) {
|
||||
return binn_value(BINN_UINT32, &value, 0, NULL);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_uint64(uint64 value) {
|
||||
return binn_value(BINN_UINT64, &value, 0, NULL);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_float(float value) {
|
||||
return binn_value(BINN_FLOAT, &value, 0, NULL);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_double(double value) {
|
||||
return binn_value(BINN_DOUBLE, &value, 0, NULL);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_bool(BOOL value) {
|
||||
return binn_value(BINN_BOOL, &value, 0, NULL);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_null() {
|
||||
return binn_value(BINN_NULL, NULL, 0, NULL);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_string(char *str, binn_mem_free freefn) {
|
||||
return binn_value(BINN_STRING, str, 0, freefn);
|
||||
}
|
||||
ALWAYS_INLINE binn * binn_blob(void *ptr, int size, binn_mem_free freefn) {
|
||||
return binn_value(BINN_BLOB, ptr, size, freefn);
|
||||
}
|
||||
|
||||
|
||||
// --- READ FUNCTIONS -------------------------------------------------------------
|
||||
|
||||
// these functions accept pointer to the binn structure and pointer to the binn buffer
|
||||
void * APIENTRY binn_ptr(void *ptr);
|
||||
int APIENTRY binn_size(void *ptr);
|
||||
int APIENTRY binn_type(void *ptr);
|
||||
int APIENTRY binn_count(void *ptr);
|
||||
|
||||
BOOL APIENTRY binn_is_valid(void *ptr, int *ptype, int *pcount, int *psize);
|
||||
/* the function returns the values (type, count and size) and they don't need to be
|
||||
initialized. these values are read from the buffer. example:
|
||||
|
||||
int type, count, size;
|
||||
result = binn_is_valid(ptr, &type, &count, &size);
|
||||
*/
|
||||
BOOL APIENTRY binn_is_valid_ex(void *ptr, int *ptype, int *pcount, int *psize);
|
||||
/* if some value is informed (type, count or size) then the function will check if
|
||||
the value returned from the serialized data matches the informed value. otherwise
|
||||
the values must be initialized to zero. example:
|
||||
|
||||
int type=0, count=0, size = known_size;
|
||||
result = binn_is_valid_ex(ptr, &type, &count, &size);
|
||||
*/
|
||||
|
||||
BOOL APIENTRY binn_is_struct(void *ptr);
|
||||
|
||||
|
||||
// Loading a binn buffer into a binn value - this is optional
|
||||
|
||||
BOOL APIENTRY binn_load(void *data, binn *item); // on stack
|
||||
binn * APIENTRY binn_open(void *data); // allocated
|
||||
|
||||
|
||||
// easiest interface to use, but don't check if the value is there
|
||||
|
||||
signed char APIENTRY binn_list_int8(void *list, int pos);
|
||||
short APIENTRY binn_list_int16(void *list, int pos);
|
||||
int APIENTRY binn_list_int32(void *list, int pos);
|
||||
int64 APIENTRY binn_list_int64(void *list, int pos);
|
||||
unsigned char APIENTRY binn_list_uint8(void *list, int pos);
|
||||
unsigned short APIENTRY binn_list_uint16(void *list, int pos);
|
||||
unsigned int APIENTRY binn_list_uint32(void *list, int pos);
|
||||
uint64 APIENTRY binn_list_uint64(void *list, int pos);
|
||||
float APIENTRY binn_list_float(void *list, int pos);
|
||||
double APIENTRY binn_list_double(void *list, int pos);
|
||||
BOOL APIENTRY binn_list_bool(void *list, int pos);
|
||||
BOOL APIENTRY binn_list_null(void *list, int pos);
|
||||
char * APIENTRY binn_list_str(void *list, int pos);
|
||||
void * APIENTRY binn_list_blob(void *list, int pos, int *psize);
|
||||
void * APIENTRY binn_list_list(void *list, int pos);
|
||||
void * APIENTRY binn_list_map(void *list, int pos);
|
||||
void * APIENTRY binn_list_object(void *list, int pos);
|
||||
|
||||
signed char APIENTRY binn_map_int8(void *map, int id);
|
||||
short APIENTRY binn_map_int16(void *map, int id);
|
||||
int APIENTRY binn_map_int32(void *map, int id);
|
||||
int64 APIENTRY binn_map_int64(void *map, int id);
|
||||
unsigned char APIENTRY binn_map_uint8(void *map, int id);
|
||||
unsigned short APIENTRY binn_map_uint16(void *map, int id);
|
||||
unsigned int APIENTRY binn_map_uint32(void *map, int id);
|
||||
uint64 APIENTRY binn_map_uint64(void *map, int id);
|
||||
float APIENTRY binn_map_float(void *map, int id);
|
||||
double APIENTRY binn_map_double(void *map, int id);
|
||||
BOOL APIENTRY binn_map_bool(void *map, int id);
|
||||
BOOL APIENTRY binn_map_null(void *map, int id);
|
||||
char * APIENTRY binn_map_str(void *map, int id);
|
||||
void * APIENTRY binn_map_blob(void *map, int id, int *psize);
|
||||
void * APIENTRY binn_map_list(void *map, int id);
|
||||
void * APIENTRY binn_map_map(void *map, int id);
|
||||
void * APIENTRY binn_map_object(void *map, int id);
|
||||
|
||||
signed char APIENTRY binn_object_int8(void *obj, char *key);
|
||||
short APIENTRY binn_object_int16(void *obj, char *key);
|
||||
int APIENTRY binn_object_int32(void *obj, char *key);
|
||||
int64 APIENTRY binn_object_int64(void *obj, char *key);
|
||||
unsigned char APIENTRY binn_object_uint8(void *obj, char *key);
|
||||
unsigned short APIENTRY binn_object_uint16(void *obj, char *key);
|
||||
unsigned int APIENTRY binn_object_uint32(void *obj, char *key);
|
||||
uint64 APIENTRY binn_object_uint64(void *obj, char *key);
|
||||
float APIENTRY binn_object_float(void *obj, char *key);
|
||||
double APIENTRY binn_object_double(void *obj, char *key);
|
||||
BOOL APIENTRY binn_object_bool(void *obj, char *key);
|
||||
BOOL APIENTRY binn_object_null(void *obj, char *key);
|
||||
char * APIENTRY binn_object_str(void *obj, char *key);
|
||||
void * APIENTRY binn_object_blob(void *obj, char *key, int *psize);
|
||||
void * APIENTRY binn_object_list(void *obj, char *key);
|
||||
void * APIENTRY binn_object_map(void *obj, char *key);
|
||||
void * APIENTRY binn_object_object(void *obj, char *key);
|
||||
|
||||
|
||||
// return a pointer to an allocated binn structure - must be released with the free() function or equivalent set in binn_set_alloc_functions()
|
||||
binn * APIENTRY binn_list_value(void *list, int pos);
|
||||
binn * APIENTRY binn_map_value(void *map, int id);
|
||||
binn * APIENTRY binn_object_value(void *obj, char *key);
|
||||
|
||||
// read the value to a binn structure on the stack
|
||||
BOOL APIENTRY binn_list_get_value(void* list, int pos, binn *value);
|
||||
BOOL APIENTRY binn_map_get_value(void* map, int id, binn *value);
|
||||
BOOL APIENTRY binn_object_get_value(void *obj, char *key, binn *value);
|
||||
|
||||
// single interface - these functions check the data type
|
||||
BOOL APIENTRY binn_list_get(void *list, int pos, int type, void *pvalue, int *psize);
|
||||
BOOL APIENTRY binn_map_get(void *map, int id, int type, void *pvalue, int *psize);
|
||||
BOOL APIENTRY binn_object_get(void *obj, char *key, int type, void *pvalue, int *psize);
|
||||
|
||||
// these 3 functions return a pointer to the value and the data type
|
||||
// they are thread-safe on big-endian devices
|
||||
// on little-endian devices they are thread-safe only to return pointers to list, map, object, blob and strings
|
||||
// the returned pointer to 16, 32 and 64 bits values must be used only by single-threaded applications
|
||||
void * APIENTRY binn_list_read(void *list, int pos, int *ptype, int *psize);
|
||||
void * APIENTRY binn_map_read(void *map, int id, int *ptype, int *psize);
|
||||
void * APIENTRY binn_object_read(void *obj, char *key, int *ptype, int *psize);
|
||||
|
||||
|
||||
// READ PAIR FUNCTIONS
|
||||
|
||||
// these functions use base 1 in the 'pos' argument
|
||||
|
||||
// on stack
|
||||
BOOL APIENTRY binn_map_get_pair(void *map, int pos, int *pid, binn *value);
|
||||
BOOL APIENTRY binn_object_get_pair(void *obj, int pos, char *pkey, binn *value); // must free the memory returned in the pkey
|
||||
|
||||
// allocated
|
||||
binn * APIENTRY binn_map_pair(void *map, int pos, int *pid);
|
||||
binn * APIENTRY binn_object_pair(void *obj, int pos, char *pkey); // must free the memory returned in the pkey
|
||||
|
||||
// these 2 functions return a pointer to the value and the data type
|
||||
// they are thread-safe on big-endian devices
|
||||
// on little-endian devices they are thread-safe only to return pointers to list, map, object, blob and strings
|
||||
// the returned pointer to 16, 32 and 64 bits values must be used only by single-threaded applications
|
||||
void * APIENTRY binn_map_read_pair(void *ptr, int pos, int *pid, int *ptype, int *psize);
|
||||
void * APIENTRY binn_object_read_pair(void *ptr, int pos, char *pkey, int *ptype, int *psize);
|
||||
|
||||
|
||||
// SEQUENTIAL READ FUNCTIONS
|
||||
|
||||
typedef struct binn_iter_struct {
|
||||
unsigned char *pnext;
|
||||
unsigned char *plimit;
|
||||
int type;
|
||||
int count;
|
||||
int current;
|
||||
} binn_iter;
|
||||
|
||||
BOOL APIENTRY binn_iter_init(binn_iter *iter, void *pbuf, int type);
|
||||
|
||||
// allocated
|
||||
binn * APIENTRY binn_list_next_value(binn_iter *iter);
|
||||
binn * APIENTRY binn_map_next_value(binn_iter *iter, int *pid);
|
||||
binn * APIENTRY binn_object_next_value(binn_iter *iter, char *pkey); // the key must be declared as: char key[256];
|
||||
|
||||
// on stack
|
||||
BOOL APIENTRY binn_list_next(binn_iter *iter, binn *value);
|
||||
BOOL APIENTRY binn_map_next(binn_iter *iter, int *pid, binn *value);
|
||||
BOOL APIENTRY binn_object_next(binn_iter *iter, char *pkey, binn *value); // the key must be declared as: char key[256];
|
||||
|
||||
// these 3 functions return a pointer to the value and the data type
|
||||
// they are thread-safe on big-endian devices
|
||||
// on little-endian devices they are thread-safe only to return pointers to list, map, object, blob and strings
|
||||
// the returned pointer to 16, 32 and 64 bits values must be used only by single-threaded applications
|
||||
void * APIENTRY binn_list_read_next(binn_iter *iter, int *ptype, int *psize);
|
||||
void * APIENTRY binn_map_read_next(binn_iter *iter, int *pid, int *ptype, int *psize);
|
||||
void * APIENTRY binn_object_read_next(binn_iter *iter, char *pkey, int *ptype, int *psize); // the key must be declared as: char key[256];
|
||||
|
||||
|
||||
// --- MACROS ------------------------------------------------------------
|
||||
|
||||
|
||||
#define binn_is_writable(item) (item)->writable;
|
||||
|
||||
|
||||
// set values on stack allocated binn structures
|
||||
|
||||
#define binn_set_null(item) do { (item)->type = BINN_NULL; } while (0)
|
||||
|
||||
#define binn_set_bool(item,value) do { (item)->type = BINN_BOOL; (item)->vbool = value; (item)->ptr = &((item)->vbool); } while (0)
|
||||
|
||||
#define binn_set_int(item,value) do { (item)->type = BINN_INT32; (item)->vint32 = value; (item)->ptr = &((item)->vint32); } while (0)
|
||||
#define binn_set_int64(item,value) do { (item)->type = BINN_INT64; (item)->vint64 = value; (item)->ptr = &((item)->vint64); } while (0)
|
||||
|
||||
#define binn_set_uint(item,value) do { (item)->type = BINN_UINT32; (item)->vuint32 = value; (item)->ptr = &((item)->vuint32); } while (0)
|
||||
#define binn_set_uint64(item,value) do { (item)->type = BINN_UINT64; (item)->vuint64 = value; (item)->ptr = &((item)->vuint64); } while (0)
|
||||
|
||||
#define binn_set_float(item,value) do { (item)->type = BINN_FLOAT; (item)->vfloat = value; (item)->ptr = &((item)->vfloat); } while (0)
|
||||
#define binn_set_double(item,value) do { (item)->type = BINN_DOUBLE; (item)->vdouble = value; (item)->ptr = &((item)->vdouble); } while (0)
|
||||
|
||||
//#define binn_set_string(item,str,pfree) do { (item)->type = BINN_STRING; (item)->ptr = str; (item)->freefn = pfree; } while (0)
|
||||
//#define binn_set_blob(item,ptr,size,pfree) do { (item)->type = BINN_BLOB; (item)->ptr = ptr; (item)->freefn = pfree; (item)->size = size; } while (0)
|
||||
BOOL APIENTRY binn_set_string(binn *item, char *str, binn_mem_free pfree);
|
||||
BOOL APIENTRY binn_set_blob(binn *item, void *ptr, int size, binn_mem_free pfree);
|
||||
|
||||
|
||||
//#define binn_double(value) { (item)->type = BINN_DOUBLE; (item)->vdouble = value; (item)->ptr = &((item)->vdouble) }
|
||||
|
||||
|
||||
|
||||
// FOREACH MACROS
|
||||
// must use these declarations in the function that will use them:
|
||||
// binn_iter iter;
|
||||
// char key[256]; // only for the object
|
||||
// int id; // only for the map
|
||||
// binn value;
|
||||
|
||||
#define binn_object_foreach(object, key, value) \
|
||||
binn_iter_init(&iter, object, BINN_OBJECT); \
|
||||
while (binn_object_next(&iter, key, &value))
|
||||
|
||||
#define binn_map_foreach(map, id, value) \
|
||||
binn_iter_init(&iter, map, BINN_MAP); \
|
||||
while (binn_map_next(&iter, &id, &value))
|
||||
|
||||
#define binn_list_foreach(list, value) \
|
||||
binn_iter_init(&iter, list, BINN_LIST); \
|
||||
while (binn_list_next(&iter, &value))
|
||||
|
||||
|
||||
|
||||
/*************************************************************************************/
|
||||
/*** SET FUNCTIONS *******************************************************************/
|
||||
/*************************************************************************************/
|
||||
|
||||
ALWAYS_INLINE BOOL binn_list_add_int8(binn *list, signed char value) {
|
||||
return binn_list_add(list, BINN_INT8, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_int16(binn *list, short value) {
|
||||
return binn_list_add(list, BINN_INT16, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_int32(binn *list, int value) {
|
||||
return binn_list_add(list, BINN_INT32, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_int64(binn *list, int64 value) {
|
||||
return binn_list_add(list, BINN_INT64, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_uint8(binn *list, unsigned char value) {
|
||||
return binn_list_add(list, BINN_UINT8, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_uint16(binn *list, unsigned short value) {
|
||||
return binn_list_add(list, BINN_UINT16, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_uint32(binn *list, unsigned int value) {
|
||||
return binn_list_add(list, BINN_UINT32, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_uint64(binn *list, uint64 value) {
|
||||
return binn_list_add(list, BINN_UINT64, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_float(binn *list, float value) {
|
||||
return binn_list_add(list, BINN_FLOAT32, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_double(binn *list, double value) {
|
||||
return binn_list_add(list, BINN_FLOAT64, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_bool(binn *list, BOOL value) {
|
||||
return binn_list_add(list, BINN_BOOL, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_null(binn *list) {
|
||||
return binn_list_add(list, BINN_NULL, NULL, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_str(binn *list, char *str) {
|
||||
return binn_list_add(list, BINN_STRING, str, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_blob(binn *list, void *ptr, int size) {
|
||||
return binn_list_add(list, BINN_BLOB, ptr, size);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_list(binn *list, void *list2) {
|
||||
return binn_list_add(list, BINN_LIST, binn_ptr(list2), binn_size(list2));
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_map(binn *list, void *map) {
|
||||
return binn_list_add(list, BINN_MAP, binn_ptr(map), binn_size(map));
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_object(binn *list, void *obj) {
|
||||
return binn_list_add(list, BINN_OBJECT, binn_ptr(obj), binn_size(obj));
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_add_value(binn *list, binn *value) {
|
||||
return binn_list_add(list, value->type, binn_ptr(value), binn_size(value));
|
||||
}
|
||||
|
||||
/*************************************************************************************/
|
||||
|
||||
ALWAYS_INLINE BOOL binn_map_set_int8(binn *map, int id, signed char value) {
|
||||
return binn_map_set(map, id, BINN_INT8, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_int16(binn *map, int id, short value) {
|
||||
return binn_map_set(map, id, BINN_INT16, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_int32(binn *map, int id, int value) {
|
||||
return binn_map_set(map, id, BINN_INT32, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_int64(binn *map, int id, int64 value) {
|
||||
return binn_map_set(map, id, BINN_INT64, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_uint8(binn *map, int id, unsigned char value) {
|
||||
return binn_map_set(map, id, BINN_UINT8, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_uint16(binn *map, int id, unsigned short value) {
|
||||
return binn_map_set(map, id, BINN_UINT16, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_uint32(binn *map, int id, unsigned int value) {
|
||||
return binn_map_set(map, id, BINN_UINT32, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_uint64(binn *map, int id, uint64 value) {
|
||||
return binn_map_set(map, id, BINN_UINT64, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_float(binn *map, int id, float value) {
|
||||
return binn_map_set(map, id, BINN_FLOAT32, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_double(binn *map, int id, double value) {
|
||||
return binn_map_set(map, id, BINN_FLOAT64, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_bool(binn *map, int id, BOOL value) {
|
||||
return binn_map_set(map, id, BINN_BOOL, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_null(binn *map, int id) {
|
||||
return binn_map_set(map, id, BINN_NULL, NULL, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_str(binn *map, int id, char *str) {
|
||||
return binn_map_set(map, id, BINN_STRING, str, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_blob(binn *map, int id, void *ptr, int size) {
|
||||
return binn_map_set(map, id, BINN_BLOB, ptr, size);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_list(binn *map, int id, void *list) {
|
||||
return binn_map_set(map, id, BINN_LIST, binn_ptr(list), binn_size(list));
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_map(binn *map, int id, void *map2) {
|
||||
return binn_map_set(map, id, BINN_MAP, binn_ptr(map2), binn_size(map2));
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_object(binn *map, int id, void *obj) {
|
||||
return binn_map_set(map, id, BINN_OBJECT, binn_ptr(obj), binn_size(obj));
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_set_value(binn *map, int id, binn *value) {
|
||||
return binn_map_set(map, id, value->type, binn_ptr(value), binn_size(value));
|
||||
}
|
||||
|
||||
/*************************************************************************************/
|
||||
|
||||
ALWAYS_INLINE BOOL binn_object_set_int8(binn *obj, char *key, signed char value) {
|
||||
return binn_object_set(obj, key, BINN_INT8, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_int16(binn *obj, char *key, short value) {
|
||||
return binn_object_set(obj, key, BINN_INT16, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_int32(binn *obj, char *key, int value) {
|
||||
return binn_object_set(obj, key, BINN_INT32, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_int64(binn *obj, char *key, int64 value) {
|
||||
return binn_object_set(obj, key, BINN_INT64, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_uint8(binn *obj, char *key, unsigned char value) {
|
||||
return binn_object_set(obj, key, BINN_UINT8, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_uint16(binn *obj, char *key, unsigned short value) {
|
||||
return binn_object_set(obj, key, BINN_UINT16, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_uint32(binn *obj, char *key, unsigned int value) {
|
||||
return binn_object_set(obj, key, BINN_UINT32, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_uint64(binn *obj, char *key, uint64 value) {
|
||||
return binn_object_set(obj, key, BINN_UINT64, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_float(binn *obj, char *key, float value) {
|
||||
return binn_object_set(obj, key, BINN_FLOAT32, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_double(binn *obj, char *key, double value) {
|
||||
return binn_object_set(obj, key, BINN_FLOAT64, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_bool(binn *obj, char *key, BOOL value) {
|
||||
return binn_object_set(obj, key, BINN_BOOL, &value, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_null(binn *obj, char *key) {
|
||||
return binn_object_set(obj, key, BINN_NULL, NULL, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_str(binn *obj, char *key, char *str) {
|
||||
return binn_object_set(obj, key, BINN_STRING, str, 0);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_blob(binn *obj, char *key, void *ptr, int size) {
|
||||
return binn_object_set(obj, key, BINN_BLOB, ptr, size);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_list(binn *obj, char *key, void *list) {
|
||||
return binn_object_set(obj, key, BINN_LIST, binn_ptr(list), binn_size(list));
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_map(binn *obj, char *key, void *map) {
|
||||
return binn_object_set(obj, key, BINN_MAP, binn_ptr(map), binn_size(map));
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_object(binn *obj, char *key, void *obj2) {
|
||||
return binn_object_set(obj, key, BINN_OBJECT, binn_ptr(obj2), binn_size(obj2));
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_set_value(binn *obj, char *key, binn *value) {
|
||||
return binn_object_set(obj, key, value->type, binn_ptr(value), binn_size(value));
|
||||
}
|
||||
|
||||
/*************************************************************************************/
|
||||
/*** GET FUNCTIONS *******************************************************************/
|
||||
/*************************************************************************************/
|
||||
|
||||
ALWAYS_INLINE BOOL binn_list_get_int8(void *list, int pos, signed char *pvalue) {
|
||||
return binn_list_get(list, pos, BINN_INT8, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_int16(void *list, int pos, short *pvalue) {
|
||||
return binn_list_get(list, pos, BINN_INT16, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_int32(void *list, int pos, int *pvalue) {
|
||||
return binn_list_get(list, pos, BINN_INT32, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_int64(void *list, int pos, int64 *pvalue) {
|
||||
return binn_list_get(list, pos, BINN_INT64, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_uint8(void *list, int pos, unsigned char *pvalue) {
|
||||
return binn_list_get(list, pos, BINN_UINT8, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_uint16(void *list, int pos, unsigned short *pvalue) {
|
||||
return binn_list_get(list, pos, BINN_UINT16, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_uint32(void *list, int pos, unsigned int *pvalue) {
|
||||
return binn_list_get(list, pos, BINN_UINT32, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_uint64(void *list, int pos, uint64 *pvalue) {
|
||||
return binn_list_get(list, pos, BINN_UINT64, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_float(void *list, int pos, float *pvalue) {
|
||||
return binn_list_get(list, pos, BINN_FLOAT32, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_double(void *list, int pos, double *pvalue) {
|
||||
return binn_list_get(list, pos, BINN_FLOAT64, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_bool(void *list, int pos, BOOL *pvalue) {
|
||||
return binn_list_get(list, pos, BINN_BOOL, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_str(void *list, int pos, char **pvalue) {
|
||||
return binn_list_get(list, pos, BINN_STRING, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_blob(void *list, int pos, void **pvalue, int *psize) {
|
||||
return binn_list_get(list, pos, BINN_BLOB, pvalue, psize);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_list(void *list, int pos, void **pvalue) {
|
||||
return binn_list_get(list, pos, BINN_LIST, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_map(void *list, int pos, void **pvalue) {
|
||||
return binn_list_get(list, pos, BINN_MAP, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_list_get_object(void *list, int pos, void **pvalue) {
|
||||
return binn_list_get(list, pos, BINN_OBJECT, pvalue, NULL);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
ALWAYS_INLINE BOOL binn_map_get_int8(void *map, int id, signed char *pvalue) {
|
||||
return binn_map_get(map, id, BINN_INT8, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_int16(void *map, int id, short *pvalue) {
|
||||
return binn_map_get(map, id, BINN_INT16, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_int32(void *map, int id, int *pvalue) {
|
||||
return binn_map_get(map, id, BINN_INT32, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_int64(void *map, int id, int64 *pvalue) {
|
||||
return binn_map_get(map, id, BINN_INT64, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_uint8(void *map, int id, unsigned char *pvalue) {
|
||||
return binn_map_get(map, id, BINN_UINT8, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_uint16(void *map, int id, unsigned short *pvalue) {
|
||||
return binn_map_get(map, id, BINN_UINT16, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_uint32(void *map, int id, unsigned int *pvalue) {
|
||||
return binn_map_get(map, id, BINN_UINT32, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_uint64(void *map, int id, uint64 *pvalue) {
|
||||
return binn_map_get(map, id, BINN_UINT64, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_float(void *map, int id, float *pvalue) {
|
||||
return binn_map_get(map, id, BINN_FLOAT32, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_double(void *map, int id, double *pvalue) {
|
||||
return binn_map_get(map, id, BINN_FLOAT64, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_bool(void *map, int id, BOOL *pvalue) {
|
||||
return binn_map_get(map, id, BINN_BOOL, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_str(void *map, int id, char **pvalue) {
|
||||
return binn_map_get(map, id, BINN_STRING, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_blob(void *map, int id, void **pvalue, int *psize) {
|
||||
return binn_map_get(map, id, BINN_BLOB, pvalue, psize);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_list(void *map, int id, void **pvalue) {
|
||||
return binn_map_get(map, id, BINN_LIST, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_map(void *map, int id, void **pvalue) {
|
||||
return binn_map_get(map, id, BINN_MAP, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_map_get_object(void *map, int id, void **pvalue) {
|
||||
return binn_map_get(map, id, BINN_OBJECT, pvalue, NULL);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// usage:
|
||||
// if (binn_object_get_int32(obj, "key", &value) == FALSE) xxx;
|
||||
|
||||
ALWAYS_INLINE BOOL binn_object_get_int8(void *obj, char *key, signed char *pvalue) {
|
||||
return binn_object_get(obj, key, BINN_INT8, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_int16(void *obj, char *key, short *pvalue) {
|
||||
return binn_object_get(obj, key, BINN_INT16, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_int32(void *obj, char *key, int *pvalue) {
|
||||
return binn_object_get(obj, key, BINN_INT32, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_int64(void *obj, char *key, int64 *pvalue) {
|
||||
return binn_object_get(obj, key, BINN_INT64, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_uint8(void *obj, char *key, unsigned char *pvalue) {
|
||||
return binn_object_get(obj, key, BINN_UINT8, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_uint16(void *obj, char *key, unsigned short *pvalue) {
|
||||
return binn_object_get(obj, key, BINN_UINT16, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_uint32(void *obj, char *key, unsigned int *pvalue) {
|
||||
return binn_object_get(obj, key, BINN_UINT32, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_uint64(void *obj, char *key, uint64 *pvalue) {
|
||||
return binn_object_get(obj, key, BINN_UINT64, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_float(void *obj, char *key, float *pvalue) {
|
||||
return binn_object_get(obj, key, BINN_FLOAT32, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_double(void *obj, char *key, double *pvalue) {
|
||||
return binn_object_get(obj, key, BINN_FLOAT64, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_bool(void *obj, char *key, BOOL *pvalue) {
|
||||
return binn_object_get(obj, key, BINN_BOOL, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_str(void *obj, char *key, char **pvalue) {
|
||||
return binn_object_get(obj, key, BINN_STRING, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_blob(void *obj, char *key, void **pvalue, int *psize) {
|
||||
return binn_object_get(obj, key, BINN_BLOB, pvalue, psize);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_list(void *obj, char *key, void **pvalue) {
|
||||
return binn_object_get(obj, key, BINN_LIST, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_map(void *obj, char *key, void **pvalue) {
|
||||
return binn_object_get(obj, key, BINN_MAP, pvalue, NULL);
|
||||
}
|
||||
ALWAYS_INLINE BOOL binn_object_get_object(void *obj, char *key, void **pvalue) {
|
||||
return binn_object_get(obj, key, BINN_OBJECT, pvalue, NULL);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
BOOL APIENTRY binn_get_int32(binn *value, int *pint);
|
||||
BOOL APIENTRY binn_get_int64(binn *value, int64 *pint);
|
||||
BOOL APIENTRY binn_get_double(binn *value, double *pfloat);
|
||||
BOOL APIENTRY binn_get_bool(binn *value, BOOL *pbool);
|
||||
char * APIENTRY binn_get_str(binn *value);
|
||||
|
||||
// boolean string values:
|
||||
// 1, true, yes, on
|
||||
// 0, false, no, off
|
||||
|
||||
// boolean number values:
|
||||
// !=0 [true]
|
||||
// ==0 [false]
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //BINN_H
|
5014
vendor/confini.c
vendored
Normal file
5014
vendor/confini.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
547
vendor/confini.h
vendored
Normal file
547
vendor/confini.h
vendored
Normal file
|
@ -0,0 +1,547 @@
|
|||
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
|
||||
|
||||
/**
|
||||
|
||||
@file confini.h
|
||||
@brief libconfini header
|
||||
@author Stefano Gioffré
|
||||
@copyright GNU General Public License, version 3 or any later version
|
||||
@version 1.14.0
|
||||
@date 2016-2020
|
||||
@see https://madmurphy.github.io/libconfini
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#ifndef _LIBCONFINI_HEADER_
|
||||
#define _LIBCONFINI_HEADER_
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* PRIVATE (HEADER-SCOPED) MACROS */
|
||||
|
||||
|
||||
#define __INIFORMAT_TABLE_CB_FIELDS__(NAME, OFFSET, SIZE, DEFVAL) \
|
||||
unsigned char NAME:SIZE;
|
||||
#define __INIFORMAT_TABLE_CB_DEFAULT__(NAME, OFFSET, SIZE, DEFVAL) DEFVAL,
|
||||
#define __INIFORMAT_TABLE_CB_ZERO__(NAME, OFFSET, SIZE, DEFVAL) 0,
|
||||
#define _LIBCONFINI_INIFORMAT_TYPE_ \
|
||||
struct IniFormat { INIFORMAT_TABLE_AS(__INIFORMAT_TABLE_CB_FIELDS__) }
|
||||
#define _LIBCONFINI_DEFAULT_FORMAT_ \
|
||||
{ INIFORMAT_TABLE_AS(__INIFORMAT_TABLE_CB_DEFAULT__) }
|
||||
#define _LIBCONFINI_UNIXLIKE_FORMAT_ \
|
||||
{ INIFORMAT_TABLE_AS(__INIFORMAT_TABLE_CB_ZERO__) }
|
||||
|
||||
|
||||
|
||||
/* PUBLIC MACROS */
|
||||
|
||||
|
||||
/**
|
||||
@brief Calls a user-given macro (that accepts four arguments) for each row
|
||||
of the table
|
||||
**/
|
||||
/*
|
||||
NOTE: The following table and the order of its rows **define** (and link
|
||||
together) both the #IniFormat and #IniFormatNum data types declared in this
|
||||
header
|
||||
*/
|
||||
#define INIFORMAT_TABLE_AS(_____) /* IniFormat table *\
|
||||
|
||||
NAME BIT SIZE DEFAULT
|
||||
*/\
|
||||
_____( delimiter_symbol, 0, 7, INI_EQUALS ) \
|
||||
_____( case_sensitive, 7, 1, false )/*
|
||||
*/\
|
||||
_____( semicolon_marker, 8, 2, INI_DISABLED_OR_COMMENT ) \
|
||||
_____( hash_marker, 10, 2, INI_DISABLED_OR_COMMENT ) \
|
||||
_____( section_paths, 12, 2, INI_ABSOLUTE_AND_RELATIVE ) \
|
||||
_____( multiline_nodes, 14, 2, INI_MULTILINE_EVERYWHERE )/*
|
||||
*/\
|
||||
_____( no_single_quotes, 16, 1, false ) \
|
||||
_____( no_double_quotes, 17, 1, false ) \
|
||||
_____( no_spaces_in_names, 18, 1, false ) \
|
||||
_____( implicit_is_not_empty, 19, 1, false ) \
|
||||
_____( do_not_collapse_values, 20, 1, false ) \
|
||||
_____( preserve_empty_quotes, 21, 1, false ) \
|
||||
_____( disabled_after_space, 22, 1, false ) \
|
||||
_____( disabled_can_be_implicit, 23, 1, false )
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief Checks whether a format does **not** support escape sequences
|
||||
**/
|
||||
#define INIFORMAT_HAS_NO_ESC(FORMAT) \
|
||||
(FORMAT.multiline_nodes == INI_NO_MULTILINE && \
|
||||
FORMAT.no_double_quotes && FORMAT.no_single_quotes)
|
||||
|
||||
|
||||
|
||||
/* PUBLIC TYPEDEFS */
|
||||
|
||||
|
||||
/**
|
||||
@brief 24-bit bitfield representing the format of an INI file (INI
|
||||
dialect)
|
||||
**/
|
||||
typedef _LIBCONFINI_INIFORMAT_TYPE_ IniFormat;
|
||||
|
||||
|
||||
/**
|
||||
@brief Global statistics about an INI file
|
||||
**/
|
||||
typedef struct IniStatistics {
|
||||
const IniFormat format;
|
||||
const size_t bytes;
|
||||
const size_t members;
|
||||
} IniStatistics;
|
||||
|
||||
|
||||
/**
|
||||
@brief Dispatch of a single INI node
|
||||
**/
|
||||
typedef struct IniDispatch {
|
||||
const IniFormat format;
|
||||
uint8_t type;
|
||||
char * data;
|
||||
char * value;
|
||||
const char * append_to;
|
||||
size_t d_len;
|
||||
size_t v_len;
|
||||
size_t at_len;
|
||||
size_t dispatch_id;
|
||||
} IniDispatch;
|
||||
|
||||
|
||||
/**
|
||||
@brief The unique ID of an INI format (24-bit maximum)
|
||||
**/
|
||||
typedef uint32_t IniFormatNum;
|
||||
|
||||
|
||||
/**
|
||||
@brief Callback function for handling an #IniStatistics structure
|
||||
**/
|
||||
typedef int (* IniStatsHandler) (
|
||||
IniStatistics * statistics,
|
||||
void * user_data
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
@brief Callback function for handling an #IniDispatch structure
|
||||
**/
|
||||
typedef int (* IniDispHandler) (
|
||||
IniDispatch * dispatch,
|
||||
void * user_data
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
@brief Callback function for handling an INI string belonging to a
|
||||
sequence of INI strings
|
||||
**/
|
||||
typedef int (* IniStrHandler) (
|
||||
char * ini_string,
|
||||
size_t string_length,
|
||||
size_t string_num,
|
||||
IniFormat format,
|
||||
void * user_data
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
@brief Callback function for handling a selected fragment of an INI string
|
||||
**/
|
||||
typedef int (* IniSubstrHandler) (
|
||||
const char * ini_string,
|
||||
size_t fragm_offset,
|
||||
size_t fragm_length,
|
||||
size_t fragm_num,
|
||||
IniFormat format,
|
||||
void * user_data
|
||||
);
|
||||
|
||||
|
||||
|
||||
/* PUBLIC FUNCTIONS */
|
||||
|
||||
|
||||
extern int strip_ini_cache (
|
||||
register char * const ini_source,
|
||||
const size_t ini_length,
|
||||
const IniFormat format,
|
||||
const IniStatsHandler f_init,
|
||||
const IniDispHandler f_foreach,
|
||||
void * const user_data
|
||||
);
|
||||
|
||||
|
||||
extern int load_ini_file (
|
||||
FILE * const ini_file,
|
||||
const IniFormat format,
|
||||
const IniStatsHandler f_init,
|
||||
const IniDispHandler f_foreach,
|
||||
void * const user_data
|
||||
);
|
||||
|
||||
|
||||
extern int load_ini_path (
|
||||
const char * const path,
|
||||
const IniFormat format,
|
||||
const IniStatsHandler f_init,
|
||||
const IniDispHandler f_foreach,
|
||||
void * const user_data
|
||||
);
|
||||
|
||||
|
||||
extern bool ini_string_match_ss (
|
||||
const char * const simple_string_a,
|
||||
const char * const simple_string_b,
|
||||
const IniFormat format
|
||||
);
|
||||
|
||||
|
||||
extern bool ini_string_match_si (
|
||||
const char * const simple_string,
|
||||
const char * const ini_string,
|
||||
const IniFormat format
|
||||
);
|
||||
|
||||
|
||||
extern bool ini_string_match_ii (
|
||||
const char * const ini_string_a,
|
||||
const char * const ini_string_b,
|
||||
const IniFormat format
|
||||
);
|
||||
|
||||
|
||||
extern bool ini_array_match (
|
||||
const char * const ini_string_a,
|
||||
const char * const ini_string_b,
|
||||
const char delimiter,
|
||||
const IniFormat format
|
||||
);
|
||||
|
||||
|
||||
extern size_t ini_unquote (
|
||||
char * const ini_string,
|
||||
const IniFormat format
|
||||
);
|
||||
|
||||
|
||||
extern size_t ini_string_parse (
|
||||
char * const ini_string,
|
||||
const IniFormat format
|
||||
);
|
||||
|
||||
|
||||
extern size_t ini_array_get_length (
|
||||
const char * const ini_string,
|
||||
const char delimiter,
|
||||
const IniFormat format
|
||||
);
|
||||
|
||||
|
||||
extern int ini_array_foreach (
|
||||
const char * const ini_string,
|
||||
const char delimiter,
|
||||
const IniFormat format,
|
||||
const IniSubstrHandler f_foreach,
|
||||
void * const user_data
|
||||
);
|
||||
|
||||
|
||||
extern size_t ini_array_shift (
|
||||
const char ** const ini_strptr,
|
||||
const char delimiter,
|
||||
const IniFormat format
|
||||
);
|
||||
|
||||
|
||||
extern size_t ini_array_collapse (
|
||||
char * const ini_string,
|
||||
const char delimiter,
|
||||
const IniFormat format
|
||||
);
|
||||
|
||||
|
||||
extern char * ini_array_break (
|
||||
char * const ini_string,
|
||||
const char delimiter,
|
||||
const IniFormat format
|
||||
);
|
||||
|
||||
|
||||
extern char * ini_array_release (
|
||||
char ** const ini_strptr,
|
||||
const char delimiter,
|
||||
const IniFormat format
|
||||
);
|
||||
|
||||
|
||||
extern int ini_array_split (
|
||||
char * const ini_string,
|
||||
const char delimiter,
|
||||
const IniFormat format,
|
||||
const IniStrHandler f_foreach,
|
||||
void * const user_data
|
||||
);
|
||||
|
||||
|
||||
extern void ini_global_set_lowercase_mode (
|
||||
const bool lowercase
|
||||
);
|
||||
|
||||
|
||||
extern void ini_global_set_implicit_value (
|
||||
char * const implicit_value,
|
||||
const size_t implicit_v_len
|
||||
);
|
||||
|
||||
|
||||
extern IniFormatNum ini_fton (
|
||||
const IniFormat format
|
||||
);
|
||||
|
||||
|
||||
extern IniFormat ini_ntof (
|
||||
const IniFormatNum format_id
|
||||
);
|
||||
|
||||
|
||||
extern int ini_get_bool (
|
||||
const char * const ini_string,
|
||||
const int when_fail
|
||||
);
|
||||
|
||||
|
||||
|
||||
/* PUBLIC LINKS */
|
||||
|
||||
|
||||
extern int (* const ini_get_int) (
|
||||
const char * ini_string
|
||||
);
|
||||
|
||||
|
||||
extern long int (* const ini_get_lint) (
|
||||
const char * ini_string
|
||||
);
|
||||
|
||||
|
||||
extern long long int (* const ini_get_llint) (
|
||||
const char * ini_string
|
||||
);
|
||||
|
||||
|
||||
extern double (* const ini_get_double) (
|
||||
const char * ini_string
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
@brief Legacy support, soon to be replaced with a `float` data type --
|
||||
please **do not use `ini_get_float()`!**
|
||||
**/
|
||||
#define ini_get_float \
|
||||
_Pragma("GCC warning \"function `ini_get_float()` is deprecated for parsing a `double` data type; use `ini_get_double()` instead\"") \
|
||||
ini_get_double
|
||||
|
||||
|
||||
|
||||
/* PUBLIC CONSTANTS AND VARIABLES */
|
||||
|
||||
|
||||
/**
|
||||
@brief Error mask (flags not present in user-generated interruptions)
|
||||
**/
|
||||
#define CONFINI_ERROR 252
|
||||
|
||||
|
||||
/**
|
||||
@brief Error codes
|
||||
**/
|
||||
enum ConfiniInterruptNo {
|
||||
CONFINI_SUCCESS = 0, /**< There have been no interruptions, everything
|
||||
went well [value=0] **/
|
||||
CONFINI_IINTR = 1, /**< Interrupted by the user during `f_init()`
|
||||
[value=1] **/
|
||||
CONFINI_FEINTR = 2, /**< Interrupted by the user during `f_foreach()`
|
||||
[value=2] **/
|
||||
CONFINI_ENOENT = 4, /**< File inaccessible [value=4] **/
|
||||
CONFINI_ENOMEM = 5, /**< Error allocating virtual memory [value=5] **/
|
||||
CONFINI_EIO = 6, /**< Error reading the file [value=6] **/
|
||||
CONFINI_EOOR = 7, /**< Out-of-range error: callbacks are more than
|
||||
expected [value=7] **/
|
||||
CONFINI_EBADF = 8, /**< The stream specified is not a seekable stream
|
||||
[value=8] **/
|
||||
CONFINI_EFBIG = 9, /**< File too large [value=9] **/
|
||||
CONFINI_EROADDR = 10 /**< Address is read-only [value=10] **/
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@brief INI node types
|
||||
**/
|
||||
enum IniNodeType {
|
||||
INI_UNKNOWN = 0, /**< This is a node impossible to categorize
|
||||
[value=0] **/
|
||||
INI_VALUE = 1, /**< Not used by **libconfini** (values are
|
||||
dispatched together with keys) -- but
|
||||
available for user's implementations
|
||||
[value=1] **/
|
||||
INI_KEY = 2, /**< This is a key [value=2] **/
|
||||
INI_SECTION = 3, /**< This is a section or a section path
|
||||
[value=3] **/
|
||||
INI_COMMENT = 4, /**< This is a comment [value=4] **/
|
||||
INI_INLINE_COMMENT = 5, /**< This is an inline comment [value=5] **/
|
||||
INI_DISABLED_KEY = 6, /**< This is a disabled key [value=6] **/
|
||||
INI_DISABLED_SECTION = 7 /**< This is a disabled section path
|
||||
[value=7] **/
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@brief Common array and key-value delimiters (but a delimiter may also be
|
||||
any other ASCII character not present in this list)
|
||||
**/
|
||||
enum IniDelimiters {
|
||||
INI_ANY_SPACE = 0, /**< In multi-line INIs:
|
||||
`/(?:\\(?:\n\r?|\r\n?)|[\t \v\f])+/`, in
|
||||
non-multi-line INIs: `/[\t \v\f])+/` **/
|
||||
INI_EQUALS = '=', /**< Equals character (`=`) **/
|
||||
INI_COLON = ':', /**< Colon character (`:`) **/
|
||||
INI_DOT = '.', /**< Dot character (`.`) **/
|
||||
INI_COMMA = ',' /**< Comma character (`,`) **/
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@brief Possible values of #IniFormat::semicolon_marker and
|
||||
#IniFormat::hash_marker (i.e., meaning of `/\s+;/` and `/\s+#/` in
|
||||
respect to a format)
|
||||
**/
|
||||
enum IniCommentMarker {
|
||||
INI_DISABLED_OR_COMMENT = 0, /**< This marker opens a comment or a
|
||||
disabled entry **/
|
||||
INI_ONLY_COMMENT = 1, /**< This marker opens a comment **/
|
||||
INI_IGNORE = 2, /**< This marker opens a comment that has
|
||||
been marked for deletion and must not
|
||||
be dispatched or counted **/
|
||||
INI_IS_NOT_A_MARKER = 3 /**< This is not a marker at all, but a
|
||||
normal character instead **/
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@brief Possible values of #IniFormat::section_paths
|
||||
**/
|
||||
enum IniSectionPaths {
|
||||
INI_ABSOLUTE_AND_RELATIVE = 0, /**< Section paths starting with a dot
|
||||
express nesting to the current parent,
|
||||
to root otherwise **/
|
||||
INI_ABSOLUTE_ONLY = 1, /**< Section paths starting with a dot will
|
||||
be cleaned of their leading dot and
|
||||
appended to root **/
|
||||
INI_ONE_LEVEL_ONLY = 2, /**< Format supports sections, but the dot
|
||||
does not express nesting and is not a
|
||||
meta-character **/
|
||||
INI_NO_SECTIONS = 3 /**< Format does *not* support sections --
|
||||
`/\[[^\]]*\]/g`, if any, will be
|
||||
treated as keys! **/
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@brief Possible values of #IniFormat::multiline_nodes
|
||||
**/
|
||||
enum IniMultiline {
|
||||
INI_MULTILINE_EVERYWHERE = 0, /**< Comments, section paths and keys
|
||||
-- disabled or not -- are allowed
|
||||
to be multi-line **/
|
||||
INI_BUT_COMMENTS = 1, /**< Only section paths and keys --
|
||||
disabled or not -- are allowed to
|
||||
be multi-line **/
|
||||
INI_BUT_DISABLED_AND_COMMENTS = 2, /**< Only active section paths and
|
||||
active keys are allowed to be
|
||||
multi-line **/
|
||||
INI_NO_MULTILINE = 3 /**< Multi-line escape sequences are
|
||||
disabled **/
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@brief A model format for standard INI files
|
||||
**/
|
||||
static const IniFormat INI_DEFAULT_FORMAT = _LIBCONFINI_DEFAULT_FORMAT_;
|
||||
|
||||
|
||||
/**
|
||||
@brief A model format for Unix-like .conf files (where space characters
|
||||
are delimiters between keys and values)
|
||||
**/
|
||||
/* All fields are set to `0` here. */
|
||||
static const IniFormat INI_UNIXLIKE_FORMAT = _LIBCONFINI_UNIXLIKE_FORMAT_;
|
||||
|
||||
|
||||
/**
|
||||
@brief If set to `true`, key and section names in case-insensitive INI
|
||||
formats will be dispatched lowercase, verbatim otherwise (default
|
||||
value: `false`)
|
||||
**/
|
||||
extern bool INI_GLOBAL_LOWERCASE_MODE;
|
||||
|
||||
|
||||
/**
|
||||
@brief Value to be assigned to implicit keys (default value: `NULL`)
|
||||
**/
|
||||
extern char * INI_GLOBAL_IMPLICIT_VALUE;
|
||||
|
||||
|
||||
/**
|
||||
@brief Length of the value assigned to implicit keys (default value: `0`)
|
||||
**/
|
||||
extern size_t INI_GLOBAL_IMPLICIT_V_LEN;
|
||||
|
||||
|
||||
|
||||
/* CLEAN THE PRIVATE ENVIRONMENT */
|
||||
|
||||
|
||||
#undef _LIBCONFINI_UNIXLIKE_FORMAT_
|
||||
#undef _LIBCONFINI_DEFAULT_FORMAT_
|
||||
#undef _LIBCONFINI_INIFORMAT_TYPE_
|
||||
#undef __INIFORMAT_TABLE_CB_ZERO__
|
||||
#undef __INIFORMAT_TABLE_CB_DEFAULT__
|
||||
#undef __INIFORMAT_TABLE_CB_FIELDS__
|
||||
|
||||
|
||||
|
||||
/* END OF `_LIBCONFINI_HEADER_` */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue