]> mj.ucw.cz Git - libucw.git/commitdiff
Extended types: First attempt at interface
authorMartin Mares <mj@ucw.cz>
Thu, 10 Jul 2014 14:04:44 +0000 (16:04 +0200)
committerMartin Mares <mj@ucw.cz>
Thu, 10 Jul 2014 14:04:44 +0000 (16:04 +0200)
ucw/Makefile
ucw/doc/Makefile
ucw/doc/xtypes.txt [new file with mode: 0644]
ucw/xtypes-basic.c [new file with mode: 0644]
ucw/xtypes.c [new file with mode: 0644]
ucw/xtypes.h [new file with mode: 0644]

index 71e66311e476bc8efc1d5b1ed21550b3fec61142..6bc4f26fe68c760a0e90f626ed6432113b67ea2c 100644 (file)
@@ -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 \
index 0b60aa1060680f5a4a508228ae884262e85686f2..fc38637e463e8ee37063184cac6c31b24a4acfdb 100644 (file)
@@ -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 (file)
index 0000000..b75f827
--- /dev/null
@@ -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 (file)
index 0000000..f17fc4e
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *     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,
+};
diff --git a/ucw/xtypes.c b/ucw/xtypes.c
new file mode 100644 (file)
index 0000000..18ee5b6
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *     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 "";
+}
diff --git a/ucw/xtypes.h b/ucw/xtypes.h
new file mode 100644 (file)
index 0000000..c06b3a2
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *     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