Addressed PR comments.
diff --git a/python/message.c b/python/message.c
index 392d8e0..1b3a7bb 100644
--- a/python/message.c
+++ b/python/message.c
@@ -469,6 +469,21 @@
return PyUpb_Message_IsEqual(m1_msg, m2_msg, m1_msgdef);
}
+static const upb_fielddef* PyUpb_CMessage_InitAsMsg(PyUpb_CMessage* m,
+ upb_arena* arena) {
+ const upb_fielddef* f = PyUpb_CMessage_GetFieldDef(m);
+ m->ptr.msg = upb_msg_new(upb_fielddef_msgsubdef(f), arena);
+ m->def = (uintptr_t)upb_fielddef_msgsubdef(f);
+ return f;
+}
+
+static void PyUpb_CMessage_SetField(PyUpb_CMessage* p, const upb_fielddef* cf,
+ PyUpb_CMessage* c, upb_arena* arena) {
+ upb_msg_set(p->ptr.msg, cf, (upb_msgval){.msg_val = c->ptr.msg}, arena);
+ PyUpb_WeakMap_Delete(p->unset_subobj_map, cf);
+ PyUpb_ObjCache_Add(c->ptr.msg, &c->ob_base);
+}
+
/*
* PyUpb_CMessage_AssureWritable()
*
@@ -487,42 +502,29 @@
* Post-condition:
* PyUpb_CMessage_IsUnset(self) is false
*/
-void PyUpb_CMessage_AssureWritable(PyUpb_CMessage* self) {
- if (!PyUpb_CMessage_IsUnset(self)) return;
-
+void PyUpb_CMessage_AssureWritable(PyUpb_CMessage* child) {
+ if (!PyUpb_CMessage_IsUnset(child)) return;
// This is a non-present message. We need to create a real upb_msg for this
// object and every parent until we reach a present message.
- upb_arena* arena = PyUpb_Arena_Get(self->arena);
- PyUpb_CMessage* child = self;
- PyUpb_CMessage* parent = self->ptr.parent;
- const upb_fielddef* child_f = PyUpb_CMessage_GetFieldDef(child);
- // This overwrites child->ptr.parent.
- child->ptr.msg = upb_msg_new(upb_fielddef_msgsubdef(child_f), arena);
+ upb_arena* arena = PyUpb_Arena_Get(child->arena);
- while (PyUpb_CMessage_IsUnset(child)) {
- PyUpb_CMessage* next_parent = parent->ptr.parent;
+ PyUpb_CMessage* next_parent = NULL;
+ PyUpb_CMessage* parent = child->ptr.parent;
+ const upb_fielddef* child_f = PyUpb_CMessage_InitAsMsg(child, arena);
+ do {
const upb_fielddef* parent_f = NULL;
if (PyUpb_CMessage_IsUnset(parent)) {
- parent_f = PyUpb_CMessage_GetFieldDef(parent);
- // This overwrites parent->ptr.parent.
- parent->ptr.msg = upb_msg_new(upb_fielddef_msgsubdef(parent_f), arena);
+ next_parent = parent->ptr.parent;
+ parent_f = PyUpb_CMessage_InitAsMsg(parent, arena);
}
- upb_msgval msgval;
- msgval.msg_val = child->ptr.msg;
- upb_msg_set(parent->ptr.msg, child_f, msgval, arena);
- child->def = (uintptr_t)upb_fielddef_msgsubdef(child_f);
- PyUpb_WeakMap_Delete(parent->unset_subobj_map, child_f);
- PyUpb_ObjCache_Add(child->ptr.msg, &child->ob_base);
- if (child != self) {
- Py_DECREF(child); // Was previously a parent.
- }
- child = parent;
+ PyUpb_CMessage_SetField(parent, child_f, child, arena);
+ Py_DECREF(&child->ob_base);
child_f = parent_f;
+ child = parent;
parent = next_parent;
- }
+ } while (PyUpb_CMessage_IsUnset(child));
- Py_DECREF(child);
- self->version++;
+ child->version++;
}
static void PyUpb_CMessage_SyncSubobjs(PyUpb_CMessage* self);