• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 #include "upb/message/message.h"
9 
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <string.h>
13 
14 #include "upb/mem/arena.h"
15 #include "upb/message/accessors.h"
16 #include "upb/message/array.h"
17 #include "upb/message/internal/accessors.h"
18 #include "upb/message/internal/extension.h"
19 #include "upb/message/internal/message.h"
20 #include "upb/message/internal/types.h"
21 #include "upb/message/map.h"
22 #include "upb/message/value.h"
23 #include "upb/mini_table/extension.h"
24 #include "upb/mini_table/field.h"
25 #include "upb/mini_table/internal/field.h"
26 #include "upb/mini_table/message.h"
27 
28 // Must be last.
29 #include "upb/port/def.inc"
30 
31 static const size_t message_overhead = sizeof(upb_Message_Internal);
32 
upb_Message_New(const upb_MiniTable * m,upb_Arena * a)33 upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* a) {
34   return _upb_Message_New(m, a);
35 }
36 
UPB_PRIVATE(_upb_Message_AddUnknown)37 bool UPB_PRIVATE(_upb_Message_AddUnknown)(upb_Message* msg, const char* data,
38                                           size_t len, upb_Arena* arena) {
39   UPB_ASSERT(!upb_Message_IsFrozen(msg));
40   if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, len, arena)) return false;
41   upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
42   memcpy(UPB_PTR_AT(in, in->unknown_end, char), data, len);
43   in->unknown_end += len;
44   return true;
45 }
46 
_upb_Message_DiscardUnknown_shallow(upb_Message * msg)47 void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) {
48   UPB_ASSERT(!upb_Message_IsFrozen(msg));
49   upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
50   if (in) {
51     in->unknown_end = message_overhead;
52   }
53 }
54 
upb_Message_GetUnknown(const upb_Message * msg,size_t * len)55 const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) {
56   upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
57   if (in) {
58     *len = in->unknown_end - message_overhead;
59     return (char*)(in + 1);
60   } else {
61     *len = 0;
62     return NULL;
63   }
64 }
65 
upb_Message_DeleteUnknown(upb_Message * msg,const char * data,size_t len)66 void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len) {
67   UPB_ASSERT(!upb_Message_IsFrozen(msg));
68   upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
69   const char* internal_unknown_end = UPB_PTR_AT(in, in->unknown_end, char);
70 
71 #ifndef NDEBUG
72   size_t full_unknown_size;
73   const char* full_unknown = upb_Message_GetUnknown(msg, &full_unknown_size);
74   UPB_ASSERT((uintptr_t)data >= (uintptr_t)full_unknown);
75   UPB_ASSERT((uintptr_t)data < (uintptr_t)(full_unknown + full_unknown_size));
76   UPB_ASSERT((uintptr_t)(data + len) > (uintptr_t)data);
77   UPB_ASSERT((uintptr_t)(data + len) <= (uintptr_t)internal_unknown_end);
78 #endif
79 
80   if ((data + len) != internal_unknown_end) {
81     memmove((char*)data, data + len, internal_unknown_end - data - len);
82   }
83   in->unknown_end -= len;
84 }
85 
upb_Message_ExtensionCount(const upb_Message * msg)86 size_t upb_Message_ExtensionCount(const upb_Message* msg) {
87   size_t count;
88   UPB_PRIVATE(_upb_Message_Getexts)(msg, &count);
89   return count;
90 }
91 
upb_Message_Freeze(upb_Message * msg,const upb_MiniTable * m)92 void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) {
93   if (upb_Message_IsFrozen(msg)) return;
94   UPB_PRIVATE(_upb_Message_ShallowFreeze)(msg);
95 
96   // Base Fields.
97   const size_t field_count = upb_MiniTable_FieldCount(m);
98 
99   for (size_t i = 0; i < field_count; i++) {
100     const upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, i);
101     const upb_MiniTable* m2 = upb_MiniTable_SubMessage(m, f);
102 
103     switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) {
104       case kUpb_FieldMode_Array: {
105         upb_Array* arr = upb_Message_GetMutableArray(msg, f);
106         if (arr) upb_Array_Freeze(arr, m2);
107         break;
108       }
109       case kUpb_FieldMode_Map: {
110         upb_Map* map = upb_Message_GetMutableMap(msg, f);
111         if (map) {
112           const upb_MiniTableField* f2 = upb_MiniTable_MapValue(m2);
113           const upb_MiniTable* m3 = upb_MiniTable_SubMessage(m2, f2);
114           upb_Map_Freeze(map, m3);
115         }
116         break;
117       }
118       case kUpb_FieldMode_Scalar: {
119         if (m2) {
120           upb_Message* msg2 = upb_Message_GetMutableMessage(msg, f);
121           if (msg2) upb_Message_Freeze(msg2, m2);
122         }
123         break;
124       }
125     }
126   }
127 
128   // Extensions.
129   size_t ext_count;
130   const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &ext_count);
131 
132   for (size_t i = 0; i < ext_count; i++) {
133     const upb_MiniTableExtension* e = ext[i].ext;
134     const upb_MiniTableField* f = &e->UPB_PRIVATE(field);
135     const upb_MiniTable* m2 = upb_MiniTableExtension_GetSubMessage(e);
136 
137     upb_MessageValue val;
138     memcpy(&val, &ext[i].data, sizeof(upb_MessageValue));
139 
140     switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) {
141       case kUpb_FieldMode_Array: {
142         upb_Array* arr = (upb_Array*)val.array_val;
143         if (arr) upb_Array_Freeze(arr, m2);
144         break;
145       }
146       case kUpb_FieldMode_Map:
147         UPB_UNREACHABLE();  // Maps cannot be extensions.
148         break;
149       case kUpb_FieldMode_Scalar:
150         if (upb_MiniTableField_IsSubMessage(f)) {
151           upb_Message* msg2 = (upb_Message*)val.msg_val;
152           if (msg2) upb_Message_Freeze(msg2, m2);
153         }
154         break;
155     }
156   }
157 }
158