aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval/decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/eval/decode.c')
-rw-r--r--src/nvim/eval/decode.c946
1 files changed, 455 insertions, 491 deletions
diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c
index 5c03f55621..c8734c9b9c 100644
--- a/src/nvim/eval/decode.c
+++ b/src/nvim/eval/decode.c
@@ -1,20 +1,19 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-#include <stddef.h>
-
#include <msgpack.h>
+#include <stddef.h>
-#include "nvim/eval/typval.h"
+#include "nvim/ascii.h"
+#include "nvim/charset.h" // vim_str2nr
#include "nvim/eval.h"
#include "nvim/eval/decode.h"
#include "nvim/eval/encode.h"
-#include "nvim/ascii.h"
-#include "nvim/macros.h"
-#include "nvim/message.h"
+#include "nvim/eval/typval.h"
#include "nvim/globals.h"
-#include "nvim/charset.h" // vim_str2nr
#include "nvim/lib/kvec.h"
+#include "nvim/macros.h"
+#include "nvim/message.h"
#include "nvim/vim.h" // OK, FAIL
/// Helper structure for container_struct
@@ -52,8 +51,7 @@ typedef kvec_t(ContainerStackItem) ContainerStack;
/// @param[out] rettv Location where created dictionary will be saved.
/// @param[in] type Type of the dictionary.
/// @param[in] val Value associated with the _VAL key.
-static inline void create_special_dict(typval_T *const rettv,
- const MessagePackType type,
+static inline void create_special_dict(typval_T *const rettv, const MessagePackType type,
typval_T val)
FUNC_ATTR_NONNULL_ALL
{
@@ -97,12 +95,9 @@ static inline void create_special_dict(typval_T *const rettv,
/// value when decoder is restarted, otherwise unused.
///
/// @return OK in case of success, FAIL in case of error.
-static inline int json_decoder_pop(ValuesStackItem obj,
- ValuesStack *const stack,
- ContainerStack *const container_stack,
- const char **const pp,
- bool *const next_map_special,
- bool *const didcomma,
+static inline int json_decoder_pop(ValuesStackItem obj, ValuesStack *const stack,
+ ContainerStack *const container_stack, const char **const pp,
+ bool *const next_map_special, bool *const didcomma,
bool *const didcolon)
FUNC_ATTR_NONNULL_ALL
{
@@ -114,9 +109,9 @@ static inline int json_decoder_pop(ValuesStackItem obj,
const char *val_location = *pp;
if (obj.val.v_type == last_container.container.v_type
// vval.v_list and vval.v_dict should have the same size and offset
- && ((void *) obj.val.vval.v_list
- == (void *) last_container.container.vval.v_list)) {
- (void) kv_pop(*container_stack);
+ && ((void *)obj.val.vval.v_list
+ == (void *)last_container.container.vval.v_list)) {
+ (void)kv_pop(*container_stack);
val_location = last_container.s;
last_container = kv_last(*container_stack);
}
@@ -142,8 +137,7 @@ static inline int json_decoder_pop(ValuesStackItem obj,
assert(!(key.is_special_string
|| key.val.vval.v_string == NULL
|| *key.val.vval.v_string == NUL));
- dictitem_T *const obj_di = tv_dict_item_alloc(
- (const char *)key.val.vval.v_string);
+ dictitem_T *const obj_di = tv_dict_item_alloc((const char *)key.val.vval.v_string);
tv_clear(&key.val);
if (tv_dict_add(last_container.container.vval.v_dict, obj_di)
== FAIL) {
@@ -179,9 +173,9 @@ static inline int json_decoder_pop(ValuesStackItem obj,
tv_clear(&obj.val);
// Restart
- (void) kv_pop(*container_stack);
+ (void)kv_pop(*container_stack);
ValuesStackItem last_container_val =
- kv_A(*stack, last_container.stack_index);
+ kv_A(*stack, last_container.stack_index);
while (kv_size(*stack) > last_container.stack_index) {
tv_clear(&(kv_pop(*stack).val));
}
@@ -197,7 +191,7 @@ static inline int json_decoder_pop(ValuesStackItem obj,
}
#define LENP(p, e) \
- ((int) ((e) - (p))), (p)
+ ((int)((e) - (p))), (p)
#define OBJ(obj_tv, is_sp_string, didcomma_, didcolon_) \
((ValuesStackItem) { \
.is_special_string = (is_sp_string), \
@@ -229,8 +223,7 @@ static inline int json_decoder_pop(ValuesStackItem obj,
///
/// @return [allocated] list which should contain key-value pairs. Return value
/// may be safely ignored.
-list_T *decode_create_map_special_dict(typval_T *const ret_tv,
- const ptrdiff_t len)
+list_T *decode_create_map_special_dict(typval_T *const ret_tv, const ptrdiff_t len)
FUNC_ATTR_NONNULL_ALL
{
list_T *const list = tv_list_alloc(len);
@@ -260,9 +253,8 @@ list_T *decode_create_map_special_dict(typval_T *const ret_tv,
/// will be freed.
///
/// @return Decoded string.
-typval_T decode_string(const char *const s, const size_t len,
- const TriState hasnul, const bool binary,
- const bool s_allocated)
+typval_T decode_string(const char *const s, const size_t len, const TriState hasnul,
+ const bool binary, const bool s_allocated)
FUNC_ATTR_WARN_UNUSED_RESULT
{
assert(s != NULL || len == 0);
@@ -280,10 +272,10 @@ typval_T decode_string(const char *const s, const size_t len,
tv_list_ref(list);
create_special_dict(&tv, kMPString,
((typval_T){
- .v_type = VAR_LIST,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_list = list },
- }));
+ .v_type = VAR_LIST,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_list = list },
+ }));
const int elw_ret = encode_list_write((void *)list, s, len);
if (s_allocated) {
xfree((void *)s);
@@ -299,7 +291,7 @@ typval_T decode_string(const char *const s, const size_t len,
.v_type = VAR_STRING,
.v_lock = VAR_UNLOCKED,
.vval = { .v_string = (char_u *)(
- (s == NULL || s_allocated) ? (char *)s : xmemdupz(s, len)) },
+ (s == NULL || s_allocated) ? (char *)s : xmemdupz(s, len)) },
};
}
}
@@ -323,11 +315,9 @@ typval_T decode_string(const char *const s, const size_t len,
///
/// @return OK in case of success, FAIL in case of error.
static inline int parse_json_string(const char *const buf, const size_t buf_len,
- const char **const pp,
- ValuesStack *const stack,
+ const char **const pp, ValuesStack *const stack,
ContainerStack *const container_stack,
- bool *const next_map_special,
- bool *const didcomma,
+ bool *const next_map_special, bool *const didcomma,
bool *const didcolon)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE
{
@@ -341,55 +331,52 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
p++;
if (p == e) {
emsgf(_("E474: Unfinished escape sequence: %.*s"),
- (int) buf_len, buf);
+ (int)buf_len, buf);
goto parse_json_string_fail;
}
switch (*p) {
- case 'u': {
- if (p + 4 >= e) {
- emsgf(_("E474: Unfinished unicode escape sequence: %.*s"),
- (int) buf_len, buf);
- goto parse_json_string_fail;
- } else if (!ascii_isxdigit(p[1])
- || !ascii_isxdigit(p[2])
- || !ascii_isxdigit(p[3])
- || !ascii_isxdigit(p[4])) {
- emsgf(_("E474: Expected four hex digits after \\u: %.*s"),
- LENP(p - 1, e));
- goto parse_json_string_fail;
- }
- // One UTF-8 character below U+10000 can take up to 3 bytes,
- // above up to 6, but they are encoded using two \u escapes.
- len += 3;
- p += 5;
- break;
- }
- case '\\':
- case '/':
- case '"':
- case 't':
- case 'b':
- case 'n':
- case 'r':
- case 'f': {
- len++;
- p++;
- break;
- }
- default: {
- emsgf(_("E474: Unknown escape sequence: %.*s"), LENP(p - 1, e));
+ case 'u':
+ if (p + 4 >= e) {
+ emsgf(_("E474: Unfinished unicode escape sequence: %.*s"),
+ (int)buf_len, buf);
+ goto parse_json_string_fail;
+ } else if (!ascii_isxdigit(p[1])
+ || !ascii_isxdigit(p[2])
+ || !ascii_isxdigit(p[3])
+ || !ascii_isxdigit(p[4])) {
+ emsgf(_("E474: Expected four hex digits after \\u: %.*s"),
+ LENP(p - 1, e));
goto parse_json_string_fail;
}
+ // One UTF-8 character below U+10000 can take up to 3 bytes,
+ // above up to 6, but they are encoded using two \u escapes.
+ len += 3;
+ p += 5;
+ break;
+ case '\\':
+ case '/':
+ case '"':
+ case 't':
+ case 'b':
+ case 'n':
+ case 'r':
+ case 'f':
+ len++;
+ p++;
+ break;
+ default:
+ emsgf(_("E474: Unknown escape sequence: %.*s"), LENP(p - 1, e));
+ goto parse_json_string_fail;
}
} else {
- uint8_t p_byte = (uint8_t) *p;
+ uint8_t p_byte = (uint8_t)*p;
// unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
if (p_byte < 0x20) {
emsgf(_("E474: ASCII control characters cannot be present "
"inside string: %.*s"), LENP(p, e));
goto parse_json_string_fail;
}
- const int ch = utf_ptr2char((char_u *) p);
+ const int ch = utf_ptr2char((char_u *)p);
// All characters above U+007F are encoded using two or more bytes
// and thus cannot possibly be equal to *p. But utf_ptr2char({0xFF,
// 0}) will return 0xFF, even though 0xFF cannot start any UTF-8
@@ -397,7 +384,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
//
// The only exception is U+00C3 which is represented as 0xC3 0x83.
if (ch >= 0x80 && p_byte == ch
- && !(ch == 0xC3 && p + 1 < e && (uint8_t) p[1] == 0x83)) {
+ && !(ch == 0xC3 && p + 1 < e && (uint8_t)p[1] == 0x83)) {
emsgf(_("E474: Only UTF-8 strings allowed: %.*s"), LENP(p, e));
goto parse_json_string_fail;
} else if (ch > 0x10FFFF) {
@@ -405,14 +392,14 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
"are allowed to appear unescaped: %.*s"), LENP(p, e));
goto parse_json_string_fail;
}
- const size_t ch_len = (size_t) utf_char2len(ch);
- assert(ch_len == (size_t) (ch ? utf_ptr2len((char_u *) p) : 1));
+ const size_t ch_len = (size_t)utf_char2len(ch);
+ assert(ch_len == (size_t)(ch ? utf_ptr2len((char_u *)p) : 1));
len += ch_len;
p += ch_len;
}
}
if (p == e || *p != '"') {
- emsgf(_("E474: Expected string end: %.*s"), (int) buf_len, buf);
+ emsgf(_("E474: Expected string end: %.*s"), (int)buf_len, buf);
goto parse_json_string_fail;
}
if (len == 0) {
@@ -429,7 +416,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
#define PUT_FST_IN_PAIR(fst_in_pair, str_end) \
do { \
if (fst_in_pair != 0) { \
- str_end += utf_char2bytes(fst_in_pair, (char_u *) str_end); \
+ str_end += utf_char2bytes(fst_in_pair, (char_u *)str_end); \
fst_in_pair = 0; \
} \
} while (0)
@@ -440,56 +427,55 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
if (*t == '\\') {
t++;
switch (*t) {
- case 'u': {
- const char ubuf[] = { t[1], t[2], t[3], t[4] };
- t += 4;
- uvarnumber_T ch;
- vim_str2nr((char_u *)ubuf, NULL, NULL,
- STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true);
- if (ch == 0) {
- hasnul = true;
- }
- if (SURROGATE_HI_START <= ch && ch <= SURROGATE_HI_END) {
- PUT_FST_IN_PAIR(fst_in_pair, str_end);
- fst_in_pair = (int) ch;
- } else if (SURROGATE_LO_START <= ch && ch <= SURROGATE_LO_END
- && fst_in_pair != 0) {
- const int full_char = (
- (int) (ch - SURROGATE_LO_START)
- + ((fst_in_pair - SURROGATE_HI_START) << 10)
- + SURROGATE_FIRST_CHAR);
- str_end += utf_char2bytes(full_char, (char_u *) str_end);
- fst_in_pair = 0;
- } else {
- PUT_FST_IN_PAIR(fst_in_pair, str_end);
- str_end += utf_char2bytes((int) ch, (char_u *) str_end);
- }
- break;
+ case 'u': {
+ const char ubuf[] = { t[1], t[2], t[3], t[4] };
+ t += 4;
+ uvarnumber_T ch;
+ vim_str2nr((char_u *)ubuf, NULL, NULL,
+ STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true);
+ if (ch == 0) {
+ hasnul = true;
}
- case '\\':
- case '/':
- case '"':
- case 't':
- case 'b':
- case 'n':
- case 'r':
- case 'f': {
- static const char escapes[] = {
- ['\\'] = '\\',
- ['/'] = '/',
- ['"'] = '"',
- ['t'] = TAB,
- ['b'] = BS,
- ['n'] = NL,
- ['r'] = CAR,
- ['f'] = FF,
- };
- *str_end++ = escapes[(int) *t];
- break;
- }
- default: {
- abort();
+ if (SURROGATE_HI_START <= ch && ch <= SURROGATE_HI_END) {
+ PUT_FST_IN_PAIR(fst_in_pair, str_end);
+ fst_in_pair = (int)ch;
+ } else if (SURROGATE_LO_START <= ch && ch <= SURROGATE_LO_END
+ && fst_in_pair != 0) {
+ const int full_char = (
+ (int)(ch - SURROGATE_LO_START)
+ + ((fst_in_pair - SURROGATE_HI_START) << 10)
+ + SURROGATE_FIRST_CHAR);
+ str_end += utf_char2bytes(full_char, (char_u *)str_end);
+ fst_in_pair = 0;
+ } else {
+ PUT_FST_IN_PAIR(fst_in_pair, str_end);
+ str_end += utf_char2bytes((int)ch, (char_u *)str_end);
}
+ break;
+ }
+ case '\\':
+ case '/':
+ case '"':
+ case 't':
+ case 'b':
+ case 'n':
+ case 'r':
+ case 'f': {
+ static const char escapes[] = {
+ ['\\'] = '\\',
+ ['/'] = '/',
+ ['"'] = '"',
+ ['t'] = TAB,
+ ['b'] = BS,
+ ['n'] = NL,
+ ['r'] = CAR,
+ ['f'] = FF,
+ };
+ *str_end++ = escapes[(int)*t];
+ break;
+ }
+ default:
+ abort();
}
} else {
*str_end++ = *t;
@@ -498,8 +484,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
PUT_FST_IN_PAIR(fst_in_pair, str_end);
#undef PUT_FST_IN_PAIR
*str_end = NUL;
- typval_T obj = decode_string(
- str, (size_t)(str_end - str), hasnul ? kTrue : kFalse, false, true);
+ typval_T obj = decode_string(str, (size_t)(str_end - str), hasnul ? kTrue : kFalse, false, true);
if (obj.v_type == VAR_UNKNOWN) {
goto parse_json_string_fail;
}
@@ -536,11 +521,9 @@ parse_json_string_ret:
///
/// @return OK in case of success, FAIL in case of error.
static inline int parse_json_number(const char *const buf, const size_t buf_len,
- const char **const pp,
- ValuesStack *const stack,
+ const char **const pp, ValuesStack *const stack,
ContainerStack *const container_stack,
- bool *const next_map_special,
- bool *const didcomma,
+ bool *const next_map_special, bool *const didcomma,
bool *const didcolon)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE
{
@@ -605,14 +588,14 @@ parse_json_number_check:
.v_type = VAR_NUMBER,
.v_lock = VAR_UNLOCKED,
};
- const size_t exp_num_len = (size_t) (p - s);
+ const size_t exp_num_len = (size_t)(p - s);
if (fracs || exps) {
// Convert floating-point number
const size_t num_len = string2float(s, &tv.vval.v_float);
if (exp_num_len != num_len) {
emsgf(_("E685: internal error: while converting number \"%.*s\" "
"to float string2float consumed %zu bytes in place of %zu"),
- (int) exp_num_len, s, num_len, exp_num_len);
+ (int)exp_num_len, s, num_len, exp_num_len);
}
tv.v_type = VAR_FLOAT;
} else {
@@ -623,7 +606,7 @@ parse_json_number_check:
if ((int)exp_num_len != num_len) {
emsgf(_("E685: internal error: while converting number \"%.*s\" "
"to integer vim_str2nr consumed %i bytes in place of %zu"),
- (int) exp_num_len, s, num_len, exp_num_len);
+ (int)exp_num_len, s, num_len, exp_num_len);
}
tv.vval.v_number = nr;
}
@@ -664,8 +647,7 @@ parse_json_number_ret:
/// @param[out] rettv Location where to save results.
///
/// @return OK in case of success, FAIL otherwise.
-int json_decode_string(const char *const buf, const size_t buf_len,
- typval_T *const rettv)
+int json_decode_string(const char *const buf, const size_t buf_len, typval_T *const rettv)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
const char *p = buf;
@@ -688,219 +670,212 @@ int json_decode_string(const char *const buf, const size_t buf_len,
json_decode_string_cycle_start:
assert(*p == '{' || next_map_special == false);
switch (*p) {
- case '}':
- case ']': {
- if (kv_size(container_stack) == 0) {
- emsgf(_("E474: No container to close: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- }
- ContainerStackItem last_container = kv_last(container_stack);
- if (*p == '}' && last_container.container.v_type != VAR_DICT) {
- emsgf(_("E474: Closing list with curly bracket: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- } else if (*p == ']' && last_container.container.v_type != VAR_LIST) {
- emsgf(_("E474: Closing dictionary with square bracket: %.*s"),
- LENP(p, e));
- goto json_decode_string_fail;
- } else if (didcomma) {
- emsgf(_("E474: Trailing comma: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- } else if (didcolon) {
- emsgf(_("E474: Expected value after colon: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- } else if (last_container.stack_index != kv_size(stack) - 1) {
- assert(last_container.stack_index < kv_size(stack) - 1);
- emsgf(_("E474: Expected value: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- }
- if (kv_size(stack) == 1) {
- p++;
- (void) kv_pop(container_stack);
- goto json_decode_string_after_cycle;
- } else {
- if (json_decoder_pop(kv_pop(stack), &stack, &container_stack, &p,
- &next_map_special, &didcomma, &didcolon)
- == FAIL) {
- goto json_decode_string_fail;
- }
- assert(!next_map_special);
- break;
- }
+ case '}':
+ case ']': {
+ if (kv_size(container_stack) == 0) {
+ emsgf(_("E474: No container to close: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
}
- case ',': {
- if (kv_size(container_stack) == 0) {
- emsgf(_("E474: Comma not inside container: %.*s"), LENP(p, e));
+ ContainerStackItem last_container = kv_last(container_stack);
+ if (*p == '}' && last_container.container.v_type != VAR_DICT) {
+ emsgf(_("E474: Closing list with curly bracket: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
+ } else if (*p == ']' && last_container.container.v_type != VAR_LIST) {
+ emsgf(_("E474: Closing dictionary with square bracket: %.*s"),
+ LENP(p, e));
+ goto json_decode_string_fail;
+ } else if (didcomma) {
+ emsgf(_("E474: Trailing comma: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
+ } else if (didcolon) {
+ emsgf(_("E474: Expected value after colon: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
+ } else if (last_container.stack_index != kv_size(stack) - 1) {
+ assert(last_container.stack_index < kv_size(stack) - 1);
+ emsgf(_("E474: Expected value: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
+ }
+ if (kv_size(stack) == 1) {
+ p++;
+ (void)kv_pop(container_stack);
+ goto json_decode_string_after_cycle;
+ } else {
+ if (json_decoder_pop(kv_pop(stack), &stack, &container_stack, &p,
+ &next_map_special, &didcomma, &didcolon)
+ == FAIL) {
goto json_decode_string_fail;
}
- ContainerStackItem last_container = kv_last(container_stack);
- if (didcomma) {
- emsgf(_("E474: Duplicate comma: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- } else if (didcolon) {
- emsgf(_("E474: Comma after colon: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- } else if (last_container.container.v_type == VAR_DICT
- && last_container.stack_index != kv_size(stack) - 1) {
- emsgf(_("E474: Using comma in place of colon: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- } else if (last_container.special_val == NULL
+ assert(!next_map_special);
+ break;
+ }
+ }
+ case ',': {
+ if (kv_size(container_stack) == 0) {
+ emsgf(_("E474: Comma not inside container: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
+ }
+ ContainerStackItem last_container = kv_last(container_stack);
+ if (didcomma) {
+ emsgf(_("E474: Duplicate comma: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
+ } else if (didcolon) {
+ emsgf(_("E474: Comma after colon: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
+ } else if (last_container.container.v_type == VAR_DICT
+ && last_container.stack_index != kv_size(stack) - 1) {
+ emsgf(_("E474: Using comma in place of colon: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
+ } else if (last_container.special_val == NULL
? (last_container.container.v_type == VAR_DICT
? (DICT_LEN(last_container.container.vval.v_dict) == 0)
: (tv_list_len(last_container.container.vval.v_list)
== 0))
- : (tv_list_len(last_container.special_val) == 0)) {
- emsgf(_("E474: Leading comma: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- }
- didcomma = true;
- continue;
+ : (tv_list_len(last_container.special_val) == 0)) {
+ emsgf(_("E474: Leading comma: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
}
- case ':': {
- if (kv_size(container_stack) == 0) {
- emsgf(_("E474: Colon not inside container: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- }
- ContainerStackItem last_container = kv_last(container_stack);
- if (last_container.container.v_type != VAR_DICT) {
- emsgf(_("E474: Using colon not in dictionary: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- } else if (last_container.stack_index != kv_size(stack) - 2) {
- emsgf(_("E474: Unexpected colon: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- } else if (didcomma) {
- emsgf(_("E474: Colon after comma: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- } else if (didcolon) {
- emsgf(_("E474: Duplicate colon: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- }
- didcolon = true;
- continue;
+ didcomma = true;
+ continue;
+ }
+ case ':': {
+ if (kv_size(container_stack) == 0) {
+ emsgf(_("E474: Colon not inside container: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
}
- case ' ':
- case TAB:
- case NL:
- case CAR: {
- continue;
+ ContainerStackItem last_container = kv_last(container_stack);
+ if (last_container.container.v_type != VAR_DICT) {
+ emsgf(_("E474: Using colon not in dictionary: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
+ } else if (last_container.stack_index != kv_size(stack) - 2) {
+ emsgf(_("E474: Unexpected colon: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
+ } else if (didcomma) {
+ emsgf(_("E474: Colon after comma: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
+ } else if (didcolon) {
+ emsgf(_("E474: Duplicate colon: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
}
- case 'n': {
- if ((p + 3) >= e || strncmp(p + 1, "ull", 3) != 0) {
- emsgf(_("E474: Expected null: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- }
- p += 3;
- POP(((typval_T) {
- .v_type = VAR_SPECIAL,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_special = kSpecialVarNull },
- }), false);
- break;
+ didcolon = true;
+ continue;
+ }
+ case ' ':
+ case TAB:
+ case NL:
+ case CAR:
+ continue;
+ case 'n':
+ if ((p + 3) >= e || strncmp(p + 1, "ull", 3) != 0) {
+ emsgf(_("E474: Expected null: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
}
- case 't': {
- if ((p + 3) >= e || strncmp(p + 1, "rue", 3) != 0) {
- emsgf(_("E474: Expected true: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- }
- p += 3;
- POP(((typval_T) {
- .v_type = VAR_BOOL,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_bool = kBoolVarTrue },
- }), false);
- break;
+ p += 3;
+ POP(((typval_T) {
+ .v_type = VAR_SPECIAL,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_special = kSpecialVarNull },
+ }), false);
+ break;
+ case 't':
+ if ((p + 3) >= e || strncmp(p + 1, "rue", 3) != 0) {
+ emsgf(_("E474: Expected true: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
}
- case 'f': {
- if ((p + 4) >= e || strncmp(p + 1, "alse", 4) != 0) {
- emsgf(_("E474: Expected false: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- }
- p += 4;
- POP(((typval_T) {
- .v_type = VAR_BOOL,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_bool = kBoolVarFalse },
- }), false);
- break;
+ p += 3;
+ POP(((typval_T) {
+ .v_type = VAR_BOOL,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_bool = kBoolVarTrue },
+ }), false);
+ break;
+ case 'f':
+ if ((p + 4) >= e || strncmp(p + 1, "alse", 4) != 0) {
+ emsgf(_("E474: Expected false: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
}
- case '"': {
- if (parse_json_string(buf, buf_len, &p, &stack, &container_stack,
- &next_map_special, &didcomma, &didcolon)
- == FAIL) {
- // Error message was already given
- goto json_decode_string_fail;
- }
- if (next_map_special) {
- goto json_decode_string_cycle_start;
- }
- break;
+ p += 4;
+ POP(((typval_T) {
+ .v_type = VAR_BOOL,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_bool = kBoolVarFalse },
+ }), false);
+ break;
+ case '"':
+ if (parse_json_string(buf, buf_len, &p, &stack, &container_stack,
+ &next_map_special, &didcomma, &didcolon)
+ == FAIL) {
+ // Error message was already given
+ goto json_decode_string_fail;
}
- case '-':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': {
- if (parse_json_number(buf, buf_len, &p, &stack, &container_stack,
- &next_map_special, &didcomma, &didcolon)
- == FAIL) {
- // Error message was already given
- goto json_decode_string_fail;
- }
- if (next_map_special) {
- goto json_decode_string_cycle_start;
- }
- break;
+ if (next_map_special) {
+ goto json_decode_string_cycle_start;
}
- case '[': {
- list_T *list = tv_list_alloc(kListLenMayKnow);
- tv_list_ref(list);
- typval_T tv = {
- .v_type = VAR_LIST,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_list = list },
- };
- kv_push(container_stack, ((ContainerStackItem) {
+ break;
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (parse_json_number(buf, buf_len, &p, &stack, &container_stack,
+ &next_map_special, &didcomma, &didcolon)
+ == FAIL) {
+ // Error message was already given
+ goto json_decode_string_fail;
+ }
+ if (next_map_special) {
+ goto json_decode_string_cycle_start;
+ }
+ break;
+ case '[': {
+ list_T *list = tv_list_alloc(kListLenMayKnow);
+ tv_list_ref(list);
+ typval_T tv = {
+ .v_type = VAR_LIST,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_list = list },
+ };
+ kv_push(container_stack, ((ContainerStackItem) {
.stack_index = kv_size(stack),
.s = p,
.container = tv,
.special_val = NULL,
}));
- kv_push(stack, OBJ(tv, false, didcomma, didcolon));
- break;
+ kv_push(stack, OBJ(tv, false, didcomma, didcolon));
+ break;
+ }
+ case '{': {
+ typval_T tv;
+ list_T *val_list = NULL;
+ if (next_map_special) {
+ next_map_special = false;
+ val_list = decode_create_map_special_dict(&tv, kListLenMayKnow);
+ } else {
+ dict_T *dict = tv_dict_alloc();
+ dict->dv_refcount++;
+ tv = (typval_T) {
+ .v_type = VAR_DICT,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_dict = dict },
+ };
}
- case '{': {
- typval_T tv;
- list_T *val_list = NULL;
- if (next_map_special) {
- next_map_special = false;
- val_list = decode_create_map_special_dict(&tv, kListLenMayKnow);
- } else {
- dict_T *dict = tv_dict_alloc();
- dict->dv_refcount++;
- tv = (typval_T) {
- .v_type = VAR_DICT,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_dict = dict },
- };
- }
- kv_push(container_stack, ((ContainerStackItem) {
+ kv_push(container_stack, ((ContainerStackItem) {
.stack_index = kv_size(stack),
.s = p,
.container = tv,
.special_val = val_list,
}));
- kv_push(stack, OBJ(tv, false, didcomma, didcolon));
- break;
- }
- default: {
- emsgf(_("E474: Unidentified byte: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- }
+ kv_push(stack, OBJ(tv, false, didcomma, didcolon));
+ break;
+ }
+ default:
+ emsgf(_("E474: Unidentified byte: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
}
didcomma = false;
didcolon = false;
@@ -912,23 +887,21 @@ json_decode_string_cycle_start:
json_decode_string_after_cycle:
for (; p < e; p++) {
switch (*p) {
- case NL:
- case ' ':
- case TAB:
- case CAR: {
- break;
- }
- default: {
- emsgf(_("E474: Trailing characters: %.*s"), LENP(p, e));
- goto json_decode_string_fail;
- }
+ case NL:
+ case ' ':
+ case TAB:
+ case CAR:
+ break;
+ default:
+ emsgf(_("E474: Trailing characters: %.*s"), LENP(p, e));
+ goto json_decode_string_fail;
}
}
if (kv_size(stack) == 1 && kv_size(container_stack) == 0) {
*rettv = kv_pop(stack).val;
goto json_decode_string_ret;
}
- emsgf(_("E474: Unexpected end of input: %.*s"), (int) buf_len, buf);
+ emsgf(_("E474: Unexpected end of input: %.*s"), (int)buf_len, buf);
json_decode_string_fail:
ret = FAIL;
while (kv_size(stack)) {
@@ -952,192 +925,183 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
switch (mobj.type) {
- case MSGPACK_OBJECT_NIL: {
+ case MSGPACK_OBJECT_NIL:
+ *rettv = (typval_T) {
+ .v_type = VAR_SPECIAL,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_special = kSpecialVarNull },
+ };
+ break;
+ case MSGPACK_OBJECT_BOOLEAN:
+ *rettv = (typval_T) {
+ .v_type = VAR_BOOL,
+ .v_lock = VAR_UNLOCKED,
+ .vval = {
+ .v_bool = mobj.via.boolean ? kBoolVarTrue : kBoolVarFalse
+ },
+ };
+ break;
+ case MSGPACK_OBJECT_POSITIVE_INTEGER:
+ if (mobj.via.u64 <= VARNUMBER_MAX) {
*rettv = (typval_T) {
- .v_type = VAR_SPECIAL,
+ .v_type = VAR_NUMBER,
.v_lock = VAR_UNLOCKED,
- .vval = { .v_special = kSpecialVarNull },
+ .vval = { .v_number = (varnumber_T)mobj.via.u64 },
};
- break;
+ } else {
+ list_T *const list = tv_list_alloc(4);
+ tv_list_ref(list);
+ create_special_dict(rettv, kMPInteger, ((typval_T) {
+ .v_type = VAR_LIST,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_list = list },
+ }));
+ uint64_t n = mobj.via.u64;
+ tv_list_append_number(list, 1);
+ tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3));
+ tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF));
+ tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF));
}
- case MSGPACK_OBJECT_BOOLEAN: {
+ break;
+ case MSGPACK_OBJECT_NEGATIVE_INTEGER:
+ if (mobj.via.i64 >= VARNUMBER_MIN) { // -V547
*rettv = (typval_T) {
- .v_type = VAR_BOOL,
+ .v_type = VAR_NUMBER,
.v_lock = VAR_UNLOCKED,
- .vval = {
- .v_bool = mobj.via.boolean ? kBoolVarTrue : kBoolVarFalse
- },
+ .vval = { .v_number = (varnumber_T)mobj.via.i64 },
};
- break;
- }
- case MSGPACK_OBJECT_POSITIVE_INTEGER: {
- if (mobj.via.u64 <= VARNUMBER_MAX) {
- *rettv = (typval_T) {
- .v_type = VAR_NUMBER,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_number = (varnumber_T) mobj.via.u64 },
- };
- } else {
- list_T *const list = tv_list_alloc(4);
- tv_list_ref(list);
- create_special_dict(rettv, kMPInteger, ((typval_T) {
- .v_type = VAR_LIST,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_list = list },
- }));
- uint64_t n = mobj.via.u64;
- tv_list_append_number(list, 1);
- tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3));
- tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF));
- tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF));
- }
- break;
- }
- case MSGPACK_OBJECT_NEGATIVE_INTEGER: {
- if (mobj.via.i64 >= VARNUMBER_MIN) { // -V547
- *rettv = (typval_T) {
- .v_type = VAR_NUMBER,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_number = (varnumber_T) mobj.via.i64 },
- };
- } else {
- list_T *const list = tv_list_alloc(4);
- tv_list_ref(list);
- create_special_dict(rettv, kMPInteger, ((typval_T) {
- .v_type = VAR_LIST,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_list = list },
- }));
- uint64_t n = -((uint64_t)mobj.via.i64);
- tv_list_append_number(list, -1);
- tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3));
- tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF));
- tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF));
- }
- break;
+ } else {
+ list_T *const list = tv_list_alloc(4);
+ tv_list_ref(list);
+ create_special_dict(rettv, kMPInteger, ((typval_T) {
+ .v_type = VAR_LIST,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_list = list },
+ }));
+ uint64_t n = -((uint64_t)mobj.via.i64);
+ tv_list_append_number(list, -1);
+ tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3));
+ tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF));
+ tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF));
}
+ break;
#ifdef NVIM_MSGPACK_HAS_FLOAT32
- case MSGPACK_OBJECT_FLOAT32:
- case MSGPACK_OBJECT_FLOAT64:
+ case MSGPACK_OBJECT_FLOAT32:
+ case MSGPACK_OBJECT_FLOAT64:
#else
- case MSGPACK_OBJECT_FLOAT:
+ case MSGPACK_OBJECT_FLOAT:
#endif
- {
- *rettv = (typval_T) {
- .v_type = VAR_FLOAT,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_float = mobj.via.f64 },
- };
- break;
+ *rettv = (typval_T) {
+ .v_type = VAR_FLOAT,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_float = mobj.via.f64 },
+ };
+ break;
+ case MSGPACK_OBJECT_STR:
+ *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kTrue, false,
+ false);
+ if (rettv->v_type == VAR_UNKNOWN) {
+ return FAIL;
}
- case MSGPACK_OBJECT_STR: {
- *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kTrue, false,
- false);
- if (rettv->v_type == VAR_UNKNOWN) {
- return FAIL;
- }
- break;
+ break;
+ case MSGPACK_OBJECT_BIN:
+ *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kNone, true,
+ false);
+ if (rettv->v_type == VAR_UNKNOWN) {
+ return FAIL;
}
- case MSGPACK_OBJECT_BIN: {
- *rettv = decode_string(mobj.via.bin.ptr, mobj.via.bin.size, kNone, true,
- false);
- if (rettv->v_type == VAR_UNKNOWN) {
+ break;
+ case MSGPACK_OBJECT_ARRAY: {
+ list_T *const list = tv_list_alloc((ptrdiff_t)mobj.via.array.size);
+ tv_list_ref(list);
+ *rettv = (typval_T) {
+ .v_type = VAR_LIST,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_list = list },
+ };
+ for (size_t i = 0; i < mobj.via.array.size; i++) {
+ // Not populated yet, need to create list item to push.
+ tv_list_append_owned_tv(list, (typval_T) { .v_type = VAR_UNKNOWN });
+ if (msgpack_to_vim(mobj.via.array.ptr[i],
+ TV_LIST_ITEM_TV(tv_list_last(list)))
+ == FAIL) {
return FAIL;
}
- break;
}
- case MSGPACK_OBJECT_ARRAY: {
- list_T *const list = tv_list_alloc((ptrdiff_t)mobj.via.array.size);
- tv_list_ref(list);
- *rettv = (typval_T) {
- .v_type = VAR_LIST,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_list = list },
- };
- for (size_t i = 0; i < mobj.via.array.size; i++) {
- // Not populated yet, need to create list item to push.
- tv_list_append_owned_tv(list, (typval_T) { .v_type = VAR_UNKNOWN });
- if (msgpack_to_vim(mobj.via.array.ptr[i],
- TV_LIST_ITEM_TV(tv_list_last(list)))
- == FAIL) {
- return FAIL;
- }
+ break;
+ }
+ case MSGPACK_OBJECT_MAP: {
+ for (size_t i = 0; i < mobj.via.map.size; i++) {
+ if (mobj.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR
+ || mobj.via.map.ptr[i].key.via.str.size == 0
+ || memchr(mobj.via.map.ptr[i].key.via.str.ptr, NUL,
+ mobj.via.map.ptr[i].key.via.str.size) != NULL) {
+ goto msgpack_to_vim_generic_map;
}
- break;
}
- case MSGPACK_OBJECT_MAP: {
- for (size_t i = 0; i < mobj.via.map.size; i++) {
- if (mobj.via.map.ptr[i].key.type != MSGPACK_OBJECT_STR
- || mobj.via.map.ptr[i].key.via.str.size == 0
- || memchr(mobj.via.map.ptr[i].key.via.str.ptr, NUL,
- mobj.via.map.ptr[i].key.via.str.size) != NULL) {
- goto msgpack_to_vim_generic_map;
- }
+ dict_T *const dict = tv_dict_alloc();
+ dict->dv_refcount++;
+ *rettv = (typval_T) {
+ .v_type = VAR_DICT,
+ .v_lock = VAR_UNLOCKED,
+ .vval = { .v_dict = dict },
+ };
+ for (size_t i = 0; i < mobj.via.map.size; i++) {
+ dictitem_T *const di = xmallocz(offsetof(dictitem_T, di_key)
+ + mobj.via.map.ptr[i].key.via.str.size);
+ memcpy(&di->di_key[0], mobj.via.map.ptr[i].key.via.str.ptr,
+ mobj.via.map.ptr[i].key.via.str.size);
+ di->di_tv.v_type = VAR_UNKNOWN;
+ if (tv_dict_add(dict, di) == FAIL) {
+ // Duplicate key: fallback to generic map
+ tv_clear(rettv);
+ xfree(di);
+ goto msgpack_to_vim_generic_map;
}
- dict_T *const dict = tv_dict_alloc();
- dict->dv_refcount++;
- *rettv = (typval_T) {
- .v_type = VAR_DICT,
- .v_lock = VAR_UNLOCKED,
- .vval = { .v_dict = dict },
- };
- for (size_t i = 0; i < mobj.via.map.size; i++) {
- dictitem_T *const di = xmallocz(offsetof(dictitem_T, di_key)
- + mobj.via.map.ptr[i].key.via.str.size);
- memcpy(&di->di_key[0], mobj.via.map.ptr[i].key.via.str.ptr,
- mobj.via.map.ptr[i].key.via.str.size);
- di->di_tv.v_type = VAR_UNKNOWN;
- if (tv_dict_add(dict, di) == FAIL) {
- // Duplicate key: fallback to generic map
- tv_clear(rettv);
- xfree(di);
- goto msgpack_to_vim_generic_map;
- }
- if (msgpack_to_vim(mobj.via.map.ptr[i].val, &di->di_tv) == FAIL) {
- return FAIL;
- }
+ if (msgpack_to_vim(mobj.via.map.ptr[i].val, &di->di_tv) == FAIL) {
+ return FAIL;
}
- break;
+ }
+ break;
msgpack_to_vim_generic_map: {}
- list_T *const list = decode_create_map_special_dict(
- rettv, (ptrdiff_t)mobj.via.map.size);
- for (size_t i = 0; i < mobj.via.map.size; i++) {
- list_T *const kv_pair = tv_list_alloc(2);
- tv_list_append_list(list, kv_pair);
+ list_T *const list = decode_create_map_special_dict(rettv, (ptrdiff_t)mobj.via.map.size);
+ for (size_t i = 0; i < mobj.via.map.size; i++) {
+ list_T *const kv_pair = tv_list_alloc(2);
+ tv_list_append_list(list, kv_pair);
- typval_T key_tv = { .v_type = VAR_UNKNOWN };
- if (msgpack_to_vim(mobj.via.map.ptr[i].key, &key_tv) == FAIL) {
- tv_clear(&key_tv);
- return FAIL;
- }
- tv_list_append_owned_tv(kv_pair, key_tv);
+ typval_T key_tv = { .v_type = VAR_UNKNOWN };
+ if (msgpack_to_vim(mobj.via.map.ptr[i].key, &key_tv) == FAIL) {
+ tv_clear(&key_tv);
+ return FAIL;
+ }
+ tv_list_append_owned_tv(kv_pair, key_tv);
- typval_T val_tv = { .v_type = VAR_UNKNOWN };
- if (msgpack_to_vim(mobj.via.map.ptr[i].val, &val_tv) == FAIL) {
- tv_clear(&val_tv);
- return FAIL;
- }
- tv_list_append_owned_tv(kv_pair, val_tv);
+ typval_T val_tv = { .v_type = VAR_UNKNOWN };
+ if (msgpack_to_vim(mobj.via.map.ptr[i].val, &val_tv) == FAIL) {
+ tv_clear(&val_tv);
+ return FAIL;
}
- break;
+ tv_list_append_owned_tv(kv_pair, val_tv);
}
- case MSGPACK_OBJECT_EXT: {
- list_T *const list = tv_list_alloc(2);
- tv_list_ref(list);
- tv_list_append_number(list, mobj.via.ext.type);
- list_T *const ext_val_list = tv_list_alloc(kListLenMayKnow);
- tv_list_append_list(list, ext_val_list);
- create_special_dict(rettv, kMPExt, ((typval_T) {
+ break;
+ }
+ case MSGPACK_OBJECT_EXT: {
+ list_T *const list = tv_list_alloc(2);
+ tv_list_ref(list);
+ tv_list_append_number(list, mobj.via.ext.type);
+ list_T *const ext_val_list = tv_list_alloc(kListLenMayKnow);
+ tv_list_append_list(list, ext_val_list);
+ create_special_dict(rettv, kMPExt, ((typval_T) {
.v_type = VAR_LIST,
.v_lock = VAR_UNLOCKED,
.vval = { .v_list = list },
}));
- if (encode_list_write((void *) ext_val_list, mobj.via.ext.ptr,
- mobj.via.ext.size) == -1) {
- return FAIL;
- }
- break;
+ if (encode_list_write((void *)ext_val_list, mobj.via.ext.ptr,
+ mobj.via.ext.size) == -1) {
+ return FAIL;
}
+ break;
+ }
}
return OK;
}