diff options
author | Ondřej Surý <ondrej@sury.org> | 2013-06-28 12:59:40 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2013-06-28 12:59:40 +0200 |
commit | 124965832295a277b9ca6ae9fac4f45a74a36b2a (patch) | |
tree | f299e2335863f74e0be0707f84b85211baaf2d03 /src/utils/common/token.c | |
parent | 3d2d198c71a6b844b60fa9ef68801b66bba93361 (diff) | |
download | knot-upstream/1.3.0_rc3.tar.gz |
New upstream version 1.3.0~rc3upstream/1.3.0_rc3
Diffstat (limited to 'src/utils/common/token.c')
-rw-r--r-- | src/utils/common/token.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/utils/common/token.c b/src/utils/common/token.c new file mode 100644 index 0000000..457a7c0 --- /dev/null +++ b/src/utils/common/token.c @@ -0,0 +1,136 @@ +/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> +#include "utils/common/token.h" + +#include <stdio.h> +#include <stdlib.h> // free +#include <ctype.h> // isspace +#include <string.h> // memcmp + +#include "common/errcode.h" // KNOT_EOK +#include "common/getline.h" // knot_getline +#include "utils/common/msg.h" // ERR + +int tok_scan(const char* lp, const char **tbl, int *lpm) +{ + if (lp == NULL || tbl == NULL || *tbl == NULL || lpm == NULL) { + DBG_NULL; + return -1; + } + + const char *prefix = lp; /* Ptr to line start. */ + int i = 0, pl = 1; /* Match index, prefix length. */ + unsigned char len = 0; /* Read length. */ + for(;;) { + const char *tok = tbl[i]; + if (*lp == '\0' || isspace((unsigned char)(*lp))) { + if (tok && TOK_L(tok) == len) { /* Consumed whole w? */ + return i; /* Identifier */ + } else { /* Word is shorter than cmd? */ + break; + } + } + + /* Find next prefix match. */ + ++len; + while (tok) { + if (TOK_L(tok) >= len) { /* Is prefix of current token */ + if (*lp < tok[pl]) { /* Terminate early. */ + tok = NULL; + break; /* No match could be found. */ + } + if (*lp == tok[pl]) { /* Match */ + if(lpm) *lpm = i; + ++pl; + break; + } + } + + /* No early cut, no match - seek next. */ + while ((tok = tbl[++i]) != NULL) { + if (TOK_L(tok) >= len && + memcmp(TOK_S(tok), prefix, len) == 0) { + break; + } + } + } + + if (tok == NULL) { + break; /* All tokens exhausted. */ + } else { + ++lp; /* Next char */ + } + } + + return -1; +} + +int tok_find(const char *lp, const char **tbl) +{ + if (lp == NULL || tbl == NULL || *tbl == NULL) { + DBG_NULL; + return KNOT_EINVAL; + } + + int lpm = -1; + int bp = 0; + if ((bp = tok_scan(lp, tbl, &lpm)) < 0) { + if (lpm > -1) { + ERR("unexpected literal: '%s', did you mean '%s' ?\n", + lp, TOK_S(tbl[lpm])); + } else { + ERR("unexpected literal: '%s'\n", lp); + } + + return KNOT_EPARSEFAIL; + } + + return bp; +} + +const char* tok_skipspace(const char *lp) +{ + if (lp == NULL) { + DBG_NULL; + return NULL; + } + + while (isspace((unsigned char)(*lp))) ++lp; return lp; +} + +int tok_process_lines(FILE *fp, lparse_f cb, void *arg) +{ + if (fp == NULL || cb == NULL) { + DBG_NULL; + return KNOT_EINVAL; + } + + int ret = KNOT_EOK; + + /* Parse lines. */ + char *buf = NULL; + size_t buflen = 0; + ssize_t rb = 0; + while ((rb = knot_getline(&buf, &buflen, fp)) != -1) { + ret = cb(buf, rb, arg); + if (ret != KNOT_EOK) break; + } + + free(buf); + return ret; +} |