#include "upb/sink.h" bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink) { void *subc; bool ret; upb_bufhandle handle; upb_bufhandle_init(&handle); upb_bufhandle_setbuf(&handle, buf, 0); ret = upb_bytessink_start(sink, len, &subc); if (ret && len != 0) { ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) >= len); } if (ret) { ret = upb_bytessink_end(sink); } upb_bufhandle_uninit(&handle); return ret; } struct upb_bufsink { upb_byteshandler handler; upb_bytessink sink; upb_env *env; char *ptr; size_t len, size; }; static void *upb_bufsink_start(void *_sink, const void *hd, size_t size_hint) { upb_bufsink *sink = _sink; UPB_UNUSED(hd); UPB_UNUSED(size_hint); sink->len = 0; return sink; } static size_t upb_bufsink_string(void *_sink, const void *hd, const char *ptr, size_t len, const upb_bufhandle *handle) { upb_bufsink *sink = _sink; size_t new_size = sink->size; UPB_ASSERT(new_size > 0); UPB_UNUSED(hd); UPB_UNUSED(handle); while (sink->len + len > new_size) { new_size *= 2; } if (new_size != sink->size) { sink->ptr = upb_env_realloc(sink->env, sink->ptr, sink->size, new_size); sink->size = new_size; } memcpy(sink->ptr + sink->len, ptr, len); sink->len += len; return len; } upb_bufsink *upb_bufsink_new(upb_env *env) { upb_bufsink *sink = upb_env_malloc(env, sizeof(upb_bufsink)); upb_byteshandler_init(&sink->handler); upb_byteshandler_setstartstr(&sink->handler, upb_bufsink_start, NULL); upb_byteshandler_setstring(&sink->handler, upb_bufsink_string, NULL); upb_bytessink_reset(&sink->sink, &sink->handler, sink); sink->env = env; sink->size = 32; sink->ptr = upb_env_malloc(env, sink->size); sink->len = 0; return sink; } void upb_bufsink_free(upb_bufsink *sink) { upb_env_free(sink->env, sink->ptr); upb_env_free(sink->env, sink); } upb_bytessink *upb_bufsink_sink(upb_bufsink *sink) { return &sink->sink; } const char *upb_bufsink_getdata(const upb_bufsink *sink, size_t *len) { *len = sink->len; return sink->ptr; }