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