pull/13171/head
Joshua Haberman 6 years ago
parent a9c375f8ea
commit cb26d883d1
  1. 8
      google/protobuf/descriptor.upb.h
  2. 16
      tests/conformance_upb.c
  3. 4
      tests/json/test_json.cc
  4. 14
      tests/pb/test_decoder.cc
  5. 9
      tests/pb/test_encoder.cc
  6. 2
      tests/test_cpp.cc
  7. 21
      tests/test_util.h
  8. 9
      upb/bindings/lua/def.c
  9. 13
      upb/bindings/lua/msg.c
  10. 8
      upb/bindings/lua/upb/pb.c
  11. 8
      upb/decode.h
  12. 41
      upb/def.c
  13. 37
      upb/def.h
  14. 8
      upb/encode.h
  15. 3
      upb/generated_util.h
  16. 8
      upb/handlers.c
  17. 39
      upb/handlers.h
  18. 259
      upb/json/parser.c
  19. 37
      upb/json/parser.h
  20. 153
      upb/json/parser.rl
  21. 8
      upb/json/printer.c
  22. 14
      upb/json/printer.h
  23. 28
      upb/msg.h
  24. 12
      upb/msgfactory.h
  25. 2
      upb/pb/compile_decoder.c
  26. 22
      upb/pb/decoder.c
  27. 28
      upb/pb/decoder.h
  28. 4
      upb/pb/decoder.int.h
  29. 22
      upb/pb/encoder.c
  30. 14
      upb/pb/encoder.h
  31. 26
      upb/pb/textprinter.c
  32. 75
      upb/pb/textprinter.h
  33. 70
      upb/sink.c
  34. 33
      upb/sink.h
  35. 15
      upb/table.int.h
  36. 75
      upb/upb.c
  37. 161
      upb/upb.h
  38. 8
      upbc/generator.cc

@ -16,7 +16,9 @@
#include "upb/decode.h"
#include "upb/encode.h"
#include "upb/port_def.inc"
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
struct google_protobuf_FileDescriptorSet;
struct google_protobuf_FileDescriptorProto;
@ -1668,7 +1670,9 @@ UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_prot
}
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
#endif
#include "upb/port_undef.inc"

@ -130,7 +130,7 @@ void DoTest(
}
bool DoTestIo() {
upb_arena arena;
upb_arena *arena;
upb_alloc *alloc;
upb_status status;
char *serialized_input;
@ -145,8 +145,8 @@ bool DoTestIo() {
return false;
}
upb_arena_init(&arena);
alloc = upb_arena_alloc(&arena);
arena = upb_arena_new();
alloc = upb_arena_alloc(arena);
serialized_input = upb_malloc(alloc, input_size);
if (!CheckedRead(STDIN_FILENO, serialized_input, input_size)) {
@ -155,24 +155,26 @@ bool DoTestIo() {
}
request = conformance_ConformanceRequest_parsenew(
upb_stringview_make(serialized_input, input_size), &arena);
response = conformance_ConformanceResponse_new(&arena);
upb_stringview_make(serialized_input, input_size), arena);
response = conformance_ConformanceResponse_new(arena);
if (request) {
DoTest(request, response, &arena);
DoTest(request, response, arena);
} else {
fprintf(stderr, "conformance_upb: parse of ConformanceRequest failed: %s\n",
upb_status_errmsg(&status));
}
serialized_output = conformance_ConformanceResponse_serialize(
response, &arena, &output_size);
response, arena, &output_size);
CheckedWrite(STDOUT_FILENO, &output_size, sizeof(uint32_t));
CheckedWrite(STDOUT_FILENO, serialized_output, output_size);
test_count++;
upb_arena_free(arena);
return true;
}

@ -174,9 +174,9 @@ void test_json_roundtrip_message(const char* json_src,
VerboseParserEnvironment env(verbose);
StringSink data_sink;
upb::json::PrinterPtr printer = upb::json::PrinterPtr::Create(
env.env(), serialize_handlers, data_sink.Sink());
env.arena(), serialize_handlers, data_sink.Sink());
upb::json::ParserPtr parser = upb::json::ParserPtr::Create(
env.env(), parser_method, NULL, printer.input(), false);
env.arena(), parser_method, NULL, printer.input(), false);
env.ResetBytesSink(parser.input());
env.Reset(json_src, strlen(json_src), false, false);

@ -452,10 +452,10 @@ void callback(const void *closure, upb::Handlers* h_ptr) {
const upb::Handlers *global_handlers;
upb::pb::DecoderMethodPtr global_method;
upb::pb::DecoderPtr CreateDecoder(upb::Environment* env,
upb::pb::DecoderPtr CreateDecoder(upb::Arena* arena,
upb::pb::DecoderMethodPtr method,
upb::Sink sink) {
upb::pb::DecoderPtr ret = upb::pb::DecoderPtr::Create(env, method, sink);
upb::pb::DecoderPtr ret = upb::pb::DecoderPtr::Create(arena, method, sink);
ret.set_max_nesting(MAX_NESTING);
return ret;
}
@ -556,7 +556,7 @@ void do_run_decoder(VerboseParserEnvironment* env, upb::pb::DecoderPtr decoder,
void run_decoder(const string& proto, const string* expected_output) {
VerboseParserEnvironment env(filter_hash != 0);
upb::Sink sink(global_handlers, &closures[0]);
upb::pb::DecoderPtr decoder = CreateDecoder(env.env(), global_method, sink);
upb::pb::DecoderPtr decoder = CreateDecoder(env.arena(), global_method, sink);
env.ResetBytesSink(decoder.input());
for (size_t i = 0; i < proto.size(); i++) {
for (size_t j = i; j < UPB_MIN(proto.size(), i + 5); j++) {
@ -872,10 +872,9 @@ void test_valid() {
if (!filter_hash || filter_hash == testhash) {
testhash = emptyhash;
upb::Status status;
upb::Environment env;
env.ReportErrorsTo(&status);
upb::Arena arena;
upb::Sink sink(global_handlers, &closures[0]);
upb::pb::DecoderPtr decoder = CreateDecoder(&env, global_method, sink);
upb::pb::DecoderPtr decoder = CreateDecoder(&arena, global_method, sink);
output.clear();
bool ok = upb::PutBuffer(std::string(), decoder.input());
ASSERT(ok);
@ -1161,7 +1160,8 @@ void test_emptyhandlers(upb::SymbolTable* symtab, bool allowjit) {
for (int i = 0; testdata[i].data; i++) {
VerboseParserEnvironment env(filter_hash != 0);
upb::Sink sink(global_method.dest_handlers(), &closures[0]);
upb::pb::DecoderPtr decoder = CreateDecoder(env.env(), global_method, sink);
upb::pb::DecoderPtr decoder =
CreateDecoder(env.arena(), global_method, sink);
env.ResetBytesSink(decoder.input());
env.Reset(testdata[i].data, testdata[i].length, true, false);
ASSERT(env.Start());

@ -24,7 +24,7 @@ void test_pb_roundtrip() {
upb::Arena arena;
google_protobuf_FileDescriptorSet *set =
google_protobuf_FileDescriptorSet_parsenew(
upb_stringview_make(input.c_str(), input.size()), &arena);
upb_stringview_make(input.c_str(), input.size()), arena.ptr());
ASSERT(set);
size_t n;
const google_protobuf_FileDescriptorProto *const *files =
@ -33,7 +33,7 @@ void test_pb_roundtrip() {
upb::Status status;
bool ok = symtab.AddFile(files[0], &status);
if (!ok) {
fprintf(stderr, "Error building def: %s\n", upb_status_errmsg(&status));
fprintf(stderr, "Error building def: %s\n", status.error_message());
ASSERT(false);
}
upb::MessageDefPtr md =
@ -43,13 +43,12 @@ void test_pb_roundtrip() {
ASSERT(encoder_handlers);
const upb::pb::DecoderMethodPtr method = decoder_cache.Get(md);
upb::InlinedEnvironment<512> env;
std::string output;
upb::StringSink string_sink(&output);
upb::pb::EncoderPtr encoder =
upb::pb::EncoderPtr::Create(&env, encoder_handlers, string_sink.input());
upb::pb::EncoderPtr::Create(&arena, encoder_handlers, string_sink.input());
upb::pb::DecoderPtr decoder =
upb::pb::DecoderPtr::Create(&env, method, encoder.input());
upb::pb::DecoderPtr::Create(&arena, method, encoder.input());
ok = upb::PutBuffer(input, decoder.input());
ASSERT(ok);
ASSERT(input == output);

@ -672,7 +672,7 @@ void DoNothingStringBufHandler(C* closure, const char *buf, size_t len) {
}
template <class C>
void DoNothingEndMessageHandler(C* closure, upb::Status *status) {
void DoNothingEndMessageHandler(C* closure, upb_status *status) {
UPB_UNUSED(closure);
UPB_UNUSED(status);
}

@ -30,15 +30,11 @@ upb_bufhandle global_handle;
class VerboseParserEnvironment {
public:
/* Pass verbose=true to print detailed diagnostics to stderr. */
VerboseParserEnvironment(bool verbose) : verbose_(verbose) {
env_.SetErrorFunction(&VerboseParserEnvironment::OnError, this);
}
VerboseParserEnvironment(bool verbose) : verbose_(verbose) {}
static bool OnError(void *ud, const upb::Status* status) {
VerboseParserEnvironment* env = static_cast<VerboseParserEnvironment*>(ud);
env->saw_error_ = true;
if (env->expect_error_ && env->verbose_) {
fprintf(stderr, "Encountered error, as expected: ");
} else if (!env->expect_error_) {
@ -56,7 +52,6 @@ class VerboseParserEnvironment {
len_ = len;
ofs_ = 0;
expect_error_ = expect_error;
saw_error_ = false;
end_ok_set_ = false;
skip_until_ = may_skip ? 0 : -1;
skipped_with_null_ = false;
@ -94,12 +89,12 @@ class VerboseParserEnvironment {
bool CheckConsistency() {
/* If we called end (which we should only do when previous bytes are fully
* accepted), then end() should return true iff there were no errors. */
if (end_ok_set_ && end_ok_ != !saw_error_) {
if (end_ok_set_ && end_ok_ != status_.ok()) {
fprintf(stderr, "End() status and saw_error didn't match.\n");
return false;
}
if (expect_error_ && !saw_error_) {
if (expect_error_ && status_.ok()) {
fprintf(stderr, "Expected error but saw none.\n");
return false;
}
@ -158,8 +153,9 @@ class VerboseParserEnvironment {
}
}
if (saw_error_)
if (!status_.ok()) {
return false;
}
if (parsed > bytes && skip_until_ >= 0) {
skip_until_ = ofs_ + parsed;
@ -175,12 +171,14 @@ class VerboseParserEnvironment {
}
size_t ofs() { return ofs_; }
upb::Environment* env() { return &env_; }
bool SkippedWithNull() { return skipped_with_null_; }
upb::Arena* arena() { return &arena_; }
private:
upb::Environment env_;
upb::Arena arena_;
upb::Status status_;
upb::BytesSink sink_;
const char* buf_;
size_t len_;
@ -188,7 +186,6 @@ class VerboseParserEnvironment {
size_t ofs_;
void *subc_;
bool expect_error_;
bool saw_error_;
bool end_ok_;
bool end_ok_set_;

@ -15,13 +15,14 @@
#define LUPB_SYMTAB "lupb.symtab"
#define LUPB_OBJCACHE "lupb.objcache"
#define CHK(pred) do { \
upb_status status = UPB_STATUS_INIT; \
pred; \
#define CHK(pred) \
do { \
upb_status status; \
upb_status_clear(&status); \
pred; \
lupb_checkstatus(L, &status); \
} while (0)
/* lupb_wrapper ***************************************************************/
/* Wrappers around upb objects. */

@ -100,16 +100,21 @@ static void *lupb_newuserdata(lua_State *L, size_t size, const char *type) {
* it is an internal memory management detail. Other objects refer to this
* object from their userdata to keep the arena-owned data alive. */
typedef struct {
upb_arena *arena;
} lupb_arena;
upb_arena *lupb_arena_check(lua_State *L, int narg) {
return luaL_checkudata(L, narg, LUPB_ARENA);
lupb_arena *a = luaL_checkudata(L, narg, LUPB_ARENA);
return a ? a->arena : NULL;
}
int lupb_arena_new(lua_State *L) {
upb_arena *a = lupb_newuserdata(L, sizeof(upb_arena), LUPB_ARENA);
lupb_arena *a = lupb_newuserdata(L, sizeof(lupb_arena), LUPB_ARENA);
/* TODO(haberman): use Lua alloc func as block allocator? Would need to
* verify that all cases of upb_malloc in msg/table are longjmp-safe. */
upb_arena_init(a);
a->arena = upb_arena_new();
return 1;
}
@ -140,7 +145,7 @@ static void lupb_arena_initsingleton(lua_State *L) {
static int lupb_arena_gc(lua_State *L) {
upb_arena *a = lupb_arena_check(L, 1);
upb_arena_uninit(a);
upb_arena_free(a);
return 0;
}

@ -27,17 +27,15 @@ static int lupb_pb_decode(lua_State *L) {
static int lupb_pb_encode(lua_State *L) {
const upb_msglayout *layout;
const upb_msg *msg = lupb_msg_checkmsg2(L, 1, &layout);
upb_arena arena;
upb_arena *arena = upb_arena_new();
size_t size;
char *result;
upb_arena_init(&arena);
result = upb_encode(msg, (const void*)layout, &arena, &size);
result = upb_encode(msg, (const void*)layout, arena, &size);
/* Free resources before we potentially bail on error. */
lua_pushlstring(L, result, size);
upb_arena_uninit(&arena);
upb_arena_free(arena);
/* TODO(haberman): check for error. */
return 1;

@ -7,10 +7,14 @@
#include "upb/msg.h"
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
bool upb_decode(upb_stringview buf, upb_msg *msg, const upb_msglayout *l);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* UPB_DECODE_H_ */

@ -125,7 +125,7 @@ static upb_value pack_def(const void *ptr, upb_deftype_t type) {
}
struct upb_symtab {
upb_arena arena;
upb_arena *arena;
upb_strtable syms; /* full_name -> packed def ptr */
upb_strtable files; /* file_name -> upb_filedef* */
};
@ -224,7 +224,7 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
fields = upb_gmalloc(n * sizeof(*fields));
if (!fields) {
upb_upberr_setoom(s);
upb_status_setoom(s);
return false;
}
@ -870,7 +870,7 @@ const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) {
}
void upb_symtab_free(upb_symtab *s) {
upb_arena_uninit(&s->arena);
upb_arena_free(s->arena);
upb_gfree(s);
}
@ -882,12 +882,12 @@ upb_symtab *upb_symtab_new() {
return NULL;
}
upb_arena_init(&s->arena);
alloc = upb_arena_alloc(&s->arena);
s->arena = upb_arena_new();
alloc = upb_arena_alloc(s->arena);
if (!upb_strtable_init2(&s->syms, UPB_CTYPE_CONSTPTR, alloc) ||
!upb_strtable_init2(&s->files, UPB_CTYPE_CONSTPTR, alloc)) {
upb_arena_uninit(&s->arena);
upb_arena_free(s->arena);
upb_gfree(s);
s = NULL;
}
@ -922,7 +922,7 @@ const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
* to validate important constraints like uniqueness of names and numbers. */
#define CHK(x) if (!(x)) { return false; }
#define CHK_OOM(x) if (!(x)) { upb_upberr_setoom(ctx->status); return false; }
#define CHK_OOM(x) if (!(x)) { upb_status_setoom(ctx->status); return false; }
typedef struct {
const upb_symtab *symtab;
@ -1632,7 +1632,7 @@ static bool build_filedef(
static bool upb_symtab_addtotabs(upb_symtab *s, symtab_addctx *ctx,
upb_status *status) {
const upb_filedef *file = ctx->file;
upb_alloc *alloc = upb_arena_alloc(&s->arena);
upb_alloc *alloc = upb_arena_alloc(s->arena);
upb_strtable_iter iter;
CHK_OOM(upb_strtable_insert3(&s->files, file->name, strlen(file->name),
@ -1652,9 +1652,9 @@ static bool upb_symtab_addtotabs(upb_symtab *s, symtab_addctx *ctx,
bool upb_symtab_addfile(upb_symtab *s,
const google_protobuf_FileDescriptorProto *file_proto,
upb_status *status) {
upb_arena tmparena;
upb_arena *tmparena = upb_arena_new();
upb_strtable addtab;
upb_alloc *alloc = upb_arena_alloc(&s->arena);
upb_alloc *alloc = upb_arena_alloc(s->arena);
upb_filedef *file = upb_malloc(alloc, sizeof(*file));
bool ok;
symtab_addctx ctx;
@ -1662,18 +1662,16 @@ bool upb_symtab_addfile(upb_symtab *s,
ctx.file = file;
ctx.symtab = s;
ctx.alloc = alloc;
ctx.tmp = upb_arena_alloc(&tmparena);
ctx.tmp = upb_arena_alloc(tmparena);
ctx.addtab = &addtab;
ctx.status = status;
upb_arena_init(&tmparena);
ok = file &&
upb_strtable_init2(&addtab, UPB_CTYPE_CONSTPTR, ctx.tmp) &&
build_filedef(&ctx, file, file_proto) &&
upb_symtab_addtotabs(s, &ctx, status);
upb_arena_uninit(&tmparena);
upb_arena_free(tmparena);
return ok;
}
@ -1685,19 +1683,22 @@ bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) {
* print errors to stderr instead of returning error status to the user. */
upb_def_init **deps = init->deps;
google_protobuf_FileDescriptorProto *file;
upb_arena arena;
upb_status status = UPB_STATUS_INIT;
upb_arena *arena;
upb_status status;
upb_status_clear(&status);
if (upb_strtable_lookup(&s->files, init->filename, NULL)) {
return true;
}
arena = upb_arena_new();
for (; *deps; deps++) {
if (!_upb_symtab_loaddefinit(s, *deps)) goto err;
}
upb_arena_init(&arena);
file = google_protobuf_FileDescriptorProto_parsenew(init->descriptor, &arena);
file = google_protobuf_FileDescriptorProto_parsenew(init->descriptor, arena);
if (!file) {
upb_status_seterrf(
@ -1710,13 +1711,13 @@ bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) {
if (!upb_symtab_addfile(s, file, &status)) goto err;
upb_arena_uninit(&arena);
upb_arena_free(arena);
return true;
err:
fprintf(stderr, "Error loading compiled-in descriptor: %s\n",
upb_status_errmsg(&status));
upb_arena_uninit(&arena);
upb_arena_free(arena);
return false;
}

@ -56,7 +56,9 @@ typedef struct upb_symtab upb_symtab;
* protobuf wire format. */
#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
const char *upb_fielddef_fullname(const upb_fielddef *f);
upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f);
@ -93,9 +95,8 @@ const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f);
/* Internal only. */
uint32_t upb_fielddef_selectorbase(const upb_fielddef *f);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
/* A upb_fielddef describes a single field in a message. It is most often
* found as a part of a upb_msgdef, but can also stand alone to represent
@ -228,7 +229,9 @@ class upb::FieldDefPtr {
/* upb_oneofdef ***************************************************************/
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
typedef upb_inttable_iter upb_oneof_iter;
@ -262,9 +265,8 @@ void upb_oneof_iter_setdone(upb_oneof_iter *iter);
bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1,
const upb_oneof_iter *iter2);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
/* Class that represents a oneof. */
class upb::OneofDefPtr {
@ -365,7 +367,9 @@ typedef upb_strtable_iter upb_msg_oneof_iter;
#define UPB_TIMESTAMP_SECONDS 1
#define UPB_TIMESTAMP_NANOS 2
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
const char *upb_msgdef_fullname(const upb_msgdef *m);
const upb_filedef *upb_msgdef_file(const upb_msgdef *m);
@ -441,9 +445,8 @@ void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter);
bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
const upb_msg_oneof_iter *iter2);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
/* Structure that describes a single .proto message type. */
class upb::MessageDefPtr {
@ -711,7 +714,9 @@ class upb::EnumDefPtr {
/* upb_filedef ****************************************************************/
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
const char *upb_filedef_name(const upb_filedef *f);
const char *upb_filedef_package(const upb_filedef *f);
@ -725,9 +730,8 @@ const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i);
const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i);
const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
/* Class that represents a .proto file with some things defined in it.
*
@ -773,7 +777,9 @@ class upb::FileDefPtr {
/* upb_symtab *****************************************************************/
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
upb_symtab *upb_symtab_new();
void upb_symtab_free(upb_symtab* s);
@ -795,9 +801,8 @@ typedef struct upb_def_init {
bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
/* Non-const methods in upb::SymbolTable are NOT thread-safe. */
class upb::SymbolTable {
@ -823,7 +828,7 @@ class upb::SymbolTable {
/* Adds the given serialized FileDescriptorProto to the pool. */
bool AddFile(const google_protobuf_FileDescriptorProto *file_proto,
Status *status) {
return upb_symtab_addfile(ptr_.get(), file_proto, status);
return upb_symtab_addfile(ptr_.get(), file_proto, status->ptr());
}
private:

@ -7,11 +7,15 @@
#include "upb/msg.h"
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
char *upb_encode(const void *msg, const upb_msglayout *l, upb_arena *arena,
size_t *size);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* UPB_ENCODE_H_ */

@ -54,10 +54,9 @@ UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size,
size_t new_size = UPB_MAX(arr->size, 4);
size_t old_bytes = arr->size * elem_size;
size_t new_bytes;
upb_alloc *alloc = upb_arena_alloc(arr->arena);
while (new_size < size) new_size *= 2;
new_bytes = new_size * elem_size;
arr->data = upb_realloc(alloc, arr->data, old_bytes, new_bytes);
arr->data = upb_arena_realloc(arena, arr->data, old_bytes, new_bytes);
if (!arr->data) {
return NULL;
}

@ -390,7 +390,7 @@ uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
/* upb_handlercache ***********************************************************/
struct upb_handlercache {
upb_arena arena;
upb_arena *arena;
upb_inttable tab; /* maps upb_msgdef* -> upb_handlers*. */
upb_inttable cleanup_;
upb_handlers_callback *callback;
@ -407,7 +407,7 @@ const upb_handlers *upb_handlercache_get(upb_handlercache *c,
return upb_value_getptr(v);
}
h = upb_handlers_new(md, c, &c->arena);
h = upb_handlers_new(md, c, c->arena);
v = upb_value_ptr(h);
if (!h) return NULL;
@ -442,7 +442,7 @@ upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback,
if (!cache) return NULL;
upb_arena_init(&cache->arena);
cache->arena = upb_arena_new();
cache->callback = callback;
cache->closure = closure;
@ -470,7 +470,7 @@ void upb_handlercache_free(upb_handlercache *cache) {
upb_inttable_uninit(&cache->tab);
upb_inttable_uninit(&cache->cleanup_);
upb_arena_uninit(&cache->arena);
upb_arena_free(cache->arena);
upb_gfree(cache);
}

@ -157,7 +157,9 @@ typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf,
struct upb_handlers;
typedef struct upb_handlers upb_handlers;
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
/* Mutating accessors. */
const upb_status *upb_handlers_status(upb_handlers *h);
@ -235,9 +237,8 @@ UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) {
uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f);
uint32_t upb_handlers_selectorcount(const upb_fielddef *f);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
namespace upb {
typedef upb_handlers Handlers;
@ -303,7 +304,9 @@ template <class T> class upb::Handler {
const upb_handlerattr& attr() const { return attr_; }
private:
UPB_DISALLOW_COPY_AND_ASSIGN(Handler)
Handler(const Handler&) = delete;
Handler& operator=(const Handler&) = delete;
FuncPtr handler_;
mutable upb_handlerattr attr_;
mutable bool registered_;
@ -334,7 +337,8 @@ class upb::HandlersPtr {
typedef Handler<void *(*)(void *, const void *)> StartFieldHandler;
typedef Handler<bool (*)(void *, const void *)> EndFieldHandler;
typedef Handler<bool (*)(void *, const void *)> StartMessageHandler;
typedef Handler<bool (*)(void *, const void *, Status *)> EndMessageHandler;
typedef Handler<bool (*)(void *, const void *, upb_status *)>
EndMessageHandler;
typedef Handler<void *(*)(void *, const void *, size_t)> StartStringHandler;
typedef Handler<size_t (*)(void *, const void *, const char *, size_t,
const upb_bufhandle *)>
@ -590,7 +594,9 @@ class upb::HandlersPtr {
/* upb_handlercache ***********************************************************/
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
struct upb_handlercache;
typedef struct upb_handlercache upb_handlercache;
@ -605,9 +611,8 @@ const upb_handlers *upb_handlercache_get(upb_handlercache *cache,
bool upb_handlercache_addcleanup(upb_handlercache *h, void *p,
upb_handlerfree *hfree);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
class upb::HandlerCache {
public:
@ -631,8 +636,6 @@ class upb::HandlerCache {
/* upb_byteshandler ***********************************************************/
UPB_BEGIN_EXTERN_C
typedef struct {
upb_func *func;
@ -665,6 +668,10 @@ UPB_INLINE void upb_byteshandler_init(upb_byteshandler *handler) {
*handler = init;
}
#ifdef __cplusplus
extern "C" {
#endif
/* Caller must ensure that "d" outlives the handlers. */
bool upb_byteshandler_setstartstr(upb_byteshandler *h,
upb_startstr_handlerfunc *func, void *d);
@ -674,16 +681,18 @@ bool upb_byteshandler_setendstr(upb_byteshandler *h,
upb_endfield_handlerfunc *func, void *d);
#ifdef __cplusplus
} /* extern "C" */
namespace upb {
typedef upb_byteshandler BytesHandler;
}
#endif
UPB_END_EXTERN_C
/** Message handlers ******************************************************************/
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
/* These are the handlers used internally by upb_msgfactory_getmergehandlers().
* They write scalar data to a known offset from the message pointer.
@ -710,7 +719,9 @@ bool upb_msg_getscalarhandlerdata(const upb_handlers *h,
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
#endif
#include "upb/handlers-inl.h"

@ -212,7 +212,7 @@ typedef struct {
} upb_jsonparser_frame;
struct upb_json_parser {
upb_env *env;
upb_arena *arena;
const upb_json_parsermethod *method;
upb_bytessink input_;
@ -221,7 +221,7 @@ struct upb_json_parser {
upb_jsonparser_frame *top;
upb_jsonparser_frame *limit;
upb_status status;
upb_status *status;
/* Ragel's internal parsing stack for the parsing state machine. */
int current_state;
@ -259,7 +259,7 @@ struct upb_json_parser {
};
struct upb_json_codecache {
upb_arena arena;
upb_arena *arena;
upb_inttable methods; /* upb_msgdef* -> upb_json_parsermethod* */
};
@ -277,7 +277,7 @@ static upb_jsonparser_any_frame *json_parser_any_frame_new(
upb_json_parser *p) {
upb_jsonparser_any_frame *frame;
frame = upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame));
frame = upb_arena_malloc(p->arena, sizeof(upb_jsonparser_any_frame));
frame->encoder_handlercache = upb_pb_encoder_newcache();
frame->parser_codecache = upb_json_codecache_new();
@ -301,12 +301,12 @@ static void json_parser_any_frame_set_payload_type(
/* Initialize encoder. */
h = upb_handlercache_get(frame->encoder_handlercache, payload_type);
encoder = upb_pb_encoder_create(p->env, h, frame->stringsink.sink);
encoder = upb_pb_encoder_create(p->arena, h, frame->stringsink.sink);
/* Initialize parser. */
parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type);
upb_sink_reset(&frame->sink, h, encoder);
frame->parser = upb_json_parser_create(p->env, parser_method, p->symtab,
frame->parser = upb_json_parser_create(p->arena, parser_method, p->symtab,
frame->sink, p->ignore_json_unknown);
}
@ -372,8 +372,7 @@ static upb_selector_t parser_getsel(upb_json_parser *p) {
static bool check_stack(upb_json_parser *p) {
if ((p->top + 1) == p->limit) {
upb_status_seterrmsg(&p->status, "Nesting too deep");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "Nesting too deep");
return false;
}
@ -468,10 +467,9 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
char output[3];
if (limit - ptr < 4) {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"Base64 input for bytes field not a multiple of 4: %s",
upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -495,10 +493,9 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
otherchar:
if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
nonbase64(ptr[3]) ) {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"Non-base64 characters in bytes field: %s",
upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false;
} if (ptr[2] == '=') {
uint32_t val;
@ -536,11 +533,10 @@ otherchar:
}
badpadding:
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"Incorrect base64 padding for field: %s (%.*s)",
upb_fielddef_name(p->top->f),
4, ptr);
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -584,10 +580,9 @@ static bool accumulate_realloc(upb_json_parser *p, size_t need) {
new_size = saturating_multiply(new_size, 2);
}
mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
mem = upb_arena_realloc(p->arena, p->accumulate_buf, old_size, new_size);
if (!mem) {
upb_status_seterrmsg(&p->status, "Out of memory allocating buffer.");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "Out of memory allocating buffer.");
return false;
}
@ -610,8 +605,7 @@ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
}
if (!checked_add(p->accumulated_len, len, &need)) {
upb_status_seterrmsg(&p->status, "Integer overflow.");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "Integer overflow.");
return false;
}
@ -689,8 +683,7 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
switch (p->multipart_state) {
case MULTIPART_INACTIVE:
upb_status_seterrmsg(
&p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
upb_env_reporterror(p->env, &p->status);
p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
return false;
case MULTIPART_ACCUMULATE:
@ -1055,8 +1048,7 @@ static bool parse_number(upb_json_parser *p, bool is_quoted) {
multipart_end(p);
return true;
} else {
upb_status_seterrf(&p->status, "error parsing number: %s", buf);
upb_env_reporterror(p->env, &p->status);
upb_status_seterrf(p->status, "error parsing number: %s", buf);
multipart_end(p);
return false;
}
@ -1070,10 +1062,9 @@ static bool parser_putbool(upb_json_parser *p, bool val) {
}
if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"Boolean value specified for non-bool field: %s",
upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -1248,10 +1239,9 @@ static bool start_stringval(upb_json_parser *p) {
multipart_startaccum(p);
return true;
} else {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"String specified for bool or submessage field: %s",
upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false;
}
}
@ -1284,8 +1274,7 @@ static bool end_any_stringval(upb_json_parser *p) {
payload_type = upb_symtab_lookupmsg2(p->symtab, buf, len);
if (payload_type == NULL) {
upb_status_seterrf(
&p->status, "Cannot find packed type: %.*s\n", (int)len, buf);
upb_env_reporterror(p->env, &p->status);
p->status, "Cannot find packed type: %.*s\n", (int)len, buf);
return false;
}
@ -1294,8 +1283,7 @@ static bool end_any_stringval(upb_json_parser *p) {
return true;
} else {
upb_status_seterrf(
&p->status, "Invalid type url: %.*s\n", (int)len, buf);
upb_env_reporterror(p->env, &p->status);
p->status, "Invalid type url: %.*s\n", (int)len, buf);
return false;
}
}
@ -1347,8 +1335,7 @@ static bool end_stringval_nontop(upb_json_parser *p) {
upb_selector_t sel = parser_getsel(p);
upb_sink_putint32(&p->top->sink, sel, int_val);
} else {
upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf);
upb_env_reporterror(p->env, &p->status);
upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf);
}
break;
@ -1365,8 +1352,7 @@ static bool end_stringval_nontop(upb_json_parser *p) {
default:
UPB_ASSERT(false);
upb_status_seterrmsg(&p->status, "Internal error in JSON decoder");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "Internal error in JSON decoder");
ok = false;
break;
}
@ -1445,25 +1431,22 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
memcpy(seconds_buf, buf, fraction_start);
seconds = strtol(seconds_buf, &end, 10);
if (errno == ERANGE || end != seconds_buf + fraction_start) {
upb_status_seterrf(&p->status, "error parsing duration: %s",
upb_status_seterrf(p->status, "error parsing duration: %s",
seconds_buf);
upb_env_reporterror(p->env, &p->status);
return false;
}
if (seconds > 315576000000) {
upb_status_seterrf(&p->status, "error parsing duration: "
upb_status_seterrf(p->status, "error parsing duration: "
"maximum acceptable value is "
"315576000000");
upb_env_reporterror(p->env, &p->status);
return false;
}
if (seconds < -315576000000) {
upb_status_seterrf(&p->status, "error parsing duration: "
upb_status_seterrf(p->status, "error parsing duration: "
"minimum acceptable value is "
"-315576000000");
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -1472,9 +1455,8 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
memcpy(nanos_buf + 1, buf + fraction_start, len - fraction_start);
val = strtod(nanos_buf, &end);
if (errno == ERANGE || end != nanos_buf + len - fraction_start + 1) {
upb_status_seterrf(&p->status, "error parsing duration: %s",
upb_status_seterrf(p->status, "error parsing duration: %s",
nanos_buf);
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -1500,7 +1482,7 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
upb_sink_putint32(&p->top->sink, parser_getsel(p), nanos);
end_member(p);
/* Continue previous environment */
/* Continue previous arena */
multipart_startaccum(p);
return true;
@ -1530,8 +1512,7 @@ static bool end_timestamp_base(upb_json_parser *p, const char *ptr) {
/* Parse seconds */
if (strptime(timestamp_buf, "%FT%H:%M:%S%Z", &p->tm) == NULL) {
upb_status_seterrf(&p->status, "error parsing timestamp: %s", buf);
upb_env_reporterror(p->env, &p->status);
upb_status_seterrf(p->status, "error parsing timestamp: %s", buf);
return false;
}
@ -1564,9 +1545,8 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
buf = accumulate_getptr(p, &len);
if (len > 10) {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"error parsing timestamp: at most 9-digit fraction.");
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -1576,9 +1556,8 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
val = strtod(nanos_buf, &end);
if (errno == ERANGE || end != nanos_buf + len + 1) {
upb_status_seterrf(&p->status, "error parsing timestamp nanos: %s",
upb_status_seterrf(p->status, "error parsing timestamp nanos: %s",
nanos_buf);
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -1620,8 +1599,7 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
if (buf[0] != 'Z') {
if (sscanf(buf + 1, "%2d:00", &hours) != 1) {
upb_status_seterrf(&p->status, "error parsing timestamp offset");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrf(p->status, "error parsing timestamp offset");
return false;
}
@ -1637,10 +1615,9 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
/* Check timestamp boundary */
if (seconds < -62135596800) {
upb_status_seterrf(&p->status, "error parsing timestamp: "
upb_status_seterrf(p->status, "error parsing timestamp: "
"minimum acceptable value is "
"0001-01-01T00:00:00Z");
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -1681,8 +1658,7 @@ static bool parse_mapentry_key(upb_json_parser *p) {
p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
if (p->top->f == NULL) {
upb_status_seterrmsg(&p->status, "mapentry message has no key");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "mapentry message has no key");
return false;
}
switch (upb_fielddef_type(p->top->f)) {
@ -1705,9 +1681,8 @@ static bool parse_mapentry_key(upb_json_parser *p) {
return false;
}
} else {
upb_status_seterrmsg(&p->status,
upb_status_seterrmsg(p->status,
"Map bool key not 'true' or 'false'");
upb_env_reporterror(p->env, &p->status);
return false;
}
multipart_end(p);
@ -1725,8 +1700,7 @@ static bool parse_mapentry_key(upb_json_parser *p) {
break;
}
default:
upb_status_seterrmsg(&p->status, "Invalid field type for map key");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "Invalid field type for map key");
return false;
}
@ -1785,8 +1759,7 @@ static bool handle_mapentry(upb_json_parser *p) {
p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */
p->top->mapfield = mapfield;
if (p->top->f == NULL) {
upb_status_seterrmsg(&p->status, "mapentry message has no value");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "mapentry message has no value");
return false;
}
@ -1821,8 +1794,7 @@ static bool end_membername(upb_json_parser *p) {
multipart_end(p);
return true;
} else {
upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf);
upb_env_reporterror(p->env, &p->status);
upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf);
return false;
}
}
@ -1848,14 +1820,13 @@ static bool end_any_membername(upb_json_parser *p) {
static void end_member(upb_json_parser *p) {
/* If we just parsed a map-entry value, end that frame too. */
if (p->top->is_mapentry) {
upb_status s = UPB_STATUS_INIT;
upb_selector_t sel;
bool ok;
const upb_fielddef *mapfield;
UPB_ASSERT(p->top > p->stack);
/* send ENDMSG on submsg. */
upb_sink_endmsg(&p->top->sink, &s);
upb_sink_endmsg(&p->top->sink, p->status);
mapfield = p->top->mapfield;
/* send ENDSUBMSG in repeated-field-of-mapentries frame. */
@ -1949,10 +1920,9 @@ static bool start_subobject(upb_json_parser *p) {
return true;
} else {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"Object specified for non-message/group field: %s",
upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false;
}
}
@ -2060,10 +2030,9 @@ static bool start_array(upb_json_parser *p) {
}
if (!upb_fielddef_isseq(p->top->f)) {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"Array specified for non-repeated field: %s",
upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -2122,12 +2091,7 @@ static void start_object(upb_json_parser *p) {
static void end_object(upb_json_parser *p) {
if (!p->top->is_map && p->top->m != NULL) {
upb_status status;
upb_status_clear(&status);
upb_sink_endmsg(&p->top->sink, &status);
if (!upb_ok(&status)) {
upb_env_reporterror(p->env, &status);
}
upb_sink_endmsg(&p->top->sink, p->status);
}
}
@ -2146,8 +2110,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
if (json_parser_any_frame_has_value(p->top->any_frame) &&
!json_parser_any_frame_has_type_url(p->top->any_frame)) {
upb_status_seterrmsg(&p->status, "No valid type url");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "No valid type url");
return false;
}
@ -2162,8 +2125,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
p->top->any_frame->before_type_url_end -
p->top->any_frame->before_type_url_start);
if (p->top->any_frame->before_type_url_start == NULL) {
upb_status_seterrmsg(&p->status, "invalid data for well known type.");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "invalid data for well known type.");
return false;
}
p->top->any_frame->before_type_url_start++;
@ -2175,8 +2137,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
(ptr + 1) -
p->top->any_frame->after_type_url_start);
if (p->top->any_frame->after_type_url_start == NULL) {
upb_status_seterrmsg(&p->status, "Invalid data for well known type.");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "Invalid data for well known type.");
return false;
}
p->top->any_frame->after_type_url_start++;
@ -2249,7 +2210,6 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
/* Deallocate any parse frame. */
json_parser_any_frame_free(p->top->any_frame);
upb_env_free(p->env, p->top->any_frame);
return true;
}
@ -2419,11 +2379,11 @@ static bool is_string_wrapper_object(upb_json_parser *p) {
* final state once, when the closing '"' is seen. */
#line 2581 "upb/json/parser.rl"
#line 2541 "upb/json/parser.rl"
#line 2427 "upb/json/parser.c"
#line 2387 "upb/json/parser.c"
static const char _json_actions[] = {
0, 1, 0, 1, 1, 1, 3, 1,
4, 1, 6, 1, 7, 1, 8, 1,
@ -2670,7 +2630,7 @@ static const int json_en_value_machine = 75;
static const int json_en_main = 1;
#line 2584 "upb/json/parser.rl"
#line 2544 "upb/json/parser.rl"
size_t parse(void *closure, const void *hd, const char *buf, size_t size,
const upb_bufhandle *handle) {
@ -2693,7 +2653,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
capture_resume(parser, buf);
#line 2697 "upb/json/parser.c"
#line 2657 "upb/json/parser.c"
{
int _klen;
unsigned int _trans;
@ -2768,83 +2728,83 @@ _match:
switch ( *_acts++ )
{
case 1:
#line 2432 "upb/json/parser.rl"
#line 2392 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 2:
#line 2434 "upb/json/parser.rl"
#line 2394 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 23;goto _again;} }
break;
case 3:
#line 2438 "upb/json/parser.rl"
#line 2398 "upb/json/parser.rl"
{ start_text(parser, p); }
break;
case 4:
#line 2439 "upb/json/parser.rl"
#line 2399 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_text(parser, p)); }
break;
case 5:
#line 2445 "upb/json/parser.rl"
#line 2405 "upb/json/parser.rl"
{ start_hex(parser); }
break;
case 6:
#line 2446 "upb/json/parser.rl"
#line 2406 "upb/json/parser.rl"
{ hexdigit(parser, p); }
break;
case 7:
#line 2447 "upb/json/parser.rl"
#line 2407 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_hex(parser)); }
break;
case 8:
#line 2453 "upb/json/parser.rl"
#line 2413 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(escape(parser, p)); }
break;
case 9:
#line 2459 "upb/json/parser.rl"
#line 2419 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 10:
#line 2471 "upb/json/parser.rl"
#line 2431 "upb/json/parser.rl"
{ start_duration_base(parser, p); }
break;
case 11:
#line 2472 "upb/json/parser.rl"
#line 2432 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_duration_base(parser, p)); }
break;
case 12:
#line 2474 "upb/json/parser.rl"
#line 2434 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 13:
#line 2479 "upb/json/parser.rl"
#line 2439 "upb/json/parser.rl"
{ start_timestamp_base(parser, p); }
break;
case 14:
#line 2480 "upb/json/parser.rl"
#line 2440 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_base(parser, p)); }
break;
case 15:
#line 2482 "upb/json/parser.rl"
#line 2442 "upb/json/parser.rl"
{ start_timestamp_fraction(parser, p); }
break;
case 16:
#line 2483 "upb/json/parser.rl"
#line 2443 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); }
break;
case 17:
#line 2485 "upb/json/parser.rl"
#line 2445 "upb/json/parser.rl"
{ start_timestamp_zone(parser, p); }
break;
case 18:
#line 2486 "upb/json/parser.rl"
#line 2446 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); }
break;
case 19:
#line 2488 "upb/json/parser.rl"
#line 2448 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
case 20:
#line 2493 "upb/json/parser.rl"
#line 2453 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) {
{stack[top++] = cs; cs = 47;goto _again;}
@ -2856,11 +2816,11 @@ _match:
}
break;
case 21:
#line 2504 "upb/json/parser.rl"
#line 2464 "upb/json/parser.rl"
{ p--; {stack[top++] = cs; cs = 75;goto _again;} }
break;
case 22:
#line 2509 "upb/json/parser.rl"
#line 2469 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
start_any_member(parser, p);
@ -2870,11 +2830,11 @@ _match:
}
break;
case 23:
#line 2516 "upb/json/parser.rl"
#line 2476 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_membername(parser)); }
break;
case 24:
#line 2519 "upb/json/parser.rl"
#line 2479 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
end_any_member(parser, p);
@ -2884,7 +2844,7 @@ _match:
}
break;
case 25:
#line 2530 "upb/json/parser.rl"
#line 2490 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
start_any_object(parser, p);
@ -2894,7 +2854,7 @@ _match:
}
break;
case 26:
#line 2539 "upb/json/parser.rl"
#line 2499 "upb/json/parser.rl"
{
if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
CHECK_RETURN_TOP(end_any_object(parser, p));
@ -2904,54 +2864,54 @@ _match:
}
break;
case 27:
#line 2551 "upb/json/parser.rl"
#line 2511 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_array(parser)); }
break;
case 28:
#line 2555 "upb/json/parser.rl"
#line 2515 "upb/json/parser.rl"
{ end_array(parser); }
break;
case 29:
#line 2560 "upb/json/parser.rl"
#line 2520 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_number(parser, p)); }
break;
case 30:
#line 2561 "upb/json/parser.rl"
#line 2521 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
break;
case 31:
#line 2563 "upb/json/parser.rl"
#line 2523 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_stringval(parser)); }
break;
case 32:
#line 2564 "upb/json/parser.rl"
#line 2524 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_stringval(parser)); }
break;
case 33:
#line 2566 "upb/json/parser.rl"
#line 2526 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, true)); }
break;
case 34:
#line 2568 "upb/json/parser.rl"
#line 2528 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, false)); }
break;
case 35:
#line 2570 "upb/json/parser.rl"
#line 2530 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_null(parser)); }
break;
case 36:
#line 2572 "upb/json/parser.rl"
#line 2532 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(start_subobject_full(parser)); }
break;
case 37:
#line 2573 "upb/json/parser.rl"
#line 2533 "upb/json/parser.rl"
{ end_subobject_full(parser); }
break;
case 38:
#line 2578 "upb/json/parser.rl"
#line 2538 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; goto _again;} }
break;
#line 2955 "upb/json/parser.c"
#line 2915 "upb/json/parser.c"
}
}
@ -2968,32 +2928,32 @@ _again:
while ( __nacts-- > 0 ) {
switch ( *__acts++ ) {
case 0:
#line 2430 "upb/json/parser.rl"
#line 2390 "upb/json/parser.rl"
{ p--; {cs = stack[--top]; if ( p == pe )
goto _test_eof;
goto _again;} }
break;
case 30:
#line 2561 "upb/json/parser.rl"
#line 2521 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_number(parser, p)); }
break;
case 33:
#line 2566 "upb/json/parser.rl"
#line 2526 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, true)); }
break;
case 34:
#line 2568 "upb/json/parser.rl"
#line 2528 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_bool(parser, false)); }
break;
case 35:
#line 2570 "upb/json/parser.rl"
#line 2530 "upb/json/parser.rl"
{ CHECK_RETURN_TOP(end_null(parser)); }
break;
case 37:
#line 2573 "upb/json/parser.rl"
#line 2533 "upb/json/parser.rl"
{ end_subobject_full(parser); }
break;
#line 2997 "upb/json/parser.c"
#line 2957 "upb/json/parser.c"
}
}
}
@ -3001,11 +2961,10 @@ goto _again;} }
_out: {}
}
#line 2606 "upb/json/parser.rl"
#line 2566 "upb/json/parser.rl"
if (p != pe) {
upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p);
upb_env_reporterror(parser->env, &parser->status);
upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p);
} else {
capture_suspend(parser, &p);
}
@ -3049,26 +3008,25 @@ static void json_parser_reset(upb_json_parser *p) {
/* Emit Ragel initialization of the parser. */
#line 3053 "upb/json/parser.c"
#line 3012 "upb/json/parser.c"
{
cs = json_start;
top = 0;
}
#line 2653 "upb/json/parser.rl"
#line 2612 "upb/json/parser.rl"
p->current_state = cs;
p->parser_top = top;
accumulate_clear(p);
p->multipart_state = MULTIPART_INACTIVE;
p->capture = NULL;
p->accumulated = NULL;
upb_status_clear(&p->status);
}
static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c,
const upb_msgdef *md) {
upb_msg_field_iter i;
upb_alloc *alloc = upb_arena_alloc(&c->arena);
upb_alloc *alloc = upb_arena_alloc(c->arena);
upb_json_parsermethod *m = upb_malloc(alloc, sizeof(*m));
@ -3109,19 +3067,20 @@ static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c,
/* Public API *****************************************************************/
upb_json_parser *upb_json_parser_create(upb_env *env,
upb_json_parser *upb_json_parser_create(upb_arena *arena,
const upb_json_parsermethod *method,
const upb_symtab* symtab,
upb_sink output,
bool ignore_json_unknown) {
#ifndef NDEBUG
const size_t size_before = upb_env_bytesallocated(env);
const size_t size_before = upb_arena_bytesallocated(arena);
#endif
upb_json_parser *p = upb_env_malloc(env, sizeof(upb_json_parser));
upb_json_parser *p = upb_arena_malloc(arena, sizeof(upb_json_parser));
if (!p) return false;
p->env = env;
p->arena = arena;
p->method = method;
p->status = NULL;
p->limit = p->stack + UPB_JSON_MAX_DEPTH;
p->accumulate_buf = NULL;
p->accumulate_buf_size = 0;
@ -3143,8 +3102,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env,
p->ignore_json_unknown = ignore_json_unknown;
/* If this fails, uncomment and increase the value in parser.h. */
/* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <=
/* fprintf(stderr, "%zd\n", upb_arena_bytesallocated(arena) - size_before); */
UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <=
UPB_JSON_PARSER_SIZE);
return p;
}
@ -3164,8 +3123,8 @@ upb_json_codecache *upb_json_codecache_new() {
c = upb_gmalloc(sizeof(*c));
upb_arena_init(&c->arena);
alloc = upb_arena_alloc(&c->arena);
c->arena = upb_arena_new();
alloc = upb_arena_alloc(c->arena);
upb_inttable_init2(&c->methods, UPB_CTYPE_CONSTPTR, alloc);
@ -3173,7 +3132,7 @@ upb_json_codecache *upb_json_codecache_new() {
}
void upb_json_codecache_free(upb_json_codecache *c) {
upb_arena_uninit(&c->arena);
upb_arena_free(c->arena);
upb_gfree(c);
}
@ -3182,7 +3141,7 @@ const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c,
upb_json_parsermethod *m;
upb_value v;
upb_msg_field_iter i;
upb_alloc *alloc = upb_arena_alloc(&c->arena);
upb_alloc *alloc = upb_arena_alloc(c->arena);
if (upb_inttable_lookupptr(&c->methods, md, &v)) {
return upb_value_getconstptr(v);

@ -25,14 +25,15 @@ class ParserMethodPtr;
struct upb_json_parsermethod;
typedef struct upb_json_parsermethod upb_json_parsermethod;
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
const upb_byteshandler* upb_json_parsermethod_inputhandler(
const upb_json_parsermethod* m);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
class upb::json::ParserMethodPtr {
public:
@ -62,17 +63,19 @@ class upb::json::ParserMethodPtr {
struct upb_json_parser;
typedef struct upb_json_parser upb_json_parser;
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
upb_json_parser*
upb_json_parser_create(upb_env* e, const upb_json_parsermethod* m,
const upb_symtab* symtab, upb_sink output,
bool ignore_json_unknown);
upb_json_parser* upb_json_parser_create(upb_arena* a,
const upb_json_parsermethod* m,
const upb_symtab* symtab,
upb_sink output,
bool ignore_json_unknown);
upb_bytessink upb_json_parser_input(upb_json_parser* p);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
/* Parses an incoming BytesStream, pushing the results to the destination
* sink. */
@ -80,12 +83,13 @@ class upb::json::ParserPtr {
public:
ParserPtr(upb_json_parser* ptr) : ptr_(ptr) {}
static ParserPtr Create(Environment* env, ParserMethodPtr method,
static ParserPtr Create(Arena* arena, ParserMethodPtr method,
SymbolTable* symtab, Sink output,
bool ignore_json_unknown) {
upb_symtab* symtab_ptr = symtab ? symtab->ptr() : nullptr;
return ParserPtr(upb_json_parser_create(
env, method.ptr(), symtab_ptr, output.sink(), ignore_json_unknown));
return ParserPtr(upb_json_parser_create(arena->ptr(), method.ptr(),
symtab_ptr, output.sink(),
ignore_json_unknown));
}
BytesSink input() { return upb_json_parser_input(ptr_); }
@ -101,16 +105,17 @@ class upb::json::ParserPtr {
struct upb_json_codecache;
typedef struct upb_json_codecache upb_json_codecache;
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
upb_json_codecache *upb_json_codecache_new();
void upb_json_codecache_free(upb_json_codecache *cache);
const upb_json_parsermethod* upb_json_codecache_get(upb_json_codecache* cache,
const upb_msgdef* md);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
class upb::json::CodeCache {
public:

@ -210,7 +210,7 @@ typedef struct {
} upb_jsonparser_frame;
struct upb_json_parser {
upb_env *env;
upb_arena *arena;
const upb_json_parsermethod *method;
upb_bytessink input_;
@ -219,7 +219,7 @@ struct upb_json_parser {
upb_jsonparser_frame *top;
upb_jsonparser_frame *limit;
upb_status status;
upb_status *status;
/* Ragel's internal parsing stack for the parsing state machine. */
int current_state;
@ -257,7 +257,7 @@ struct upb_json_parser {
};
struct upb_json_codecache {
upb_arena arena;
upb_arena *arena;
upb_inttable methods; /* upb_msgdef* -> upb_json_parsermethod* */
};
@ -275,7 +275,7 @@ static upb_jsonparser_any_frame *json_parser_any_frame_new(
upb_json_parser *p) {
upb_jsonparser_any_frame *frame;
frame = upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame));
frame = upb_arena_malloc(p->arena, sizeof(upb_jsonparser_any_frame));
frame->encoder_handlercache = upb_pb_encoder_newcache();
frame->parser_codecache = upb_json_codecache_new();
@ -299,12 +299,12 @@ static void json_parser_any_frame_set_payload_type(
/* Initialize encoder. */
h = upb_handlercache_get(frame->encoder_handlercache, payload_type);
encoder = upb_pb_encoder_create(p->env, h, frame->stringsink.sink);
encoder = upb_pb_encoder_create(p->arena, h, frame->stringsink.sink);
/* Initialize parser. */
parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type);
upb_sink_reset(&frame->sink, h, encoder);
frame->parser = upb_json_parser_create(p->env, parser_method, p->symtab,
frame->parser = upb_json_parser_create(p->arena, parser_method, p->symtab,
frame->sink, p->ignore_json_unknown);
}
@ -370,8 +370,7 @@ static upb_selector_t parser_getsel(upb_json_parser *p) {
static bool check_stack(upb_json_parser *p) {
if ((p->top + 1) == p->limit) {
upb_status_seterrmsg(&p->status, "Nesting too deep");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "Nesting too deep");
return false;
}
@ -466,10 +465,9 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
char output[3];
if (limit - ptr < 4) {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"Base64 input for bytes field not a multiple of 4: %s",
upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -493,10 +491,9 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
otherchar:
if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
nonbase64(ptr[3]) ) {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"Non-base64 characters in bytes field: %s",
upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false;
} if (ptr[2] == '=') {
uint32_t val;
@ -534,11 +531,10 @@ otherchar:
}
badpadding:
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"Incorrect base64 padding for field: %s (%.*s)",
upb_fielddef_name(p->top->f),
4, ptr);
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -582,10 +578,9 @@ static bool accumulate_realloc(upb_json_parser *p, size_t need) {
new_size = saturating_multiply(new_size, 2);
}
mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
mem = upb_arena_realloc(p->arena, p->accumulate_buf, old_size, new_size);
if (!mem) {
upb_status_seterrmsg(&p->status, "Out of memory allocating buffer.");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "Out of memory allocating buffer.");
return false;
}
@ -608,8 +603,7 @@ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
}
if (!checked_add(p->accumulated_len, len, &need)) {
upb_status_seterrmsg(&p->status, "Integer overflow.");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "Integer overflow.");
return false;
}
@ -687,8 +681,7 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
switch (p->multipart_state) {
case MULTIPART_INACTIVE:
upb_status_seterrmsg(
&p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
upb_env_reporterror(p->env, &p->status);
p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
return false;
case MULTIPART_ACCUMULATE:
@ -1053,8 +1046,7 @@ static bool parse_number(upb_json_parser *p, bool is_quoted) {
multipart_end(p);
return true;
} else {
upb_status_seterrf(&p->status, "error parsing number: %s", buf);
upb_env_reporterror(p->env, &p->status);
upb_status_seterrf(p->status, "error parsing number: %s", buf);
multipart_end(p);
return false;
}
@ -1068,10 +1060,9 @@ static bool parser_putbool(upb_json_parser *p, bool val) {
}
if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"Boolean value specified for non-bool field: %s",
upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -1246,10 +1237,9 @@ static bool start_stringval(upb_json_parser *p) {
multipart_startaccum(p);
return true;
} else {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"String specified for bool or submessage field: %s",
upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false;
}
}
@ -1282,8 +1272,7 @@ static bool end_any_stringval(upb_json_parser *p) {
payload_type = upb_symtab_lookupmsg2(p->symtab, buf, len);
if (payload_type == NULL) {
upb_status_seterrf(
&p->status, "Cannot find packed type: %.*s\n", (int)len, buf);
upb_env_reporterror(p->env, &p->status);
p->status, "Cannot find packed type: %.*s\n", (int)len, buf);
return false;
}
@ -1292,8 +1281,7 @@ static bool end_any_stringval(upb_json_parser *p) {
return true;
} else {
upb_status_seterrf(
&p->status, "Invalid type url: %.*s\n", (int)len, buf);
upb_env_reporterror(p->env, &p->status);
p->status, "Invalid type url: %.*s\n", (int)len, buf);
return false;
}
}
@ -1345,8 +1333,7 @@ static bool end_stringval_nontop(upb_json_parser *p) {
upb_selector_t sel = parser_getsel(p);
upb_sink_putint32(&p->top->sink, sel, int_val);
} else {
upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf);
upb_env_reporterror(p->env, &p->status);
upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf);
}
break;
@ -1363,8 +1350,7 @@ static bool end_stringval_nontop(upb_json_parser *p) {
default:
UPB_ASSERT(false);
upb_status_seterrmsg(&p->status, "Internal error in JSON decoder");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "Internal error in JSON decoder");
ok = false;
break;
}
@ -1443,25 +1429,22 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
memcpy(seconds_buf, buf, fraction_start);
seconds = strtol(seconds_buf, &end, 10);
if (errno == ERANGE || end != seconds_buf + fraction_start) {
upb_status_seterrf(&p->status, "error parsing duration: %s",
upb_status_seterrf(p->status, "error parsing duration: %s",
seconds_buf);
upb_env_reporterror(p->env, &p->status);
return false;
}
if (seconds > 315576000000) {
upb_status_seterrf(&p->status, "error parsing duration: "
upb_status_seterrf(p->status, "error parsing duration: "
"maximum acceptable value is "
"315576000000");
upb_env_reporterror(p->env, &p->status);
return false;
}
if (seconds < -315576000000) {
upb_status_seterrf(&p->status, "error parsing duration: "
upb_status_seterrf(p->status, "error parsing duration: "
"minimum acceptable value is "
"-315576000000");
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -1470,9 +1453,8 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
memcpy(nanos_buf + 1, buf + fraction_start, len - fraction_start);
val = strtod(nanos_buf, &end);
if (errno == ERANGE || end != nanos_buf + len - fraction_start + 1) {
upb_status_seterrf(&p->status, "error parsing duration: %s",
upb_status_seterrf(p->status, "error parsing duration: %s",
nanos_buf);
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -1498,7 +1480,7 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) {
upb_sink_putint32(&p->top->sink, parser_getsel(p), nanos);
end_member(p);
/* Continue previous environment */
/* Continue previous arena */
multipart_startaccum(p);
return true;
@ -1528,8 +1510,7 @@ static bool end_timestamp_base(upb_json_parser *p, const char *ptr) {
/* Parse seconds */
if (strptime(timestamp_buf, "%FT%H:%M:%S%Z", &p->tm) == NULL) {
upb_status_seterrf(&p->status, "error parsing timestamp: %s", buf);
upb_env_reporterror(p->env, &p->status);
upb_status_seterrf(p->status, "error parsing timestamp: %s", buf);
return false;
}
@ -1562,9 +1543,8 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
buf = accumulate_getptr(p, &len);
if (len > 10) {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"error parsing timestamp: at most 9-digit fraction.");
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -1574,9 +1554,8 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
val = strtod(nanos_buf, &end);
if (errno == ERANGE || end != nanos_buf + len + 1) {
upb_status_seterrf(&p->status, "error parsing timestamp nanos: %s",
upb_status_seterrf(p->status, "error parsing timestamp nanos: %s",
nanos_buf);
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -1618,8 +1597,7 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
if (buf[0] != 'Z') {
if (sscanf(buf + 1, "%2d:00", &hours) != 1) {
upb_status_seterrf(&p->status, "error parsing timestamp offset");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrf(p->status, "error parsing timestamp offset");
return false;
}
@ -1635,10 +1613,9 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
/* Check timestamp boundary */
if (seconds < -62135596800) {
upb_status_seterrf(&p->status, "error parsing timestamp: "
upb_status_seterrf(p->status, "error parsing timestamp: "
"minimum acceptable value is "
"0001-01-01T00:00:00Z");
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -1679,8 +1656,7 @@ static bool parse_mapentry_key(upb_json_parser *p) {
p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
if (p->top->f == NULL) {
upb_status_seterrmsg(&p->status, "mapentry message has no key");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "mapentry message has no key");
return false;
}
switch (upb_fielddef_type(p->top->f)) {
@ -1703,9 +1679,8 @@ static bool parse_mapentry_key(upb_json_parser *p) {
return false;
}
} else {
upb_status_seterrmsg(&p->status,
upb_status_seterrmsg(p->status,
"Map bool key not 'true' or 'false'");
upb_env_reporterror(p->env, &p->status);
return false;
}
multipart_end(p);
@ -1723,8 +1698,7 @@ static bool parse_mapentry_key(upb_json_parser *p) {
break;
}
default:
upb_status_seterrmsg(&p->status, "Invalid field type for map key");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "Invalid field type for map key");
return false;
}
@ -1783,8 +1757,7 @@ static bool handle_mapentry(upb_json_parser *p) {
p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */
p->top->mapfield = mapfield;
if (p->top->f == NULL) {
upb_status_seterrmsg(&p->status, "mapentry message has no value");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "mapentry message has no value");
return false;
}
@ -1819,8 +1792,7 @@ static bool end_membername(upb_json_parser *p) {
multipart_end(p);
return true;
} else {
upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf);
upb_env_reporterror(p->env, &p->status);
upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf);
return false;
}
}
@ -1846,14 +1818,13 @@ static bool end_any_membername(upb_json_parser *p) {
static void end_member(upb_json_parser *p) {
/* If we just parsed a map-entry value, end that frame too. */
if (p->top->is_mapentry) {
upb_status s = UPB_STATUS_INIT;
upb_selector_t sel;
bool ok;
const upb_fielddef *mapfield;
UPB_ASSERT(p->top > p->stack);
/* send ENDMSG on submsg. */
upb_sink_endmsg(&p->top->sink, &s);
upb_sink_endmsg(&p->top->sink, p->status);
mapfield = p->top->mapfield;
/* send ENDSUBMSG in repeated-field-of-mapentries frame. */
@ -1947,10 +1918,9 @@ static bool start_subobject(upb_json_parser *p) {
return true;
} else {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"Object specified for non-message/group field: %s",
upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false;
}
}
@ -2058,10 +2028,9 @@ static bool start_array(upb_json_parser *p) {
}
if (!upb_fielddef_isseq(p->top->f)) {
upb_status_seterrf(&p->status,
upb_status_seterrf(p->status,
"Array specified for non-repeated field: %s",
upb_fielddef_name(p->top->f));
upb_env_reporterror(p->env, &p->status);
return false;
}
@ -2120,12 +2089,7 @@ static void start_object(upb_json_parser *p) {
static void end_object(upb_json_parser *p) {
if (!p->top->is_map && p->top->m != NULL) {
upb_status status;
upb_status_clear(&status);
upb_sink_endmsg(&p->top->sink, &status);
if (!upb_ok(&status)) {
upb_env_reporterror(p->env, &status);
}
upb_sink_endmsg(&p->top->sink, p->status);
}
}
@ -2144,8 +2108,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
if (json_parser_any_frame_has_value(p->top->any_frame) &&
!json_parser_any_frame_has_type_url(p->top->any_frame)) {
upb_status_seterrmsg(&p->status, "No valid type url");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "No valid type url");
return false;
}
@ -2160,8 +2123,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
p->top->any_frame->before_type_url_end -
p->top->any_frame->before_type_url_start);
if (p->top->any_frame->before_type_url_start == NULL) {
upb_status_seterrmsg(&p->status, "invalid data for well known type.");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "invalid data for well known type.");
return false;
}
p->top->any_frame->before_type_url_start++;
@ -2173,8 +2135,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
(ptr + 1) -
p->top->any_frame->after_type_url_start);
if (p->top->any_frame->after_type_url_start == NULL) {
upb_status_seterrmsg(&p->status, "Invalid data for well known type.");
upb_env_reporterror(p->env, &p->status);
upb_status_seterrmsg(p->status, "Invalid data for well known type.");
return false;
}
p->top->any_frame->after_type_url_start++;
@ -2247,7 +2208,6 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) {
/* Deallocate any parse frame. */
json_parser_any_frame_free(p->top->any_frame);
upb_env_free(p->env, p->top->any_frame);
return true;
}
@ -2605,8 +2565,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size,
%% write exec;
if (p != pe) {
upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p);
upb_env_reporterror(parser->env, &parser->status);
upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p);
} else {
capture_suspend(parser, &p);
}
@ -2656,13 +2615,12 @@ static void json_parser_reset(upb_json_parser *p) {
p->multipart_state = MULTIPART_INACTIVE;
p->capture = NULL;
p->accumulated = NULL;
upb_status_clear(&p->status);
}
static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c,
const upb_msgdef *md) {
upb_msg_field_iter i;
upb_alloc *alloc = upb_arena_alloc(&c->arena);
upb_alloc *alloc = upb_arena_alloc(c->arena);
upb_json_parsermethod *m = upb_malloc(alloc, sizeof(*m));
@ -2703,19 +2661,20 @@ static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c,
/* Public API *****************************************************************/
upb_json_parser *upb_json_parser_create(upb_env *env,
upb_json_parser *upb_json_parser_create(upb_arena *arena,
const upb_json_parsermethod *method,
const upb_symtab* symtab,
upb_sink output,
bool ignore_json_unknown) {
#ifndef NDEBUG
const size_t size_before = upb_env_bytesallocated(env);
const size_t size_before = upb_arena_bytesallocated(arena);
#endif
upb_json_parser *p = upb_env_malloc(env, sizeof(upb_json_parser));
upb_json_parser *p = upb_arena_malloc(arena, sizeof(upb_json_parser));
if (!p) return false;
p->env = env;
p->arena = arena;
p->method = method;
p->status = NULL;
p->limit = p->stack + UPB_JSON_MAX_DEPTH;
p->accumulate_buf = NULL;
p->accumulate_buf_size = 0;
@ -2737,8 +2696,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env,
p->ignore_json_unknown = ignore_json_unknown;
/* If this fails, uncomment and increase the value in parser.h. */
/* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <=
/* fprintf(stderr, "%zd\n", upb_arena_bytesallocated(arena) - size_before); */
UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <=
UPB_JSON_PARSER_SIZE);
return p;
}
@ -2758,8 +2717,8 @@ upb_json_codecache *upb_json_codecache_new() {
c = upb_gmalloc(sizeof(*c));
upb_arena_init(&c->arena);
alloc = upb_arena_alloc(&c->arena);
c->arena = upb_arena_new();
alloc = upb_arena_alloc(c->arena);
upb_inttable_init2(&c->methods, UPB_CTYPE_CONSTPTR, alloc);
@ -2767,7 +2726,7 @@ upb_json_codecache *upb_json_codecache_new() {
}
void upb_json_codecache_free(upb_json_codecache *c) {
upb_arena_uninit(&c->arena);
upb_arena_free(c->arena);
upb_gfree(c);
}
@ -2776,7 +2735,7 @@ const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c,
upb_json_parsermethod *m;
upb_value v;
upb_msg_field_iter i;
upb_alloc *alloc = upb_arena_alloc(&c->arena);
upb_alloc *alloc = upb_arena_alloc(c->arena);
if (upb_inttable_lookupptr(&c->methods, md, &v)) {
return upb_value_getconstptr(v);

@ -1252,13 +1252,13 @@ static void json_printer_reset(upb_json_printer *p) {
/* Public API *****************************************************************/
upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h,
upb_bytessink output) {
#ifndef NDEBUG
size_t size_before = upb_env_bytesallocated(e);
size_t size_before = upb_arena_bytesallocated(a);
#endif
upb_json_printer *p = upb_env_malloc(e, sizeof(upb_json_printer));
upb_json_printer *p = upb_arena_malloc(a, sizeof(upb_json_printer));
if (!p) return NULL;
p->output_ = output;
@ -1268,7 +1268,7 @@ upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
p->nanos = 0;
/* If this fails, increase the value in printer.h. */
UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <=
UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <=
UPB_JSON_PRINTER_SIZE);
return p;
}

@ -24,10 +24,12 @@ class PrinterPtr;
struct upb_json_printer;
typedef struct upb_json_printer upb_json_printer;
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
/* Native C API. */
upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h,
upb_bytessink output);
upb_sink upb_json_printer_input(upb_json_printer *p);
const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
@ -36,18 +38,18 @@ const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
/* Prints an incoming stream of data to a BytesSink in JSON format. */
class upb::json::PrinterPtr {
public:
PrinterPtr(upb_json_printer* ptr) : ptr_(ptr) {}
static PrinterPtr Create(Environment *env, const upb::Handlers *handlers,
static PrinterPtr Create(Arena *arena, const upb::Handlers *handlers,
BytesSink output) {
return PrinterPtr(upb_json_printer_create(env, handlers, output.sink()));
return PrinterPtr(
upb_json_printer_create(arena->ptr(), handlers, output.sink()));
}
/* The input to the printer. */

@ -37,18 +37,22 @@ class MessageLayout;
#endif
UPB_DECLARE_TYPE(upb::Map, upb_map)
UPB_DECLARE_TYPE(upb::MapIterator, upb_mapiter)
struct upb_array;
typedef struct upb_array upb_array;
/* TODO(haberman): C++ accessors */
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
typedef void upb_msg;
struct upb_array;
typedef struct upb_array upb_array;
struct upb_map;
typedef struct upb_map upb_map;
struct upb_mapiter;
typedef struct upb_mapiter upb_mapiter;
/** upb_msglayout *************************************************************/
@ -75,7 +79,6 @@ typedef struct upb_msglayout {
bool extendable;
} upb_msglayout;
/** upb_stringview ************************************************************/
typedef struct {
@ -103,7 +106,6 @@ UPB_INLINE bool upb_stringview_eql(upb_stringview a, upb_stringview b) {
#define UPB_STRINGVIEW_INIT(ptr, len) {ptr, len}
/** upb_msgval ****************************************************************/
/* A union representing all possible protobuf values. Used for generic get/set
@ -156,7 +158,6 @@ UPB_INLINE upb_msgval upb_msgval_makestr(const char *data, size_t size) {
return upb_msgval_str(upb_stringview_make(data, size));
}
/** upb_msg *******************************************************************/
/* A upb_msg represents a protobuf message. It always corresponds to a specific
@ -216,7 +217,6 @@ bool upb_msg_clearfield(upb_msg *msg,
/* TODO(haberman): copyfrom()/mergefrom()? */
/** upb_array *****************************************************************/
/* A upb_array stores data for a repeated field. The memory management
@ -236,7 +236,6 @@ upb_msgval upb_array_get(const upb_array *arr, size_t i);
bool upb_array_set(upb_array *arr, size_t i, upb_msgval val);
/** upb_map *******************************************************************/
/* A upb_map stores data for a map field. The memory management semantics are
@ -268,7 +267,6 @@ bool upb_map_set(upb_map *map,
/* Deletes an entry in the map. Returns true if the key was present. */
bool upb_map_del(upb_map *map, upb_msgval key);
/** upb_mapiter ***************************************************************/
/* For iterating over a map. Map iterators are invalidated by mutations to the
@ -290,6 +288,8 @@ upb_msgval upb_mapiter_value(const upb_mapiter *i);
void upb_mapiter_setdone(upb_mapiter *i);
bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* UPB_MSG_H_ */

@ -5,10 +5,15 @@
#ifndef UPB_MSGFACTORY_H_
#define UPB_MSGFACTORY_H_
UPB_DECLARE_TYPE(upb::MessageFactory, upb_msgfactory)
/** upb_msgfactory ************************************************************/
struct upb_msgfactory;
typedef struct upb_msgfactory upb_msgfactory;
#ifdef __cplusplus
extern "C" {
#endif
/* A upb_msgfactory contains a cache of upb_msglayout, upb_handlers, and
* upb_visitorplan objects. These are the objects necessary to represent,
* populate, and and visit upb_msg objects.
@ -36,5 +41,8 @@ const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f);
const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f,
const upb_msgdef *m);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* UPB_MSGFACTORY_H_ */

@ -907,7 +907,7 @@ upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest) {
c->allow_jit = true;
c->lazy = false;
upb_arena_init(&c->arena);
c->arena = upb_arena_new();
if (!upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR)) return NULL;
return c;

@ -99,9 +99,7 @@ static bool in_residual_buf(const upb_pbdecoder *d, const char *p);
* benchmarks. */
static void seterr(upb_pbdecoder *d, const char *msg) {
upb_status status = UPB_STATUS_INIT;
upb_status_seterrmsg(&status, msg);
upb_env_reporterror(d->env, &status);
upb_status_seterrmsg(d->status, msg);
}
void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) {
@ -992,24 +990,24 @@ void upb_pbdecoder_reset(upb_pbdecoder *d) {
d->residual_end = d->residual;
}
upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m,
upb_pbdecoder *upb_pbdecoder_create(upb_arena *a, const upb_pbdecodermethod *m,
upb_sink sink) {
const size_t default_max_nesting = 64;
#ifndef NDEBUG
size_t size_before = upb_env_bytesallocated(e);
size_t size_before = upb_arena_bytesallocated(a);
#endif
upb_pbdecoder *d = upb_env_malloc(e, sizeof(upb_pbdecoder));
upb_pbdecoder *d = upb_arena_malloc(a, sizeof(upb_pbdecoder));
if (!d) return NULL;
d->method_ = m;
d->callstack = upb_env_malloc(e, callstacksize(d, default_max_nesting));
d->stack = upb_env_malloc(e, stacksize(d, default_max_nesting));
d->callstack = upb_arena_malloc(a, callstacksize(d, default_max_nesting));
d->stack = upb_arena_malloc(a, stacksize(d, default_max_nesting));
if (!d->stack || !d->callstack) {
return NULL;
}
d->env = e;
d->arena = a;
d->limit = d->stack + default_max_nesting - 1;
d->stack_size = default_max_nesting;
d->status = NULL;
@ -1024,7 +1022,7 @@ upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m,
d->top->sink = sink;
/* If this fails, increase the value in decoder.h. */
UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <=
UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <=
UPB_PB_DECODER_SIZE);
return d;
}
@ -1057,7 +1055,7 @@ bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
/* Need to reallocate stack and callstack to accommodate. */
size_t old_size = stacksize(d, d->stack_size);
size_t new_size = stacksize(d, max);
void *p = upb_env_realloc(d->env, d->stack, old_size, new_size);
void *p = upb_arena_realloc(d->arena, d->stack, old_size, new_size);
if (!p) {
return false;
}
@ -1065,7 +1063,7 @@ bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
old_size = callstacksize(d, d->stack_size);
new_size = callstacksize(d, max);
p = upb_env_realloc(d->env, d->callstack, old_size, new_size);
p = upb_arena_realloc(d->arena, d->callstack, old_size, new_size);
if (!p) {
return false;
}

@ -40,7 +40,9 @@ class DecoderMethodOptions;
struct upb_pbdecodermethod;
typedef struct upb_pbdecodermethod upb_pbdecodermethod;
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
const upb_handlers *upb_pbdecodermethod_desthandlers(
const upb_pbdecodermethod *m);
@ -48,9 +50,8 @@ const upb_byteshandler *upb_pbdecodermethod_inputhandler(
const upb_pbdecodermethod *m);
bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
/* Represents the code to parse a protobuf according to a destination
* Handlers. */
@ -95,9 +96,11 @@ class upb::pb::DecoderMethodPtr {
struct upb_pbdecoder;
typedef struct upb_pbdecoder upb_pbdecoder;
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
upb_pbdecoder *upb_pbdecoder_create(upb_env *e,
upb_pbdecoder *upb_pbdecoder_create(upb_arena *arena,
const upb_pbdecodermethod *method,
upb_sink output);
const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d);
@ -107,9 +110,8 @@ size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d);
bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max);
void upb_pbdecoder_reset(upb_pbdecoder *d);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
/* A Decoder receives binary protobuf data on its input sink and pushes the
* decoded data to its output sink. */
@ -124,9 +126,10 @@ class upb::pb::DecoderPtr {
* must also outlive this decoder.
*
* The sink must match the given method. */
static DecoderPtr Create(Environment *env, DecoderMethodPtr method,
static DecoderPtr Create(Arena *arena, DecoderMethodPtr method,
upb::Sink output) {
return DecoderPtr(upb_pbdecoder_create(env, method.ptr(), output.sink()));
return DecoderPtr(
upb_pbdecoder_create(arena->ptr(), method.ptr(), output.sink()));
}
/* Returns the DecoderMethod this decoder is parsing from. */
@ -171,7 +174,9 @@ class upb::pb::DecoderPtr {
struct upb_pbcodecache;
typedef struct upb_pbcodecache upb_pbcodecache;
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest);
void upb_pbcodecache_free(upb_pbcodecache *c);
@ -181,9 +186,8 @@ void upb_pbcodecache_setlazy(upb_pbcodecache *c, bool lazy);
const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c,
const upb_msgdef *md);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
/* A class for caching protobuf processing code, whether bytecode for the
* interpreted decoder or machine code for the JIT.

@ -73,7 +73,7 @@ typedef enum {
UPB_INLINE opcode getop(uint32_t instr) { return instr & 0xff; }
struct upb_pbcodecache {
upb_arena arena;
upb_arena *arena;
upb_handlercache *dest;
bool allow_jit;
bool lazy;
@ -169,7 +169,7 @@ struct upb_pbdecodermethod {
};
struct upb_pbdecoder {
upb_env *env;
upb_arena *arena;
/* Our input sink. */
upb_bytessink input_;

@ -91,7 +91,7 @@ typedef struct {
} upb_pb_encoder_segment;
struct upb_pb_encoder {
upb_env *env;
upb_arena *arena;
/* Our input and output. */
upb_sink input_;
@ -150,7 +150,7 @@ static bool reserve(upb_pb_encoder *e, size_t bytes) {
new_size *= 2;
}
new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size);
new_buf = upb_arena_realloc(e->arena, e->buf, old_size, new_size);
if (new_buf == NULL) {
return false;
@ -230,7 +230,7 @@ static bool start_delim(upb_pb_encoder *e) {
(e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment);
size_t new_size = old_size * 2;
upb_pb_encoder_segment *new_buf =
upb_env_realloc(e->env, e->segbuf, old_size, new_size);
upb_arena_realloc(e->arena, e->segbuf, old_size, new_size);
if (new_buf == NULL) {
return false;
@ -526,22 +526,22 @@ upb_handlercache *upb_pb_encoder_newcache() {
return upb_handlercache_new(newhandlers_callback, NULL);
}
upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h,
upb_pb_encoder *upb_pb_encoder_create(upb_arena *arena, const upb_handlers *h,
upb_bytessink output) {
const size_t initial_bufsize = 256;
const size_t initial_segbufsize = 16;
/* TODO(haberman): make this configurable. */
const size_t stack_size = 64;
#ifndef NDEBUG
const size_t size_before = upb_env_bytesallocated(env);
const size_t size_before = upb_arena_bytesallocated(arena);
#endif
upb_pb_encoder *e = upb_env_malloc(env, sizeof(upb_pb_encoder));
upb_pb_encoder *e = upb_arena_malloc(arena, sizeof(upb_pb_encoder));
if (!e) return NULL;
e->buf = upb_env_malloc(env, initial_bufsize);
e->segbuf = upb_env_malloc(env, initial_segbufsize * sizeof(*e->segbuf));
e->stack = upb_env_malloc(env, stack_size * sizeof(*e->stack));
e->buf = upb_arena_malloc(arena, initial_bufsize);
e->segbuf = upb_arena_malloc(arena, initial_segbufsize * sizeof(*e->segbuf));
e->stack = upb_arena_malloc(arena, stack_size * sizeof(*e->stack));
if (!e->buf || !e->segbuf || !e->stack) {
return NULL;
@ -554,13 +554,13 @@ upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h,
upb_pb_encoder_reset(e);
upb_sink_reset(&e->input_, h, e);
e->env = env;
e->arena = arena;
e->output_ = output;
e->subc = output.closure;
e->ptr = e->buf;
/* If this fails, increase the value in encoder.h. */
UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <=
UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <=
UPB_PB_ENCODER_SIZE);
return e;
}

@ -35,17 +35,18 @@ class EncoderPtr;
struct upb_pb_encoder;
typedef struct upb_pb_encoder upb_pb_encoder;
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
upb_sink upb_pb_encoder_input(upb_pb_encoder *p);
upb_pb_encoder* upb_pb_encoder_create(upb_env* e, const upb_handlers* h,
upb_pb_encoder* upb_pb_encoder_create(upb_arena* a, const upb_handlers* h,
upb_bytessink output);
upb_handlercache *upb_pb_encoder_newcache();
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" { */
class upb::pb::EncoderPtr {
public:
@ -55,9 +56,10 @@ class upb::pb::EncoderPtr {
/* Creates a new encoder in the given environment. The Handlers must have
* come from NewHandlers() below. */
static EncoderPtr Create(Environment* env, const Handlers* handlers,
static EncoderPtr Create(Arena* arena, const Handlers* handlers,
BytesSink output) {
return EncoderPtr(upb_pb_encoder_create(env, handlers, output.sink()));
return EncoderPtr(
upb_pb_encoder_create(arena->ptr(), handlers, output.sink()));
}
/* The input to the encoder. */

@ -18,7 +18,7 @@
struct upb_textprinter {
upb_sink input_;
upb_bytessink *output_;
upb_bytessink output_;
int indent_depth_;
bool single_line_;
void *subc;
@ -35,13 +35,13 @@ static int indent(upb_textprinter *p) {
int i;
if (!p->single_line_)
for (i = 0; i < p->indent_depth_; i++)
upb_bytessink_putbuf(p->output_, p->subc, " ", 2, NULL);
upb_bytessink_putbuf(&p->output_, p->subc, " ", 2, NULL);
return 0;
}
static int endfield(upb_textprinter *p) {
const char ch = (p->single_line_ ? ' ' : '\n');
upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL);
upb_bytessink_putbuf(&p->output_, p->subc, &ch, 1, NULL);
return 0;
}
@ -60,7 +60,7 @@ static int putescaped(upb_textprinter *p, const char *buf, size_t len,
bool is_hex_escape;
if (dstend - dst < 4) {
upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
upb_bytessink_putbuf(&p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
dst = dstbuf;
}
@ -88,7 +88,7 @@ static int putescaped(upb_textprinter *p, const char *buf, size_t len,
last_hex_escape = is_hex_escape;
}
/* Flush remaining data. */
upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
upb_bytessink_putbuf(&p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
return 0;
}
@ -114,7 +114,7 @@ bool putf(upb_textprinter *p, const char *fmt, ...) {
va_end(args);
UPB_ASSERT(written == len);
ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL);
ok = upb_bytessink_putbuf(&p->output_, p->subc, str, len, NULL);
upb_gfree(str);
return ok;
}
@ -126,7 +126,7 @@ static bool textprinter_startmsg(void *c, const void *hd) {
upb_textprinter *p = c;
UPB_UNUSED(hd);
if (p->indent_depth_ == 0) {
upb_bytessink_start(p->output_, 0, &p->subc);
upb_bytessink_start(&p->output_, 0, &p->subc);
}
return true;
}
@ -136,7 +136,7 @@ static bool textprinter_endmsg(void *c, const void *hd, upb_status *s) {
UPB_UNUSED(hd);
UPB_UNUSED(s);
if (p->indent_depth_ == 0) {
upb_bytessink_end(p->output_);
upb_bytessink_end(&p->output_);
}
return true;
}
@ -241,7 +241,7 @@ static bool textprinter_endsubmsg(void *closure, const void *handler_data) {
UPB_UNUSED(handler_data);
p->indent_depth_--;
CHECK(indent(p));
upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL);
upb_bytessink_putbuf(&p->output_, p->subc, "}", 1, NULL);
CHECK(endfield(p));
return true;
err:
@ -315,9 +315,9 @@ static void textprinter_reset(upb_textprinter *p, bool single_line) {
/* Public API *****************************************************************/
upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h,
upb_bytessink *output) {
upb_textprinter *p = upb_env_malloc(env, sizeof(upb_textprinter));
upb_textprinter *upb_textprinter_create(upb_arena *arena, const upb_handlers *h,
upb_bytessink output) {
upb_textprinter *p = upb_arena_malloc(arena, sizeof(upb_textprinter));
if (!p) return NULL;
p->output_ = output;
@ -331,7 +331,7 @@ upb_handlercache *upb_textprinter_newcache() {
return upb_handlercache_new(&onmreg, NULL);
}
upb_sink *upb_textprinter_input(upb_textprinter *p) { return &p->input_; }
upb_sink upb_textprinter_input(upb_textprinter *p) { return p->input_; }
void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) {
p->single_line_ = single_line;

@ -17,60 +17,51 @@ class TextPrinter;
} /* namespace upb */
#endif
UPB_DECLARE_TYPE(upb::pb::TextPrinter, upb_textprinter)
/* upb_textprinter ************************************************************/
struct upb_textprinter;
typedef struct upb_textprinter upb_textprinter;
#ifdef __cplusplus
extern "C" {
#endif
class upb::pb::TextPrinter {
/* C API. */
upb_textprinter *upb_textprinter_create(upb_arena *arena, const upb_handlers *h,
upb_bytessink output);
void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line);
upb_sink upb_textprinter_input(upb_textprinter *p);
upb_handlercache *upb_textprinter_newcache();
#ifdef __cplusplus
} /* extern "C" */
class upb::pb::TextPrinterPtr {
public:
TextPrinterPtr(upb_textprinter* ptr) : ptr_(ptr) {}
/* The given handlers must have come from NewHandlers(). It must outlive the
* TextPrinter. */
static TextPrinter *Create(Environment *env, const upb::Handlers *handlers,
BytesSink *output);
static TextPrinterPtr *Create(Arena *arena, const upb::Handlers *handlers,
BytesSink output) {
return TextPrinterPtr(upb_textprinter_create(arena, handlers, output));
}
void SetSingleLineMode(bool single_line);
void SetSingleLineMode(bool single_line) {
upb_textprinter_setsingleline(ptr_, single_line);
}
Sink* input();
Sink input() { return upb_textprinter_input(ptr_); }
/* If handler caching becomes a requirement we can add a code cache as in
* decoder.h */
static HandlerCache* NewCache();
};
#endif
UPB_BEGIN_EXTERN_C
static HandlerCache NewCache() {
return HandlerCache(upb_textprinter_newcache());
}
/* C API. */
upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h,
upb_bytessink *output);
void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line);
upb_sink *upb_textprinter_input(upb_textprinter *p);
upb_handlercache *upb_textprinter_newcache();
UPB_END_EXTERN_C
#ifdef __cplusplus
namespace upb {
namespace pb {
inline TextPrinter *TextPrinter::Create(Environment *env,
const upb::Handlers *handlers,
BytesSink *output) {
return upb_textprinter_create(env, handlers, output);
}
inline void TextPrinter::SetSingleLineMode(bool single_line) {
upb_textprinter_setsingleline(this, single_line);
}
inline Sink* TextPrinter::input() {
return upb_textprinter_input(this);
}
inline HandlerCache* TextPrinter::NewCache() {
return upb_textprinter_newcache();
}
} /* namespace pb */
} /* namespace upb */
private:
upb_textprinter* ptr_;
};
#endif

@ -15,73 +15,3 @@ bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink) {
}
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;
}

@ -29,7 +29,9 @@ class Sink;
/* upb_sink *******************************************************************/
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
const upb_handlers *handlers;
@ -192,9 +194,8 @@ UPB_INLINE bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) {
return endsubmsg(s->closure, hd);
}
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
/* A upb::Sink is an object that binds a upb::Handlers object to some runtime
* state. It represents an endpoint to which data can be sent.
@ -288,7 +289,9 @@ class upb::Sink {
* sink->EndMessage(&status);
* sink->EndSubMessage(endsubmsg_selector); */
bool StartMessage() { return upb_sink_startmsg(&sink_); }
bool EndMessage(Status* status) { return upb_sink_endmsg(&sink_, status); }
bool EndMessage(upb_status *status) {
return upb_sink_endmsg(&sink_, status);
}
/* Putting of individual values. These work for both repeated and
* non-repeated fields, but for repeated fields you must wrap them in
@ -489,13 +492,14 @@ class upb::BytesSink {
/* upb_bufsrc *****************************************************************/
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink);
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
namespace upb {
template <class T> bool PutBuffer(const T& str, BytesSink sink) {
@ -505,19 +509,4 @@ template <class T> bool PutBuffer(const T& str, BytesSink sink) {
#endif /* __cplusplus */
/* upb_bufsink ****************************************************************/
/* A class for accumulating output string data in a flat buffer. */
struct upb_bufsink;
typedef struct upb_bufsink upb_bufsink;
UPB_BEGIN_EXTERN_C
upb_bufsink *upb_bufsink_init(upb_env *env);
void upb_bufsink_free(upb_bufsink *sink);
upb_bytessink *upb_bufsink_sink(upb_bufsink *sink);
const char *upb_bufsink_getdata(const upb_bufsink *sink, size_t *len);
UPB_END_EXTERN_C
#endif

@ -156,21 +156,6 @@ UPB_INLINE upb_value upb_value_double(double cval) {
* initializing a non-first union member. */
typedef uintptr_t upb_tabkey;
#define UPB_TABKEY_NUM(n) n
#define UPB_TABKEY_NONE 0
/* The preprocessor isn't quite powerful enough to turn the compile-time string
* length into a byte-wise string representation, so code generation needs to
* help it along.
*
* "len1" is the low byte and len4 is the high byte. */
#ifdef UPB_BIG_ENDIAN
#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \
(uintptr_t)(len4 len3 len2 len1 strval)
#else
#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \
(uintptr_t)(len1 len2 len3 len4 strval)
#endif
UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
char* mem = (char*)key;
if (len) memcpy(len, mem, sizeof(*len));

@ -8,12 +8,6 @@
#include <string.h>
#include "upb/upb.h"
bool upb_dumptostderr(void *closure, const upb_status* status) {
UPB_UNUSED(closure);
fprintf(stderr, "%s\n", upb_status_errmsg(status));
return false;
}
/* Guarantee null-termination and provide ellipsis truncation.
* It may be tempting to "optimize" this by initializing these final
* four bytes up-front and then being careful never to overwrite them,
@ -29,24 +23,17 @@ static void nullz(upb_status *status) {
void upb_status_clear(upb_status *status) {
if (!status) return;
status->ok_ = true;
status->code_ = 0;
status->ok = true;
status->msg[0] = '\0';
}
bool upb_ok(const upb_status *status) { return status->ok_; }
upb_errorspace *upb_status_errspace(const upb_status *status) {
return status->error_space_;
}
int upb_status_errcode(const upb_status *status) { return status->code_; }
bool upb_ok(const upb_status *status) { return status->ok; }
const char *upb_status_errmsg(const upb_status *status) { return status->msg; }
void upb_status_seterrmsg(upb_status *status, const char *msg) {
if (!status) return;
status->ok_ = false;
status->ok = false;
strncpy(status->msg, msg, sizeof(status->msg));
nullz(status);
}
@ -60,17 +47,11 @@ void upb_status_seterrf(upb_status *status, const char *fmt, ...) {
void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
if (!status) return;
status->ok_ = false;
status->ok = false;
_upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args);
nullz(status);
}
void upb_status_copy(upb_status *to, const upb_status *from) {
if (!to) return;
*to = *from;
}
/* upb_alloc ******************************************************************/
static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
@ -87,7 +68,6 @@ static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
upb_alloc upb_alloc_global = {&upb_global_allocfunc};
/* upb_arena ******************************************************************/
/* Be conservative and choose 16 in case anyone is using SSE. */
@ -115,11 +95,7 @@ struct upb_arena {
/* Cleanup entries. Pointer to a cleanup_ent, defined in env.c */
void *cleanup_head;
/* For future expansion, since the size of this struct is exposed to users. */
void *future1;
void *future2;
} upb_arena;
};
typedef struct mem_block {
struct mem_block *next;
@ -149,7 +125,6 @@ static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size,
/* TODO(haberman): ASAN poison. */
}
static mem_block *upb_arena_allocblock(upb_arena *a, size_t size) {
size_t block_size = UPB_MAX(size, a->next_block_size) + sizeof(mem_block);
mem_block *block = upb_malloc(a->block_alloc, block_size);
@ -202,7 +177,25 @@ static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize,
/* Public Arena API ***********************************************************/
void upb_arena_init(upb_arena *a) {
upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) {
const size_t first_block_overhead = sizeof(upb_arena) + sizeof(mem_block);
upb_arena *a;
bool owned = false;
if (n < first_block_overhead) {
/* We need to malloc the initial block. */
n = first_block_overhead + 256;
owned = true;
if (!alloc || !(mem = upb_malloc(alloc, n))) {
return NULL;
}
}
a = mem;
mem = (char*)mem + sizeof(*a);
n -= sizeof(*a);
upb_arena_addblock(a, mem, n, owned);
a->alloc.func = &upb_arena_doalloc;
a->block_alloc = &upb_alloc_global;
a->bytes_allocated = 0;
@ -210,21 +203,12 @@ void upb_arena_init(upb_arena *a) {
a->max_block_size = 16384;
a->cleanup_head = NULL;
a->block_head = NULL;
}
void upb_arena_init2(upb_arena *a, void *mem, size_t size, upb_alloc *alloc) {
upb_arena_init(a);
a->block_alloc = alloc;
if (size > sizeof(mem_block)) {
upb_arena_addblock(a, mem, size, false);
}
if (alloc) {
a->block_alloc = alloc;
}
return a;
}
void upb_arena_uninit(upb_arena *a) {
void upb_arena_free(upb_arena *a) {
cleanup_ent *ent = a->cleanup_head;
mem_block *block = a->block_head;
@ -236,6 +220,7 @@ void upb_arena_uninit(upb_arena *a) {
/* Must do this after running cleanup functions, because this will delete
* the memory we store our cleanup entries in! */
while (block) {
/* Load first since we are deleting block. */
mem_block *next = block->next;
if (block->owned) {
@ -244,10 +229,6 @@ void upb_arena_uninit(upb_arena *a) {
block = next;
}
/* Protect against multiple-uninit. */
a->cleanup_head = NULL;
a->block_head = NULL;
}
bool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud) {

@ -15,14 +15,11 @@
#include <stdint.h>
#ifdef __cplusplus
#include <memory>
namespace upb {
class Allocator;
class Arena;
class Environment;
class ErrorSpace;
class Status;
template <int N> class InlinedArena;
template <int N> class InlinedEnvironment;
}
#endif
@ -74,46 +71,14 @@ template <int N> class InlinedEnvironment;
#error Need implementations of [v]snprintf and va_copy
#endif
#if (defined(__cplusplus) && __cplusplus >= 201103L) || \
defined(__GXX_EXPERIMENTAL_CXX0X__) || \
#ifdef __cplusplus
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \
(defined(_MSC_VER) && _MSC_VER >= 1900)
// C++11 is present
#else
#error upb requires C++11 for C++ support
#endif
/* UPB_DISALLOW_COPY_AND_ASSIGN()
* UPB_DISALLOW_POD_OPS()
*
* Declare these in the "private" section of a C++ class to forbid copy/assign
* or all POD ops (construct, destruct, copy, assign) on that class. */
#include <type_traits>
#define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \
class_name(const class_name&) = delete; \
void operator=(const class_name&) = delete;
#define UPB_DISALLOW_POD_OPS(class_name, full_class_name) \
class_name() = delete; \
~class_name() = delete; \
UPB_DISALLOW_COPY_AND_ASSIGN(class_name)
#define UPB_ASSERT_STDLAYOUT(type) \
static_assert(std::is_standard_layout<type>::value, \
#type " must be standard layout");
#ifdef __cplusplus
#define UPB_BEGIN_EXTERN_C extern "C" {
#define UPB_END_EXTERN_C }
#define UPB_DECLARE_TYPE(cppname, cname) typedef cppname cname;
#else /* !defined(__cplusplus) */
#define UPB_BEGIN_EXTERN_C
#define UPB_END_EXTERN_C
#define UPB_DECLARE_TYPE(cppname, cname) \
struct cname; \
typedef struct cname cname;
#endif /* defined(__cplusplus) */
#endif
#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
@ -138,21 +103,26 @@ template <int N> class InlinedEnvironment;
#define UPB_UNREACHABLE() do { assert(0); } while(0)
#endif
/* upb::Status ****************************************************************/
/* upb_status *****************************************************************/
/* upb::Status represents a success or failure status and error message.
/* upb_status represents a success or failure status and error message.
* It owns no resources and allocates no memory, so it should work
* even in OOM situations. */
UPB_DECLARE_TYPE(upb::Status, upb_status)
/* The maximum length of an error message before it will get truncated. */
#define UPB_STATUS_MAX_MESSAGE 128
#define UPB_STATUS_MAX_MESSAGE 127
UPB_BEGIN_EXTERN_C
typedef struct {
bool ok;
char msg[UPB_STATUS_MAX_MESSAGE]; /* Error message; NULL-terminated. */
} upb_status;
#ifdef __cplusplus
extern "C" {
#endif
const char *upb_status_errmsg(const upb_status *status);
bool upb_ok(const upb_status *status);
int upb_status_errcode(const upb_status *status);
/* Any of the functions that write to a status object allow status to be NULL,
* to support use cases where the function's caller does not care about the
@ -161,60 +131,44 @@ void upb_status_clear(upb_status *status);
void upb_status_seterrmsg(upb_status *status, const char *msg);
void upb_status_seterrf(upb_status *status, const char *fmt, ...);
void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args);
void upb_status_copy(upb_status *to, const upb_status *from);
UPB_END_EXTERN_C
UPB_INLINE void upb_status_setoom(upb_status *status) {
upb_status_seterrmsg(status, "out of memory");
}
#ifdef __cplusplus
} /* extern "C" */
class upb::Status {
public:
Status() { upb_status_clear(this); }
Status() { upb_status_clear(&status_); }
/* Returns true if there is no error. */
bool ok() const { return upb_ok(this); }
upb_status* ptr() { return &status_; }
/* Optional error space and code, useful if the caller wants to
* programmatically check the specific kind of error. */
ErrorSpace* error_space() { return upb_status_errspace(this); }
int error_code() const { return upb_status_errcode(this); }
/* Returns true if there is no error. */
bool ok() const { return upb_ok(&status_); }
/* The returned string is invalidated by any other call into the status. */
const char *error_message() const { return upb_status_errmsg(this); }
/* Guaranteed to be NULL-terminated. */
const char *error_message() const { return upb_status_errmsg(&status_); }
/* The error message will be truncated if it is longer than
* UPB_STATUS_MAX_MESSAGE-4. */
void SetErrorMessage(const char* msg) { upb_status_seterrmsg(this, msg); }
void SetFormattedErrorMessage(const char* fmt, ...) {
void SetErrorMessage(const char *msg) { upb_status_seterrmsg(&status_, msg); }
void SetFormattedErrorMessage(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
upb_status_vseterrf(this, fmt, args);
upb_status_vseterrf(&status_, fmt, args);
va_end(args);
}
/* Resets the status to a successful state with no message. */
void Clear() { upb_status_clear(this); }
void CopyFrom(const Status& other) { upb_status_copy(this, &other); }
void Clear() { upb_status_clear(&status_); }
private:
UPB_DISALLOW_COPY_AND_ASSIGN(Status)
#else
struct upb_status {
#endif
bool ok_;
/* Specific status code defined by some error space (optional). */
int code_;
upb_errorspace *error_space_;
/* TODO(haberman): add file/line of error? */
/* Error message; NULL-terminated. */
char msg[UPB_STATUS_MAX_MESSAGE];
upb_status status_;
};
#define UPB_STATUS_INIT {true, 0, NULL, {0}}
#endif /* __cplusplus */
/** upb_alloc *****************************************************************/
@ -291,17 +245,23 @@ UPB_INLINE void upb_gfree(void *ptr) {
typedef void upb_cleanup_func(void *ud);
struct upb_arena;
typedef upb_arena upb_arena;
typedef struct upb_arena upb_arena;
UPB_BEGIN_EXTERN_C
#ifdef __cplusplus
extern "C" {
#endif
upb_arena *upb_arena_new2(void *mem, size_t n, upb_alloc *alloc);
/* Creates an arena from the given initial block (if any -- n may be 0).
* Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this
* is a fixed-size arena and cannot grow. */
upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc);
void upb_arena_free(upb_arena *a);
bool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud);
size_t upb_arena_bytesallocated(const upb_arena *a);
UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; }
/* Convenience wrappers around upb_alloc functions. */
UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) {
return upb_malloc(upb_arena_alloc(a), size);
}
@ -312,52 +272,38 @@ UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize,
}
UPB_INLINE upb_arena *upb_arena_new() {
return upb_arena_new2(NULL, 0, &upb_alloc_global);
return upb_arena_init(NULL, 0, &upb_alloc_global);
}
UPB_END_EXTERN_C
#ifdef __cplusplus
} /* extern "C" */
class upb::Arena {
public:
/* A simple arena with no initial memory block and the default allocator. */
Arena() { upb_arena_init(&arena_); }
Arena() : ptr_(upb_arena_new(), upb_arena_free) {}
upb_arena* ptr() { return &arena_; }
/* Constructs an arena with the given initial block which allocates blocks
* with the given allocator. The given allocator must outlive the Arena.
*
* If you pass NULL for the allocator it will default to the global allocator
* upb_alloc_global, and NULL/0 for the initial block will cause there to be
* no initial block. */
Arena(void *mem, size_t len, upb_alloc *a) {
upb_arena_init2(&arena_, mem, len, a);
}
~Arena() { upb_arena_uninit(&arena_); }
upb_arena* ptr() { return ptr_.get(); }
/* Allows this arena to be used as a generic allocator.
*
* The arena does not need free() calls so when using Arena as an allocator
* it is safe to skip them. However they are no-ops so there is no harm in
* calling free() either. */
upb_alloc *allocator() { return upb_arena_alloc(&arena_); }
upb_alloc *allocator() { return upb_arena_alloc(ptr_.get()); }
/* Add a cleanup function to run when the arena is destroyed.
* Returns false on out-of-memory. */
bool AddCleanup(upb_cleanup_func *func, void *ud) {
return upb_arena_addcleanup(&arena_, func, ud);
return upb_arena_addcleanup(ptr_.get(), func, ud);
}
/* Total number of bytes that have been allocated. It is undefined what
* Realloc() does to &arena_ counter. */
size_t BytesAllocated() const { return upb_arena_bytesallocated(&arena_); }
size_t BytesAllocated() const { return upb_arena_bytesallocated(ptr_.get()); }
private:
UPB_DISALLOW_COPY_AND_ASSIGN(Arena)
upb_arena arena_;
std::unique_ptr<upb_arena, decltype(&upb_arena_free)> ptr_;
};
#endif
@ -373,13 +319,16 @@ class upb::Arena {
template <int N> class upb::InlinedArena : public upb::Arena {
public:
InlinedArena() : Arena(initial_block_, N, NULL) {}
explicit InlinedArena(Allocator* a) : Arena(initial_block_, N, a) {}
InlinedArena() : ptr_(upb_arena_new(&initial_block_, N, &upb_alloc_global)) {}
upb_arena* ptr() { return ptr_.get(); }
private:
UPB_DISALLOW_COPY_AND_ASSIGN(InlinedArena)
InlinedArena(const InlinedArena*) = delete;
InlinedArena& operator=(const InlinedArena*) = delete;
char initial_block_[N + UPB_ARENA_BLOCK_OVERHEAD];
std::unique_ptr<upb_arena, decltype(&upb_arena_free)> ptr_;
char initial_block_[N];
};
#endif /* __cplusplus */

@ -502,7 +502,9 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output) {
"#include \"upb/decode.h\"\n"
"#include \"upb/encode.h\"\n"
"#include \"upb/port_def.inc\"\n"
"UPB_BEGIN_EXTERN_C\n\n",
"#ifdef __cplusplus\n"
"extern \"C\" {\n"
"#endif\n\n",
ToPreproc(file->name()));
// Forward-declare types defined in this file.
@ -548,7 +550,9 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output) {
}
output(
"UPB_END_EXTERN_C\n"
"#ifdef __cplusplus\n"
"} /* extern \"C\" */\n"
"#endif\n"
"\n"
"#include \"upb/port_undef.inc\"\n"
"\n"

Loading…
Cancel
Save