summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/src/config/config.c
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2014-11-04 15:46:40 -0500
committerEliot Horowitz <eliot@10gen.com>2014-11-05 11:21:19 -0500
commit5ca2daf551a2c631a5f573cb054406f5d49fbef5 (patch)
treeb0a23d34ffdb376bac0b79ed17b5619cfc0d9b47 /src/third_party/wiredtiger/src/config/config.c
parent017704acdfc7517efadb3fab167bba06c025c01a (diff)
downloadmongo-5ca2daf551a2c631a5f573cb054406f5d49fbef5.tar.gz
SERVER-15953: add wiredtiger to third_party
Diffstat (limited to 'src/third_party/wiredtiger/src/config/config.c')
-rw-r--r--src/third_party/wiredtiger/src/config/config.c745
1 files changed, 745 insertions, 0 deletions
diff --git a/src/third_party/wiredtiger/src/config/config.c b/src/third_party/wiredtiger/src/config/config.c
new file mode 100644
index 00000000000..c792cb4fcf2
--- /dev/null
+++ b/src/third_party/wiredtiger/src/config/config.c
@@ -0,0 +1,745 @@
+/*-
+ * Copyright (c) 2008-2014 WiredTiger, Inc.
+ * All rights reserved.
+ *
+ * See the file LICENSE for redistribution information.
+ */
+
+#include "wt_internal.h"
+
+/*
+ * __config_err --
+ * Error message and return for config string parse failures.
+ */
+static int
+__config_err(WT_CONFIG *conf, const char *msg, int err)
+{
+ WT_RET_MSG(conf->session, err,
+ "Error parsing '%.*s' at byte %u: %s",
+ (int)(conf->end - conf->orig), conf->orig,
+ (u_int)(conf->cur - conf->orig), msg);
+}
+
+/*
+ * __wt_config_initn --
+ * Initialize a config handle, used to iterate through a config string of
+ * specified length.
+ */
+int
+__wt_config_initn(
+ WT_SESSION_IMPL *session, WT_CONFIG *conf, const char *str, size_t len)
+{
+ conf->session = session;
+ conf->orig = conf->cur = str;
+ conf->end = str + len;
+ conf->depth = 0;
+ conf->top = -1;
+ conf->go = NULL;
+
+ return (0);
+}
+
+/*
+ * __wt_config_init --
+ * Initialize a config handle, used to iterate through a NUL-terminated
+ * config string.
+ */
+int
+__wt_config_init(WT_SESSION_IMPL *session, WT_CONFIG *conf, const char *str)
+{
+ size_t len;
+
+ len = (str == NULL) ? 0 : strlen(str);
+
+ return (__wt_config_initn(session, conf, str, len));
+}
+
+/*
+ * __wt_config_subinit --
+ * Initialize a config handle, used to iterate through a config string
+ * extracted from another config string (used for parsing nested
+ * structures).
+ */
+int
+__wt_config_subinit(
+ WT_SESSION_IMPL *session, WT_CONFIG *conf, WT_CONFIG_ITEM *item)
+{
+ return (__wt_config_initn(session, conf, item->str, item->len));
+}
+
+#define PUSH(i, t) do { \
+ if (conf->top == -1) \
+ conf->top = conf->depth; \
+ if (conf->depth == conf->top) { \
+ if (out->len > 0) \
+ return (__config_err(conf, \
+ "New value starts without a separator", \
+ EINVAL)); \
+ out->type = (t); \
+ out->str = (conf->cur + (i)); \
+ } \
+} while (0)
+
+#define CAP(i) do { \
+ if (conf->depth == conf->top) \
+ out->len = (size_t)((conf->cur + (i) + 1) - out->str); \
+} while (0)
+
+typedef enum {
+ A_LOOP, A_BAD, A_DOWN, A_UP, A_VALUE, A_NEXT, A_QDOWN, A_QUP,
+ A_ESC, A_UNESC, A_BARE, A_NUMBARE, A_UNBARE, A_UTF8_2,
+ A_UTF8_3, A_UTF8_4, A_UTF_CONTINUE
+} CONFIG_ACTION;
+
+/*
+ * static void *gostruct[] = {
+ * [0 ... 255] = &&l_bad,
+ * ['\t'] = &&l_loop, [' '] = &&l_loop,
+ * ['\r'] = &&l_loop, ['\n'] = &&l_loop,
+ * ['"'] = &&l_qup,
+ * [':'] = &&l_value, ['='] = &&l_value,
+ * [','] = &&l_next,
+ * // tracking [] and {} individually would allow fuller
+ * // validation but is really messy
+ * ['('] = &&l_up, [')'] = &&l_down,
+ * ['['] = &&l_up, [']'] = &&l_down,
+ * ['{'] = &&l_up, ['}'] = &&l_down,
+ * // bare identifiers
+ * ['-'] = &&l_numbare,
+ * ['0' ... '9'] = &&l_numbare,
+ * ['_'] = &&l_bare,
+ * ['A' ... 'Z'] = &&l_bare, ['a' ... 'z'] = &&l_bare,
+ * ['/'] = &&l_bare,
+ * };
+ */
+static const int8_t gostruct[256] = {
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_LOOP, A_LOOP, A_BAD, A_BAD, A_LOOP, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_LOOP, A_BAD, A_QUP,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_UP, A_DOWN, A_BAD, A_BAD,
+ A_NEXT, A_NUMBARE, A_BARE, A_BARE, A_NUMBARE, A_NUMBARE,
+ A_NUMBARE, A_NUMBARE, A_NUMBARE, A_NUMBARE, A_NUMBARE,
+ A_NUMBARE, A_NUMBARE, A_NUMBARE, A_VALUE, A_BAD, A_BAD,
+ A_VALUE, A_BAD, A_BAD, A_BAD, A_BARE, A_BARE, A_BARE, A_BARE,
+ A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE,
+ A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE,
+ A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_UP, A_BAD,
+ A_DOWN, A_BAD, A_BARE, A_BAD, A_BARE, A_BARE, A_BARE, A_BARE,
+ A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE,
+ A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE,
+ A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_BARE, A_UP, A_BAD,
+ A_DOWN, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD
+};
+
+/*
+ * static void *gobare[] =
+ * {
+ * [0 ... 31] = &&l_bad,
+ * // could be more pedantic/validation-checking
+ * [32 ... 126] = &&l_loop,
+ * ['\t'] = &&l_unbare, [' '] = &&l_unbare,
+ * ['\r'] = &&l_unbare, ['\n'] = &&l_unbare,
+ * [':'] = &&l_unbare, ['='] = &&l_unbare,
+ * [','] = &&l_unbare,
+ * [')'] = &&l_unbare, [']'] = &&l_unbare, ['}'] = &&l_unbare,
+ * [127 ... 255] = &&l_bad
+ * };
+ */
+static const int8_t gobare[256] = {
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_UNBARE, A_UNBARE, A_BAD, A_BAD, A_UNBARE, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_UNBARE,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_UNBARE, A_LOOP, A_LOOP, A_UNBARE, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_UNBARE, A_LOOP, A_LOOP, A_UNBARE, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_UNBARE,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_UNBARE, A_LOOP, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD
+};
+
+/*
+ * static void *gostring[] =
+ * {
+ * [0 ... 31] = &&l_bad, [127] = &&l_bad,
+ * [32 ... 126] = &&l_loop,
+ * ['\\'] = &&l_esc, ['"'] = &&l_qdown,
+ * [128 ... 191] = &&l_bad,
+ * [192 ... 223] = &&l_utf8_2,
+ * [224 ... 239] = &&l_utf8_3,
+ * [240 ... 247] = &&l_utf8_4,
+ * [248 ... 255] = &&l_bad
+ * };
+ */
+static const int8_t gostring[256] = {
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_LOOP, A_LOOP, A_QDOWN,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_ESC, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_LOOP,
+ A_LOOP, A_LOOP, A_LOOP, A_LOOP, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_UTF8_2,
+ A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2,
+ A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2,
+ A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2,
+ A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2,
+ A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2, A_UTF8_2,
+ A_UTF8_2, A_UTF8_3, A_UTF8_3, A_UTF8_3, A_UTF8_3, A_UTF8_3,
+ A_UTF8_3, A_UTF8_3, A_UTF8_3, A_UTF8_3, A_UTF8_3, A_UTF8_3,
+ A_UTF8_3, A_UTF8_3, A_UTF8_3, A_UTF8_3, A_UTF8_3, A_UTF8_4,
+ A_UTF8_4, A_UTF8_4, A_UTF8_4, A_UTF8_4, A_UTF8_4, A_UTF8_4,
+ A_UTF8_4, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD
+};
+
+/*
+ * static void *goutf8_continue[] =
+ * {
+ * [0 ... 127] = &&l_bad,
+ * [128 ... 191] = &&l_utf_continue,
+ * [192 ... 255] = &&l_bad
+ * };
+ */
+static const int8_t goutf8_continue[256] = {
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE, A_UTF_CONTINUE,
+ A_UTF_CONTINUE, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD
+};
+
+/*
+ * static void *goesc[] =
+ * {
+ * [0 ... 255] = &&l_bad,
+ * ['"'] = &&l_unesc, ['\\'] = &&l_unesc,
+ * ['/'] = &&l_unesc, ['b'] = &&l_unesc,
+ * ['f'] = &&l_unesc, ['n'] = &&l_unesc,
+ * ['r'] = &&l_unesc, ['t'] = &&l_unesc, ['u'] = &&l_unesc
+ * };
+ */
+static const int8_t goesc[256] = {
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_UNESC,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_UNESC, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_UNESC, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_UNESC, A_BAD, A_BAD, A_BAD, A_UNESC, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_UNESC, A_BAD,
+ A_BAD, A_BAD, A_UNESC, A_BAD, A_UNESC, A_UNESC, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD,
+ A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD, A_BAD
+};
+
+/*
+ * __config_next --
+ * Get the next config item in the string without processing the value.
+ */
+static int
+__config_next(WT_CONFIG *conf, WT_CONFIG_ITEM *key, WT_CONFIG_ITEM *value)
+{
+ WT_CONFIG_ITEM *out = key;
+ int utf8_remain = 0;
+ static const WT_CONFIG_ITEM true_value = {
+ "", 0, 1, WT_CONFIG_ITEM_BOOL
+ };
+
+ key->len = 0;
+ /* Keys with no value default to true. */
+ *value = true_value;
+
+ if (conf->go == NULL)
+ conf->go = gostruct;
+
+ while (conf->cur < conf->end) {
+ switch (conf->go[(int)*conf->cur]) {
+ case A_LOOP:
+ break;
+
+ case A_BAD:
+ return (__config_err(
+ conf, "Unexpected character", EINVAL));
+
+ case A_DOWN:
+ --conf->depth;
+ CAP(0);
+ break;
+
+ case A_UP:
+ if (conf->top == -1)
+ conf->top = 1;
+ PUSH(0, WT_CONFIG_ITEM_STRUCT);
+ ++conf->depth;
+ break;
+
+ case A_VALUE:
+ if (conf->depth == conf->top) {
+ /*
+ * Special case: ':' is permitted in unquoted
+ * values.
+ */
+ if (out == value && *conf->cur != ':')
+ return (__config_err(conf,
+ "Value already complete", EINVAL));
+ out = value;
+ }
+ break;
+
+ case A_NEXT:
+ /*
+ * If we're at the top level and we have a complete
+ * key (and optional value), we're done.
+ */
+ if (conf->depth == conf->top && key->len > 0) {
+ ++conf->cur;
+ return (0);
+ } else
+ break;
+
+ case A_QDOWN:
+ CAP(-1);
+ conf->go = gostruct;
+ break;
+
+ case A_QUP:
+ PUSH(1, WT_CONFIG_ITEM_STRING);
+ conf->go = gostring;
+ break;
+
+ case A_ESC:
+ conf->go = goesc;
+ break;
+
+ case A_UNESC:
+ conf->go = gostring;
+ break;
+
+ case A_BARE:
+ PUSH(0, WT_CONFIG_ITEM_ID);
+ conf->go = gobare;
+ break;
+
+ case A_NUMBARE:
+ PUSH(0, WT_CONFIG_ITEM_NUM);
+ conf->go = gobare;
+ break;
+
+ case A_UNBARE:
+ CAP(-1);
+ conf->go = gostruct;
+ continue;
+
+ case A_UTF8_2:
+ conf->go = goutf8_continue;
+ utf8_remain = 1;
+ break;
+
+ case A_UTF8_3:
+ conf->go = goutf8_continue;
+ utf8_remain = 2;
+ break;
+
+ case A_UTF8_4:
+ conf->go = goutf8_continue;
+ utf8_remain = 3;
+ break;
+
+ case A_UTF_CONTINUE:
+ if (!--utf8_remain)
+ conf->go = gostring;
+ break;
+ }
+
+ conf->cur++;
+ }
+
+ /* Might have a trailing key/value without a closing brace */
+ if (conf->go == gobare) {
+ CAP(-1);
+ conf->go = gostruct;
+ }
+
+ /* Did we find something? */
+ if (conf->depth <= conf->top && key->len > 0)
+ return (0);
+
+ /* We're either at the end of the string or we failed to parse. */
+ if (conf->depth == 0)
+ return (WT_NOTFOUND);
+
+ return (__config_err(conf,
+ "Closing brackets missing from config string", EINVAL));
+}
+
+/*
+ * Arithmetic shift of a negative number is undefined by ISO/IEC 9899, and the
+ * WiredTiger API supports negative numbers. Check it's not a negative number,
+ * and then cast the shift out of paranoia.
+ */
+#define WT_SHIFT_INT64(v, s) do { \
+ if ((v) < 0) \
+ goto range; \
+ (v) = (int64_t)(((uint64_t)(v)) << (s)); \
+} while (0)
+
+/*
+ * __config_process_value --
+ * Deal with special config values like true / false.
+ */
+static int
+__config_process_value(WT_CONFIG *conf, WT_CONFIG_ITEM *value)
+{
+ char *endptr;
+
+ /* Empty values are okay: we can't do anything interesting with them. */
+ if (value->len == 0)
+ return (0);
+
+ if (value->type == WT_CONFIG_ITEM_ID) {
+ if (strncasecmp(value->str, "true", value->len) == 0) {
+ value->type = WT_CONFIG_ITEM_BOOL;
+ value->val = 1;
+ } else if (strncasecmp(value->str, "false", value->len) == 0) {
+ value->type = WT_CONFIG_ITEM_BOOL;
+ value->val = 0;
+ }
+ } else if (value->type == WT_CONFIG_ITEM_NUM) {
+ errno = 0;
+ value->val = strtoll(value->str, &endptr, 10);
+
+ /* Check any leftover characters. */
+ while (endptr < value->str + value->len)
+ switch (*endptr++) {
+ case 'b':
+ case 'B':
+ /* Byte: no change. */
+ break;
+ case 'k':
+ case 'K':
+ WT_SHIFT_INT64(value->val, 10);
+ break;
+ case 'm':
+ case 'M':
+ WT_SHIFT_INT64(value->val, 20);
+ break;
+ case 'g':
+ case 'G':
+ WT_SHIFT_INT64(value->val, 30);
+ break;
+ case 't':
+ case 'T':
+ WT_SHIFT_INT64(value->val, 40);
+ break;
+ case 'p':
+ case 'P':
+ WT_SHIFT_INT64(value->val, 50);
+ break;
+ default:
+ /*
+ * We didn't get a well-formed number. That
+ * might be okay, the required type will be
+ * checked by __wt_config_check.
+ */
+ value->type = WT_CONFIG_ITEM_ID;
+ break;
+ }
+
+ /*
+ * If we parsed the whole string but the number is out of range,
+ * report an error. Don't report an error for strings that
+ * aren't well-formed integers: if an integer is expected, that
+ * will be caught by __wt_config_check.
+ */
+ if (value->type == WT_CONFIG_ITEM_NUM && errno == ERANGE)
+ goto range;
+ }
+
+ return (0);
+
+range:
+ return (__config_err(conf, "Number out of range", ERANGE));
+}
+
+/*
+ * __wt_config_next --
+ * Get the next config item in the string and process the value.
+ */
+int
+__wt_config_next(WT_CONFIG *conf, WT_CONFIG_ITEM *key, WT_CONFIG_ITEM *value)
+{
+ WT_RET(__config_next(conf, key, value));
+ return (__config_process_value(conf, value));
+}
+
+/*
+ * __config_getraw --
+ * Given a config parser, find the final value for a given key.
+ */
+static int
+__config_getraw(
+ WT_CONFIG *cparser, WT_CONFIG_ITEM *key, WT_CONFIG_ITEM *value, int top)
+{
+ WT_CONFIG sparser;
+ WT_CONFIG_ITEM k, v, subk;
+ WT_DECL_RET;
+ int found;
+
+ found = 0;
+ while ((ret = __config_next(cparser, &k, &v)) == 0) {
+ if (k.type != WT_CONFIG_ITEM_STRING &&
+ k.type != WT_CONFIG_ITEM_ID)
+ continue;
+ if (k.len == key->len &&
+ strncasecmp(key->str, k.str, k.len) == 0) {
+ *value = v;
+ found = 1;
+ } else if (k.len < key->len && key->str[k.len] == '.' &&
+ strncasecmp(key->str, k.str, k.len) == 0) {
+ subk.str = key->str + k.len + 1;
+ subk.len = (key->len - k.len) - 1;
+ WT_RET(__wt_config_initn(
+ cparser->session, &sparser, v.str, v.len));
+ if ((ret =
+ __config_getraw(&sparser, &subk, value, 0)) == 0)
+ found = 1;
+ WT_RET_NOTFOUND_OK(ret);
+ }
+ }
+ WT_RET_NOTFOUND_OK(ret);
+
+ if (!found)
+ return (WT_NOTFOUND);
+ return (top ? __config_process_value(cparser, value) : 0);
+}
+
+/*
+ * __wt_config_get --
+ * Given a NULL-terminated list of configuration strings, find
+ * the final value for a given key.
+ */
+int
+__wt_config_get(WT_SESSION_IMPL *session,
+ const char **cfg, WT_CONFIG_ITEM *key, WT_CONFIG_ITEM *value)
+{
+ WT_CONFIG cparser;
+ WT_DECL_RET;
+ int found;
+
+ for (found = 0; *cfg != NULL; cfg++) {
+ WT_RET(__wt_config_init(session, &cparser, *cfg));
+ if ((ret = __config_getraw(&cparser, key, value, 1)) == 0)
+ found = 1;
+ else if (ret != WT_NOTFOUND)
+ return (ret);
+ }
+
+ return (found ? 0 : WT_NOTFOUND);
+}
+
+/*
+ * __wt_config_gets --
+ * Given a NULL-terminated list of configuration strings, find the final
+ * value for a given string key.
+ */
+int
+__wt_config_gets(WT_SESSION_IMPL *session,
+ const char **cfg, const char *key, WT_CONFIG_ITEM *value)
+{
+ WT_CONFIG_ITEM key_item =
+ { key, strlen(key), 0, WT_CONFIG_ITEM_STRING };
+
+ return (__wt_config_get(session, cfg, &key_item, value));
+}
+
+/*
+ * __wt_config_getone --
+ * Get the value for a given key from a single config string.
+ */
+int
+__wt_config_getone(WT_SESSION_IMPL *session,
+ const char *config, WT_CONFIG_ITEM *key, WT_CONFIG_ITEM *value)
+{
+ WT_CONFIG cparser;
+
+ WT_RET(__wt_config_init(session, &cparser, config));
+ return (__config_getraw(&cparser, key, value, 1));
+}
+
+/*
+ * __wt_config_getones --
+ * Get the value for a given string key from a single config string.
+ */
+int
+__wt_config_getones(WT_SESSION_IMPL *session,
+ const char *config, const char *key, WT_CONFIG_ITEM *value)
+{
+ WT_CONFIG cparser;
+ WT_CONFIG_ITEM key_item =
+ { key, strlen(key), 0, WT_CONFIG_ITEM_STRING };
+
+ WT_RET(__wt_config_init(session, &cparser, config));
+ return (__config_getraw(&cparser, &key_item, value, 1));
+}
+
+/*
+ * __wt_config_gets_def --
+ * Performance hack: skip parsing config strings by hard-coding defaults.
+ *
+ * It's expensive to repeatedly parse configuration strings, so don't do
+ * it unless it's necessary in performance paths like cursor creation.
+ * Assume the second configuration string is the application's
+ * configuration string, and if it's not set (which is true most of the
+ * time), then use the supplied default value. This makes it faster to
+ * open cursors when checking for obscure open configuration strings like
+ * "next_random".
+ */
+int
+__wt_config_gets_def(WT_SESSION_IMPL *session,
+ const char **cfg, const char *key, int def, WT_CONFIG_ITEM *value)
+{
+ static const WT_CONFIG_ITEM false_value = {
+ "", 0, 0, WT_CONFIG_ITEM_NUM
+ };
+
+ *value = false_value;
+ value->val = def;
+ if (cfg == NULL || cfg[0] == NULL || cfg[1] == NULL)
+ return (0);
+ else if (cfg[2] == NULL)
+ WT_RET_NOTFOUND_OK(
+ __wt_config_getones(session, cfg[1], key, value));
+ return (__wt_config_gets(session, cfg, key, value));
+}
+
+/*
+ * __wt_config_subgetraw --
+ * Get the value for a given key from a config string in a WT_CONFIG_ITEM.
+ * This is useful for dealing with nested structs in config strings.
+ */
+int
+__wt_config_subgetraw(WT_SESSION_IMPL *session,
+ WT_CONFIG_ITEM *cfg, WT_CONFIG_ITEM *key, WT_CONFIG_ITEM *value)
+{
+ WT_CONFIG cparser;
+
+ WT_RET(__wt_config_initn(session, &cparser, cfg->str, cfg->len));
+ return (__config_getraw(&cparser, key, value, 1));
+}
+
+/*
+ * __wt_config_subgets --
+ * Get the value for a given key from a config string in a WT_CONFIG_ITEM.
+ * This is useful for dealing with nested structs in config strings.
+ */
+int
+__wt_config_subgets(WT_SESSION_IMPL *session,
+ WT_CONFIG_ITEM *cfg, const char *key, WT_CONFIG_ITEM *value)
+{
+ WT_CONFIG_ITEM key_item =
+ { key, strlen(key), 0, WT_CONFIG_ITEM_STRING };
+
+ return (__wt_config_subgetraw(session, cfg, &key_item, value));
+}