From 1bcab1377de6afe8c0f9c895cdba04baacf3e4a5 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Thu, 22 Dec 2011 11:37:01 -0800 Subject: Sync with internal Google development. This breaks the open-source build, will follow up with a change to fix it. --- bindings/cpp/upb/bytestream.cc | 39 +++++++ bindings/cpp/upb/bytestream.hpp | 238 ++++++++++++++++++++++++++++++++++++++++ bindings/cpp/upb/def.hpp | 77 +++++++------ bindings/cpp/upb/handlers.hpp | 95 ++++++++-------- bindings/cpp/upb/pb/decoder.hpp | 83 ++++++++++++++ bindings/cpp/upb/upb.hpp | 23 +++- 6 files changed, 458 insertions(+), 97 deletions(-) create mode 100644 bindings/cpp/upb/bytestream.cc create mode 100644 bindings/cpp/upb/bytestream.hpp create mode 100644 bindings/cpp/upb/pb/decoder.hpp (limited to 'bindings/cpp/upb') diff --git a/bindings/cpp/upb/bytestream.cc b/bindings/cpp/upb/bytestream.cc new file mode 100644 index 0000000..df0797e --- /dev/null +++ b/bindings/cpp/upb/bytestream.cc @@ -0,0 +1,39 @@ +// +// upb - a minimalist implementation of protocol buffers. +// +// Copyright (c) 2011 Google Inc. See LICENSE for details. +// Author: Josh Haberman + +#include "bytestream.hpp" + +namespace upb { + +upb_bytesrc_vtbl* ByteSourceBase::vtable() { + static upb_bytesrc_vtbl vtbl = { + &ByteSourceBase::VFetch, + &ByteSourceBase::VDiscard, + &ByteSourceBase::VCopy, + &ByteSourceBase::VGetPtr, + }; + return &vtbl; +} + +upb_bytesuccess_t ByteSourceBase::VFetch(void *src, uint64_t ofs, size_t *len) { + return static_cast(src)->Fetch(ofs, len); +} + +void ByteSourceBase::VCopy( + const void *src, uint64_t ofs, size_t len, char* dest) { + static_cast(src)->Copy(ofs, len, dest); +} + +void ByteSourceBase::VDiscard(void *src, uint64_t ofs) { + static_cast(src)->Discard(ofs); +} + +const char * ByteSourceBase::VGetPtr( + const void *src, uint64_t ofs, size_t* len) { + return static_cast(src)->GetPtr(ofs, len); +} + +} // namespace upb diff --git a/bindings/cpp/upb/bytestream.hpp b/bindings/cpp/upb/bytestream.hpp new file mode 100644 index 0000000..968d542 --- /dev/null +++ b/bindings/cpp/upb/bytestream.hpp @@ -0,0 +1,238 @@ +// +// upb - a minimalist implementation of protocol buffers. +// +// Copyright (c) 2011 Google Inc. See LICENSE for details. +// Author: Josh Haberman +// +// This file defines three core interfaces: +// - upb::ByteSink: for writing streams of data. +// - upb::ByteSource: for reading streams of data. +// - upb::ByteRegion: for reading from a specific region of a ByteSource; +// should be used by decoders instead of using a ByteSource directly. +// +// These interfaces are used by streaming encoders and decoders: for example, a +// protobuf parser gets its input from a upb::ByteRegion. They are virtual +// base classes so concrete implementations can get the data from a fd, a +// FILE*, a string, etc. +// +// A ByteRegion represents a region of data from a ByteSource. +// +// Parsers get data from this interface instead of a bytesrc because we often +// want to parse only a specific region of the input. For example, if we parse +// a string from our input but know that the string represents a protobuf, we +// can pass its ByteRegion to an appropriate protobuf parser. +// +// Since the bytes may be coming from a file or network socket, bytes must be +// fetched before they can be read (though in some cases this fetch may be a +// no-op). "fetch" is the only operation on a byteregion that could fail or +// block, because it is the only operation that actually performs I/O. +// +// Bytes can be discarded when they are no longer needed. Parsers should +// always discard bytes they no longer need, both so the buffers can be freed +// when possible and to give better visibility into what bytes the parser is +// still using. +// +// start discard read fetch end +// ofs ofs ofs ofs ofs +// | |--->Discard() | |--->Fetch() | +// V V V V V +// +-------------+-------------------------+-----------------+-----------------+ +// | discarded | | | fetchable | +// +-------------+-------------------------+-----------------+-----------------+ +// | <------------- loaded ------------------> | +// | <- available -> | +// | <---------- remaining ----------> | +// +// Note that the start offset may be something other than zero! A byteregion +// is a view into an underlying bytesrc stream, and the region may start +// somewhere other than the beginning of that stream. +// +// The region can be either delimited or nondelimited. A non-delimited region +// will keep returning data until the underlying data source returns EOF. A +// delimited region will return EOF at a predetermined offset. +// +// end +// ofs +// | +// V +// +-----------------------+ +// | delimited region | <-- hard EOF, even if data source has more data. +// +-----------------------+ +// +// +------------------------ +// | nondelimited region Z <-- won't return EOF until data source hits EOF. +// +------------------------ + +#ifndef UPB_BYTESTREAM_HPP +#define UPB_BYTESTREAM_HPP + +#include "upb/bytestream.h" +#include "upb/upb.hpp" + +namespace upb { + +typedef upb_bytesuccess_t ByteSuccess; + +// Implement this interface to vend bytes to ByteRegions which will be used by +// a decoder. +class ByteSourceBase : public upb_bytesrc { + public: + ByteSourceBase() { upb_bytesrc_init(this, vtable()); } + virtual ~ByteSourceBase() { upb_bytesrc_uninit(this); } + + // Fetches at least one byte starting at ofs, setting *len to the actual + // number of bytes fetched (or 0 on EOF or error: see return value for + // details). It is valid for bytes to be fetched multiple times, as long as + // the bytes have not been previously discarded. + virtual ByteSuccess Fetch(uint64_t ofs, size_t* len) = 0; + + // Discards all data prior to ofs (except data that is pinned, if pinning + // support is added -- see TODO below). + virtual void Discard(uint64_t ofs) = 0; + + // Copies "len" bytes of data from ofs to "dst", which must be at least "len" + // bytes long. The given region must not be discarded. + virtual void Copy(uint64_t ofs, size_t len, char *dst) const = 0; + + // Returns a pointer to the bytesrc's internal buffer, storing in *len how + // much data is available. The given offset must not be discarded. The + // returned buffer is valid for as long as its bytes are not discarded (in + // the case that part of the returned buffer is discarded, only the + // non-discarded bytes remain valid). + virtual const char *GetPtr(uint64_t ofs, size_t *len) const = 0; + + // TODO: Add if/when there is a demonstrated need: + // + // // When the caller pins a region (which must not be already discarded), it + // // is guaranteed that the region will not be discarded (nor will the + // // bytesrc be destroyed) until the region is unpinned. However, not all + // // bytesrc's support pinning; a false return indicates that a pin was not + // // possible. + // virtual bool Pin(uint64_t ofs, size_t len); + // + // // Releases some number of pinned bytes from the beginning of a pinned + // // region (which may be fewer than the total number of bytes pinned). + // virtual void Unpin(uint64_t ofs, size_t len, size_t bytes_to_release); + // + // Adding pinning support would also involve adding a "pin_ofs" parameter to + // upb_bytesrc_fetch, so that the fetch can extend an already-pinned region. + private: + static upb_bytesrc_vtbl* vtable(); + static upb_bytesuccess_t VFetch(void*, uint64_t, size_t*); + static void VDiscard(void*, uint64_t); + static void VCopy(const void*, uint64_t, size_t, char*); + static const char *VGetPtr(const void*, uint64_t, size_t*); +}; + +class ByteRegion : public upb_byteregion { + public: + static const uint64_t kNondelimited = UPB_NONDELIMITED; + + ByteRegion() { upb_byteregion_init(this); } + ~ByteRegion() { upb_byteregion_uninit(this); } + + // Accessors for the regions bounds -- the meaning of these is described in + // the diagram above. + uint64_t start_ofs() const { return upb_byteregion_startofs(this); } + uint64_t discard_ofs() const { return upb_byteregion_discardofs(this); } + uint64_t fetch_ofs() const { return upb_byteregion_fetchofs(this); } + uint64_t end_ofs() const { return upb_byteregion_endofs(this); } + + // Returns how many bytes are fetched and available for reading starting from + // offset "offset". + uint64_t BytesAvailable(uint64_t offset) const { + return upb_byteregion_available(this, offset); + } + + // Returns the total number of bytes remaining after offset "offset", or + // kNondelimited if the byteregion is non-delimited. + uint64_t BytesRemaining(uint64_t offset) const { + return upb_byteregion_remaining(this, offset); + } + + uint64_t Length() const { return upb_byteregion_len(this); } + + // Sets the value of this byteregion to be a subset of the given byteregion's + // data. The caller is responsible for releasing this region before the src + // region is released (unless the region is first pinned, if pinning support + // is added. see below). + void Reset(const upb_byteregion *src, uint64_t ofs, uint64_t len) { + upb_byteregion_reset(this, src, ofs, len); + } + void Release() { upb_byteregion_release(this); } + + // Attempts to fetch more data, extending the fetched range of this + // byteregion. Returns true if the fetched region was extended by at least + // one byte, false on EOF or error (see *s for details). + ByteSuccess Fetch() { return upb_byteregion_fetch(this); } + + // Fetches all remaining data, returning false if the operation failed (see + // *s for details). May only be used on delimited byteregions. + ByteSuccess FetchAll() { return upb_byteregion_fetchall(this); } + + // Discards bytes from the byteregion up until ofs (which must be greater or + // equal to discard_ofs()). It is valid to discard bytes that have not been + // fetched (such bytes will never be fetched) but it is an error to discard + // past the end of a delimited byteregion. + void Discard(uint64_t ofs) { return upb_byteregion_discard(this, ofs); } + + // Copies "len" bytes of data into "dst", starting at ofs. The specified + // region must be available. + void Copy(uint64_t ofs, size_t len, char *dst) const { + upb_byteregion_copy(this, ofs, len, dst); + } + + // Copies all bytes from the byteregion into dst. Requires that the entire + // byteregion is fetched and that none has been discarded. + void CopyAll(char *dst) const { + upb_byteregion_copyall(this, dst); + } + + // Returns a pointer to the internal buffer for the byteregion starting at + // offset "ofs." Stores the number of bytes available in this buffer in *len. + // The returned buffer is invalidated when the byteregion is reset or + // released, or when the bytes are discarded. If the byteregion is not + // currently pinned, the pointer is only valid for the lifetime of the parent + // byteregion. + const char *GetPtr(uint64_t ofs, size_t *len) const { + return upb_byteregion_getptr(this, ofs, len); + } + + // Copies the contents of the byteregion into a newly-allocated, + // NULL-terminated string. Requires that the byteregion is fully fetched. + char *StrDup() const { + return upb_byteregion_strdup(this); + } + + // TODO: add if/when there is a demonstrated need. + // + // // Pins this byteregion's bytes in memory, allowing it to outlive its + // // parent byteregion. Normally a byteregion may only be used while its + // // parent is still valid, but a pinned byteregion may continue to be used + // // until it is reset or released. A byteregion must be fully fetched to + // // be pinned (this implies that the byteregion must be delimited). + // // + // // In some cases this operation may cause the input data to be copied. + // // + // // void Pin(); +}; + +class StringSource : public upb_stringsrc { + public: + StringSource() : upb_stringsrc() { upb_stringsrc_init(this); } + ~StringSource() { upb_stringsrc_uninit(this); } + + void Reset(const char* data, size_t len) { + upb_stringsrc_reset(this, data, len); + } + + ByteRegion* AllBytes() { + return static_cast(upb_stringsrc_allbytes(this)); + } + + upb_bytesrc* ByteSource() { return upb_stringsrc_bytesrc(this); } +}; + +} // namespace upb + +#endif diff --git a/bindings/cpp/upb/def.hpp b/bindings/cpp/upb/def.hpp index ac9aff1..030ba40 100644 --- a/bindings/cpp/upb/def.hpp +++ b/bindings/cpp/upb/def.hpp @@ -1,42 +1,41 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * The set of upb::*Def classes and upb::SymbolTable allow for defining and - * manipulating schema information (as defined in .proto files). - * - * Defs go through two distinct phases of life: - * - * 1. MUTABLE: when first created, the properties of the def can be set freely - * (for example a message's name, its list of fields, the name/number of - * fields, etc). During this phase the def is *not* thread-safe, and may - * not be used for any purpose except to set its properties (it can't be - * used to parse anything, create any messages in memory, etc). - * - * 2. FINALIZED: after being added to a symtab (which links the defs together) - * the defs become finalized (thread-safe and immutable). Programs may only - * access defs through a CONST POINTER during this stage -- upb_symtab will - * help you out with this requirement by only vending const pointers, but - * you need to make sure not to use any non-const pointers you still have - * sitting around. In practice this means that you may not call any setters - * on the defs (or functions that themselves call the setters). If you want - * to modify an existing immutable def, copy it with upb_*_dup(), modify the - * copy, and add the modified def to the symtab (replacing the existing - * def). - * - * You can test for which stage of life a def is in by calling - * upb::Def::IsMutable(). This is particularly useful for dynamic language - * bindings, which must properly guarantee that the dynamic language cannot - * break the rules laid out above. - * - * It would be possible to make the defs thread-safe during stage 1 by using - * mutexes internally and changing any methods returning pointers to return - * copies instead. This could be important if we are integrating with a VM or - * interpreter that does not naturally serialize access to wrapped objects (for - * example, in the case of Python this is not necessary because of the GIL). - */ +// +// upb - a minimalist implementation of protocol buffers. +// +// Copyright (c) 2011 Google Inc. See LICENSE for details. +// Author: Josh Haberman +// +// The set of upb::*Def classes and upb::SymbolTable allow for defining and +// manipulating schema information (as defined in .proto files). +// +// Defs go through two distinct phases of life: +// +// 1. MUTABLE: when first created, the properties of the def can be set freely +// (for example a message's name, its list of fields, the name/number of +// fields, etc). During this phase the def is *not* thread-safe, and may +// not be used for any purpose except to set its properties (it can't be +// used to parse anything, create any messages in memory, etc). +// +// 2. FINALIZED: after being added to a symtab (which links the defs together) +// the defs become finalized (thread-safe and immutable). Programs may only +// access defs through a CONST POINTER during this stage -- upb_symtab will +// help you out with this requirement by only vending const pointers, but +// you need to make sure not to use any non-const pointers you still have +// sitting around. In practice this means that you may not call any setters +// on the defs (or functions that themselves call the setters). If you want +// to modify an existing immutable def, copy it with upb_*_dup(), modify the +// copy, and add the modified def to the symtab (replacing the existing +// def). +// +// You can test for which stage of life a def is in by calling +// upb::Def::IsMutable(). This is particularly useful for dynamic language +// bindings, which must properly guarantee that the dynamic language cannot +// break the rules laid out above. +// +// It would be possible to make the defs thread-safe during stage 1 by using +// mutexes internally and changing any methods returning pointers to return +// copies instead. This could be important if we are integrating with a VM or +// interpreter that does not naturally serialize access to wrapped objects (for +// example, in the case of Python this is not necessary because of the GIL). #ifndef UPB_DEF_HPP #define UPB_DEF_HPP diff --git a/bindings/cpp/upb/handlers.hpp b/bindings/cpp/upb/handlers.hpp index 07683f6..d356a33 100644 --- a/bindings/cpp/upb/handlers.hpp +++ b/bindings/cpp/upb/handlers.hpp @@ -1,15 +1,14 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - * - * upb::Handlers is a generic visitor-like interface for iterating over a - * stream of protobuf data. You can register function pointers that will be - * called for each message and/or field as the data is being parsed or iterated - * over, without having to know the source format that we are parsing from. - * This decouples the parsing logic from the processing logic. - */ +// +// upb - a minimalist implementation of protocol buffers. +// +// Copyright (c) 2011 Google Inc. See LICENSE for details. +// Author: Josh Haberman +// +// upb::Handlers is a generic visitor-like interface for iterating over a +// stream of protobuf data. You can register function pointers that will be +// called for each message and/or field as the data is being parsed or iterated +// over, without having to know the source format that we are parsing from. +// This decouples the parsing logic from the processing logic. #ifndef UPB_HANDLERS_HPP #define UPB_HANDLERS_HPP @@ -18,6 +17,7 @@ namespace upb { +typedef upb_fieldtype_t FieldType; typedef upb_flow_t Flow; class MessageHandlers; @@ -30,8 +30,8 @@ class FieldHandlers : public upb_fhandlers { // The FieldHandlers will live at least as long as the upb::Handlers to // which it belongs, but can be Ref'd/Unref'd to make it live longer (which // will prolong the life of the underlying upb::Handlers also). - void Ref() const { upb_fhandlers_ref(this); } - void Unref() const { upb_fhandlers_unref(this); } + void Ref() { upb_fhandlers_ref(this); } + void Unref() { upb_fhandlers_unref(this); } // Functions to set this field's handlers. // These return "this" so they can be conveniently chained, eg. @@ -46,13 +46,13 @@ class FieldHandlers : public upb_fhandlers { upb_fhandlers_setstartseq(this, h); return this; } FieldHandlers* SetEndSequenceHandler(EndFieldHandler* h) { - upb_fhandlers_endseq(this, h); return this; + upb_fhandlers_setendseq(this, h); return this; } FieldHandlers* SetStartSubmessageHandler(StartFieldHandler* h) { upb_fhandlers_setstartsubmsg(this, h); return this; } FieldHandlers* SetEndSubmessageHandler(EndFieldHandler* h) { - upb_fhandlers_endsubmsg(this, h); return this; + upb_fhandlers_setendsubmsg(this, h); return this; } // Get/Set the field's bound value, which will be passed to its handlers. @@ -62,27 +62,20 @@ class FieldHandlers : public upb_fhandlers { } // Returns the MessageHandlers to which we belong. - MessageHandlers* GetMessageHandlers() const { - return upb_fhandlers_msg(this); - } - + MessageHandlers* GetMessageHandlers() const; // Returns the MessageHandlers for this field's submessage (invalid to call // unless this field's type UPB_TYPE(MESSAGE) or UPB_TYPE(GROUP). - MessageHandlers* GetSubMessageHandlers() const { - return upb_fhandlers_submsg(this); - } - + MessageHandlers* GetSubMessageHandlers() const; // If set to >=0, the given hasbit will be set after the value callback is - // called (relative to the current closure). - int32_t GetValueHasbit() const { return upb_fhandler_valuehasbit(this); } - void SetValueHasbit(int32_t bit) { upb_fhandler_setvaluehasbit(this, bit); } + // called (offset relative to the current closure). + int32_t GetValueHasbit() const { return upb_fhandlers_getvaluehasbit(this); } + void SetValueHasbit(int32_t bit) { upb_fhandlers_setvaluehasbit(this, bit); } private: FieldHandlers(); // Only created by upb::Handlers. ~FieldHandlers(); // Only destroyed by refcounting. }; - class MessageHandlers : public upb_mhandlers { public: typedef upb_startmsg_handler StartMessageHandler; @@ -91,8 +84,8 @@ class MessageHandlers : public upb_mhandlers { // The MessageHandlers will live at least as long as the upb::Handlers to // which it belongs, but can be Ref'd/Unref'd to make it live longer (which // will prolong the life of the underlying upb::Handlers also). - void Ref() const { upb_mhandlers_ref(this); } - void Unref() const { upb_mhandlers_unref(this); } + void Ref() { upb_mhandlers_ref(this); } + void Unref() { upb_mhandlers_unref(this); } // Functions to set this message's handlers. // These return "this" so they can be conveniently chained, eg. @@ -107,12 +100,10 @@ class MessageHandlers : public upb_mhandlers { } // Functions to create new FieldHandlers for this message. - FieldHandlers* NewFieldHandlers(uint32_t fieldnum, upb_fieldtype_t type, + FieldHandlers* NewFieldHandlers(uint32_t fieldnum, FieldType type, bool repeated) { - return upb_mhandlers_newfhandlers(this, fieldnum, type, repeated); - } - FieldHandlers* NewFieldHandlers(FieldDef* f) { - return upb_mhandlers_newfhandlers_fordef(f); + return static_cast( + upb_mhandlers_newfhandlers(this, fieldnum, type, repeated)); } // Like the previous but for MESSAGE or GROUP fields. For GROUP fields, the @@ -120,15 +111,10 @@ class MessageHandlers : public upb_mhandlers { FieldHandlers* NewFieldHandlersForSubmessage(uint32_t n, const char *name, FieldType type, bool repeated, MessageHandlers* subm) { - return upb_mhandlers_newsubmsgfhandlers(this, n, type, repeated, subm); - } - - FieldHandlers* NewFieldHandlersForSubmessage(FieldDef* f, - MessageHandlers* subm) { - return upb_mhandlers_newsubmsgfhandlers_fordef(f); + return static_cast( + upb_mhandlers_newfhandlers_subm(this, n, type, repeated, subm)); } - private: MessageHandlers(); // Only created by upb::Handlers. ~MessageHandlers(); // Only destroyed by refcounting. @@ -137,26 +123,31 @@ class MessageHandlers : public upb_mhandlers { class Handlers : public upb_handlers { public: // Creates a new Handlers instance. - Handlers* New() { return static_cast(upb_handlers_new()); } + static Handlers* New() { return static_cast(upb_handlers_new()); } void Ref() { upb_handlers_ref(this); } void Unref() { upb_handlers_unref(this); } // Returns a new MessageHandlers object. The first such message that is // obtained will be the top-level message for this Handlers object. - MessageHandlers* NewMessageHandlers() { return upb_handlers_newmhandlers(this); } - - // Freezes the handlers against future modification. Handlers must be - // finalized before they can be passed to a data producer. After Finalize() - // has been called, you may only call const methods on the Handlers and its - // MessageHandlers/FieldHandlers. - void Finalize() { upb_handlers_finalize(this); } + MessageHandlers* NewMessageHandlers() { + return static_cast(upb_handlers_newmhandlers(this)); + } private: - FieldHandlers(); // Only created by Handlers::New(). - ~FieldHandlers(); // Only destroyed by refcounting. + Handlers(); // Only created by Handlers::New(). + ~Handlers(); // Only destroyed by refcounting. }; + +MessageHandlers* FieldHandlers::GetMessageHandlers() const { + return static_cast(upb_fhandlers_getmsg(this)); +} + +MessageHandlers* FieldHandlers::GetSubMessageHandlers() const { + return static_cast(upb_fhandlers_getsubmsg(this)); +} + } // namespace upb #endif diff --git a/bindings/cpp/upb/pb/decoder.hpp b/bindings/cpp/upb/pb/decoder.hpp new file mode 100644 index 0000000..05bcb8a --- /dev/null +++ b/bindings/cpp/upb/pb/decoder.hpp @@ -0,0 +1,83 @@ +// +// upb - a minimalist implementation of protocol buffers. +// +// Copyright (c) 2011 Google Inc. See LICENSE for details. +// Author: Josh Haberman +// +// upb::Decoder is a high performance, streaming decoder for protobuf +// data that works by getting its input data from a ubp::ByteRegion and calling +// into a upb::Handlers. +// +// A DecoderPlan contains whatever data structures and generated (JIT-ted) code +// are necessary to decode protobuf data of a specific type to a specific set +// of handlers. By generating the plan ahead of time, we avoid having to +// redo this work every time we decode. +// +// A DecoderPlan is threadsafe, meaning that it can be used concurrently by +// different upb::Decoders in different threads. However, the upb::Decoders are +// *not* thread-safe. + +#ifndef UPB_PB_DECODER_HPP +#define UPB_PB_DECODER_HPP + +#include "upb/pb/decoder.h" + +#include "upb/bytestream.hpp" +#include "upb/upb.hpp" + +namespace upb { + +class DecoderPlan : public upb_decoderplan { + public: + static DecoderPlan* New(Handlers* h, bool allow_jit) { + return static_cast(upb_decoderplan_new(h, allow_jit)); + } + void Unref() { upb_decoderplan_unref(this); } + + // Returns true if the plan contains JIT-ted code. This may not be the same + // as the "allowjit" parameter to the constructor if support for JIT-ting was + // not compiled in. + bool HasJitCode() { return upb_decoderplan_hasjitcode(this); } + + private: + DecoderPlan() {} // Only constructed by New +}; + +class Decoder : public upb_decoder { + public: + Decoder() { upb_decoder_init(this); } + ~Decoder() { upb_decoder_uninit(this); } + + // Resets the plan that the decoder will parse from. This will also reset the + // decoder's input to be uninitialized -- ResetInput() must be called before + // parsing can occur. The plan must live until the decoder is destroyed or + // reset to a different plan. + // + // Must be called before ResetInput() or Decode(). + void ResetPlan(DecoderPlan* plan, int32_t msg_offset) { + upb_decoder_resetplan(this, plan, msg_offset); + } + + // Resets the input of the decoder. This puts it in a state where it has not + // seen any data, and expects the next data to be from the beginning of a new + // protobuf. + // + // ResetInput() must be called before Decode() but may be called more than + // once. "input" must live until the decoder destroyed or ResetInput is + // called again. "c" is the closure that will be passed to the handlers. + void ResetInput(ByteRegion* byte_region, void* c) { + upb_decoder_resetinput(this, byte_region, c); + } + + // Decodes serialized data (calling Handlers as the data is parsed) until + // error or EOF (see status() for details). + Success Decode() { return upb_decoder_decode(this); } + + const upb::Status& status() { + return static_cast(*upb_decoder_status(this)); + } +}; + +} // namespace upb + +#endif diff --git a/bindings/cpp/upb/upb.hpp b/bindings/cpp/upb/upb.hpp index 4fb337d..226859c 100644 --- a/bindings/cpp/upb/upb.hpp +++ b/bindings/cpp/upb/upb.hpp @@ -1,23 +1,34 @@ -/* - * upb - a minimalist implementation of protocol buffers. - * - * Copyright (c) 2011 Google Inc. See LICENSE for details. - * Author: Josh Haberman - */ +// +// upb - a minimalist implementation of protocol buffers. +// +// Copyright (c) 2011 Google Inc. See LICENSE for details. +// Author: Josh Haberman #ifndef UPB_HPP #define UPB_HPP #include "upb/upb.h" +#include namespace upb { +typedef upb_success_t Success; + class Status : public upb_status { public: Status() { upb_status_init(this); } ~Status() { upb_status_uninit(this); } + bool ok() const { return upb_ok(this); } + bool eof() const { return upb_eof(this); } + const char *GetString() const { return upb_status_getstr(this); } + void SetEof() { upb_status_seteof(this); } + void SetErrorLiteral(const char* msg) { + upb_status_seterrliteral(this, msg); + } + + void Clear() { upb_status_clear(this); } }; class Value : public upb_value { -- cgit v1.2.3