• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** upb::Sink (upb_sink)
3 ** upb::BytesSink (upb_bytessink)
4 **
5 ** A upb_sink is an object that binds a upb_handlers object to some runtime
6 ** state.  It is the object that can actually receive data via the upb_handlers
7 ** interface.
8 **
9 ** Unlike upb_def and upb_handlers, upb_sink is never frozen, immutable, or
10 ** thread-safe.  You can create as many of them as you want, but each one may
11 ** only be used in a single thread at a time.
12 **
13 ** If we compare with class-based OOP, a you can think of a upb_def as an
14 ** abstract base class, a upb_handlers as a concrete derived class, and a
15 ** upb_sink as an object (class instance).
16 */
17 
18 #ifndef UPB_SINK_H
19 #define UPB_SINK_H
20 
21 #include "upb/handlers.h"
22 
23 #include "upb/port_def.inc"
24 
25 #ifdef __cplusplus
26 namespace upb {
27 class BytesSink;
28 class Sink;
29 }
30 #endif
31 
32 /* upb_sink *******************************************************************/
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 typedef struct {
39   const upb_handlers *handlers;
40   void *closure;
41 } upb_sink;
42 
43 #define PUTVAL(type, ctype)                                           \
44   UPB_INLINE bool upb_sink_put##type(upb_sink s, upb_selector_t sel,  \
45                                      ctype val) {                     \
46     typedef upb_##type##_handlerfunc functype;                        \
47     functype *func;                                                   \
48     const void *hd;                                                   \
49     if (!s.handlers) return true;                                     \
50     func = (functype *)upb_handlers_gethandler(s.handlers, sel, &hd); \
51     if (!func) return true;                                           \
52     return func(s.closure, hd, val);                                  \
53   }
54 
PUTVAL(int32,int32_t)55 PUTVAL(int32,  int32_t)
56 PUTVAL(int64,  int64_t)
57 PUTVAL(uint32, uint32_t)
58 PUTVAL(uint64, uint64_t)
59 PUTVAL(float,  float)
60 PUTVAL(double, double)
61 PUTVAL(bool,   bool)
62 #undef PUTVAL
63 
64 UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) {
65   s->handlers = h;
66   s->closure = c;
67 }
68 
upb_sink_putstring(upb_sink s,upb_selector_t sel,const char * buf,size_t n,const upb_bufhandle * handle)69 UPB_INLINE size_t upb_sink_putstring(upb_sink s, upb_selector_t sel,
70                                      const char *buf, size_t n,
71                                      const upb_bufhandle *handle) {
72   typedef upb_string_handlerfunc func;
73   func *handler;
74   const void *hd;
75   if (!s.handlers) return n;
76   handler = (func *)upb_handlers_gethandler(s.handlers, sel, &hd);
77 
78   if (!handler) return n;
79   return handler(s.closure, hd, buf, n, handle);
80 }
81 
upb_sink_putunknown(upb_sink s,const char * buf,size_t n)82 UPB_INLINE bool upb_sink_putunknown(upb_sink s, const char *buf, size_t n) {
83   typedef upb_unknown_handlerfunc func;
84   func *handler;
85   const void *hd;
86   if (!s.handlers) return true;
87   handler =
88       (func *)upb_handlers_gethandler(s.handlers, UPB_UNKNOWN_SELECTOR, &hd);
89 
90   if (!handler) return n;
91   return handler(s.closure, hd, buf, n);
92 }
93 
upb_sink_startmsg(upb_sink s)94 UPB_INLINE bool upb_sink_startmsg(upb_sink s) {
95   typedef upb_startmsg_handlerfunc func;
96   func *startmsg;
97   const void *hd;
98   if (!s.handlers) return true;
99   startmsg =
100       (func *)upb_handlers_gethandler(s.handlers, UPB_STARTMSG_SELECTOR, &hd);
101 
102   if (!startmsg) return true;
103   return startmsg(s.closure, hd);
104 }
105 
upb_sink_endmsg(upb_sink s,upb_status * status)106 UPB_INLINE bool upb_sink_endmsg(upb_sink s, upb_status *status) {
107   typedef upb_endmsg_handlerfunc func;
108   func *endmsg;
109   const void *hd;
110   if (!s.handlers) return true;
111   endmsg =
112       (func *)upb_handlers_gethandler(s.handlers, UPB_ENDMSG_SELECTOR, &hd);
113 
114   if (!endmsg) return true;
115   return endmsg(s.closure, hd, status);
116 }
117 
upb_sink_startseq(upb_sink s,upb_selector_t sel,upb_sink * sub)118 UPB_INLINE bool upb_sink_startseq(upb_sink s, upb_selector_t sel,
119                                   upb_sink *sub) {
120   typedef upb_startfield_handlerfunc func;
121   func *startseq;
122   const void *hd;
123   sub->closure = s.closure;
124   sub->handlers = s.handlers;
125   if (!s.handlers) return true;
126   startseq = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
127 
128   if (!startseq) return true;
129   sub->closure = startseq(s.closure, hd);
130   return sub->closure ? true : false;
131 }
132 
upb_sink_endseq(upb_sink s,upb_selector_t sel)133 UPB_INLINE bool upb_sink_endseq(upb_sink s, upb_selector_t sel) {
134   typedef upb_endfield_handlerfunc func;
135   func *endseq;
136   const void *hd;
137   if (!s.handlers) return true;
138   endseq = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
139 
140   if (!endseq) return true;
141   return endseq(s.closure, hd);
142 }
143 
upb_sink_startstr(upb_sink s,upb_selector_t sel,size_t size_hint,upb_sink * sub)144 UPB_INLINE bool upb_sink_startstr(upb_sink s, upb_selector_t sel,
145                                   size_t size_hint, upb_sink *sub) {
146   typedef upb_startstr_handlerfunc func;
147   func *startstr;
148   const void *hd;
149   sub->closure = s.closure;
150   sub->handlers = s.handlers;
151   if (!s.handlers) return true;
152   startstr = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
153 
154   if (!startstr) return true;
155   sub->closure = startstr(s.closure, hd, size_hint);
156   return sub->closure ? true : false;
157 }
158 
upb_sink_endstr(upb_sink s,upb_selector_t sel)159 UPB_INLINE bool upb_sink_endstr(upb_sink s, upb_selector_t sel) {
160   typedef upb_endfield_handlerfunc func;
161   func *endstr;
162   const void *hd;
163   if (!s.handlers) return true;
164   endstr = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
165 
166   if (!endstr) return true;
167   return endstr(s.closure, hd);
168 }
169 
upb_sink_startsubmsg(upb_sink s,upb_selector_t sel,upb_sink * sub)170 UPB_INLINE bool upb_sink_startsubmsg(upb_sink s, upb_selector_t sel,
171                                      upb_sink *sub) {
172   typedef upb_startfield_handlerfunc func;
173   func *startsubmsg;
174   const void *hd;
175   sub->closure = s.closure;
176   if (!s.handlers) {
177     sub->handlers = NULL;
178     return true;
179   }
180   sub->handlers = upb_handlers_getsubhandlers_sel(s.handlers, sel);
181   startsubmsg = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
182 
183   if (!startsubmsg) return true;
184   sub->closure = startsubmsg(s.closure, hd);
185   return sub->closure ? true : false;
186 }
187 
upb_sink_endsubmsg(upb_sink s,upb_sink sub,upb_selector_t sel)188 UPB_INLINE bool upb_sink_endsubmsg(upb_sink s, upb_sink sub,
189                                    upb_selector_t sel) {
190   typedef upb_endfield_handlerfunc func;
191   func *endsubmsg;
192   const void *hd;
193   if (!s.handlers) return true;
194   endsubmsg = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
195 
196   if (!endsubmsg) return true;
197   return endsubmsg(sub.closure, hd);
198 }
199 
200 #ifdef __cplusplus
201 }  /* extern "C" */
202 
203 /* A upb::Sink is an object that binds a upb::Handlers object to some runtime
204  * state.  It represents an endpoint to which data can be sent.
205  *
206  * TODO(haberman): right now all of these functions take selectors.  Should they
207  * take selectorbase instead?
208  *
209  * ie. instead of calling:
210  *   sink->StartString(FOO_FIELD_START_STRING, ...)
211  * a selector base would let you say:
212  *   sink->StartString(FOO_FIELD, ...)
213  *
214  * This would make call sites a little nicer and require emitting fewer selector
215  * definitions in .h files.
216  *
217  * But the current scheme has the benefit that you can retrieve a function
218  * pointer for any handler with handlers->GetHandler(selector), without having
219  * to have a separate GetHandler() function for each handler type.  The JIT
220  * compiler uses this.  To accommodate we'd have to expose a separate
221  * GetHandler() for every handler type.
222  *
223  * Also to ponder: selectors right now are independent of a specific Handlers
224  * instance.  In other words, they allocate a number to every possible handler
225  * that *could* be registered, without knowing anything about what handlers
226  * *are* registered.  That means that using selectors as table offsets prohibits
227  * us from compacting the handler table at Freeze() time.  If the table is very
228  * sparse, this could be wasteful.
229  *
230  * Having another selector-like thing that is specific to a Handlers instance
231  * would allow this compacting, but then it would be impossible to write code
232  * ahead-of-time that can be bound to any Handlers instance at runtime.  For
233  * example, a .proto file parser written as straight C will not know what
234  * Handlers it will be bound to, so when it calls sink->StartString() what
235  * selector will it pass?  It needs a selector like we have today, that is
236  * independent of any particular upb::Handlers.
237  *
238  * Is there a way then to allow Handlers table compaction? */
239 class upb::Sink {
240  public:
241   /* Constructor with no initialization; must be Reset() before use. */
Sink()242   Sink() {}
243 
244   Sink(const Sink&) = default;
245   Sink& operator=(const Sink&) = default;
246 
Sink(const upb_sink & sink)247   Sink(const upb_sink& sink) : sink_(sink) {}
248   Sink &operator=(const upb_sink &sink) {
249     sink_ = sink;
250     return *this;
251   }
252 
sink()253   upb_sink sink() { return sink_; }
254 
255   /* Constructs a new sink for the given frozen handlers and closure.
256    *
257    * TODO: once the Handlers know the expected closure type, verify that T
258    * matches it. */
Sink(const upb_handlers * handlers,T * closure)259   template <class T> Sink(const upb_handlers* handlers, T* closure) {
260     Reset(handlers, closure);
261   }
262 
ptr()263   upb_sink* ptr() { return &sink_; }
264 
265   /* Resets the value of the sink. */
Reset(const upb_handlers * handlers,T * closure)266   template <class T> void Reset(const upb_handlers* handlers, T* closure) {
267     upb_sink_reset(&sink_, handlers, closure);
268   }
269 
270   /* Returns the top-level object that is bound to this sink.
271    *
272    * TODO: once the Handlers know the expected closure type, verify that T
273    * matches it. */
GetObject()274   template <class T> T* GetObject() const {
275     return static_cast<T*>(sink_.closure);
276   }
277 
278   /* Functions for pushing data into the sink.
279    *
280    * These return false if processing should stop (either due to error or just
281    * to suspend).
282    *
283    * These may not be called from within one of the same sink's handlers (in
284    * other words, handlers are not re-entrant). */
285 
286   /* Should be called at the start and end of every message; both the top-level
287    * message and submessages.  This means that submessages should use the
288    * following sequence:
289    *   sink->StartSubMessage(startsubmsg_selector);
290    *   sink->StartMessage();
291    *   // ...
292    *   sink->EndMessage(&status);
293    *   sink->EndSubMessage(endsubmsg_selector); */
StartMessage()294   bool StartMessage() { return upb_sink_startmsg(sink_); }
EndMessage(upb_status * status)295   bool EndMessage(upb_status *status) {
296     return upb_sink_endmsg(sink_, status);
297   }
298 
299   /* Putting of individual values.  These work for both repeated and
300    * non-repeated fields, but for repeated fields you must wrap them in
301    * calls to StartSequence()/EndSequence(). */
PutInt32(HandlersPtr::Selector s,int32_t val)302   bool PutInt32(HandlersPtr::Selector s, int32_t val) {
303     return upb_sink_putint32(sink_, s, val);
304   }
305 
PutInt64(HandlersPtr::Selector s,int64_t val)306   bool PutInt64(HandlersPtr::Selector s, int64_t val) {
307     return upb_sink_putint64(sink_, s, val);
308   }
309 
PutUInt32(HandlersPtr::Selector s,uint32_t val)310   bool PutUInt32(HandlersPtr::Selector s, uint32_t val) {
311     return upb_sink_putuint32(sink_, s, val);
312   }
313 
PutUInt64(HandlersPtr::Selector s,uint64_t val)314   bool PutUInt64(HandlersPtr::Selector s, uint64_t val) {
315     return upb_sink_putuint64(sink_, s, val);
316   }
317 
PutFloat(HandlersPtr::Selector s,float val)318   bool PutFloat(HandlersPtr::Selector s, float val) {
319     return upb_sink_putfloat(sink_, s, val);
320   }
321 
PutDouble(HandlersPtr::Selector s,double val)322   bool PutDouble(HandlersPtr::Selector s, double val) {
323     return upb_sink_putdouble(sink_, s, val);
324   }
325 
PutBool(HandlersPtr::Selector s,bool val)326   bool PutBool(HandlersPtr::Selector s, bool val) {
327     return upb_sink_putbool(sink_, s, val);
328   }
329 
330   /* Putting of string/bytes values.  Each string can consist of zero or more
331    * non-contiguous buffers of data.
332    *
333    * For StartString(), the function will write a sink for the string to "sub."
334    * The sub-sink must be used for any/all PutStringBuffer() calls. */
StartString(HandlersPtr::Selector s,size_t size_hint,Sink * sub)335   bool StartString(HandlersPtr::Selector s, size_t size_hint, Sink* sub) {
336     upb_sink sub_c;
337     bool ret = upb_sink_startstr(sink_, s, size_hint, &sub_c);
338     *sub = sub_c;
339     return ret;
340   }
341 
PutStringBuffer(HandlersPtr::Selector s,const char * buf,size_t len,const upb_bufhandle * handle)342   size_t PutStringBuffer(HandlersPtr::Selector s, const char *buf, size_t len,
343                          const upb_bufhandle *handle) {
344     return upb_sink_putstring(sink_, s, buf, len, handle);
345   }
346 
EndString(HandlersPtr::Selector s)347   bool EndString(HandlersPtr::Selector s) {
348     return upb_sink_endstr(sink_, s);
349   }
350 
351   /* For submessage fields.
352    *
353    * For StartSubMessage(), the function will write a sink for the string to
354    * "sub." The sub-sink must be used for any/all handlers called within the
355    * submessage. */
StartSubMessage(HandlersPtr::Selector s,Sink * sub)356   bool StartSubMessage(HandlersPtr::Selector s, Sink* sub) {
357     upb_sink sub_c;
358     bool ret = upb_sink_startsubmsg(sink_, s, &sub_c);
359     *sub = sub_c;
360     return ret;
361   }
362 
EndSubMessage(HandlersPtr::Selector s,Sink sub)363   bool EndSubMessage(HandlersPtr::Selector s, Sink sub) {
364     return upb_sink_endsubmsg(sink_, sub.sink_, s);
365   }
366 
367   /* For repeated fields of any type, the sequence of values must be wrapped in
368    * these calls.
369    *
370    * For StartSequence(), the function will write a sink for the string to
371    * "sub." The sub-sink must be used for any/all handlers called within the
372    * sequence. */
StartSequence(HandlersPtr::Selector s,Sink * sub)373   bool StartSequence(HandlersPtr::Selector s, Sink* sub) {
374     upb_sink sub_c;
375     bool ret = upb_sink_startseq(sink_, s, &sub_c);
376     *sub = sub_c;
377     return ret;
378   }
379 
EndSequence(HandlersPtr::Selector s)380   bool EndSequence(HandlersPtr::Selector s) {
381     return upb_sink_endseq(sink_, s);
382   }
383 
384   /* Copy and assign specifically allowed.
385    * We don't even bother making these members private because so many
386    * functions need them and this is mainly just a dumb data container anyway.
387    */
388 
389  private:
390   upb_sink sink_;
391 };
392 
393 #endif  /* __cplusplus */
394 
395 /* upb_bytessink **************************************************************/
396 
397 typedef struct {
398   const upb_byteshandler *handler;
399   void *closure;
400 } upb_bytessink ;
401 
upb_bytessink_reset(upb_bytessink * s,const upb_byteshandler * h,void * closure)402 UPB_INLINE void upb_bytessink_reset(upb_bytessink* s, const upb_byteshandler *h,
403                                     void *closure) {
404   s->handler = h;
405   s->closure = closure;
406 }
407 
upb_bytessink_start(upb_bytessink s,size_t size_hint,void ** subc)408 UPB_INLINE bool upb_bytessink_start(upb_bytessink s, size_t size_hint,
409                                     void **subc) {
410   typedef upb_startstr_handlerfunc func;
411   func *start;
412   *subc = s.closure;
413   if (!s.handler) return true;
414   start = (func *)s.handler->table[UPB_STARTSTR_SELECTOR].func;
415 
416   if (!start) return true;
417   *subc = start(s.closure,
418                 s.handler->table[UPB_STARTSTR_SELECTOR].attr.handler_data,
419                 size_hint);
420   return *subc != NULL;
421 }
422 
upb_bytessink_putbuf(upb_bytessink s,void * subc,const char * buf,size_t size,const upb_bufhandle * handle)423 UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink s, void *subc,
424                                        const char *buf, size_t size,
425                                        const upb_bufhandle* handle) {
426   typedef upb_string_handlerfunc func;
427   func *putbuf;
428   if (!s.handler) return true;
429   putbuf = (func *)s.handler->table[UPB_STRING_SELECTOR].func;
430 
431   if (!putbuf) return true;
432   return putbuf(subc, s.handler->table[UPB_STRING_SELECTOR].attr.handler_data,
433                 buf, size, handle);
434 }
435 
upb_bytessink_end(upb_bytessink s)436 UPB_INLINE bool upb_bytessink_end(upb_bytessink s) {
437   typedef upb_endfield_handlerfunc func;
438   func *end;
439   if (!s.handler) return true;
440   end = (func *)s.handler->table[UPB_ENDSTR_SELECTOR].func;
441 
442   if (!end) return true;
443   return end(s.closure,
444              s.handler->table[UPB_ENDSTR_SELECTOR].attr.handler_data);
445 }
446 
447 #ifdef __cplusplus
448 
449 class upb::BytesSink {
450  public:
BytesSink()451   BytesSink() {}
452 
453   BytesSink(const BytesSink&) = default;
454   BytesSink& operator=(const BytesSink&) = default;
455 
BytesSink(const upb_bytessink & sink)456   BytesSink(const upb_bytessink& sink) : sink_(sink) {}
457   BytesSink &operator=(const upb_bytessink &sink) {
458     sink_ = sink;
459     return *this;
460   }
461 
sink()462   upb_bytessink sink() { return sink_; }
463 
464   /* Constructs a new sink for the given frozen handlers and closure.
465    *
466    * TODO(haberman): once the Handlers know the expected closure type, verify
467    * that T matches it. */
BytesSink(const upb_byteshandler * handler,T * closure)468   template <class T> BytesSink(const upb_byteshandler* handler, T* closure) {
469     upb_bytessink_reset(sink_, handler, closure);
470   }
471 
472   /* Resets the value of the sink. */
Reset(const upb_byteshandler * handler,T * closure)473   template <class T> void Reset(const upb_byteshandler* handler, T* closure) {
474     upb_bytessink_reset(&sink_, handler, closure);
475   }
476 
Start(size_t size_hint,void ** subc)477   bool Start(size_t size_hint, void **subc) {
478     return upb_bytessink_start(sink_, size_hint, subc);
479   }
480 
PutBuffer(void * subc,const char * buf,size_t len,const upb_bufhandle * handle)481   size_t PutBuffer(void *subc, const char *buf, size_t len,
482                    const upb_bufhandle *handle) {
483     return upb_bytessink_putbuf(sink_, subc, buf, len, handle);
484   }
485 
End()486   bool End() {
487     return upb_bytessink_end(sink_);
488   }
489 
490  private:
491   upb_bytessink sink_;
492 };
493 
494 #endif  /* __cplusplus */
495 
496 /* upb_bufsrc *****************************************************************/
497 
498 #ifdef __cplusplus
499 extern "C" {
500 #endif
501 
502 bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink);
503 
504 #ifdef __cplusplus
505 }  /* extern "C" */
506 
507 namespace upb {
PutBuffer(const T & str,BytesSink sink)508 template <class T> bool PutBuffer(const T& str, BytesSink sink) {
509   return upb_bufsrc_putbuf(str.data(), str.size(), sink.sink());
510 }
511 }
512 
513 #endif  /* __cplusplus */
514 
515 #include "upb/port_undef.inc"
516 
517 #endif
518