From ceea11af344f8942871ab88a536abb2266e35c69 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Thu, 10 Jul 2014 16:04:44 +0200 Subject: [PATCH] Extended types: First attempt at interface --- ucw/Makefile | 2 +- ucw/doc/Makefile | 2 +- ucw/doc/xtypes.txt | 6 +++ ucw/xtypes-basic.c | 30 +++++++++++++++ ucw/xtypes.c | 47 +++++++++++++++++++++++ ucw/xtypes.h | 93 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 ucw/doc/xtypes.txt create mode 100644 ucw/xtypes-basic.c create mode 100644 ucw/xtypes.c create mode 100644 ucw/xtypes.h diff --git a/ucw/Makefile b/ucw/Makefile index 71e66311..6bc4f26f 100644 --- a/ucw/Makefile +++ b/ucw/Makefile @@ -38,7 +38,7 @@ LIBUCW_MODS= \ daemon daemon-ctrl \ signames \ opt opt-help opt-conf \ - table table-types + table table-types xtypes xtypes-basic LIBUCW_MAIN_INCLUDES= \ lib.h log.h tbf.h threads.h time.h \ diff --git a/ucw/doc/Makefile b/ucw/doc/Makefile index 0b60aa10..fc38637e 100644 --- a/ucw/doc/Makefile +++ b/ucw/doc/Makefile @@ -2,7 +2,7 @@ DIRS+=ucw/doc -UCW_DOCS=basics log fastbuf index config configure install basecode hash docsys conf mempool eltpool mainloop generic growbuf unaligned lists chartype unicode prime binsearch heap binheap compress sort hashtable relnotes trans string time daemon signal varint opt alloc gary table +UCW_DOCS=basics log fastbuf index config configure install basecode hash docsys conf mempool eltpool mainloop generic growbuf unaligned lists chartype unicode prime binsearch heap binheap compress sort hashtable relnotes trans string time daemon signal varint opt alloc gary table xtypes UCW_INDEX=$(o)/ucw/doc/def_index.html UCW_DOCS_HTML=$(addprefix $(o)/ucw/doc/,$(addsuffix .html,$(UCW_DOCS))) diff --git a/ucw/doc/xtypes.txt b/ucw/doc/xtypes.txt new file mode 100644 index 00000000..b75f8275 --- /dev/null +++ b/ucw/doc/xtypes.txt @@ -0,0 +1,6 @@ +Extended types +============== + +FIXME: Introduction + +!!ucw/xtypes.h diff --git a/ucw/xtypes-basic.c b/ucw/xtypes-basic.c new file mode 100644 index 00000000..f17fc4e5 --- /dev/null +++ b/ucw/xtypes-basic.c @@ -0,0 +1,30 @@ +/* + * UCW Library -- Basic Extended Types + * + * (c) 2014 Martin Mares + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. + */ + +#include +#include +#include +#include + +static const char *xt_int_parse(const char *str, void *dest, struct mempool *pool UNUSED) +{ + return str_to_int(dest, str, NULL, 10 | STN_WHOLE | STN_MINUS | STN_PLUS | STN_HEX | STN_BIN | STN_OCT); +} + +static const char *xt_int_format(void *src, u32 fmt UNUSED, struct mempool *pool) +{ + return mp_printf(pool, "%d", *(int *)src); +} + +const struct xtype xt_int = { + .size = sizeof(int), + .name = "int", + .parse = xt_int_parse, + .format = xt_int_format, +}; diff --git a/ucw/xtypes.c b/ucw/xtypes.c new file mode 100644 index 00000000..18ee5b63 --- /dev/null +++ b/ucw/xtypes.c @@ -0,0 +1,47 @@ +/* + * UCW Library -- Extended Types -- Generic Operations + * + * (c) 2014 Martin Mares + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. + */ + +#include +#include + +#include + +static const char * const fmt_names[] = { + [XTYPE_FMT_DEFAULT] = "default", + [XTYPE_FMT_RAW] = "raw", + [XTYPE_FMT_PRETTY] = "pretty", +}; + +const char *xtype_parse_fmt(struct xtype *xt, const char *str, u32 *dest, struct mempool *pool) +{ + for (uint i=0; i < ARRAY_SIZE(fmt_names); i++) + if (!strcmp(str, fmt_names[i])) + { + *dest = i; + return NULL; + } + + if (xt->parse_fmt) + return (xt->parse_fmt)(str, dest, pool); + else + return "Unknown mode"; +} + +const char *xtype_format_fmt(struct xtype *xt, u32 fmt, struct mempool *pool) +{ + if (fmt & XTYPE_FMT_CUSTOM) + { + if (xt->format_fmt) + return (xt->format_fmt)(fmt, pool); + } + else if (fmt < ARRAY_SIZE(fmt_names)) + return fmt_names[fmt]; + + return ""; +} diff --git a/ucw/xtypes.h b/ucw/xtypes.h new file mode 100644 index 00000000..c06b3a22 --- /dev/null +++ b/ucw/xtypes.h @@ -0,0 +1,93 @@ +/* + * UCW Library -- Extended Types + * + * (c) 2014 Martin Mares + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. + */ + +#ifndef _UCW_XTYPE_H +#define _UCW_XTYPE_H + +struct mempool; + +/** + * A parsing callback. Takes a string, interprets it as a value of the particular + * xtype and stores it where @dest points. Returns NULL on success and an error message + * otherwise. It may allocate memory from the @pool and the parsed value can contain + * pointers to this memory. + **/ +typedef const char * (*xtype_parser)(const char *str, void *dest, struct mempool *pool); + +/** + * A formatting callback. Takes a value of the particular xtype and a formatting + * mode @fmt (see below for how the modes work) and returns a string representation + * of the value. The string can be allocated from the @pool, but it does not have to. + * + * When @fmt is set to `XTYPE_FMT_DEFAULT`, the resulting string should be + * parseable via the parsing callback and yield a semantically equivalent value. + **/ +typedef const char * (*xtype_formatter)(void *src, u32 fmt, struct mempool *pool); + +/** + * Formatting of values is controlled by a mode parameter, which is generally + * a 32-bit integer. If the most significant bit is clear, it is one of generic + * well-known modes (`XTYPE_FMT_`'something'), which can be passed to all formatters + * and if it is not understood, it acts like `XTYPE_FMT_DEFAULT`. When the most + * significant bit is set, the meaning of the mode is specific to the particular + * xtype. + **/ + +enum xtype_fmt { + XTYPE_FMT_DEFAULT = 0, // Default format: readable, but not hostile to machine parsing + XTYPE_FMT_RAW = 1, // Raw data with no frills + XTYPE_FMT_PRETTY = 2, // Try to please humans (e.g., like "ls -h") + XTYPE_FMT_CUSTOM = 0x80000000, +}; + +/** + * A callback for parsing non-generic formatting modes. See `xtype_parser` for more + * details. It is usually called via `xtype_parse_fmt`, which handles the generic modes. + **/ +typedef const char * (*xtype_fmt_parser)(const char *str, u32 *dest, struct mempool *pool); + +/** + * A callback for constructing a string representation of non-generic formatting modes, + * analogous to `xtype_formatter`. It is usually called via `xtype_format_fmt`, + * which handles the generic modes. Returns an empty string for unknown modes. + **/ +typedef const char * (*xtype_fmt_formatter)(u32 fmt, struct mempool *pool); + +/** + * This structure describes an xtype. Among other things, it points to callback + * functions handling this xtype. + **/ +struct xtype { + size_t size; // How many bytes does a single value occupy + const char *name; // Name used in debug messages + xtype_parser parse; // Parsing callback + xtype_formatter format; // Formatting callback + xtype_fmt_parser parse_fmt; // Format mode parsing callback (optional) + xtype_fmt_formatter format_fmt; // Format mode formatting callback (optional) +}; + +/** + * Construct a formatting mode from its string representation. It is a wrapper + * around the `xtype_fmt_parser` hook, which handles generic modes first. + * + * The generic modes are called `default`, `raw`, and `pretty`. + **/ +const char *xtype_parse_fmt(struct xtype *xt, const char *str, u32 *dest, struct mempool *pool); + +/** + * Construct a string representation of a formatting mode. It is a wrapper + * around the `xtype_fmt_formatter` hook, which handles generic modes first. + * Returns an empty string for unknown modes. + **/ +const char *xtype_format_fmt(struct xtype *xt, u32 fmt, struct mempool *pool); + +// Basic set of extended types +extern const struct xtype xt_int; + +#endif -- 2.39.2