This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git

commit 364e3951121e2181e42324748a863c3fc22e4713
Author: Andrew Stitcher <[email protected]>
AuthorDate: Sun Aug 30 01:19:34 2026 +0000

    PROTON-2954: Simplify pn_data_t
    
    - The different compound types now all have the same node data
    - Call out the scratch space in compound nodes explicitly
---
 c/src/core/codec.c   | 30 ++++++++++----------
 c/src/core/data.h    | 78 ++++++++++++----------------------------------------
 c/src/core/encoder.c | 24 ++++++++--------
 3 files changed, 44 insertions(+), 88 deletions(-)

diff --git a/c/src/core/codec.c b/c/src/core/codec.c
index 75cc49e04..2b1f861a1 100644
--- a/c/src/core/codec.c
+++ b/c/src/core/codec.c
@@ -98,7 +98,7 @@ static const pn_fields_t *pni_node_fields(pn_data_t *data, 
pni_node_t *node)
   if (!node) return NULL;
   if (node->type != PN_DESCRIBED) return NULL;
 
-  pni_node_t *descriptor = pn_data_node(data, node->u.as_described.down);
+  pni_node_t *descriptor = pn_data_node(data, node->u.as_compound.down);
 
   if (!descriptor || descriptor->type != PN_ULONG) {
     return NULL;
@@ -822,8 +822,8 @@ int pn_data_vfill(pn_data_t *data, const char *fmt, va_list 
ap)
           pni_nid_t down = current->u.as_deferred.down;
           uint16_t count = current->u.as_deferred.children_count;
           current->type = PN_DESCRIBED;
-          current->u.as_described.down = down;
-          current->u.as_described.children_count = count;
+          current->u.as_compound.down = down;
+          current->u.as_compound.children_count = count;
           continue;
         } else if (parent->u.as_deferred.type == PN_NULL && 
parent->u.as_deferred.children_count == 1) {
           pn_data_exit(data);
@@ -1648,8 +1648,8 @@ int pn_data_put_list(pn_data_t *data)
   pni_node_t *node = pni_data_add(data);
   if (node == NULL) return PN_OUT_OF_MEMORY;
   node->type = PN_LIST;
-  node->u.as_list.down = 0;
-  node->u.as_list.children_count = 0;
+  node->u.as_compound.down = 0;
+  node->u.as_compound.children_count = 0;
   return 0;
 }
 
@@ -1658,8 +1658,8 @@ int pn_data_put_map(pn_data_t *data)
   pni_node_t *node = pni_data_add(data);
   if (node == NULL) return PN_OUT_OF_MEMORY;
   node->type = PN_MAP;
-  node->u.as_map.down = 0;
-  node->u.as_map.children_count = 0;
+  node->u.as_compound.down = 0;
+  node->u.as_compound.children_count = 0;
   return 0;
 }
 
@@ -1669,8 +1669,8 @@ int pn_data_put_array(pn_data_t *data, bool described, 
pn_type_t type)
   if (node == NULL) return PN_OUT_OF_MEMORY;
   node->type = described ? PN_ARRAY_DESCRIBED : PN_ARRAY;
   node->array_type = (uint8_t)type;
-  node->u.as_array.down = 0;
-  node->u.as_array.children_count = 0;
+  node->u.as_compound.down = 0;
+  node->u.as_compound.children_count = 0;
   return 0;
 }
 
@@ -1687,8 +1687,8 @@ int pn_data_put_described(pn_data_t *data)
   pni_node_t *node = pni_data_add(data);
   if (node == NULL) return PN_OUT_OF_MEMORY;
   node->type = PN_DESCRIBED;
-  node->u.as_described.down = 0;
-  node->u.as_described.children_count = 0;
+  node->u.as_compound.down = 0;
+  node->u.as_compound.children_count = 0;
   return 0;
 }
 
@@ -1903,7 +1903,7 @@ size_t pn_data_get_list(pn_data_t *data)
 {
   pni_node_t *node = pni_data_current(data);
   if (node && node->type == PN_LIST) {
-    return node->u.as_list.children_count;
+    return node->u.as_compound.children_count;
   } else {
     return 0;
   }
@@ -1913,7 +1913,7 @@ size_t pn_data_get_map(pn_data_t *data)
 {
   pni_node_t *node = pni_data_current(data);
   if (node && node->type == PN_MAP) {
-    return node->u.as_map.children_count;
+    return node->u.as_compound.children_count;
   } else {
     return 0;
   }
@@ -1925,10 +1925,10 @@ size_t pn_data_get_array(pn_data_t *data)
   if (!node) return 0;
 
   if (node->type == PN_ARRAY_DESCRIBED) {
-    return node->u.as_array.children_count - 1;  // Descriptor doesn't count
+    return node->u.as_compound.children_count - 1;  // Descriptor doesn't count
   }
   if (node->type == PN_ARRAY) {
-    return node->u.as_array.children_count;
+    return node->u.as_compound.children_count;
   }
   return 0;
 }
diff --git a/c/src/core/data.h b/c/src/core/data.h
index 4dee470e9..d7338010b 100644
--- a/c/src/core/data.h
+++ b/c/src/core/data.h
@@ -41,17 +41,12 @@ typedef uint16_t pni_nid_t;
  * buffer (data->buf); as_bytes.offset and as_bytes.size locate the bytes.
  * DECIMAL128 and UUID always have as_bytes.size == 16.
  *
- * PN_ARRAY nodes use as_array: element type, whether the array has a
- * descriptor child (described), and encoder scratch (start, small).
+ * Compound nodes share a single layout for down/children and scratch state:
+ * PN_ARRAY, PN_ARRAY_DESCRIBED, PN_LIST, PN_MAP and PN_DESCRIBED all use
+ * as_compound.
  *
- * PN_LIST nodes use as_list: whether the list is the body of a described
- * value (controls trailing-null elision during encoding), and encoder
- * scratch (start, small).
- *
- * PN_MAP nodes use as_map: encoder scratch (start, small).
- *
- * All other types (NULL, DESCRIBED) carry no payload; only the type tag
- * on pni_node_t is meaningful.
+ * All other types carry no payload; only the type tag on pni_node_t is
+ * meaningful.
  */
 typedef union {
   bool            as_bool;
@@ -79,29 +74,14 @@ typedef union {
     uint8_t       type;           /* deferred type */
   }               as_deferred;
 
-  // Compound types include navigation
+  // Compound types share the same navigation and scratch layout.
   struct {
-    pni_nid_t     down;            // offset 0: 2 bytes
-    pni_nid_t     children_count;  // offset 2: 2 bytes
-    uint32_t      start;           // offset 4: 4 bytes
-  }               as_array;        // 8 bytes
-
-  struct {
-    pni_nid_t     down;            // offset 0: 2 bytes
-    pni_nid_t     children_count;  // offset 2: 2 bytes
-    uint32_t      start;           // offset 4: 4 bytes
-  }               as_list;         // 8 bytes
-
-  struct {
-    pni_nid_t     down;            // offset 0: 2 bytes
-    pni_nid_t     children_count;  // offset 2: 2 bytes
-    uint32_t      start;           // offset 4: 4 bytes
-  }               as_map;          // 8 bytes
-
-  struct {
-    pni_nid_t     down;            // offset 0: 2 bytes
-    pni_nid_t     children_count;  // offset 2: 2 bytes
-  }               as_described;    // 4 bytes (union is 8)
+    pni_nid_t down;            // offset 0: 2 bytes
+    pni_nid_t children_count;  // offset 2: 2 bytes
+    union {
+      uint32_t as_u32;
+    } scratch;                // offset 4: 4 bytes
+  }               as_compound;     // 8 bytes
 } pni_node_payload_t;
 
 /*
@@ -173,13 +153,10 @@ static inline pni_nid_t pni_node_get_down(pni_node_t 
*node)
   switch (node->type) {
     case PN_ARRAY:
     case PN_ARRAY_DESCRIBED:
-      return node->u.as_array.down;
     case PN_LIST:
-      return node->u.as_list.down;
     case PN_MAP:
-      return node->u.as_map.down;
     case PN_DESCRIBED:
-      return node->u.as_described.down;
+      return node->u.as_compound.down;
     case PN_DEFER:
       return node->u.as_deferred.down;
     default:
@@ -193,16 +170,10 @@ static inline void pni_node_set_down(pni_node_t *node, 
pni_nid_t down)
   switch (node->type) {
     case PN_ARRAY:
     case PN_ARRAY_DESCRIBED:
-      node->u.as_array.down = down;
-      break;
     case PN_LIST:
-      node->u.as_list.down = down;
-      break;
     case PN_MAP:
-      node->u.as_map.down = down;
-      break;
     case PN_DESCRIBED:
-      node->u.as_described.down = down;
+      node->u.as_compound.down = down;
       break;
     case PN_DEFER:
       node->u.as_deferred.down = down;
@@ -218,13 +189,10 @@ static inline pni_nid_t pni_node_get_children(pni_node_t 
*node)
   switch (node->type) {
     case PN_ARRAY:
     case PN_ARRAY_DESCRIBED:
-      return node->u.as_array.children_count;
     case PN_LIST:
-      return node->u.as_list.children_count;
     case PN_MAP:
-      return node->u.as_map.children_count;
     case PN_DESCRIBED:
-      return node->u.as_described.children_count;
+      return node->u.as_compound.children_count;
     case PN_DEFER:
       return node->u.as_deferred.children_count;
     default:
@@ -238,16 +206,10 @@ static inline void pni_node_set_children(pni_node_t 
*node, pni_nid_t count)
   switch (node->type) {
     case PN_ARRAY:
     case PN_ARRAY_DESCRIBED:
-      node->u.as_array.children_count = count;
-      break;
     case PN_LIST:
-      node->u.as_list.children_count = count;
-      break;
     case PN_MAP:
-      node->u.as_map.children_count = count;
-      break;
     case PN_DESCRIBED:
-      node->u.as_described.children_count = count;
+      node->u.as_compound.children_count = count;
       break;
     case PN_DEFER:
       node->u.as_deferred.children_count = count;
@@ -263,16 +225,10 @@ static inline void pni_node_inc_children(pni_node_t *node)
   switch (node->type) {
     case PN_ARRAY:
     case PN_ARRAY_DESCRIBED:
-      node->u.as_array.children_count++;
-      break;
     case PN_LIST:
-      node->u.as_list.children_count++;
-      break;
     case PN_MAP:
-      node->u.as_map.children_count++;
-      break;
     case PN_DESCRIBED:
-      node->u.as_described.children_count++;
+      node->u.as_compound.children_count++;
       break;
     case PN_DEFER:
       node->u.as_deferred.children_count++;
diff --git a/c/src/core/encoder.c b/c/src/core/encoder.c
index 502a3a86f..f3c9f7225 100644
--- a/c/src/core/encoder.c
+++ b/c/src/core/encoder.c
@@ -328,25 +328,25 @@ static int pni_encoder_enter(void *ctx, pn_data_t *data, 
pni_node_t *node)
   case PNE_SYM8: { pn_bytes_t b = {node->u.as_bytes.size, buf.start + 
node->u.as_bytes.offset}; pn_encoder_writev8(encoder, &b); return 0; }
   case PNE_SYM32: { pn_bytes_t b = {node->u.as_bytes.size, buf.start + 
node->u.as_bytes.offset}; pn_encoder_writev32(encoder, &b); return 0; }
   case PNE_ARRAY32:
-    node->u.as_array.start = (uint32_t) encoder->position;
+    node->u.as_compound.scratch.as_u32 = (uint32_t) encoder->position;
     // we'll backfill the size on exit
     encoder->position += 4;
     bool described = (node->type == PN_ARRAY_DESCRIBED);
-    pn_encoder_writef32(encoder, described ? node->u.as_array.children_count - 
1 : node->u.as_array.children_count);
+    pn_encoder_writef32(encoder, described ? 
node->u.as_compound.children_count - 1 : node->u.as_compound.children_count);
     if (described)
       pn_encoder_writef8(encoder, 0);
     return 0;
   case PNE_LIST32:
-    node->u.as_list.start = (uint32_t) encoder->position;
+    node->u.as_compound.scratch.as_u32 = (uint32_t) encoder->position;
     // we'll backfill the size later
     encoder->position += 4;
-    pn_encoder_writef32(encoder, node->u.as_list.children_count);
+    pn_encoder_writef32(encoder, node->u.as_compound.children_count);
     return 0;
   case PNE_MAP32:
-    node->u.as_map.start = (uint32_t) encoder->position;
+    node->u.as_compound.scratch.as_u32 = (uint32_t) encoder->position;
     // we'll backfill the size later
     encoder->position += 4;
-    pn_encoder_writef32(encoder, node->u.as_map.children_count);
+    pn_encoder_writef32(encoder, node->u.as_compound.children_count);
     return 0;
   default:
     return pn_error_format(pn_data_error(data), PN_ERR, "unrecognized 
encoding: %u", code);
@@ -362,8 +362,8 @@ static int pni_encoder_exit(void *ctx, pn_data_t *data, 
pni_node_t *node)
 
   // Special case 0 length list, but not as element in an array
   pni_node_t *parent = pn_data_node(data, node->parent);
-  if (node->type==PN_LIST && 
node->u.as_list.children_count-encoder->null_count==0 && !pn_is_in_array(data, 
parent, node)) {
-    encoder->position = node->u.as_list.start - 1; // position of list opcode
+  if (node->type==PN_LIST && 
node->u.as_compound.children_count-encoder->null_count==0 && 
!pn_is_in_array(data, parent, node)) {
+    encoder->position = node->u.as_compound.scratch.as_u32 - 1; // position of 
list opcode
     pn_encoder_writef8(encoder, PNE_LIST0);
     encoder->null_count = 0;
     return 0;
@@ -372,16 +372,16 @@ static int pni_encoder_exit(void *ctx, pn_data_t *data, 
pni_node_t *node)
   switch (node->type) {
   case PN_ARRAY:
   case PN_ARRAY_DESCRIBED:
-    if ((node->type == PN_ARRAY_DESCRIBED && node->u.as_array.children_count 
== 1) ||
-        (node->type == PN_ARRAY && node->u.as_array.children_count == 0)) {
+    if ((node->type == PN_ARRAY_DESCRIBED && 
node->u.as_compound.children_count == 1) ||
+        (node->type == PN_ARRAY && node->u.as_compound.children_count == 0)) {
       pn_encoder_writef8(encoder, pn_type2code(encoder, node->array_type));
     }
     PN_FALLTHROUGH;
   case PN_LIST:
   case PN_MAP: {
     pos = encoder->position;
-    /* start is at the same offset in as_array/as_list/as_map — use as_list 
uniformly */
-    uint32_t start = node->u.as_list.start;
+    /* all compound node payloads share the same navigation and scratch layout 
*/
+    uint32_t start = node->u.as_compound.scratch.as_u32;
 
     /* content_size: bytes written after the 8-byte *32 header (size+count 
fields) */
     size_t content_size = pos - start - 8;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to