summaryrefslogtreecommitdiff
path: root/upb/pb/encoder.h
diff options
context:
space:
mode:
Diffstat (limited to 'upb/pb/encoder.h')
-rw-r--r--upb/pb/encoder.h116
1 files changed, 25 insertions, 91 deletions
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<const Handlers> 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<const Handlers> 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);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback