From 6b574175dd43735a26f171de6b34c3f15bb50f12 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Tue, 22 Feb 2011 11:31:32 -0800 Subject: Prevent the default message from getting mutated. If a Lua program references the default message, it will be copied into a mutable object. --- src/upb_msg.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'src/upb_msg.h') diff --git a/src/upb_msg.h b/src/upb_msg.h index ff8489c..468af24 100644 --- a/src/upb_msg.h +++ b/src/upb_msg.h @@ -10,6 +10,8 @@ * * upb's parsers and serializers could also be used to populate and serialize * other kinds of message objects (even one generated by Google's protobuf). + * + * TODO: consider properly supporting const instances. */ #ifndef UPB_MSG_H @@ -204,12 +206,16 @@ upb_msg *upb_msg_new(upb_msgdef *md); INLINE void upb_msg_unref(upb_msg *msg, upb_msgdef *md) { if (msg && upb_atomic_unref(&msg->refcount)) _upb_msg_free(msg, md); } + INLINE upb_msg *upb_msg_getref(upb_msg *msg) { assert(msg); upb_atomic_ref(&msg->refcount); return msg; } +// Modifies *msg to point to a newly initialized msg instance. If the msg had +// no other referents, reuses the same msg, otherwise allocates a new one. +// The caller *must* own a ref on the msg prior to calling this method! void upb_msg_recycle(upb_msg **msg, upb_msgdef *msgdef); // Tests whether the given field is explicitly set, or whether it will return a @@ -240,9 +246,17 @@ INLINE bool upb_msg_has(upb_msg *msg, upb_fielddef *f) { // // For the moment we go with (2). Google's protobuf does (3), which is likely // part of the reason we beat it in some benchmarks. +// +// If the branchiness of (2) is too great, this could be mitigated with cmov +// (both values and the conditional are cheap to calculate, much cheaper than +// the cost of a misprediction). // For submessages and strings, the returned value is not owned. -INLINE upb_value upb_msg_get(upb_msg *msg, upb_fielddef *f) { +upb_value upb_msg_get(upb_msg *msg, upb_fielddef *f); + +// A specialized version of the previous that is cheaper because it doesn't +// support submessages or arrays. +INLINE upb_value upb_msg_getscalar(upb_msg *msg, upb_fielddef *f) { if (upb_msg_has(msg, f)) { return upb_value_read(_upb_msg_getptr(msg, f), upb_field_valuetype(f)); } else { @@ -250,6 +264,9 @@ INLINE upb_value upb_msg_get(upb_msg *msg, upb_fielddef *f) { } } +// Sets the given field to the given value. If the field is a string, array, +// or submessage, releases the ref on any object we may have been referencing +// and takes a ref on the new object (if any). void upb_msg_set(upb_msg *msg, upb_fielddef *f, upb_value val); // Unsets all field values back to their defaults. -- cgit v1.2.3