From: Vsevolod Stakhov Date: Fri, 13 Jan 2017 09:24:19 +0000 (+0000) Subject: [Feature] Allow custom parse types in lua ucl X-Git-Tag: 1.5.0~358 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=d9f7a74a1c97af5b878066447178135a8349d6b5;p=rspamd.git [Feature] Allow custom parse types in lua ucl --- diff --git a/contrib/libucl/lua_ucl.c b/contrib/libucl/lua_ucl.c index 5535ad427..fa69c72d0 100644 --- a/contrib/libucl/lua_ucl.c +++ b/contrib/libucl/lua_ucl.c @@ -526,6 +526,24 @@ lua_ucl_push_opaque (lua_State *L, ucl_object_t *obj) lua_setmetatable (L, -2); } +static inline enum ucl_parse_type +lua_ucl_str_to_parse_type (const char *str) +{ + enum ucl_parse_type type = UCL_PARSE_UCL; + + if (str != NULL) { + if (strcasecmp (str, "msgpack") == 0) { + type = UCL_PARSE_MSGPACK; + } + else if (strcasecmp (str, "sexp") == 0 || + strcasecmp (str, "csexp") == 0) { + type = UCL_PARSE_CSEXP; + } + } + + return type; +} + /*** * @method parser:parse_file(name) * Parse UCL object from file. @@ -581,13 +599,19 @@ lua_ucl_parser_parse_string (lua_State *L) struct ucl_parser *parser; const char *string; size_t llen; + enum ucl_parse_type type = UCL_PARSE_UCL; int ret = 2; parser = lua_ucl_parser_get (L, 1); string = luaL_checklstring (L, 2, &llen); + if (lua_type (L, 3) == LUA_TSTRING) { + type = lua_ucl_str_to_parse_type (lua_tostring (L, 3)); + } + if (parser != NULL && string != NULL) { - if (ucl_parser_add_chunk (parser, (const unsigned char *)string, llen)) { + if (ucl_parser_add_chunk_full (parser, (const unsigned char *)string, + llen, 0, UCL_DUPLICATE_APPEND, type)) { lua_pushboolean (L, true); ret = 1; } @@ -763,6 +787,28 @@ lua_ucl_object_unwrap (lua_State *L) return 1; } +static inline enum ucl_emitter +lua_ucl_str_to_emit_type (const char *strtype) +{ + enum ucl_emitter format = UCL_EMIT_JSON_COMPACT; + + if (strcasecmp (strtype, "json") == 0) { + format = UCL_EMIT_JSON; + } + else if (strcasecmp (strtype, "json-compact") == 0) { + format = UCL_EMIT_JSON_COMPACT; + } + else if (strcasecmp (strtype, "yaml") == 0) { + format = UCL_EMIT_YAML; + } + else if (strcasecmp (strtype, "config") == 0 || + strcasecmp (strtype, "ucl") == 0) { + format = UCL_EMIT_CONFIG; + } + + return format; +} + /*** * @method object:tostring(type) * Unwraps opaque ucl object to string (json by default). Optionally you can @@ -789,19 +835,7 @@ lua_ucl_object_tostring (lua_State *L) if (lua_type (L, 2) == LUA_TSTRING) { const char *strtype = lua_tostring (L, 2); - if (strcasecmp (strtype, "json") == 0) { - format = UCL_EMIT_JSON; - } - else if (strcasecmp (strtype, "json-compact") == 0) { - format = UCL_EMIT_JSON_COMPACT; - } - else if (strcasecmp (strtype, "yaml") == 0) { - format = UCL_EMIT_YAML; - } - else if (strcasecmp (strtype, "config") == 0 || - strcasecmp (strtype, "ucl") == 0) { - format = UCL_EMIT_CONFIG; - } + format = lua_ucl_str_to_emit_type (strtype); } } @@ -1090,6 +1124,9 @@ lua_ucl_to_format (lua_State *L) strcasecmp (strtype, "ucl") == 0) { format = UCL_EMIT_CONFIG; } + else if (strcasecmp (strtype, "msgpack") == 0) { + format = UCL_EMIT_MSGPACK; + } } } diff --git a/contrib/libucl/ucl.h b/contrib/libucl/ucl.h index ec93bd7e1..ee683b163 100644 --- a/contrib/libucl/ucl.h +++ b/contrib/libucl/ucl.h @@ -205,7 +205,8 @@ enum ucl_duplicate_strategy { enum ucl_parse_type { UCL_PARSE_UCL = 0, /**< Default ucl format */ UCL_PARSE_MSGPACK, /**< Message pack input format */ - UCL_PARSE_CSEXP /**< Canonical S-expressions */ + UCL_PARSE_CSEXP, /**< Canonical S-expressions */ + UCL_PARSE_AUTO /**< Try to detect parse type */ }; /** diff --git a/contrib/libucl/ucl_internal.h b/contrib/libucl/ucl_internal.h index db8a12c40..444a40e38 100644 --- a/contrib/libucl/ucl_internal.h +++ b/contrib/libucl/ucl_internal.h @@ -569,4 +569,6 @@ bool ucl_parser_process_object_element (struct ucl_parser *parser, */ bool ucl_parse_msgpack (struct ucl_parser *parser); +bool ucl_parse_csexp (struct ucl_parser *parser); + #endif /* UCL_INTERNAL_H_ */ diff --git a/contrib/libucl/ucl_parser.c b/contrib/libucl/ucl_parser.c index fc7cea07f..82c4ca24b 100644 --- a/contrib/libucl/ucl_parser.c +++ b/contrib/libucl/ucl_parser.c @@ -2609,6 +2609,19 @@ ucl_parser_add_chunk_full (struct ucl_parser *parser, const unsigned char *data, return false; } + if (parse_type == UCL_PARSE_AUTO && len > 0) { + /* We need to detect parse type by the first symbol */ + if ((*data & 0x80) == 0x80 && (*data >= 0xdc && *data <= 0xdf)) { + parse_type = UCL_PARSE_MSGPACK; + } + else if (*data == '(') { + parse_type = UCL_PARSE_CSEXP; + } + else { + parse_type = UCL_PARSE_UCL; + } + } + chunk->begin = data; chunk->remain = len; chunk->pos = chunk->begin; @@ -2635,6 +2648,8 @@ ucl_parser_add_chunk_full (struct ucl_parser *parser, const unsigned char *data, return ucl_state_machine (parser); case UCL_PARSE_MSGPACK: return ucl_parse_msgpack (parser); + case UCL_PARSE_CSEXP: + return ucl_parse_csexp (parser); } } else { diff --git a/contrib/libucl/ucl_sexp.c b/contrib/libucl/ucl_sexp.c index 1ad93d234..c4ad75a18 100644 --- a/contrib/libucl/ucl_sexp.c +++ b/contrib/libucl/ucl_sexp.c @@ -26,7 +26,6 @@ #include "config.h" #endif -#include #include "ucl.h" #include "ucl_internal.h" #include "utlist.h"