--- /dev/null
+/*
+ * UCW Library -- Basic Extended Types
+ *
+ * (c) 2014 Martin Mares <mj@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+#include <ucw/lib.h>
+#include <ucw/mempool.h>
+#include <ucw/strtonum.h>
+#include <ucw/xtypes.h>
+
+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,
+};
--- /dev/null
+/*
+ * UCW Library -- Extended Types -- Generic Operations
+ *
+ * (c) 2014 Martin Mares <mj@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+#include <ucw/lib.h>
+#include <ucw/xtypes.h>
+
+#include <string.h>
+
+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 "";
+}
--- /dev/null
+/*
+ * UCW Library -- Extended Types
+ *
+ * (c) 2014 Martin Mares <mj@ucw.cz>
+ *
+ * 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