diff options
author | Daniil Cherednik <dan.cherednik@gmail.com> | 2023-05-05 11:09:01 +0300 |
---|---|---|
committer | Daniil Cherednik <dan.cherednik@gmail.com> | 2023-05-05 11:09:01 +0300 |
commit | b5a989b16cafa8a3b3bc076f1097a0eda6f48c06 (patch) | |
tree | 4da744117a5aab37758921fa43b95a3068e5aec1 /contrib/libs/libfyaml/src/lib/fy-emit-accum.h | |
parent | fc1cffcfa7f0497a1f97b384a24bcbf23362f3be (diff) | |
download | ydb-b5a989b16cafa8a3b3bc076f1097a0eda6f48c06.tar.gz |
Ydb stable 23-1-2623.1.26
x-stable-origin-commit: 22184a7e157553d447f17a2dffc4ea2d32dfd74d
Diffstat (limited to 'contrib/libs/libfyaml/src/lib/fy-emit-accum.h')
-rw-r--r-- | contrib/libs/libfyaml/src/lib/fy-emit-accum.h | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/contrib/libs/libfyaml/src/lib/fy-emit-accum.h b/contrib/libs/libfyaml/src/lib/fy-emit-accum.h new file mode 100644 index 0000000000..acc8ae7491 --- /dev/null +++ b/contrib/libs/libfyaml/src/lib/fy-emit-accum.h @@ -0,0 +1,383 @@ +/* + * fy-emit-accum.h - internal YAML emitter accumulator header + * + * Copyright (c) 2019 Pantelis Antoniou <pantelis.antoniou@konsulko.com> + * + * SPDX-License-Identifier: MIT + */ +#ifndef FY_EMIT_ACCUM_H +#define FY_EMIT_ACCUM_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include <stdbool.h> +#include <stdio.h> + +#include <libfyaml.h> + +#include "fy-utf8.h" +#include "fy-event.h" + +struct fy_emit_accum { + char *accum; + size_t alloc; + size_t next; + char *inplace; + size_t inplacesz; + int col, row; + int ts; + enum fy_lb_mode lb_mode; +}; + +static inline void +fy_emit_accum_init(struct fy_emit_accum *ea, + void *inplace, size_t inplacesz, + int ts, enum fy_lb_mode lb_mode) +{ + memset(ea, 0, sizeof(*ea)); + + ea->inplace = inplace; + ea->inplacesz = inplacesz; + ea->accum = ea->inplace; + ea->alloc = ea->inplacesz; + ea->ts = ts ? ts : 8; + ea->lb_mode = lb_mode; +} + +static inline void +fy_emit_accum_reset(struct fy_emit_accum *ea) +{ + ea->next = 0; + ea->col = 0; + ea->row = 0; +} + +static inline void +fy_emit_accum_cleanup(struct fy_emit_accum *ea) +{ + if (ea->accum && ea->accum != ea->inplace) + free(ea->accum); + ea->accum = ea->inplace; + ea->alloc = ea->inplacesz; + fy_emit_accum_reset(ea); +} + +static inline void +fy_emit_accum_start(struct fy_emit_accum *ea, int col, enum fy_lb_mode lb_mode) +{ + fy_emit_accum_reset(ea); + ea->col = col; + ea->lb_mode = lb_mode; +} + +static inline void +fy_emit_accum_finish(struct fy_emit_accum *ea) +{ + fy_emit_accum_reset(ea); +} + +static inline int +fy_emit_accum_grow(struct fy_emit_accum *ea, size_t need) +{ + size_t atleast, asz; + char *new_accum; + + atleast = ea->alloc + need; + asz = ea->alloc; + /* minimum buffer is 32 */ + if (asz < 32) + asz = 32; + do { + asz *= 2; + } while (asz < atleast); + assert(asz > ea->inplacesz); + new_accum = realloc(ea->accum == ea->inplace ? NULL : ea->accum, asz); + if (!new_accum) /* out of memory */ + return -1; + if (ea->accum && ea->accum == ea->inplace) + memcpy(new_accum, ea->accum, ea->next); + ea->alloc = asz; + ea->accum = new_accum; + + return 0; +} + +static inline int +fy_emit_accum_utf8_put_raw(struct fy_emit_accum *ea, int c) +{ + size_t w, avail; + int ret; + + /* grow if needed */ + w = fy_utf8_width(c); + if (w > (avail = (ea->alloc - ea->next))) { + ret = fy_emit_accum_grow(ea, w - avail); + if (ret != 0) + return ret; + } + (void)fy_utf8_put_unchecked(ea->accum + ea->next, c); + ea->next += w; + + return 0; +} + +static inline int +fy_emit_accum_put_raw(struct fy_emit_accum *ea, int c) +{ + int ret; + + /* only lower ascii please */ + if (c >= 0x80) + return -1; + + /* grow if needed */ + if (ea->next >= ea->alloc) { + ret = fy_emit_accum_grow(ea, 1); + if (ret != 0) + return ret; + } + *(ea->accum + ea->next) = (char)c; + ea->next++; + + return 0; +} + +static inline int +fy_emit_accum_utf8_put(struct fy_emit_accum *ea, int c) +{ + int ret; + + if (!fy_utf8_is_valid(c)) + return -1; + + if (fy_is_lb_m(c, ea->lb_mode)) { + ret = fy_emit_accum_put_raw(ea, '\n'); + if (ret) + return ret; + ea->col = 0; + ea->row++; + } else if (fy_is_tab(c)) { + ret = fy_emit_accum_put_raw(ea, '\t'); + if (ret) + return ret; + ea->col += (ea->ts - (ea->col % ea->ts)); + } else { + if (c < 0x80) { + ret = fy_emit_accum_put_raw(ea, c); + if (ret) + return ret; + } else { + ret = fy_emit_accum_utf8_put_raw(ea, c); + } + ea->col++; + } + + return 0; +} + +static inline int +fy_emit_accum_utf8_write_raw(struct fy_emit_accum *ea, const void *data, size_t len) +{ + size_t avail; + int ret; + + /* grow if needed */ + if (len > (avail = (ea->alloc - ea->next))) { + ret = fy_emit_accum_grow(ea, len - avail); + if (ret != 0) + return ret; + } + memcpy(ea->accum + ea->next, data, len); + ea->next += len; + + return 0; +} + +static inline int +fy_emit_accum_utf8_write(struct fy_emit_accum *ea, const void *data, size_t len) +{ + const char *s, *e; + int c, w, ret; + + for (s = data, e = s + len; (c = fy_utf8_get(s, (e - s), &w)) >= 0; s += w) { + ret = fy_emit_accum_utf8_put(ea, c); + if (ret) + break; + } + return c == FYUG_EOF ? 0 : -1; +} + +static inline int +fy_emit_accum_utf8_printf_raw(struct fy_emit_accum *ea, const char *fmt, ...) + FY_ATTRIBUTE(format(printf, 2, 3)); + +static inline int +fy_emit_accum_utf8_printf_raw(struct fy_emit_accum *ea, const char *fmt, ...) +{ + va_list ap; + size_t avail, len; + int ret; + + /* get the size of the string */ + va_start(ap, fmt); + len = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + + /* grow if needed */ + if ((len + 1) > (avail = (ea->alloc - ea->next))) { + ret = fy_emit_accum_grow(ea, (len + 1) - avail); + if (ret != 0) + return ret; + } + + va_start(ap, fmt); + (void)vsnprintf(ea->accum + ea->next, len + 1, fmt, ap); + va_end(ap); + + ea->next += len; + + return 0; +} + +static inline const char * +fy_emit_accum_get(struct fy_emit_accum *ea, size_t *lenp) +{ + *lenp = ea->next; + if (!ea->next) { + return ""; + } + return ea->accum; +} + +static inline int +fy_emit_accum_make_0_terminated(struct fy_emit_accum *ea) +{ + int ret; + + /* the empty case is special cased */ + if (!ea->next) + return 0; + + /* grow if needed for the '\0' */ + if (ea->next >= ea->alloc) { + ret = fy_emit_accum_grow(ea, 1); + if (ret != 0) + return ret; + } + assert(ea->next < ea->alloc); + *(ea->accum + ea->next) = '\0'; + return 0; +} + +static inline const char * +fy_emit_accum_get0(struct fy_emit_accum *ea) +{ + int ret; + + ret = fy_emit_accum_make_0_terminated(ea); + if (ret) + return NULL; + return ea->accum; +} + +static inline char * +fy_emit_accum_steal(struct fy_emit_accum *ea, size_t *lenp) +{ + int ret; + char *buf; + + /* empty, return a malloc'ed buffer to "" */ + if (!ea->next) { + buf = strdup(""); + if (!buf) { + *lenp = 0; + return NULL; + } + *lenp = ea->next; + } else if (ea->inplace && ea->accum == ea->inplace) { + buf = malloc(ea->next + 1); + if (!buf) { + *lenp = 0; + return NULL; + } + memcpy(buf, ea->accum, ea->next); + buf[ea->next] = '\0'; + *lenp = ea->next; + } else { + ret = fy_emit_accum_make_0_terminated(ea); + if (ret) { + *lenp = 0; + return NULL; + } + assert(ea->accum && ea->accum != ea->inplace); + buf = ea->accum; + *lenp = ea->next; + /* reset to inplace */ + ea->accum = ea->inplace; + ea->alloc = ea->inplacesz; + } + + fy_emit_accum_cleanup(ea); + return buf; +} + +static inline char * +fy_emit_accum_steal0(struct fy_emit_accum *ea) +{ + size_t len; + + return fy_emit_accum_steal(ea, &len); +} + +static inline bool +fy_emit_accum_empty(struct fy_emit_accum *ea) +{ + return ea->next == 0; +} + +static inline int +fy_emit_accum_size(struct fy_emit_accum *ea) +{ + return ea->next; +} + +static inline int +fy_emit_accum_column(struct fy_emit_accum *ea) +{ + return ea->col; +} + +static inline int +fy_emit_accum_row(struct fy_emit_accum *ea) +{ + return ea->row; +} + +struct fy_emit_accum_state { + int col; + int row; + size_t next; +}; + +static inline void +fy_emit_accum_get_state(struct fy_emit_accum *ea, struct fy_emit_accum_state *s) +{ + s->col = ea->col; + s->row = ea->row; + s->next = ea->next; +} + +static inline void +fy_emit_accum_rewind_state(struct fy_emit_accum *ea, const struct fy_emit_accum_state *s) +{ + /* we can only go back */ + assert(s->next <= ea->next); + ea->col = s->col; + ea->row = s->row; + ea->next = s->next; +} + +#endif |