From 3bd691a4975b2267ff04611507e766a7f9f87e83 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Fri, 8 May 2015 16:56:29 -0700 Subject: Google-internal development. --- upb/pb/encoder.h | 116 ++++++++++++------------------------------------------- 1 file changed, 25 insertions(+), 91 deletions(-) (limited to 'upb/pb/encoder.h') diff --git a/upb/pb/encoder.h b/upb/pb/encoder.h index 2df5797..edff95b 100644 --- a/upb/pb/encoder.h +++ b/upb/pb/encoder.h @@ -15,6 +15,7 @@ #ifndef UPB_ENCODER_H_ #define UPB_ENCODER_H_ +#include "upb/env.h" #include "upb/sink.h" #ifdef __cplusplus @@ -31,101 +32,42 @@ UPB_DECLARE_TYPE(upb::pb::Encoder, upb_pb_encoder); /* upb::pb::Encoder ***********************************************************/ -// The output buffer is divided into segments; a segment is a string of data -// that is "ready to go" -- it does not need any varint lengths inserted into -// the middle. The seams between segments are where varints will be inserted -// once they are known. -// -// We also use the concept of a "run", which is a range of encoded bytes that -// occur at a single submessage level. Every segment contains one or more runs. -// -// A segment can span messages. Consider: -// -// .--Submessage lengths---------. -// | | | -// | V V -// V | |--------------- | |----------------- -// Submessages: | |----------------------------------------------- -// Top-level msg: ------------------------------------------------------------ -// -// Segments: ----- ------------------- ----------------- -// Runs: *---- *--------------*--- *---------------- -// (* marks the start) -// -// Note that the top-level menssage is not in any segment because it does not -// have any length preceding it. -// -// A segment is only interrupted when another length needs to be inserted. So -// observe how the second segment spans both the inner submessage and part of -// the next enclosing message. -typedef struct { - UPB_PRIVATE_FOR_CPP - uint32_t msglen; // The length to varint-encode before this segment. - uint32_t seglen; // Length of the segment. -} upb_pb_encoder_segment; - -UPB_DEFINE_CLASS0(upb::pb::Encoder, - public: - Encoder(const upb::Handlers* handlers); - ~Encoder(); - - static reffed_ptr NewHandlers(const upb::MessageDef* msg); +// 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_ENCODER_SIZE 768 - // Resets the state of the printer, so that it will expect to begin a new - // document. - void Reset(); +#ifdef __cplusplus - // Resets the output pointer which will serve as our closure. - void ResetOutput(BytesSink* output); +class upb::pb::Encoder { + public: + // Creates a new encoder in the given environment. The Handlers must have + // come from NewHandlers() below. + static Encoder* Create(Environment* env, const Handlers* handlers, + BytesSink* output); // The input to the encoder. Sink* input(); - private: - UPB_DISALLOW_COPY_AND_ASSIGN(Encoder); -, -UPB_DEFINE_STRUCT0(upb_pb_encoder, UPB_QUOTE( - // Our input and output. - upb_sink input_; - upb_bytessink *output_; - - // The "subclosure" -- used as the inner closure as part of the bytessink - // protocol. - void *subc; - - // The output buffer and limit, and our current write position. "buf" - // initially points to "initbuf", but is dynamically allocated if we need to - // grow beyond the initial size. - char *buf, *ptr, *limit; + // Creates a new set of handlers for this MessageDef. + static reffed_ptr NewHandlers(const MessageDef* msg); - // The beginning of the current run, or undefined if we are at the top level. - char *runbegin; + static const size_t kSize = UPB_PB_ENCODER_SIZE; - // The list of segments we are accumulating. - upb_pb_encoder_segment *segbuf, *segptr, *seglimit; - - // The stack of enclosing submessages. Each entry in the stack points to the - // segment where this submessage's length is being accumulated. - int stack[UPB_PBENCODER_MAX_NESTING], *top, *stacklimit; - - // Depth of startmsg/endmsg calls. - int depth; + private: + UPB_DISALLOW_POD_OPS(Encoder, upb::pb::Encoder); +}; - // Initial buffers for the output buffer and segment buffer. If we outgrow - // these we will dynamically allocate bigger ones. - char initbuf[256]; - upb_pb_encoder_segment seginitbuf[32]; -))); +#endif UPB_BEGIN_EXTERN_C const upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m, const void *owner); -void upb_pb_encoder_reset(upb_pb_encoder *e); upb_sink *upb_pb_encoder_input(upb_pb_encoder *p); -void upb_pb_encoder_init(upb_pb_encoder *e, const upb_handlers *h); -void upb_pb_encoder_resetoutput(upb_pb_encoder *e, upb_bytessink *output); -void upb_pb_encoder_uninit(upb_pb_encoder *e); +upb_pb_encoder* upb_pb_encoder_create(upb_env* e, const upb_handlers* h, + upb_bytessink* output); UPB_END_EXTERN_C @@ -133,17 +75,9 @@ UPB_END_EXTERN_C namespace upb { namespace pb { -inline Encoder::Encoder(const upb::Handlers* handlers) { - upb_pb_encoder_init(this, handlers); -} -inline Encoder::~Encoder() { - upb_pb_encoder_uninit(this); -} -inline void Encoder::Reset() { - upb_pb_encoder_reset(this); -} -inline void Encoder::ResetOutput(BytesSink* output) { - upb_pb_encoder_resetoutput(this, output); +inline Encoder* Encoder::Create(Environment* env, const Handlers* handlers, + BytesSink* output) { + return upb_pb_encoder_create(env, handlers, output); } inline Sink* Encoder::input() { return upb_pb_encoder_input(this); -- cgit v1.2.3