Protocol Buffers - Google's data interchange format (grpc依赖) https://developers.google.com/protocol-buffers/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

313 lines
10 KiB

/*
** upb::pb::Decoder
**
** A high performance, streaming, resumable decoder for the binary protobuf
** format.
**
** This interface works the same regardless of what decoder backend is being
** used. A client of this class does not need to know whether decoding is using
** a JITted decoder (DynASM, LLVM, etc) or an interpreted decoder. By default,
** it will always use the fastest available decoder. However, you can call
** set_allow_jit(false) to disable any JIT decoder that might be available.
** This is primarily useful for testing purposes.
*/
#ifndef UPB_DECODER_H_
#define UPB_DECODER_H_
#include "upb/sink.h"
#ifdef __cplusplus
namespace upb {
namespace pb {
class CodeCache;
class Decoder;
class DecoderMethod;
class DecoderMethodOptions;
} /* namespace pb */
} /* namespace upb */
#endif
UPB_DECLARE_TYPE(upb::pb::CodeCache, upb_pbcodecache)
UPB_DECLARE_TYPE(upb::pb::Decoder, upb_pbdecoder)
UPB_DECLARE_TYPE(upb::pb::DecoderMethodOptions, upb_pbdecodermethodopts)
UPB_DECLARE_DERIVED_TYPE(upb::pb::DecoderMethod, upb::RefCounted,
upb_pbdecodermethod, upb_refcounted)
/* The maximum number of bytes we are required to buffer internally between
* calls to the decoder. The value is 14: a 5 byte unknown tag plus ten-byte
* varint, less one because we are buffering an incomplete value.
*
* Should only be used by unit tests. */
#define UPB_DECODER_MAX_RESIDUAL_BYTES 14
#ifdef __cplusplus
/* The parameters one uses to construct a DecoderMethod.
* TODO(haberman): move allowjit here? Seems more convenient for users.
* TODO(haberman): move this to be heap allocated for ABI stability. */
class upb::pb::DecoderMethodOptions {
public:
/* Parameter represents the destination handlers that this method will push
* to. */
explicit DecoderMethodOptions(const Handlers* dest_handlers);
/* Should the decoder push submessages to lazy handlers for fields that have
* them? The caller should set this iff the lazy handlers expect data that is
* in protobuf binary format and the caller wishes to lazy parse it. */
void set_lazy(bool lazy);
#else
struct upb_pbdecodermethodopts {
#endif
const upb_handlers *handlers;
bool lazy;
};
#ifdef __cplusplus
/* Represents the code to parse a protobuf according to a destination
* Handlers. */
class upb::pb::DecoderMethod {
public:
/* Include base methods from upb::ReferenceCounted. */
UPB_REFCOUNTED_CPPMETHODS
/* The destination handlers that are statically bound to this method.
* This method is only capable of outputting to a sink that uses these
* handlers. */
const Handlers* dest_handlers() const;
/* The input handlers for this decoder method. */
const BytesHandler* input_handler() const;
/* Whether this method is native. */
bool is_native() const;
/* Convenience method for generating a DecoderMethod without explicitly
* creating a CodeCache. */
static reffed_ptr<const DecoderMethod> New(const DecoderMethodOptions& opts);
private:
UPB_DISALLOW_POD_OPS(DecoderMethod, upb::pb::DecoderMethod)
};
#endif
/* Preallocation hint: decoder won't allocate more bytes than this when first
* constructed. This hint may be an overestimate for some build configurations.
* But if the decoder library is upgraded without recompiling the application,
* it may be an underestimate. */
#define UPB_PB_DECODER_SIZE 4416
#ifdef __cplusplus
/* A Decoder receives binary protobuf data on its input sink and pushes the
* decoded data to its output sink. */
class upb::pb::Decoder {
public:
/* Constructs a decoder instance for the given method, which must outlive this
* decoder. Any errors during parsing will be set on the given status, which
* must also outlive this decoder.
*
* The sink must match the given method. */
static Decoder* Create(Environment* env, const DecoderMethod* method,
Sink* output);
/* Returns the DecoderMethod this decoder is parsing from. */
const DecoderMethod* method() const;
/* The sink on which this decoder receives input. */
BytesSink* input();
/* Returns number of bytes successfully parsed.
*
* This can be useful for determining the stream position where an error
* occurred.
*
* This value may not be up-to-date when called from inside a parsing
* callback. */
uint64_t BytesParsed() const;
/* Gets/sets the parsing nexting limit. If the total number of nested
* submessages and repeated fields hits this limit, parsing will fail. This
* is a resource limit that controls the amount of memory used by the parsing
* stack.
*
* Setting the limit will fail if the parser is currently suspended at a depth
* greater than this, or if memory allocation of the stack fails. */
size_t max_nesting() const;
bool set_max_nesting(size_t max);
void Reset();
static const size_t kSize = UPB_PB_DECODER_SIZE;
private:
UPB_DISALLOW_POD_OPS(Decoder, upb::pb::Decoder)
};
#endif /* __cplusplus */
#ifdef __cplusplus
/* A class for caching protobuf processing code, whether bytecode for the
* interpreted decoder or machine code for the JIT.
*
* This class is not thread-safe.
*
* TODO(haberman): move this to be heap allocated for ABI stability. */
class upb::pb::CodeCache {
public:
CodeCache();
~CodeCache();
/* Whether the cache is allowed to generate machine code. Defaults to true.
* There is no real reason to turn it off except for testing or if you are
* having a specific problem with the JIT.
*
* Note that allow_jit = true does not *guarantee* that the code will be JIT
* compiled. If this platform is not supported or the JIT was not compiled
* in, the code may still be interpreted. */
bool allow_jit() const;
/* This may only be called when the object is first constructed, and prior to
* any code generation, otherwise returns false and does nothing. */
bool set_allow_jit(bool allow);
/* Returns a DecoderMethod that can push data to the given handlers.
* If a suitable method already exists, it will be returned from the cache.
*
* Specifying the destination handlers here allows the DecoderMethod to be
* statically bound to the destination handlers if possible, which can allow
* more efficient decoding. However the returned method may or may not
* actually be statically bound. But in all cases, the returned method can
* push data to the given handlers. */
const DecoderMethod *GetDecoderMethod(const DecoderMethodOptions& opts);
/* If/when someone needs to explicitly create a dynamically-bound
* DecoderMethod*, we can add a method to get it here. */
private:
UPB_DISALLOW_COPY_AND_ASSIGN(CodeCache)
#else
struct upb_pbcodecache {
#endif
bool allow_jit_;
/* Array of mgroups. */
upb_inttable groups;
};
UPB_BEGIN_EXTERN_C
upb_pbdecoder *upb_pbdecoder_create(upb_env *e,
const upb_pbdecodermethod *method,
upb_sink *output);
const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d);
upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d);
uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d);
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);
void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts,
const upb_handlers *h);
void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy);
/* Include refcounted methods like upb_pbdecodermethod_ref(). */
UPB_REFCOUNTED_CMETHODS(upb_pbdecodermethod, upb_pbdecodermethod_upcast)
const upb_handlers *upb_pbdecodermethod_desthandlers(
const upb_pbdecodermethod *m);
const upb_byteshandler *upb_pbdecodermethod_inputhandler(
const upb_pbdecodermethod *m);
bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m);
const upb_pbdecodermethod *upb_pbdecodermethod_new(
const upb_pbdecodermethodopts *opts, const void *owner);
void upb_pbcodecache_init(upb_pbcodecache *c);
void upb_pbcodecache_uninit(upb_pbcodecache *c);
bool upb_pbcodecache_allowjit(const upb_pbcodecache *c);
bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow);
const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod(
upb_pbcodecache *c, const upb_pbdecodermethodopts *opts);
UPB_END_EXTERN_C
#ifdef __cplusplus
namespace upb {
namespace pb {
/* static */
inline Decoder* Decoder::Create(Environment* env, const DecoderMethod* m,
Sink* sink) {
return upb_pbdecoder_create(env, m, sink);
}
inline const DecoderMethod* Decoder::method() const {
return upb_pbdecoder_method(this);
}
inline BytesSink* Decoder::input() {
return upb_pbdecoder_input(this);
}
inline uint64_t Decoder::BytesParsed() const {
return upb_pbdecoder_bytesparsed(this);
}
inline size_t Decoder::max_nesting() const {
return upb_pbdecoder_maxnesting(this);
}
inline bool Decoder::set_max_nesting(size_t max) {
return upb_pbdecoder_setmaxnesting(this, max);
}
inline void Decoder::Reset() { upb_pbdecoder_reset(this); }
inline DecoderMethodOptions::DecoderMethodOptions(const Handlers* h) {
upb_pbdecodermethodopts_init(this, h);
}
inline void DecoderMethodOptions::set_lazy(bool lazy) {
upb_pbdecodermethodopts_setlazy(this, lazy);
}
inline const Handlers* DecoderMethod::dest_handlers() const {
return upb_pbdecodermethod_desthandlers(this);
}
inline const BytesHandler* DecoderMethod::input_handler() const {
return upb_pbdecodermethod_inputhandler(this);
}
inline bool DecoderMethod::is_native() const {
return upb_pbdecodermethod_isnative(this);
}
/* static */
inline reffed_ptr<const DecoderMethod> DecoderMethod::New(
const DecoderMethodOptions &opts) {
const upb_pbdecodermethod *m = upb_pbdecodermethod_new(&opts, &m);
return reffed_ptr<const DecoderMethod>(m, &m);
}
inline CodeCache::CodeCache() {
upb_pbcodecache_init(this);
}
inline CodeCache::~CodeCache() {
upb_pbcodecache_uninit(this);
}
inline bool CodeCache::allow_jit() const {
return upb_pbcodecache_allowjit(this);
}
inline bool CodeCache::set_allow_jit(bool allow) {
return upb_pbcodecache_setallowjit(this, allow);
}
inline const DecoderMethod *CodeCache::GetDecoderMethod(
const DecoderMethodOptions& opts) {
return upb_pbcodecache_getdecodermethod(this, &opts);
}
} /* namespace pb */
} /* namespace upb */
#endif /* __cplusplus */
#endif /* UPB_DECODER_H_ */