diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-01-12 22:47:31 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-01-12 22:47:31 +0100 |
commit | 6e5ea8d2a995b32bbc5972edc4f827b959f2702f (patch) | |
tree | b1ad7d6a83f53220227122719d5eb97dd32ff1e6 /src/channel.c | |
parent | e3c74d249ac36404d8af25f74baf335d143b30e3 (diff) | |
download | vim-git-6e5ea8d2a995b32bbc5972edc4f827b959f2702f.tar.gz |
patch 8.1.0735: cannot handle binary datav8.1.0735
Problem: Cannot handle binary data.
Solution: Add the Blob type. (Yasuhiro Matsumoto, closes #3638)
Diffstat (limited to 'src/channel.c')
-rw-r--r-- | src/channel.c | 89 |
1 files changed, 66 insertions, 23 deletions
diff --git a/src/channel.c b/src/channel.c index 6f5bf2023..e9615279a 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1665,7 +1665,7 @@ channel_first_nl(readq_T *node) * Returns NULL if there is nothing. */ char_u * -channel_get(channel_T *channel, ch_part_T part) +channel_get(channel_T *channel, ch_part_T part, int *outlen) { readq_T *head = &channel->ch_part[part].ch_head; readq_T *node = head->rq_next; @@ -1673,6 +1673,8 @@ channel_get(channel_T *channel, ch_part_T part) if (node == NULL) return NULL; + if (outlen != NULL) + *outlen += node->rq_buflen; /* dispose of the node but keep the buffer */ p = node->rq_buffer; head->rq_next = node->rq_next; @@ -1689,7 +1691,7 @@ channel_get(channel_T *channel, ch_part_T part) * Replaces NUL bytes with NL. */ static char_u * -channel_get_all(channel_T *channel, ch_part_T part) +channel_get_all(channel_T *channel, ch_part_T part, int *outlen) { readq_T *head = &channel->ch_part[part].ch_head; readq_T *node = head->rq_next; @@ -1699,7 +1701,7 @@ channel_get_all(channel_T *channel, ch_part_T part) /* If there is only one buffer just get that one. */ if (head->rq_next == NULL || head->rq_next->rq_next == NULL) - return channel_get(channel, part); + return channel_get(channel, part, outlen); /* Concatenate everything into one buffer. */ for (node = head->rq_next; node != NULL; node = node->rq_next) @@ -1718,10 +1720,16 @@ channel_get_all(channel_T *channel, ch_part_T part) /* Free all buffers */ do { - p = channel_get(channel, part); + p = channel_get(channel, part, NULL); vim_free(p); } while (p != NULL); + if (outlen != NULL) + { + *outlen += len; + return res; + } + /* turn all NUL into NL */ while (len > 0) { @@ -1893,7 +1901,7 @@ channel_fill(js_read_T *reader) { channel_T *channel = (channel_T *)reader->js_cookie; ch_part_T part = reader->js_cookie_arg; - char_u *next = channel_get(channel, part); + char_u *next = channel_get(channel, part, NULL); int keeplen; int addlen; char_u *p; @@ -1942,7 +1950,7 @@ channel_parse_json(channel_T *channel, ch_part_T part) if (channel_peek(channel, part) == NULL) return FALSE; - reader.js_buf = channel_get(channel, part); + reader.js_buf = channel_get(channel, part, NULL); reader.js_used = 0; reader.js_fill = channel_fill; reader.js_cookie = channel; @@ -2475,7 +2483,7 @@ drop_messages(channel_T *channel, ch_part_T part) { char_u *msg; - while ((msg = channel_get(channel, part)) != NULL) + while ((msg = channel_get(channel, part, NULL)) != NULL) { ch_log(channel, "Dropping message '%s'", (char *)msg); vim_free(msg); @@ -2639,7 +2647,7 @@ may_invoke_callback(channel_T *channel, ch_part_T part) if (nl + 1 == buf + node->rq_buflen) { /* get the whole buffer, drop the NL */ - msg = channel_get(channel, part); + msg = channel_get(channel, part, NULL); *nl = NUL; } else @@ -2655,7 +2663,7 @@ may_invoke_callback(channel_T *channel, ch_part_T part) /* For a raw channel we don't know where the message ends, just * get everything we have. * Convert NUL to NL, the internal representation. */ - msg = channel_get_all(channel, part); + msg = channel_get_all(channel, part, NULL); } if (msg == NULL) @@ -3007,7 +3015,7 @@ channel_clear_one(channel_T *channel, ch_part_T part) cbq_T *cb_head = &ch_part->ch_cb_head; while (channel_peek(channel, part) != NULL) - vim_free(channel_get(channel, part)); + vim_free(channel_get(channel, part, NULL)); while (cb_head->cq_next != NULL) { @@ -3381,7 +3389,8 @@ channel_read(channel_T *channel, ch_part_T part, char *func) * Returns NULL in case of error or timeout. */ static char_u * -channel_read_block(channel_T *channel, ch_part_T part, int timeout, int raw) +channel_read_block( + channel_T *channel, ch_part_T part, int timeout, int raw, int *outlen) { char_u *buf; char_u *msg; @@ -3422,9 +3431,9 @@ channel_read_block(channel_T *channel, ch_part_T part, int timeout, int raw) } /* We have a complete message now. */ - if (mode == MODE_RAW) + if (mode == MODE_RAW || outlen != NULL) { - msg = channel_get_all(channel, part); + msg = channel_get_all(channel, part, outlen); } else { @@ -3441,12 +3450,12 @@ channel_read_block(channel_T *channel, ch_part_T part, int timeout, int raw) if (nl == NULL) { /* must be a closed channel with missing NL */ - msg = channel_get(channel, part); + msg = channel_get(channel, part, NULL); } else if (nl + 1 == buf + node->rq_buflen) { /* get the whole buffer */ - msg = channel_get(channel, part); + msg = channel_get(channel, part, NULL); *nl = NUL; } else @@ -3554,7 +3563,7 @@ channel_read_json_block( * Common for ch_read() and ch_readraw(). */ void -common_channel_read(typval_T *argvars, typval_T *rettv, int raw) +common_channel_read(typval_T *argvars, typval_T *rettv, int raw, int blob) { channel_T *channel; ch_part_T part = PART_COUNT; @@ -3585,9 +3594,32 @@ common_channel_read(typval_T *argvars, typval_T *rettv, int raw) if (opt.jo_set & JO_TIMEOUT) timeout = opt.jo_timeout; - if (raw || mode == MODE_RAW || mode == MODE_NL) + if (blob) + { + int outlen = 0; + char_u *p = channel_read_block(channel, part, + timeout, TRUE, &outlen); + if (p != NULL) + { + blob_T *b = blob_alloc(); + + if (b != NULL) + { + b->bv_ga.ga_len = outlen; + if (ga_grow(&b->bv_ga, outlen) == FAIL) + blob_free(b); + else + { + memcpy(b->bv_ga.ga_data, p, outlen); + rettv_blob_set(rettv, b); + } + } + vim_free(p); + } + } + else if (raw || mode == MODE_RAW || mode == MODE_NL) rettv->vval.v_string = channel_read_block(channel, part, - timeout, raw); + timeout, raw, NULL); else { if (opt.jo_set & JO_ID) @@ -3905,6 +3937,7 @@ channel_send( send_common( typval_T *argvars, char_u *text, + int len, int id, int eval, jobopt_T *opt, @@ -3938,7 +3971,7 @@ send_common( opt->jo_callback, opt->jo_partial, id); } - if (channel_send(channel, part_send, text, (int)STRLEN(text), fun) == OK + if (channel_send(channel, part_send, text, len, fun) == OK && opt->jo_callback == NULL) return channel; return NULL; @@ -3982,7 +4015,7 @@ ch_expr_common(typval_T *argvars, typval_T *rettv, int eval) if (text == NULL) return; - channel = send_common(argvars, text, id, eval, &opt, + channel = send_common(argvars, text, (int)STRLEN(text), id, eval, &opt, eval ? "ch_evalexpr" : "ch_sendexpr", &part_read); vim_free(text); if (channel != NULL && eval) @@ -4014,6 +4047,7 @@ ch_raw_common(typval_T *argvars, typval_T *rettv, int eval) { char_u buf[NUMBUFLEN]; char_u *text; + int len; channel_T *channel; ch_part_T part_read; jobopt_T opt; @@ -4023,8 +4057,17 @@ ch_raw_common(typval_T *argvars, typval_T *rettv, int eval) rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - text = tv_get_string_buf(&argvars[1], buf); - channel = send_common(argvars, text, 0, eval, &opt, + if (argvars[1].v_type == VAR_BLOB) + { + text = argvars[1].vval.v_blob->bv_ga.ga_data; + len = argvars[1].vval.v_blob->bv_ga.ga_len; + } + else + { + text = tv_get_string_buf(&argvars[1], buf); + len = STRLEN(text); + } + channel = send_common(argvars, text, len, 0, eval, &opt, eval ? "ch_evalraw" : "ch_sendraw", &part_read); if (channel != NULL && eval) { @@ -4033,7 +4076,7 @@ ch_raw_common(typval_T *argvars, typval_T *rettv, int eval) else timeout = channel_get_timeout(channel, part_read); rettv->vval.v_string = channel_read_block(channel, part_read, - timeout, TRUE); + timeout, TRUE, NULL); } free_job_options(&opt); } |