aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/libfyaml/src/lib/fy-emit-accum.h
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2023-05-05 11:09:01 +0300
committerDaniil Cherednik <dan.cherednik@gmail.com>2023-05-05 11:09:01 +0300
commitb5a989b16cafa8a3b3bc076f1097a0eda6f48c06 (patch)
tree4da744117a5aab37758921fa43b95a3068e5aec1 /contrib/libs/libfyaml/src/lib/fy-emit-accum.h
parentfc1cffcfa7f0497a1f97b384a24bcbf23362f3be (diff)
downloadydb-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.h383
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