Mercurial > vim
comparison src/channel.c @ 15454:1d2b5c016f17 v8.1.0735
patch 8.1.0735: cannot handle binary data
commit https://github.com/vim/vim/commit/6e5ea8d2a995b32bbc5972edc4f827b959f2702f
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jan 12 22:47:31 2019 +0100
patch 8.1.0735: cannot handle binary data
Problem: Cannot handle binary data.
Solution: Add the Blob type. (Yasuhiro Matsumoto, closes https://github.com/vim/vim/issues/3638)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 12 Jan 2019 23:00:06 +0100 |
parents | c73f1fdfb27a |
children | 55ccc2d353bd |
comparison
equal
deleted
inserted
replaced
15453:cdee6e827112 | 15454:1d2b5c016f17 |
---|---|
1663 * Return the first buffer from channel "channel"/"part" and remove it. | 1663 * Return the first buffer from channel "channel"/"part" and remove it. |
1664 * The caller must free it. | 1664 * The caller must free it. |
1665 * Returns NULL if there is nothing. | 1665 * Returns NULL if there is nothing. |
1666 */ | 1666 */ |
1667 char_u * | 1667 char_u * |
1668 channel_get(channel_T *channel, ch_part_T part) | 1668 channel_get(channel_T *channel, ch_part_T part, int *outlen) |
1669 { | 1669 { |
1670 readq_T *head = &channel->ch_part[part].ch_head; | 1670 readq_T *head = &channel->ch_part[part].ch_head; |
1671 readq_T *node = head->rq_next; | 1671 readq_T *node = head->rq_next; |
1672 char_u *p; | 1672 char_u *p; |
1673 | 1673 |
1674 if (node == NULL) | 1674 if (node == NULL) |
1675 return NULL; | 1675 return NULL; |
1676 if (outlen != NULL) | |
1677 *outlen += node->rq_buflen; | |
1676 /* dispose of the node but keep the buffer */ | 1678 /* dispose of the node but keep the buffer */ |
1677 p = node->rq_buffer; | 1679 p = node->rq_buffer; |
1678 head->rq_next = node->rq_next; | 1680 head->rq_next = node->rq_next; |
1679 if (node->rq_next == NULL) | 1681 if (node->rq_next == NULL) |
1680 head->rq_prev = NULL; | 1682 head->rq_prev = NULL; |
1687 /* | 1689 /* |
1688 * Returns the whole buffer contents concatenated for "channel"/"part". | 1690 * Returns the whole buffer contents concatenated for "channel"/"part". |
1689 * Replaces NUL bytes with NL. | 1691 * Replaces NUL bytes with NL. |
1690 */ | 1692 */ |
1691 static char_u * | 1693 static char_u * |
1692 channel_get_all(channel_T *channel, ch_part_T part) | 1694 channel_get_all(channel_T *channel, ch_part_T part, int *outlen) |
1693 { | 1695 { |
1694 readq_T *head = &channel->ch_part[part].ch_head; | 1696 readq_T *head = &channel->ch_part[part].ch_head; |
1695 readq_T *node = head->rq_next; | 1697 readq_T *node = head->rq_next; |
1696 long_u len = 0; | 1698 long_u len = 0; |
1697 char_u *res; | 1699 char_u *res; |
1698 char_u *p; | 1700 char_u *p; |
1699 | 1701 |
1700 /* If there is only one buffer just get that one. */ | 1702 /* If there is only one buffer just get that one. */ |
1701 if (head->rq_next == NULL || head->rq_next->rq_next == NULL) | 1703 if (head->rq_next == NULL || head->rq_next->rq_next == NULL) |
1702 return channel_get(channel, part); | 1704 return channel_get(channel, part, outlen); |
1703 | 1705 |
1704 /* Concatenate everything into one buffer. */ | 1706 /* Concatenate everything into one buffer. */ |
1705 for (node = head->rq_next; node != NULL; node = node->rq_next) | 1707 for (node = head->rq_next; node != NULL; node = node->rq_next) |
1706 len += node->rq_buflen; | 1708 len += node->rq_buflen; |
1707 res = lalloc(len + 1, TRUE); | 1709 res = lalloc(len + 1, TRUE); |
1716 *p = NUL; | 1718 *p = NUL; |
1717 | 1719 |
1718 /* Free all buffers */ | 1720 /* Free all buffers */ |
1719 do | 1721 do |
1720 { | 1722 { |
1721 p = channel_get(channel, part); | 1723 p = channel_get(channel, part, NULL); |
1722 vim_free(p); | 1724 vim_free(p); |
1723 } while (p != NULL); | 1725 } while (p != NULL); |
1726 | |
1727 if (outlen != NULL) | |
1728 { | |
1729 *outlen += len; | |
1730 return res; | |
1731 } | |
1724 | 1732 |
1725 /* turn all NUL into NL */ | 1733 /* turn all NUL into NL */ |
1726 while (len > 0) | 1734 while (len > 0) |
1727 { | 1735 { |
1728 --len; | 1736 --len; |
1891 static int | 1899 static int |
1892 channel_fill(js_read_T *reader) | 1900 channel_fill(js_read_T *reader) |
1893 { | 1901 { |
1894 channel_T *channel = (channel_T *)reader->js_cookie; | 1902 channel_T *channel = (channel_T *)reader->js_cookie; |
1895 ch_part_T part = reader->js_cookie_arg; | 1903 ch_part_T part = reader->js_cookie_arg; |
1896 char_u *next = channel_get(channel, part); | 1904 char_u *next = channel_get(channel, part, NULL); |
1897 int keeplen; | 1905 int keeplen; |
1898 int addlen; | 1906 int addlen; |
1899 char_u *p; | 1907 char_u *p; |
1900 | 1908 |
1901 if (next == NULL) | 1909 if (next == NULL) |
1940 int ret; | 1948 int ret; |
1941 | 1949 |
1942 if (channel_peek(channel, part) == NULL) | 1950 if (channel_peek(channel, part) == NULL) |
1943 return FALSE; | 1951 return FALSE; |
1944 | 1952 |
1945 reader.js_buf = channel_get(channel, part); | 1953 reader.js_buf = channel_get(channel, part, NULL); |
1946 reader.js_used = 0; | 1954 reader.js_used = 0; |
1947 reader.js_fill = channel_fill; | 1955 reader.js_fill = channel_fill; |
1948 reader.js_cookie = channel; | 1956 reader.js_cookie = channel; |
1949 reader.js_cookie_arg = part; | 1957 reader.js_cookie_arg = part; |
1950 | 1958 |
2473 static void | 2481 static void |
2474 drop_messages(channel_T *channel, ch_part_T part) | 2482 drop_messages(channel_T *channel, ch_part_T part) |
2475 { | 2483 { |
2476 char_u *msg; | 2484 char_u *msg; |
2477 | 2485 |
2478 while ((msg = channel_get(channel, part)) != NULL) | 2486 while ((msg = channel_get(channel, part, NULL)) != NULL) |
2479 { | 2487 { |
2480 ch_log(channel, "Dropping message '%s'", (char *)msg); | 2488 ch_log(channel, "Dropping message '%s'", (char *)msg); |
2481 vim_free(msg); | 2489 vim_free(msg); |
2482 } | 2490 } |
2483 } | 2491 } |
2637 *p = NL; | 2645 *p = NL; |
2638 | 2646 |
2639 if (nl + 1 == buf + node->rq_buflen) | 2647 if (nl + 1 == buf + node->rq_buflen) |
2640 { | 2648 { |
2641 /* get the whole buffer, drop the NL */ | 2649 /* get the whole buffer, drop the NL */ |
2642 msg = channel_get(channel, part); | 2650 msg = channel_get(channel, part, NULL); |
2643 *nl = NUL; | 2651 *nl = NUL; |
2644 } | 2652 } |
2645 else | 2653 else |
2646 { | 2654 { |
2647 /* Copy the message into allocated memory (excluding the NL) | 2655 /* Copy the message into allocated memory (excluding the NL) |
2653 else | 2661 else |
2654 { | 2662 { |
2655 /* For a raw channel we don't know where the message ends, just | 2663 /* For a raw channel we don't know where the message ends, just |
2656 * get everything we have. | 2664 * get everything we have. |
2657 * Convert NUL to NL, the internal representation. */ | 2665 * Convert NUL to NL, the internal representation. */ |
2658 msg = channel_get_all(channel, part); | 2666 msg = channel_get_all(channel, part, NULL); |
2659 } | 2667 } |
2660 | 2668 |
2661 if (msg == NULL) | 2669 if (msg == NULL) |
2662 return FALSE; /* out of memory (and avoids Coverity warning) */ | 2670 return FALSE; /* out of memory (and avoids Coverity warning) */ |
2663 | 2671 |
3005 chanpart_T *ch_part = &channel->ch_part[part]; | 3013 chanpart_T *ch_part = &channel->ch_part[part]; |
3006 jsonq_T *json_head = &ch_part->ch_json_head; | 3014 jsonq_T *json_head = &ch_part->ch_json_head; |
3007 cbq_T *cb_head = &ch_part->ch_cb_head; | 3015 cbq_T *cb_head = &ch_part->ch_cb_head; |
3008 | 3016 |
3009 while (channel_peek(channel, part) != NULL) | 3017 while (channel_peek(channel, part) != NULL) |
3010 vim_free(channel_get(channel, part)); | 3018 vim_free(channel_get(channel, part, NULL)); |
3011 | 3019 |
3012 while (cb_head->cq_next != NULL) | 3020 while (cb_head->cq_next != NULL) |
3013 { | 3021 { |
3014 cbq_T *node = cb_head->cq_next; | 3022 cbq_T *node = cb_head->cq_next; |
3015 | 3023 |
3379 * When "raw" is TRUE don't block waiting on a NL. | 3387 * When "raw" is TRUE don't block waiting on a NL. |
3380 * Returns what was read in allocated memory. | 3388 * Returns what was read in allocated memory. |
3381 * Returns NULL in case of error or timeout. | 3389 * Returns NULL in case of error or timeout. |
3382 */ | 3390 */ |
3383 static char_u * | 3391 static char_u * |
3384 channel_read_block(channel_T *channel, ch_part_T part, int timeout, int raw) | 3392 channel_read_block( |
3393 channel_T *channel, ch_part_T part, int timeout, int raw, int *outlen) | |
3385 { | 3394 { |
3386 char_u *buf; | 3395 char_u *buf; |
3387 char_u *msg; | 3396 char_u *msg; |
3388 ch_mode_T mode = channel->ch_part[part].ch_mode; | 3397 ch_mode_T mode = channel->ch_part[part].ch_mode; |
3389 sock_T fd = channel->ch_part[part].ch_fd; | 3398 sock_T fd = channel->ch_part[part].ch_fd; |
3420 } | 3429 } |
3421 channel_read(channel, part, "channel_read_block"); | 3430 channel_read(channel, part, "channel_read_block"); |
3422 } | 3431 } |
3423 | 3432 |
3424 /* We have a complete message now. */ | 3433 /* We have a complete message now. */ |
3425 if (mode == MODE_RAW) | 3434 if (mode == MODE_RAW || outlen != NULL) |
3426 { | 3435 { |
3427 msg = channel_get_all(channel, part); | 3436 msg = channel_get_all(channel, part, outlen); |
3428 } | 3437 } |
3429 else | 3438 else |
3430 { | 3439 { |
3431 char_u *p; | 3440 char_u *p; |
3432 | 3441 |
3439 *p = NL; | 3448 *p = NL; |
3440 | 3449 |
3441 if (nl == NULL) | 3450 if (nl == NULL) |
3442 { | 3451 { |
3443 /* must be a closed channel with missing NL */ | 3452 /* must be a closed channel with missing NL */ |
3444 msg = channel_get(channel, part); | 3453 msg = channel_get(channel, part, NULL); |
3445 } | 3454 } |
3446 else if (nl + 1 == buf + node->rq_buflen) | 3455 else if (nl + 1 == buf + node->rq_buflen) |
3447 { | 3456 { |
3448 /* get the whole buffer */ | 3457 /* get the whole buffer */ |
3449 msg = channel_get(channel, part); | 3458 msg = channel_get(channel, part, NULL); |
3450 *nl = NUL; | 3459 *nl = NUL; |
3451 } | 3460 } |
3452 else | 3461 else |
3453 { | 3462 { |
3454 /* Copy the message into allocated memory and remove it from the | 3463 /* Copy the message into allocated memory and remove it from the |
3552 | 3561 |
3553 /* | 3562 /* |
3554 * Common for ch_read() and ch_readraw(). | 3563 * Common for ch_read() and ch_readraw(). |
3555 */ | 3564 */ |
3556 void | 3565 void |
3557 common_channel_read(typval_T *argvars, typval_T *rettv, int raw) | 3566 common_channel_read(typval_T *argvars, typval_T *rettv, int raw, int blob) |
3558 { | 3567 { |
3559 channel_T *channel; | 3568 channel_T *channel; |
3560 ch_part_T part = PART_COUNT; | 3569 ch_part_T part = PART_COUNT; |
3561 jobopt_T opt; | 3570 jobopt_T opt; |
3562 int mode; | 3571 int mode; |
3583 mode = channel_get_mode(channel, part); | 3592 mode = channel_get_mode(channel, part); |
3584 timeout = channel_get_timeout(channel, part); | 3593 timeout = channel_get_timeout(channel, part); |
3585 if (opt.jo_set & JO_TIMEOUT) | 3594 if (opt.jo_set & JO_TIMEOUT) |
3586 timeout = opt.jo_timeout; | 3595 timeout = opt.jo_timeout; |
3587 | 3596 |
3588 if (raw || mode == MODE_RAW || mode == MODE_NL) | 3597 if (blob) |
3598 { | |
3599 int outlen = 0; | |
3600 char_u *p = channel_read_block(channel, part, | |
3601 timeout, TRUE, &outlen); | |
3602 if (p != NULL) | |
3603 { | |
3604 blob_T *b = blob_alloc(); | |
3605 | |
3606 if (b != NULL) | |
3607 { | |
3608 b->bv_ga.ga_len = outlen; | |
3609 if (ga_grow(&b->bv_ga, outlen) == FAIL) | |
3610 blob_free(b); | |
3611 else | |
3612 { | |
3613 memcpy(b->bv_ga.ga_data, p, outlen); | |
3614 rettv_blob_set(rettv, b); | |
3615 } | |
3616 } | |
3617 vim_free(p); | |
3618 } | |
3619 } | |
3620 else if (raw || mode == MODE_RAW || mode == MODE_NL) | |
3589 rettv->vval.v_string = channel_read_block(channel, part, | 3621 rettv->vval.v_string = channel_read_block(channel, part, |
3590 timeout, raw); | 3622 timeout, raw, NULL); |
3591 else | 3623 else |
3592 { | 3624 { |
3593 if (opt.jo_set & JO_ID) | 3625 if (opt.jo_set & JO_ID) |
3594 id = opt.jo_id; | 3626 id = opt.jo_id; |
3595 channel_read_json_block(channel, part, timeout, id, &listtv); | 3627 channel_read_json_block(channel, part, timeout, id, &listtv); |
3903 */ | 3935 */ |
3904 static channel_T * | 3936 static channel_T * |
3905 send_common( | 3937 send_common( |
3906 typval_T *argvars, | 3938 typval_T *argvars, |
3907 char_u *text, | 3939 char_u *text, |
3940 int len, | |
3908 int id, | 3941 int id, |
3909 int eval, | 3942 int eval, |
3910 jobopt_T *opt, | 3943 jobopt_T *opt, |
3911 char *fun, | 3944 char *fun, |
3912 ch_part_T *part_read) | 3945 ch_part_T *part_read) |
3936 } | 3969 } |
3937 channel_set_req_callback(channel, *part_read, | 3970 channel_set_req_callback(channel, *part_read, |
3938 opt->jo_callback, opt->jo_partial, id); | 3971 opt->jo_callback, opt->jo_partial, id); |
3939 } | 3972 } |
3940 | 3973 |
3941 if (channel_send(channel, part_send, text, (int)STRLEN(text), fun) == OK | 3974 if (channel_send(channel, part_send, text, len, fun) == OK |
3942 && opt->jo_callback == NULL) | 3975 && opt->jo_callback == NULL) |
3943 return channel; | 3976 return channel; |
3944 return NULL; | 3977 return NULL; |
3945 } | 3978 } |
3946 | 3979 |
3980 text = json_encode_nr_expr(id, &argvars[1], | 4013 text = json_encode_nr_expr(id, &argvars[1], |
3981 (ch_mode == MODE_JS ? JSON_JS : 0) | JSON_NL); | 4014 (ch_mode == MODE_JS ? JSON_JS : 0) | JSON_NL); |
3982 if (text == NULL) | 4015 if (text == NULL) |
3983 return; | 4016 return; |
3984 | 4017 |
3985 channel = send_common(argvars, text, id, eval, &opt, | 4018 channel = send_common(argvars, text, (int)STRLEN(text), id, eval, &opt, |
3986 eval ? "ch_evalexpr" : "ch_sendexpr", &part_read); | 4019 eval ? "ch_evalexpr" : "ch_sendexpr", &part_read); |
3987 vim_free(text); | 4020 vim_free(text); |
3988 if (channel != NULL && eval) | 4021 if (channel != NULL && eval) |
3989 { | 4022 { |
3990 if (opt.jo_set & JO_TIMEOUT) | 4023 if (opt.jo_set & JO_TIMEOUT) |
4012 void | 4045 void |
4013 ch_raw_common(typval_T *argvars, typval_T *rettv, int eval) | 4046 ch_raw_common(typval_T *argvars, typval_T *rettv, int eval) |
4014 { | 4047 { |
4015 char_u buf[NUMBUFLEN]; | 4048 char_u buf[NUMBUFLEN]; |
4016 char_u *text; | 4049 char_u *text; |
4050 int len; | |
4017 channel_T *channel; | 4051 channel_T *channel; |
4018 ch_part_T part_read; | 4052 ch_part_T part_read; |
4019 jobopt_T opt; | 4053 jobopt_T opt; |
4020 int timeout; | 4054 int timeout; |
4021 | 4055 |
4022 /* return an empty string by default */ | 4056 /* return an empty string by default */ |
4023 rettv->v_type = VAR_STRING; | 4057 rettv->v_type = VAR_STRING; |
4024 rettv->vval.v_string = NULL; | 4058 rettv->vval.v_string = NULL; |
4025 | 4059 |
4026 text = tv_get_string_buf(&argvars[1], buf); | 4060 if (argvars[1].v_type == VAR_BLOB) |
4027 channel = send_common(argvars, text, 0, eval, &opt, | 4061 { |
4062 text = argvars[1].vval.v_blob->bv_ga.ga_data; | |
4063 len = argvars[1].vval.v_blob->bv_ga.ga_len; | |
4064 } | |
4065 else | |
4066 { | |
4067 text = tv_get_string_buf(&argvars[1], buf); | |
4068 len = STRLEN(text); | |
4069 } | |
4070 channel = send_common(argvars, text, len, 0, eval, &opt, | |
4028 eval ? "ch_evalraw" : "ch_sendraw", &part_read); | 4071 eval ? "ch_evalraw" : "ch_sendraw", &part_read); |
4029 if (channel != NULL && eval) | 4072 if (channel != NULL && eval) |
4030 { | 4073 { |
4031 if (opt.jo_set & JO_TIMEOUT) | 4074 if (opt.jo_set & JO_TIMEOUT) |
4032 timeout = opt.jo_timeout; | 4075 timeout = opt.jo_timeout; |
4033 else | 4076 else |
4034 timeout = channel_get_timeout(channel, part_read); | 4077 timeout = channel_get_timeout(channel, part_read); |
4035 rettv->vval.v_string = channel_read_block(channel, part_read, | 4078 rettv->vval.v_string = channel_read_block(channel, part_read, |
4036 timeout, TRUE); | 4079 timeout, TRUE, NULL); |
4037 } | 4080 } |
4038 free_job_options(&opt); | 4081 free_job_options(&opt); |
4039 } | 4082 } |
4040 | 4083 |
4041 # define KEEP_OPEN_TIME 20 /* msec */ | 4084 # define KEEP_OPEN_TIME 20 /* msec */ |