diff --git a/docs/README.md b/docs/README.md index 7af02166..419d2e73 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2657,7 +2657,7 @@ mg_snprintf(buf, sizeof(buf), "r: %M, %d", f,1,2,7); // r: 3, 7 size_t f(void (*out)(char, void *), void *ptr, va_list *ap) { int a = va_arg(*ap, int); int b = va_arg(*ap, int); - return mg_rprintf(out, ptr, "%d", a + b); + return mg_xprintf(out, ptr, "%d", a + b); } ``` @@ -2685,8 +2685,8 @@ free(msg); ### mg\_rprintf(), mg\_vrprintf() ```c -size_t mg_rprintf(void (*out)(char, void *), void *param, const char *fmt, ...); -size_t mg_vrprintf(void (*out)(char, void *), void *param, const char *fmt, +size_t mg_xprintf(void (*out)(char, void *), void *param, const char *fmt, ...); +size_t mg_vxprintf(void (*out)(char, void *), void *param, const char *fmt, va_list *ap); ``` @@ -2704,7 +2704,7 @@ Usage example: ```c void myfn(char c, void *p); -size_t len = mg_rprintf(myfn, myfn_p, "Double quoted string: %Q!", "hi"); +size_t len = mg_xprintf(myfn, myfn_p, "Double quoted string: %Q!", "hi"); ``` ### mg\_pfn\_iobuf() @@ -2722,7 +2722,7 @@ Parameters: Usage example: ```c -mg_rprintf(mg_pfn_iobuf, &c->send, "hi!"); // Append to the output buffer +mg_xprintf(mg_pfn_iobuf, &c->send, "hi!"); // Append to the output buffer ``` ### mg\_to64() diff --git a/examples/huge-response/main.c b/examples/huge-response/main.c index 66313a26..69e0b0cc 100644 --- a/examples/huge-response/main.c +++ b/examples/huge-response/main.c @@ -34,7 +34,7 @@ static size_t printdata(mg_pfn_t out, void *ptr, va_list *ap) { size_t n = 0; if (max > DATA_SIZE) max = DATA_SIZE; while (start < max) { - n += mg_rprintf(out, ptr, "%s%d", comma, s_data[start]); + n += mg_xprintf(out, ptr, "%s%d", comma, s_data[start]); comma = ","; start++; } diff --git a/examples/webui-preact/main.c b/examples/webui-preact/main.c deleted file mode 120000 index 5f0bdc78..00000000 --- a/examples/webui-preact/main.c +++ /dev/null @@ -1 +0,0 @@ -../webui-plain/main.c \ No newline at end of file diff --git a/examples/webui-preact/main.c b/examples/webui-preact/main.c new file mode 100644 index 00000000..a80cf330 --- /dev/null +++ b/examples/webui-preact/main.c @@ -0,0 +1,63 @@ +// Copyright (c) 2022 Cesanta Software Limited +// All rights reserved +// +// UI example +// It implements the following endpoints: +// /api/config/get - respond with current config +// /api/config/set - POST a config change +// any other URI serves static files from s_root_dir +// Data and results are JSON strings + +#include "mongoose.h" + +static const char *s_http_addr = "http://localhost:8000"; // HTTP port +static const char *s_root_dir = "web_root"; +#define MQTT_SERVER "mqtt://broker.hivemq.com:1883" +#define MQTT_PUBLISH_TOPIC "mg/my_device" +#define MQTT_SUBSCRIBE_TOPIC "mg/#" + +static struct config { char *url, *pub, *sub; } s_config; + +// Try to update a single configuration value +static void update_config(struct mg_str json, const char *path, char **value) { + char *jval; + if ((jval = mg_json_get_str(json, path)) != NULL) { + free(*value); + *value = strdup(jval); + } +} + +static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { + if (ev == MG_EV_OPEN && c->is_listening) { + s_config.url = strdup(MQTT_SERVER); + s_config.pub = strdup(MQTT_PUBLISH_TOPIC); + s_config.sub = strdup(MQTT_SUBSCRIBE_TOPIC); + } else if (ev == MG_EV_HTTP_MSG) { + struct mg_http_message *hm = (struct mg_http_message *) ev_data; + if (mg_http_match_uri(hm, "/api/config/get")) { + mg_http_reply(c, 200, "Content-Type: application/json\r\n", + "{%Q:%Q,%Q:%Q,%Q:%Q}\n", "url", s_config.url, "pub", + s_config.pub, "sub", s_config.sub); + } else if (mg_http_match_uri(hm, "/api/config/set")) { + struct mg_str json = hm->body; + update_config(json, "$.url", &s_config.url); + update_config(json, "$.pub", &s_config.pub); + update_config(json, "$.sub", &s_config.sub); + mg_http_reply(c, 200, "", "ok\n"); + } else { + struct mg_http_serve_opts opts = {.root_dir = s_root_dir}; + mg_http_serve_dir(c, ev_data, &opts); + } + } + (void) fn_data; +} + +int main(void) { + struct mg_mgr mgr; // Event manager + mg_log_set(MG_LL_INFO); // Set to 3 to enable debug + mg_mgr_init(&mgr); // Initialise event manager + mg_http_listen(&mgr, s_http_addr, fn, NULL); // Create HTTP listener + for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop + mg_mgr_free(&mgr); + return 0; +} diff --git a/examples/webui-push-rest/main.c b/examples/webui-push-rest/main.c index 3933d8be..b9e44af4 100644 --- a/examples/webui-push-rest/main.c +++ b/examples/webui-push-rest/main.c @@ -30,7 +30,7 @@ static size_t printdata(void (*out)(char, void *), void *ptr, va_list *ap) { const char *comma = ""; size_t n = 0; for (int i = 0; i < DATA_SIZE; ++i) { - n += mg_rprintf(out, ptr, "%s%d", comma, s_data[i]); + n += mg_xprintf(out, ptr, "%s%d", comma, s_data[i]); comma = ","; } return n; diff --git a/mongoose.c b/mongoose.c index c9395162..7410859d 100644 --- a/mongoose.c +++ b/mongoose.c @@ -412,6 +412,32 @@ void mg_error(struct mg_connection *c, const char *fmt, ...) { +static void mg_pfn_iobuf_private(char ch, void *param, bool expand) { + struct mg_iobuf *io = (struct mg_iobuf *) param; + if (expand && io->len + 2 > io->size) mg_iobuf_resize(io, io->len + 2); + if (io->len + 2 <= io->size) { + io->buf[io->len++] = (uint8_t) ch; + io->buf[io->len] = 0; + } else if (io->len < io->size) { + io->buf[io->len++] = 0; // Guarantee to 0-terminate + } +} + +static void mg_putchar_iobuf_static(char ch, void *param) { + mg_pfn_iobuf_private(ch, param, false); +} + +void mg_pfn_iobuf(char ch, void *param) { + mg_pfn_iobuf_private(ch, param, true); +} + +size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap) { + struct mg_iobuf io = {(uint8_t *) buf, len, 0, 0}; + size_t n = mg_vxprintf(mg_putchar_iobuf_static, &io, fmt, ap); + if (n < len) buf[n] = '\0'; + return n; +} + size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...) { va_list ap; size_t n; @@ -423,7 +449,7 @@ size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...) { char *mg_vmprintf(const char *fmt, va_list *ap) { struct mg_iobuf io = {0, 0, 0, 256}; - mg_vrprintf(mg_pfn_iobuf, &io, fmt, ap); + mg_vxprintf(mg_pfn_iobuf, &io, fmt, ap); return (char *) io.buf; } @@ -436,40 +462,15 @@ char *mg_mprintf(const char *fmt, ...) { return s; } -size_t mg_rprintf(void (*out)(char, void *), void *ptr, const char *fmt, ...) { +size_t mg_xprintf(void (*out)(char, void *), void *ptr, const char *fmt, ...) { size_t len = 0; va_list ap; va_start(ap, fmt); - len = mg_vrprintf(out, ptr, fmt, &ap); + len = mg_vxprintf(out, ptr, fmt, &ap); va_end(ap); return len; } -static void mg_putchar_iobuf_static(char ch, void *param) { - struct mg_iobuf *io = (struct mg_iobuf *) param; - if (io->len + 2 <= io->size) { - io->buf[io->len++] = (uint8_t) ch; - io->buf[io->len] = 0; - } -} - -void mg_pfn_iobuf(char ch, void *param) { - struct mg_iobuf *io = (struct mg_iobuf *) param; - if (io->len + 2 > io->size) mg_iobuf_resize(io, io->len + 2); - if (io->len + 2 <= io->size) { - io->buf[io->len++] = (uint8_t) ch; - io->buf[io->len] = 0; - } -} - -size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap) { - struct mg_iobuf io = {(uint8_t *) buf, len, 0, 0}; - size_t n = mg_vrprintf(mg_putchar_iobuf_static, &io, fmt, ap); - if (n < len) buf[n] = '\0'; - // if (len > 0) buf[len - 1] = '\0'; // Guarantee to 0-terminate - return n; -} - static bool is_digit(int c) { return c >= '0' && c <= '9'; } @@ -690,7 +691,7 @@ static size_t bcpy(void (*out)(char, void *), void *ptr, uint8_t *buf, return n; } -size_t mg_vrprintf(void (*out)(char, void *), void *param, const char *fmt, +size_t mg_vxprintf(void (*out)(char, void *), void *param, const char *fmt, va_list *ap) { size_t i = 0, n = 0; while (fmt[i] != '\0') { @@ -1647,7 +1648,7 @@ static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt, va_list tmp; mg_send(c, " \r\n", 10); va_copy(tmp, ap); - mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, &tmp); + mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &tmp); va_end(tmp); if (c->send.len >= len + 10) { mg_snprintf((char *) c->send.buf + len, 9, "%08lx", c->send.len - len - 10); @@ -1702,7 +1703,7 @@ void mg_http_reply(struct mg_connection *c, int code, const char *headers, mg_http_status_code_str(code), headers == NULL ? "" : headers); len = c->send.len; va_start(ap, fmt); - mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, &ap); + mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &ap); va_end(ap); if (c->send.len > 15) { mg_snprintf((char *) &c->send.buf[len - 14], 11, "%010lu", @@ -2741,7 +2742,7 @@ bool mg_log_prefix(int level, const char *file, int line, const char *fname) { void mg_log(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - mg_vrprintf(s_log_func, s_log_func_param, fmt, &ap); + mg_vxprintf(s_log_func, s_log_func_param, fmt, &ap); va_end(ap); logc((unsigned char) '\n'); } @@ -3282,7 +3283,7 @@ size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) { size_t old = c->send.len; va_list tmp; va_copy(tmp, ap); - mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, &tmp); + mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &tmp); return c->send.len - old; } @@ -3587,10 +3588,10 @@ void mg_rpc_process(struct mg_rpc_req *r) { void mg_rpc_vok(struct mg_rpc_req *r, const char *fmt, va_list *ap) { int len, off = mg_json_get(r->frame, "$.id", &len); if (off > 0) { - mg_rprintf(r->pfn, r->pfn_data, "{%Q:%.*s,%Q:", "id", len, + mg_xprintf(r->pfn, r->pfn_data, "{%Q:%.*s,%Q:", "id", len, &r->frame.ptr[off], "result"); - mg_vrprintf(r->pfn, r->pfn_data, fmt == NULL ? "null" : fmt, ap); - mg_rprintf(r->pfn, r->pfn_data, "}"); + mg_vxprintf(r->pfn, r->pfn_data, fmt == NULL ? "null" : fmt, ap); + mg_xprintf(r->pfn, r->pfn_data, "}"); } } @@ -3603,14 +3604,14 @@ void mg_rpc_ok(struct mg_rpc_req *r, const char *fmt, ...) { void mg_rpc_verr(struct mg_rpc_req *r, int code, const char *fmt, va_list *ap) { int len, off = mg_json_get(r->frame, "$.id", &len); - mg_rprintf(r->pfn, r->pfn_data, "{"); + mg_xprintf(r->pfn, r->pfn_data, "{"); if (off > 0) { - mg_rprintf(r->pfn, r->pfn_data, "%Q:%.*s,", "id", len, &r->frame.ptr[off]); + mg_xprintf(r->pfn, r->pfn_data, "%Q:%.*s,", "id", len, &r->frame.ptr[off]); } - mg_rprintf(r->pfn, r->pfn_data, "%Q:{%Q:%d,%Q:", "error", "code", code, + mg_xprintf(r->pfn, r->pfn_data, "%Q:{%Q:%d,%Q:", "error", "code", code, "message"); - mg_vrprintf(r->pfn, r->pfn_data, fmt == NULL ? "null" : fmt, ap); - mg_rprintf(r->pfn, r->pfn_data, "}}"); + mg_vxprintf(r->pfn, r->pfn_data, fmt == NULL ? "null" : fmt, ap); + mg_xprintf(r->pfn, r->pfn_data, "}}"); } void mg_rpc_err(struct mg_rpc_req *r, int code, const char *fmt, ...) { @@ -3624,7 +3625,7 @@ static size_t print_methods(mg_pfn_t pfn, void *pfn_data, va_list *ap) { struct mg_rpc *h, **head = (struct mg_rpc **) va_arg(*ap, void **); size_t len = 0; for (h = *head; h != NULL; h = h->next) { - len += mg_rprintf(pfn, pfn_data, "%s%.*Q", h == *head ? "" : ",", + len += mg_xprintf(pfn, pfn_data, "%s%.*Q", h == *head ? "" : ",", (int) h->method.len, h->method.ptr); } return len; @@ -5654,7 +5655,7 @@ struct ws_msg { size_t mg_ws_vprintf(struct mg_connection *c, int op, const char *fmt, va_list *ap) { size_t len = c->send.len; - size_t n = mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, ap); + size_t n = mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap); mg_ws_wrap(c, c->send.len - len, op); return n; } @@ -5680,13 +5681,13 @@ static void ws_handshake(struct mg_connection *c, const struct mg_str *wskey, mg_sha1_update(&sha_ctx, (unsigned char *) magic, 36); mg_sha1_final(sha, &sha_ctx); mg_base64_encode(sha, sizeof(sha), (char *) b64_sha); - mg_rprintf(mg_pfn_iobuf, &c->send, + mg_xprintf(mg_pfn_iobuf, &c->send, "HTTP/1.1 101 Switching Protocols\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: %s\r\n", b64_sha); - if (fmt != NULL) mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, ap); + if (fmt != NULL) mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap); if (wsproto != NULL) { mg_printf(c, "Sec-WebSocket-Protocol: %.*s\r\n", (int) wsproto->len, wsproto->ptr); @@ -5873,7 +5874,7 @@ struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url, struct mg_str host = mg_url_host(url); mg_random(nonce, sizeof(nonce)); mg_base64_encode((unsigned char *) nonce, sizeof(nonce), key); - mg_rprintf(mg_pfn_iobuf, &c->send, + mg_xprintf(mg_pfn_iobuf, &c->send, "GET %s HTTP/1.1\r\n" "Upgrade: websocket\r\n" "Host: %.*s\r\n" @@ -5884,10 +5885,10 @@ struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url, if (fmt != NULL) { va_list ap; va_start(ap, fmt); - mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, &ap); + mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &ap); va_end(ap); } - mg_rprintf(mg_pfn_iobuf, &c->send, "\r\n"); + mg_xprintf(mg_pfn_iobuf, &c->send, "\r\n"); c->pfn = mg_ws_cb; c->pfn_data = NULL; } diff --git a/mongoose.h b/mongoose.h index 2cf9349d..19f3dbce 100644 --- a/mongoose.h +++ b/mongoose.h @@ -791,8 +791,8 @@ size_t mg_lld(char *buf, int64_t val, bool is_signed, bool is_hex); double mg_atod(const char *buf, int len, int *numlen); size_t mg_dtoa(char *buf, size_t len, double d, int width); -size_t mg_vrprintf(void (*)(char, void *), void *, const char *fmt, va_list *); -size_t mg_rprintf(void (*fn)(char, void *), void *, const char *fmt, ...); +size_t mg_vxprintf(void (*)(char, void *), void *, const char *fmt, va_list *); +size_t mg_xprintf(void (*fn)(char, void *), void *, const char *fmt, ...); size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap); size_t mg_snprintf(char *, size_t, const char *fmt, ...); char *mg_vmprintf(const char *fmt, va_list *ap); diff --git a/src/fmt.c b/src/fmt.c index 121df2fc..fa7ccdbe 100644 --- a/src/fmt.c +++ b/src/fmt.c @@ -1,6 +1,32 @@ #include "fmt.h" #include "iobuf.h" +static void mg_pfn_iobuf_private(char ch, void *param, bool expand) { + struct mg_iobuf *io = (struct mg_iobuf *) param; + if (expand && io->len + 2 > io->size) mg_iobuf_resize(io, io->len + 2); + if (io->len + 2 <= io->size) { + io->buf[io->len++] = (uint8_t) ch; + io->buf[io->len] = 0; + } else if (io->len < io->size) { + io->buf[io->len++] = 0; // Guarantee to 0-terminate + } +} + +static void mg_putchar_iobuf_static(char ch, void *param) { + mg_pfn_iobuf_private(ch, param, false); +} + +void mg_pfn_iobuf(char ch, void *param) { + mg_pfn_iobuf_private(ch, param, true); +} + +size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap) { + struct mg_iobuf io = {(uint8_t *) buf, len, 0, 0}; + size_t n = mg_vxprintf(mg_putchar_iobuf_static, &io, fmt, ap); + if (n < len) buf[n] = '\0'; + return n; +} + size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...) { va_list ap; size_t n; @@ -12,7 +38,7 @@ size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...) { char *mg_vmprintf(const char *fmt, va_list *ap) { struct mg_iobuf io = {0, 0, 0, 256}; - mg_vrprintf(mg_pfn_iobuf, &io, fmt, ap); + mg_vxprintf(mg_pfn_iobuf, &io, fmt, ap); return (char *) io.buf; } @@ -25,40 +51,15 @@ char *mg_mprintf(const char *fmt, ...) { return s; } -size_t mg_rprintf(void (*out)(char, void *), void *ptr, const char *fmt, ...) { +size_t mg_xprintf(void (*out)(char, void *), void *ptr, const char *fmt, ...) { size_t len = 0; va_list ap; va_start(ap, fmt); - len = mg_vrprintf(out, ptr, fmt, &ap); + len = mg_vxprintf(out, ptr, fmt, &ap); va_end(ap); return len; } -static void mg_putchar_iobuf_static(char ch, void *param) { - struct mg_iobuf *io = (struct mg_iobuf *) param; - if (io->len + 2 <= io->size) { - io->buf[io->len++] = (uint8_t) ch; - io->buf[io->len] = 0; - } -} - -void mg_pfn_iobuf(char ch, void *param) { - struct mg_iobuf *io = (struct mg_iobuf *) param; - if (io->len + 2 > io->size) mg_iobuf_resize(io, io->len + 2); - if (io->len + 2 <= io->size) { - io->buf[io->len++] = (uint8_t) ch; - io->buf[io->len] = 0; - } -} - -size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap) { - struct mg_iobuf io = {(uint8_t *) buf, len, 0, 0}; - size_t n = mg_vrprintf(mg_putchar_iobuf_static, &io, fmt, ap); - if (n < len) buf[n] = '\0'; - // if (len > 0) buf[len - 1] = '\0'; // Guarantee to 0-terminate - return n; -} - static bool is_digit(int c) { return c >= '0' && c <= '9'; } @@ -279,7 +280,7 @@ static size_t bcpy(void (*out)(char, void *), void *ptr, uint8_t *buf, return n; } -size_t mg_vrprintf(void (*out)(char, void *), void *param, const char *fmt, +size_t mg_vxprintf(void (*out)(char, void *), void *param, const char *fmt, va_list *ap) { size_t i = 0, n = 0; while (fmt[i] != '\0') { diff --git a/src/fmt.h b/src/fmt.h index b41ad67c..1afc1bf0 100644 --- a/src/fmt.h +++ b/src/fmt.h @@ -11,8 +11,8 @@ size_t mg_lld(char *buf, int64_t val, bool is_signed, bool is_hex); double mg_atod(const char *buf, int len, int *numlen); size_t mg_dtoa(char *buf, size_t len, double d, int width); -size_t mg_vrprintf(void (*)(char, void *), void *, const char *fmt, va_list *); -size_t mg_rprintf(void (*fn)(char, void *), void *, const char *fmt, ...); +size_t mg_vxprintf(void (*)(char, void *), void *, const char *fmt, va_list *); +size_t mg_xprintf(void (*fn)(char, void *), void *, const char *fmt, ...); size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap); size_t mg_snprintf(char *, size_t, const char *fmt, ...); char *mg_vmprintf(const char *fmt, va_list *ap); diff --git a/src/http.c b/src/http.c index 02024b35..b5c87b1b 100644 --- a/src/http.c +++ b/src/http.c @@ -272,7 +272,7 @@ static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt, va_list tmp; mg_send(c, " \r\n", 10); va_copy(tmp, ap); - mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, &tmp); + mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &tmp); va_end(tmp); if (c->send.len >= len + 10) { mg_snprintf((char *) c->send.buf + len, 9, "%08lx", c->send.len - len - 10); @@ -327,7 +327,7 @@ void mg_http_reply(struct mg_connection *c, int code, const char *headers, mg_http_status_code_str(code), headers == NULL ? "" : headers); len = c->send.len; va_start(ap, fmt); - mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, &ap); + mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &ap); va_end(ap); if (c->send.len > 15) { mg_snprintf((char *) &c->send.buf[len - 14], 11, "%010lu", diff --git a/src/log.c b/src/log.c index 295bb962..40e9b781 100644 --- a/src/log.c +++ b/src/log.c @@ -51,7 +51,7 @@ bool mg_log_prefix(int level, const char *file, int line, const char *fname) { void mg_log(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - mg_vrprintf(s_log_func, s_log_func_param, fmt, &ap); + mg_vxprintf(s_log_func, s_log_func_param, fmt, &ap); va_end(ap); logc((unsigned char) '\n'); } diff --git a/src/net.c b/src/net.c index 24d953c1..6f7e95da 100644 --- a/src/net.c +++ b/src/net.c @@ -9,7 +9,7 @@ size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list ap) { size_t old = c->send.len; va_list tmp; va_copy(tmp, ap); - mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, &tmp); + mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &tmp); return c->send.len - old; } diff --git a/src/rpc.c b/src/rpc.c index 53175868..c513a555 100644 --- a/src/rpc.c +++ b/src/rpc.c @@ -40,10 +40,10 @@ void mg_rpc_process(struct mg_rpc_req *r) { void mg_rpc_vok(struct mg_rpc_req *r, const char *fmt, va_list *ap) { int len, off = mg_json_get(r->frame, "$.id", &len); if (off > 0) { - mg_rprintf(r->pfn, r->pfn_data, "{%Q:%.*s,%Q:", "id", len, + mg_xprintf(r->pfn, r->pfn_data, "{%Q:%.*s,%Q:", "id", len, &r->frame.ptr[off], "result"); - mg_vrprintf(r->pfn, r->pfn_data, fmt == NULL ? "null" : fmt, ap); - mg_rprintf(r->pfn, r->pfn_data, "}"); + mg_vxprintf(r->pfn, r->pfn_data, fmt == NULL ? "null" : fmt, ap); + mg_xprintf(r->pfn, r->pfn_data, "}"); } } @@ -56,14 +56,14 @@ void mg_rpc_ok(struct mg_rpc_req *r, const char *fmt, ...) { void mg_rpc_verr(struct mg_rpc_req *r, int code, const char *fmt, va_list *ap) { int len, off = mg_json_get(r->frame, "$.id", &len); - mg_rprintf(r->pfn, r->pfn_data, "{"); + mg_xprintf(r->pfn, r->pfn_data, "{"); if (off > 0) { - mg_rprintf(r->pfn, r->pfn_data, "%Q:%.*s,", "id", len, &r->frame.ptr[off]); + mg_xprintf(r->pfn, r->pfn_data, "%Q:%.*s,", "id", len, &r->frame.ptr[off]); } - mg_rprintf(r->pfn, r->pfn_data, "%Q:{%Q:%d,%Q:", "error", "code", code, + mg_xprintf(r->pfn, r->pfn_data, "%Q:{%Q:%d,%Q:", "error", "code", code, "message"); - mg_vrprintf(r->pfn, r->pfn_data, fmt == NULL ? "null" : fmt, ap); - mg_rprintf(r->pfn, r->pfn_data, "}}"); + mg_vxprintf(r->pfn, r->pfn_data, fmt == NULL ? "null" : fmt, ap); + mg_xprintf(r->pfn, r->pfn_data, "}}"); } void mg_rpc_err(struct mg_rpc_req *r, int code, const char *fmt, ...) { @@ -77,7 +77,7 @@ static size_t print_methods(mg_pfn_t pfn, void *pfn_data, va_list *ap) { struct mg_rpc *h, **head = (struct mg_rpc **) va_arg(*ap, void **); size_t len = 0; for (h = *head; h != NULL; h = h->next) { - len += mg_rprintf(pfn, pfn_data, "%s%.*Q", h == *head ? "" : ",", + len += mg_xprintf(pfn, pfn_data, "%s%.*Q", h == *head ? "" : ",", (int) h->method.len, h->method.ptr); } return len; diff --git a/src/ws.c b/src/ws.c index 6a6c6a4e..cb5807b4 100644 --- a/src/ws.c +++ b/src/ws.c @@ -17,7 +17,7 @@ struct ws_msg { size_t mg_ws_vprintf(struct mg_connection *c, int op, const char *fmt, va_list *ap) { size_t len = c->send.len; - size_t n = mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, ap); + size_t n = mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap); mg_ws_wrap(c, c->send.len - len, op); return n; } @@ -43,13 +43,13 @@ static void ws_handshake(struct mg_connection *c, const struct mg_str *wskey, mg_sha1_update(&sha_ctx, (unsigned char *) magic, 36); mg_sha1_final(sha, &sha_ctx); mg_base64_encode(sha, sizeof(sha), (char *) b64_sha); - mg_rprintf(mg_pfn_iobuf, &c->send, + mg_xprintf(mg_pfn_iobuf, &c->send, "HTTP/1.1 101 Switching Protocols\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: %s\r\n", b64_sha); - if (fmt != NULL) mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, ap); + if (fmt != NULL) mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap); if (wsproto != NULL) { mg_printf(c, "Sec-WebSocket-Protocol: %.*s\r\n", (int) wsproto->len, wsproto->ptr); @@ -236,7 +236,7 @@ struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url, struct mg_str host = mg_url_host(url); mg_random(nonce, sizeof(nonce)); mg_base64_encode((unsigned char *) nonce, sizeof(nonce), key); - mg_rprintf(mg_pfn_iobuf, &c->send, + mg_xprintf(mg_pfn_iobuf, &c->send, "GET %s HTTP/1.1\r\n" "Upgrade: websocket\r\n" "Host: %.*s\r\n" @@ -247,10 +247,10 @@ struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url, if (fmt != NULL) { va_list ap; va_start(ap, fmt); - mg_vrprintf(mg_pfn_iobuf, &c->send, fmt, &ap); + mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &ap); va_end(ap); } - mg_rprintf(mg_pfn_iobuf, &c->send, "\r\n"); + mg_xprintf(mg_pfn_iobuf, &c->send, "\r\n"); c->pfn = mg_ws_cb; c->pfn_data = NULL; } diff --git a/test/unit_test.c b/test/unit_test.c index 2434d05a..79bb5dc4 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -1414,13 +1414,13 @@ static bool sccmp(const char *s1, const char *s2, int expected) { static size_t pf1(void (*out)(char, void *), void *ptr, va_list *ap) { int a = va_arg(*ap, int); int b = va_arg(*ap, int); - return mg_rprintf(out, ptr, "%d", a + b); + return mg_xprintf(out, ptr, "%d", a + b); } static size_t pf2(void (*out)(char, void *), void *ptr, va_list *ap) { int cnt = va_arg(*ap, int); size_t n = 0; - while (cnt-- > 0) n += mg_rprintf(out, ptr, "%d", cnt); + while (cnt-- > 0) n += mg_xprintf(out, ptr, "%d", cnt); return n; } @@ -1510,6 +1510,14 @@ static void test_str(void) { mg_snprintf(buf, sizeof(buf), "%Q", ""); ASSERT(strcmp(buf, expected) == 0); + expected = ""; + mg_snprintf(buf, 1, "%s", "abc"); + ASSERT(strcmp(buf, expected) == 0); + + expected = "a"; + mg_snprintf(buf, 2, "%s", "abc"); + ASSERT(strcmp(buf, expected) == 0); + expected = "\"hi, \\\"\""; mg_snprintf(buf, sizeof(buf), "\"hi, %q\"", "\""); MG_INFO(("[%s] [%s]", buf, expected)); @@ -1535,9 +1543,9 @@ static void test_str(void) { ASSERT(strcmp(p, "[9876543210,7]") == 0); free(p); - mg_rprintf(mg_pfn_iobuf, &io, "[%M", pf2, 10); - mg_rprintf(mg_pfn_iobuf, &io, ","); - mg_rprintf(mg_pfn_iobuf, &io, "%d]", 7); + mg_xprintf(mg_pfn_iobuf, &io, "[%M", pf2, 10); + mg_xprintf(mg_pfn_iobuf, &io, ","); + mg_xprintf(mg_pfn_iobuf, &io, "%d]", 7); ASSERT(strcmp((char *) io.buf, "[9876543210,7]") == 0); mg_iobuf_free(&io); }