diff options
author | dundargoc <33953936+dundargoc@users.noreply.github.com> | 2021-09-18 18:34:23 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-18 09:34:23 -0700 |
commit | 51a98aa0c2fe3231a0ffc8a78189bc6fafd6abf6 (patch) | |
tree | b0a582d67883864eda3231bce45dc7c159cbe97f /src/nvim/eval/decode.c | |
parent | 6cad86fffdb91d3997a707ff6adb0b5991587b3e (diff) | |
download | rneovim-51a98aa0c2fe3231a0ffc8a78189bc6fafd6abf6.tar.gz rneovim-51a98aa0c2fe3231a0ffc8a78189bc6fafd6abf6.tar.bz2 rneovim-51a98aa0c2fe3231a0ffc8a78189bc6fafd6abf6.zip |
refactor: format #15702
Diffstat (limited to 'src/nvim/eval/decode.c')
-rw-r--r-- | src/nvim/eval/decode.c | 946 |
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; } |