diff options
author | Josh Haberman <haberman@google.com> | 2013-05-25 10:26:59 -0700 |
---|---|---|
committer | Josh Haberman <haberman@google.com> | 2013-05-25 10:26:59 -0700 |
commit | 90bb4246c34580eb6c8a5a41a4e19fcd5f334f09 (patch) | |
tree | c0a5fedd4633dcaf1e975adc2edb34332a5dd686 /upb/sink.h | |
parent | cfdb9907cb87d15eaab72ceefbfa42fd7a4c3127 (diff) |
Synced with Google-internal development.
C++ handlers are now type-safe; SinkFrame is gone.
Various other changes.
Diffstat (limited to 'upb/sink.h')
-rw-r--r-- | upb/sink.h | 172 |
1 files changed, 35 insertions, 137 deletions
@@ -30,22 +30,13 @@ template <int size> class SeededPipeline; } typedef upb::Pipeline upb_pipeline; typedef upb::Sink upb_sink; -UPB_INLINE upb_sink* upb_sinkframe_sink(const upb_sinkframe* frame); -UPB_INLINE void* upb_sinkframe_userdata(const upb_sinkframe* frame); -UPB_INLINE void* upb_sinkframe_handlerdata(const upb_sinkframe* frame); #else struct upb_pipeline; struct upb_sink; typedef struct upb_pipeline upb_pipeline; typedef struct upb_sink upb_sink; #endif - -struct upb_frametype { - size_t size; - void (*init)(void* obj); - void (*uninit)(void* obj); - void (*reset)(void* obj); -}; +struct upb_sinkframe; #ifdef __cplusplus @@ -122,6 +113,13 @@ struct upb_pipeline { upb_status status_; }; +struct upb_frametype { + size_t size; + void (*init)(void* obj, upb_pipeline *p); + void (*uninit)(void* obj); + void (*reset)(void* obj); +}; + #ifdef __cplusplus // For convenience, a template for a pipeline with an array of initial memory. @@ -136,84 +134,6 @@ class upb::SeededPipeline : public upb::Pipeline { char mem_[initial_size]; }; -class upb::SinkFrame { - public: - // Returns the sink that this frame belongs to. - Sink* sink() const; - - // Returns the pipeline that this sink and frame belong to. - Pipeline* pipeline() const; - - // The depth of this frame (counts all kind of frames (sequence, submessage, - // and string frames). - int depth() const; - - // The Handlers object for this frame. - const Handlers* handlers() const; - - // Returns the user data that is bound to this sink frame (as returned - // by the Start{SubMessage,String,Sequence} handler, or passed to - // Sink::Reset()). - void* userdata() const; - - // A templated version of userdata() that type-checks the templated return - // type. - // - // TODO(haberman): this isn't truly robust until sequence and string frames - // have distinct FrameTypes in the Handlers. - template<class T> - T* GetUserdata() const { -#ifdef NDEBUG - return static_cast<T*>(userdata()); -#else - const FrameType* type = handlers()->frame_type(); - if (!type || type == GetFrameType<T>()) { - return static_cast<T*>(userdata()); - } else { - assert(false); - return NULL; - } -#endif - } - - // Returns the data that was bound to the currently-executing callback in the - // Handlers object. If not currently in a handler, the results are undefined. - void* handler_data() const; - - private: - UPB_DISALLOW_POD_OPS(SinkFrame); - friend class upb::Sink; - friend upb_sink* ::upb_sinkframe_sink(const upb_sinkframe* frame); - friend void* ::upb_sinkframe_userdata(const upb_sinkframe* frame); - friend void* ::upb_sinkframe_handlerdata(const upb_sinkframe* frame); - -#else -struct upb_sinkframe { -#endif - upb_sink *sink_; - const upb_handlers *h; - void *closure; - - union { - // For the top frame (sink->top), the handler_data for the - // currently-executing callback, otherwise undefined. - // TODO(haberman): have a special pointer value to indicate "not in a - // callback"; this will be a way to enforce non-reentrancy of a sink. - void *handler_data; - - // For other frames, the END* callback that will run when the subframe is - // popped (for example, for a "sequence" frame the frame above it will be a - // UPB_HANDLER_ENDSEQ handler). But this is only necessary for assertion - // checking inside upb_sink and can be omitted if the sink has only one - // caller. - // TODO(haberman): have a mechanism for ensuring that a sink only has one - // caller. - upb_selector_t selector; - } u; -}; - -#ifdef __cplusplus - // A upb::Sink is an object that binds a upb::Handlers object to some runtime // state. It is the object that can actually call a set of handlers. // @@ -234,13 +154,12 @@ class upb::Sink { // used as the top-level closure. void Reset(void *closure); - // Returns the top-most and base (lowest) frame of the stack, respectively. - const SinkFrame* top() const; - const SinkFrame* base() const; - // Returns the pipeline that this sink comes from. Pipeline* pipeline() const; + // Returns the top-level object that is bound to this sink. + template <class T> T* GetObject() const; + // Functions for pushing data into the sink. // // These return false if processing should stop (either due to error or just @@ -285,23 +204,9 @@ class upb::Sink { struct upb_sink { #endif upb_pipeline *pipeline_; - upb_sinkframe *top_, *limit; - upb_sinkframe stack[UPB_MAX_NESTING]; + struct upb_sinkframe *top, *limit, *stack; }; -// C API. -UPB_INLINE upb_sink *upb_sinkframe_sink(const upb_sinkframe* frame) { - return frame->sink_; -} - -UPB_INLINE void *upb_sinkframe_userdata(const upb_sinkframe* frame) { - return frame->closure; -} - -UPB_INLINE void *upb_sinkframe_handlerdata(const upb_sinkframe* frame) { - return frame->u.handler_data; -} - #ifdef __cplusplus extern "C" { #endif @@ -321,14 +226,9 @@ void upb_pipeline_donateref( upb_sink *upb_pipeline_newsink(upb_pipeline *p, const upb_handlers *h); const upb_status *upb_pipeline_status(const upb_pipeline *p); -int upb_sinkframe_depth(const upb_sinkframe* frame); -const upb_handlers* upb_sinkframe_handlers(const upb_sinkframe* frame); -upb_pipeline* upb_sinkframe_pipeline(const upb_sinkframe* frame); - void upb_sink_reset(upb_sink *s, void *closure); upb_pipeline *upb_sink_pipeline(const upb_sink *s); -const upb_sinkframe *upb_sink_top(const upb_sink *s); -const upb_sinkframe *upb_sink_base(const upb_sink *s); +void *upb_sink_getobj(const upb_sink *s); bool upb_sink_startmsg(upb_sink *s); void upb_sink_endmsg(upb_sink *s); bool upb_sink_putint32(upb_sink *s, upb_selector_t sel, int32_t val); @@ -386,36 +286,15 @@ inline void Pipeline::DonateRef(const upb::Handlers* h, const void *owner) { return upb_pipeline_donateref(this, h, owner); } -inline Sink* SinkFrame::sink() const { - return upb_sinkframe_sink(this); -} -inline Pipeline* SinkFrame::pipeline() const { - return upb_sinkframe_pipeline(this); -} -inline void* SinkFrame::userdata() const { - return upb_sinkframe_userdata(this); -} -inline void* SinkFrame::handler_data() const { - return upb_sinkframe_handlerdata(this); -} -inline int SinkFrame::depth() const { - return upb_sinkframe_depth(this); -} -inline const Handlers* SinkFrame::handlers() const { - return upb_sinkframe_handlers(this); -} - inline void Sink::Reset(void *closure) { upb_sink_reset(this, closure); } inline Pipeline* Sink::pipeline() const { return upb_sink_pipeline(this); } -inline const SinkFrame* Sink::top() const { - return upb_sink_top(this); -} -inline const SinkFrame* Sink::base() const { - return upb_sink_base(this); +template <class T> +inline T* Sink::GetObject() const { + return static_cast<T*>(upb_sink_getobj(this)); } inline bool Sink::StartMessage() { return upb_sink_startmsg(this); @@ -470,4 +349,23 @@ inline bool Sink::EndSequence(Handlers::Selector sel) { } // namespace upb #endif +// TODO(haberman): move this to sink.c. We keep it here now only because the +// JIT needs to modify it directly, which it only needs to do because it makes +// the interpreter handle fallback cases. When the JIT is self-sufficient, it +// will no longer need to touch the sink's stack at all. +struct upb_sinkframe { + const upb_handlers *h; + void *closure; + + // For any frames besides the top, this is the END* callback that will run + // when the subframe is popped (for example, for a "sequence" frame the frame + // above it will be a UPB_HANDLER_ENDSEQ handler). But this is only + // necessary for assertion checking inside upb_sink and can be omitted if the + // sink has only one caller. + // + // TODO(haberman): have a mechanism for ensuring that a sink only has one + // caller. + upb_selector_t selector; +}; + #endif |