1 /*
2  * Copyright (c) 2009-2021, Google LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of Google LLC nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29 ** Our memory representation for parsing tables and messages themselves.
30 ** Functions in this file are used by generated code and possibly reflection.
31 **
32 ** The definitions in this file are internal to upb.
33 **/
34 
35 #ifndef UPB_MESSAGE_INTERNAL_H_
36 #define UPB_MESSAGE_INTERNAL_H_
37 
38 #include <stdlib.h>
39 #include <string.h>
40 
41 #include "upb/hash/common.h"
42 #include "upb/message/extension_internal.h"
43 #include "upb/message/message.h"
44 #include "upb/mini_table/extension_internal.h"
45 #include "upb/mini_table/extension_registry.h"
46 #include "upb/mini_table/file_internal.h"
47 #include "upb/mini_table/message_internal.h"
48 
49 // Must be last.
50 #include "upb/port/def.inc"
51 
52 #ifdef __cplusplus
53 extern "C" {
54 #endif
55 
56 extern const float kUpb_FltInfinity;
57 extern const double kUpb_Infinity;
58 extern const double kUpb_NaN;
59 
60 /* Internal members of a upb_Message that track unknown fields and/or
61  * extensions. We can change this without breaking binary compatibility.  We put
62  * these before the user's data.  The user's upb_Message* points after the
63  * upb_Message_Internal. */
64 
65 typedef struct {
66   /* Total size of this structure, including the data that follows.
67    * Must be aligned to 8, which is alignof(upb_Message_Extension) */
68   uint32_t size;
69 
70   /* Offsets relative to the beginning of this structure.
71    *
72    * Unknown data grows forward from the beginning to unknown_end.
73    * Extension data grows backward from size to ext_begin.
74    * When the two meet, we're out of data and have to realloc.
75    *
76    * If we imagine that the final member of this struct is:
77    *   char data[size - overhead];  // overhead =
78    * sizeof(upb_Message_InternalData)
79    *
80    * Then we have:
81    *   unknown data: data[0 .. (unknown_end - overhead)]
82    *   extensions data: data[(ext_begin - overhead) .. (size - overhead)] */
83   uint32_t unknown_end;
84   uint32_t ext_begin;
85   /* Data follows, as if there were an array:
86    *   char data[size - sizeof(upb_Message_InternalData)]; */
87 } upb_Message_InternalData;
88 
89 typedef struct {
90   upb_Message_InternalData* internal;
91   /* Message data follows. */
92 } upb_Message_Internal;
93 
94 /* Maps upb_CType -> memory size. */
95 extern char _upb_CTypeo_size[12];
96 
upb_msg_sizeof(const upb_MiniTable * t)97 UPB_INLINE size_t upb_msg_sizeof(const upb_MiniTable* t) {
98   return t->size + sizeof(upb_Message_Internal);
99 }
100 
101 // Inline version upb_Message_New(), for internal use.
_upb_Message_New(const upb_MiniTable * mini_table,upb_Arena * arena)102 UPB_INLINE upb_Message* _upb_Message_New(const upb_MiniTable* mini_table,
103                                          upb_Arena* arena) {
104   size_t size = upb_msg_sizeof(mini_table);
105   void* mem = upb_Arena_Malloc(arena, size + sizeof(upb_Message_Internal));
106   if (UPB_UNLIKELY(!mem)) return NULL;
107   upb_Message* msg = UPB_PTR_AT(mem, sizeof(upb_Message_Internal), upb_Message);
108   memset(mem, 0, size);
109   return msg;
110 }
111 
upb_Message_Getinternal(const upb_Message * msg)112 UPB_INLINE upb_Message_Internal* upb_Message_Getinternal(
113     const upb_Message* msg) {
114   ptrdiff_t size = sizeof(upb_Message_Internal);
115   return (upb_Message_Internal*)((char*)msg - size);
116 }
117 
118 // Clears the given message.
119 void _upb_Message_Clear(upb_Message* msg, const upb_MiniTable* l);
120 
121 // Discards the unknown fields for this message only.
122 void _upb_Message_DiscardUnknown_shallow(upb_Message* msg);
123 
124 // Adds unknown data (serialized protobuf data) to the given message.
125 // The data is copied into the message instance.
126 bool _upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
127                              upb_Arena* arena);
128 
129 #ifdef __cplusplus
130 } /* extern "C" */
131 #endif
132 
133 #include "upb/port/undef.inc"
134 
135 #endif /* UPB_MESSAGE_INTERNAL_H_ */
136