1 /*
2  * Copyright (c) 2009-2022, 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 #ifndef UPB_MINI_TABLE_COMMON_H_
29 #define UPB_MINI_TABLE_COMMON_H_
30 
31 #include "upb/mini_table/field_internal.h"
32 #include "upb/mini_table/message_internal.h"
33 #include "upb/mini_table/sub_internal.h"
34 
35 // Must be last.
36 #include "upb/port/def.inc"
37 
38 typedef enum {
39   kUpb_FieldModifier_IsRepeated = 1 << 0,
40   kUpb_FieldModifier_IsPacked = 1 << 1,
41   kUpb_FieldModifier_IsClosedEnum = 1 << 2,
42   kUpb_FieldModifier_IsProto3Singular = 1 << 3,
43   kUpb_FieldModifier_IsRequired = 1 << 4,
44 } kUpb_FieldModifier;
45 
46 typedef enum {
47   kUpb_MessageModifier_ValidateUtf8 = 1 << 0,
48   kUpb_MessageModifier_DefaultIsPacked = 1 << 1,
49   kUpb_MessageModifier_IsExtendable = 1 << 2,
50 } kUpb_MessageModifier;
51 
52 #ifdef __cplusplus
53 extern "C" {
54 #endif
55 
56 UPB_API const upb_MiniTableField* upb_MiniTable_FindFieldByNumber(
57     const upb_MiniTable* table, uint32_t number);
58 
upb_MiniTable_GetFieldByIndex(const upb_MiniTable * t,uint32_t index)59 UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_GetFieldByIndex(
60     const upb_MiniTable* t, uint32_t index) {
61   return &t->fields[index];
62 }
63 
64 UPB_API upb_FieldType upb_MiniTableField_Type(const upb_MiniTableField* field);
65 
upb_MiniTableField_CType(const upb_MiniTableField * f)66 UPB_API_INLINE upb_CType upb_MiniTableField_CType(const upb_MiniTableField* f) {
67   switch (f->UPB_PRIVATE(descriptortype)) {
68     case kUpb_FieldType_Double:
69       return kUpb_CType_Double;
70     case kUpb_FieldType_Float:
71       return kUpb_CType_Float;
72     case kUpb_FieldType_Int64:
73     case kUpb_FieldType_SInt64:
74     case kUpb_FieldType_SFixed64:
75       return kUpb_CType_Int64;
76     case kUpb_FieldType_Int32:
77     case kUpb_FieldType_SFixed32:
78     case kUpb_FieldType_SInt32:
79       return kUpb_CType_Int32;
80     case kUpb_FieldType_UInt64:
81     case kUpb_FieldType_Fixed64:
82       return kUpb_CType_UInt64;
83     case kUpb_FieldType_UInt32:
84     case kUpb_FieldType_Fixed32:
85       return kUpb_CType_UInt32;
86     case kUpb_FieldType_Enum:
87       return kUpb_CType_Enum;
88     case kUpb_FieldType_Bool:
89       return kUpb_CType_Bool;
90     case kUpb_FieldType_String:
91       return kUpb_CType_String;
92     case kUpb_FieldType_Bytes:
93       return kUpb_CType_Bytes;
94     case kUpb_FieldType_Group:
95     case kUpb_FieldType_Message:
96       return kUpb_CType_Message;
97   }
98   UPB_UNREACHABLE();
99 }
100 
upb_MiniTableField_IsExtension(const upb_MiniTableField * field)101 UPB_API_INLINE bool upb_MiniTableField_IsExtension(
102     const upb_MiniTableField* field) {
103   return field->mode & kUpb_LabelFlags_IsExtension;
104 }
105 
upb_MiniTableField_IsClosedEnum(const upb_MiniTableField * field)106 UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum(
107     const upb_MiniTableField* field) {
108   return field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Enum;
109 }
110 
upb_MiniTableField_HasPresence(const upb_MiniTableField * field)111 UPB_API_INLINE bool upb_MiniTableField_HasPresence(
112     const upb_MiniTableField* field) {
113   if (upb_MiniTableField_IsExtension(field)) {
114     return !upb_IsRepeatedOrMap(field);
115   } else {
116     return field->presence != 0;
117   }
118 }
119 
120 // Returns the MiniTable for this message field.  If the field is unlinked,
121 // returns NULL.
upb_MiniTable_GetSubMessageTable(const upb_MiniTable * mini_table,const upb_MiniTableField * field)122 UPB_API_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable(
123     const upb_MiniTable* mini_table, const upb_MiniTableField* field) {
124   UPB_ASSERT(upb_MiniTableField_CType(field) == kUpb_CType_Message);
125   return mini_table->subs[field->UPB_PRIVATE(submsg_index)].submsg;
126 }
127 
128 // Returns the MiniTableEnum for this enum field.  If the field is unlinked,
129 // returns NULL.
upb_MiniTable_GetSubEnumTable(const upb_MiniTable * mini_table,const upb_MiniTableField * field)130 UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable(
131     const upb_MiniTable* mini_table, const upb_MiniTableField* field) {
132   UPB_ASSERT(upb_MiniTableField_CType(field) == kUpb_CType_Enum);
133   return mini_table->subs[field->UPB_PRIVATE(submsg_index)].subenum;
134 }
135 
136 // Returns true if this MiniTable field is linked to a MiniTable for the
137 // sub-message.
upb_MiniTable_MessageFieldIsLinked(const upb_MiniTable * mini_table,const upb_MiniTableField * field)138 UPB_API_INLINE bool upb_MiniTable_MessageFieldIsLinked(
139     const upb_MiniTable* mini_table, const upb_MiniTableField* field) {
140   return upb_MiniTable_GetSubMessageTable(mini_table, field) != NULL;
141 }
142 
143 // If this field is in a oneof, returns the first field in the oneof.
144 //
145 // Otherwise returns NULL.
146 //
147 // Usage:
148 //   const upb_MiniTableField* field = upb_MiniTable_GetOneof(m, f);
149 //   do {
150 //       ..
151 //   } while (upb_MiniTable_NextOneofField(m, &field);
152 //
153 const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m,
154                                                  const upb_MiniTableField* f);
155 
156 // Iterates to the next field in the oneof. If this is the last field in the
157 // oneof, returns false. The ordering of fields in the oneof is not
158 // guaranteed.
159 // REQUIRES: |f| is the field initialized by upb_MiniTable_GetOneof and updated
160 //           by prior upb_MiniTable_NextOneofField calls.
161 bool upb_MiniTable_NextOneofField(const upb_MiniTable* m,
162                                   const upb_MiniTableField** f);
163 
164 #ifdef __cplusplus
165 } /* extern "C" */
166 #endif
167 
168 #include "upb/port/undef.inc"
169 
170 #endif /* UPB_MINI_TABLE_COMMON_H_ */
171