@ -36,7 +36,7 @@
# include "upb/mini_table.h"
# include "upb/reflection.h"
/* Must be last. */
// Must be last.
# include "upb/port_def.inc"
typedef struct {
@ -377,6 +377,40 @@ static void assign_msg_wellknowntype(upb_MessageDef* m) {
}
}
typedef struct {
upb_DefPool * symtab ;
upb_FileDef * file ; /* File we are building. */
upb_Arena * arena ; /* Allocate defs here. */
upb_Arena * tmp_arena ; /* For temporary allocations. */
const upb_MiniTable_File * layout ; /* NULL if we should build layouts. */
int enum_count ; /* Count of enums built so far. */
int msg_count ; /* Count of messages built so far. */
int ext_count ; /* Count of extensions built so far. */
upb_Status * status ; /* Record errors here. */
jmp_buf err ; /* longjmp() on error. */
} symtab_addctx ;
UPB_NORETURN UPB_NOINLINE UPB_PRINTF ( 2 , 3 ) static void symtab_errf (
symtab_addctx * ctx , const char * fmt , . . . ) {
va_list argp ;
va_start ( argp , fmt ) ;
upb_Status_VSetErrorFormat ( ctx - > status , fmt , argp ) ;
va_end ( argp ) ;
UPB_LONGJMP ( ctx - > err , 1 ) ;
}
UPB_NORETURN UPB_NOINLINE static void symtab_oomerr ( symtab_addctx * ctx ) {
upb_Status_setoom ( ctx - > status ) ;
UPB_LONGJMP ( ctx - > err , 1 ) ;
}
void * symtab_alloc ( symtab_addctx * ctx , size_t bytes ) {
if ( bytes = = 0 ) return NULL ;
void * ret = upb_Arena_Malloc ( ctx - > arena , bytes ) ;
if ( ! ret ) symtab_oomerr ( ctx ) ;
return ret ;
}
/* upb_EnumDef ****************************************************************/
const google_protobuf_EnumOptions * upb_EnumDef_Options ( const upb_EnumDef * e ) {
@ -479,8 +513,7 @@ uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* ev) {
return ev - ev - > parent - > values ;
}
/* upb_ExtensionRange
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* upb_ExtensionRange *********************************************************/
const google_protobuf_ExtensionRangeOptions * upb_ExtensionRange_Options (
const upb_ExtensionRange * r ) {
@ -497,6 +530,12 @@ int32_t upb_ExtensionRange_Start(const upb_ExtensionRange* e) {
int32_t upb_ExtensionRange_End ( const upb_ExtensionRange * e ) { return e - > end ; }
// Allocate sufficient storage to contain an array of |n| extension ranges.
static upb_ExtensionRange * _upb_ExtensionRange_Alloc ( symtab_addctx * ctx ,
int n ) {
return symtab_alloc ( ctx , sizeof ( upb_ExtensionRange ) * n ) ;
}
/* upb_FieldDef ***************************************************************/
const google_protobuf_FieldOptions * upb_FieldDef_Options (
@ -709,8 +748,12 @@ bool upb_FieldDef_checkdescriptortype(int32_t type) {
return between ( type , 1 , 18 ) ;
}
/* upb_MessageDef
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Allocate sufficient storage to contain an array of |n| field defs.
static upb_FieldDef * _upb_FieldDef_Alloc ( symtab_addctx * ctx , int n ) {
return symtab_alloc ( ctx , sizeof ( upb_FieldDef ) * n ) ;
}
/* upb_MessageDef *************************************************************/
const google_protobuf_MessageOptions * upb_MessageDef_Options (
const upb_MessageDef * m ) {
@ -879,6 +922,11 @@ upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m) {
return m - > well_known_type ;
}
// Allocate sufficient storage to contain an array of |n| message defs.
static upb_MessageDef * _upb_MessageDef_Alloc ( symtab_addctx * ctx , int n ) {
return symtab_alloc ( ctx , sizeof ( upb_MessageDef ) * n ) ;
}
/* upb_OneofDef ***************************************************************/
const google_protobuf_OneofOptions * upb_OneofDef_Options (
@ -930,6 +978,11 @@ const upb_FieldDef* upb_OneofDef_LookupNumber(const upb_OneofDef* o,
: NULL ;
}
// Allocate sufficient storage to contain an array of |n| oneof defs.
static upb_OneofDef * _upb_OneofDef_Alloc ( symtab_addctx * ctx , int n ) {
return symtab_alloc ( ctx , sizeof ( upb_OneofDef ) * n ) ;
}
/* upb_FileDef ****************************************************************/
const google_protobuf_FileOptions * upb_FileDef_Options ( const upb_FileDef * f ) {
@ -1017,6 +1070,11 @@ const upb_ServiceDef* upb_FileDef_Service(const upb_FileDef* f, int i) {
const upb_DefPool * upb_FileDef_Pool ( const upb_FileDef * f ) { return f - > symtab ; }
// Allocate sufficient storage to contain one file def.
static upb_FileDef * _upb_FileDef_Alloc ( symtab_addctx * ctx ) {
return symtab_alloc ( ctx , sizeof ( upb_FileDef ) ) ;
}
/* upb_MethodDef **************************************************************/
const google_protobuf_MethodOptions * upb_MethodDef_Options ( const upb_MethodDef * m ) {
@ -1057,6 +1115,11 @@ bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m) {
return m - > server_streaming ;
}
// Allocate sufficient storage to contain an array of |n| method defs.
static upb_MethodDef * _upb_MethodDef_Alloc ( symtab_addctx * ctx , int n ) {
return symtab_alloc ( ctx , sizeof ( upb_MethodDef ) * n ) ;
}
/* upb_ServiceDef *************************************************************/
const google_protobuf_ServiceOptions * upb_ServiceDef_Options ( const upb_ServiceDef * s ) {
@ -1099,6 +1162,11 @@ const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s,
return NULL ;
}
// Allocate sufficient storage to contain an array of |n| service defs.
static upb_ServiceDef * _upb_ServiceDef_Alloc ( symtab_addctx * ctx , int n ) {
return symtab_alloc ( ctx , sizeof ( upb_ServiceDef ) * n ) ;
}
/* upb_DefPool ****************************************************************/
void upb_DefPool_Free ( upb_DefPool * s ) {
@ -1275,40 +1343,6 @@ const upb_FileDef* upb_DefPool_FindFileContainingSymbol(const upb_DefPool* s,
symtab_oomerr ( ctx ) ; \
}
typedef struct {
upb_DefPool * symtab ;
upb_FileDef * file ; /* File we are building. */
upb_Arena * arena ; /* Allocate defs here. */
upb_Arena * tmp_arena ; /* For temporary allocations. */
const upb_MiniTable_File * layout ; /* NULL if we should build layouts. */
int enum_count ; /* Count of enums built so far. */
int msg_count ; /* Count of messages built so far. */
int ext_count ; /* Count of extensions built so far. */
upb_Status * status ; /* Record errors here. */
jmp_buf err ; /* longjmp() on error. */
} symtab_addctx ;
UPB_NORETURN UPB_NOINLINE UPB_PRINTF ( 2 , 3 ) static void symtab_errf (
symtab_addctx * ctx , const char * fmt , . . . ) {
va_list argp ;
va_start ( argp , fmt ) ;
upb_Status_VSetErrorFormat ( ctx - > status , fmt , argp ) ;
va_end ( argp ) ;
UPB_LONGJMP ( ctx - > err , 1 ) ;
}
UPB_NORETURN UPB_NOINLINE static void symtab_oomerr ( symtab_addctx * ctx ) {
upb_Status_setoom ( ctx - > status ) ;
UPB_LONGJMP ( ctx - > err , 1 ) ;
}
void * symtab_alloc ( symtab_addctx * ctx , size_t bytes ) {
if ( bytes = = 0 ) return NULL ;
void * ret = upb_Arena_Malloc ( ctx - > arena , bytes ) ;
if ( ! ret ) symtab_oomerr ( ctx ) ;
return ret ;
}
// We want to copy the options verbatim into the destination options proto.
// We use serialize+parse as our deep copy.
# define SET_OPTIONS(target, desc_type, options_type, proto) \
@ -2426,7 +2460,7 @@ static void create_service(
methods = google_protobuf_ServiceDescriptorProto_method ( svc_proto , & n ) ;
s - > method_count = n ;
s - > methods = symtab_a lloc( ctx , sizeof ( * s - > methods ) * n ) ;
s - > methods = _upb_MethodDef_A lloc( ctx , n ) ;
SET_OPTIONS ( s - > opts , ServiceDescriptorProto , ServiceOptions , svc_proto ) ;
@ -2487,42 +2521,59 @@ static upb_MiniTable_Enum* create_enumlayout(symtab_addctx* ctx,
static void create_enumvaldef ( symtab_addctx * ctx , const char * prefix ,
const google_protobuf_EnumValueDescriptorProto * val_proto ,
upb_EnumDef * e , int i ) {
upb_EnumValueDef * val = ( upb_EnumValueDef * ) & e - > values [ i ] ;
upb_EnumDef * e , upb_EnumValueDef * v ) {
upb_StringView name = google_protobuf_EnumValueDescriptorProto_name ( val_proto ) ;
upb_value v = upb_value_constptr ( val ) ;
upb_value val = upb_value_constptr ( v ) ;
val - > parent = e ; /* Must happen prior to symtab_add(). */
val - > full_name = makefullname ( ctx , prefix , name ) ;
val - > number = google_protobuf_EnumValueDescriptorProto_number ( val_proto ) ;
symtab_add ( ctx , val - > full_name , pack_def ( val , UPB_DEFTYPE_ENUMVAL ) ) ;
v - > parent = e ; // Must happen prior to symtab_add()
v - > full_name = makefullname ( ctx , prefix , name ) ;
v - > number = google_protobuf_EnumValueDescriptorProto_number ( val_proto ) ;
symtab_add ( ctx , v - > full_name , pack_def ( v , UPB_DEFTYPE_ENUMVAL ) ) ;
SET_OPTIONS ( val - > opts , EnumValueDescriptorProto , EnumValueOptions , val_proto ) ;
SET_OPTIONS ( v - > opts , EnumValueDescriptorProto , EnumValueOptions , val_proto ) ;
if ( i = = 0 & & e - > file - > syntax = = kUpb_Syntax_Proto3 & & val - > number ! = 0 ) {
symtab_errf ( ctx , " for proto3, the first enum value must be zero (%s) " ,
e - > full_name ) ;
CHK_OOM ( upb_strtable_insert ( & e - > ntoi , name . data , name . size , val , ctx - > arena ) ) ;
// Multiple enumerators can have the same number, first one wins.
if ( ! upb_inttable_lookup ( & e - > iton , v - > number , NULL ) ) {
CHK_OOM ( upb_inttable_insert ( & e - > iton , v - > number , val , ctx - > arena ) ) ;
}
}
CHK_OOM ( upb_strtable_insert ( & e - > ntoi , name . data , name . size , v , ctx - > arena ) ) ;
// Allocate and initialize an array of |n| enum value defs.
// TODO(b/243726666): This will eventually become the (only) public constructor.
static upb_EnumValueDef * _upb_EnumValueDefs_New (
symtab_addctx * ctx , const char * prefix , int n ,
const google_protobuf_EnumValueDescriptorProto * const * protos , upb_EnumDef * e ) {
upb_EnumValueDef * v = symtab_alloc ( ctx , sizeof ( upb_EnumValueDef ) * n ) ;
// Multiple enumerators can have the same number, first one wins.
if ( ! upb_inttable_lookup ( & e - > iton , val - > number , NULL ) ) {
CHK_OOM ( upb_inttable_insert ( & e - > iton , val - > number , v , ctx - > arena ) ) ;
bool is_sorted = true ;
uint32_t previous = 0 ;
for ( size_t i = 0 ; i < n ; i + + ) {
create_enumvaldef ( ctx , prefix , protos [ i ] , e , & v [ i ] ) ;
const uint32_t current = v [ i ] . number ;
if ( previous > current ) is_sorted = false ;
previous = current ;
}
e - > is_sorted = is_sorted ;
if ( ctx - > file - > syntax = = kUpb_Syntax_Proto3 & & n > 0 & & v [ 0 ] . number ! = 0 ) {
symtab_errf ( ctx , " for proto3, the first enum value must be zero (%s) " ,
e - > full_name ) ;
}
return v ;
}
static void create_enumdef (
symtab_addctx * ctx , const char * prefix ,
const google_protobuf_EnumDescriptorProto * enum_proto ,
const upb_MessageDef * containing_type , const upb_EnumDef * _e ) {
upb_EnumDef * e = ( upb_EnumDef * ) _e ;
static void create_enumdef ( symtab_addctx * ctx , const char * prefix ,
const google_protobuf_EnumDescriptorProto * enum_proto ,
upb_EnumDef * e ) {
const google_protobuf_EnumValueDescriptorProto * const * values ;
upb_StringView name ;
size_t i , n ;
size_t n ;
e - > file = ctx - > file ; /* Must happen prior to symtab_add() */
e - > containing_type = containing_type ;
e - > file = ctx - > file ; // Must happen prior to symtab_add()
name = google_protobuf_EnumDescriptorProto_name ( enum_proto ) ;
check_ident ( ctx , name , false ) ;
@ -2535,9 +2586,8 @@ static void create_enumdef(
CHK_OOM ( upb_inttable_init ( & e - > iton , ctx - > arena ) ) ;
e - > defaultval = 0 ;
e - > is_sorted = true ;
e - > value_count = n ;
e - > values = symtab_alloc ( ctx , sizeof ( * e - > values ) * n ) ;
e - > values = _upb_EnumValueDefs_New ( ctx , prefix , n , values , e ) ;
if ( n = = 0 ) {
symtab_errf ( ctx , " enums must contain at least one value (%s) " ,
@ -2546,14 +2596,6 @@ static void create_enumdef(
SET_OPTIONS ( e - > opts , EnumDescriptorProto , EnumOptions , enum_proto ) ;
uint32_t previous = 0 ;
for ( i = 0 ; i < n ; i + + ) {
create_enumvaldef ( ctx , prefix , values [ i ] , e , i ) ;
const uint32_t current = e - > values [ i ] . number ;
if ( previous > current ) e - > is_sorted = false ;
previous = current ;
}
upb_inttable_compact ( & e - > iton , ctx - > arena ) ;
if ( e - > file - > syntax = = kUpb_Syntax_Proto2 ) {
@ -2570,6 +2612,24 @@ static void create_enumdef(
}
}
// Allocate and initialize an array of |n| enum defs.
// TODO(b/243726666): This will eventually become the (only) public constructor.
static upb_EnumDef * _upb_EnumDefs_New (
symtab_addctx * ctx , int n , const google_protobuf_EnumDescriptorProto * const * protos ,
const upb_MessageDef * containing_type ) {
// If a containing type is defined then get the full name from that.
// Otherwise use the package name from the file def.
const char * name =
containing_type ? containing_type - > full_name : ctx - > file - > package ;
upb_EnumDef * e = symtab_alloc ( ctx , sizeof ( upb_EnumDef ) * n ) ;
for ( size_t i = 0 ; i < n ; i + + ) {
create_enumdef ( ctx , name , protos [ i ] , & e [ i ] ) ;
e [ i ] . containing_type = containing_type ;
}
return e ;
}
static void msgdef_create_nested (
symtab_addctx * ctx , const google_protobuf_DescriptorProto * msg_proto ,
upb_MessageDef * m ) ;
@ -2616,20 +2676,20 @@ static void create_msgdef(symtab_addctx* ctx, const char* prefix,
SET_OPTIONS ( m - > opts , DescriptorProto , MessageOptions , msg_proto ) ;
m - > oneof_count = n_oneof ;
m - > oneofs = symtab_a lloc( ctx , sizeof ( * m - > oneofs ) * n_oneof ) ;
m - > oneofs = _upb_OneofDef_A lloc( ctx , n_oneof ) ;
for ( i = 0 ; i < n_oneof ; i + + ) {
create_oneofdef ( ctx , m , oneofs [ i ] , & m - > oneofs [ i ] ) ;
}
m - > field_count = n_field ;
m - > fields = symtab_a lloc( ctx , sizeof ( * m - > fields ) * n_field ) ;
m - > fields = _upb_FieldDef_A lloc( ctx , n_field ) ;
for ( i = 0 ; i < n_field ; i + + ) {
create_fielddef ( ctx , m - > full_name , m , fields [ i ] , & m - > fields [ i ] ,
/* is_extension= */ false ) ;
}
m - > ext_range_count = n_ext_range ;
m - > ext_ranges = symtab_alloc ( ctx , sizeof ( * m - > ext_ranges ) * n_ext_range ) ;
m - > ext_ranges = _upb_ExtensionRange_Alloc ( ctx , n_ext_range ) ;
for ( i = 0 ; i < n_ext_range ; i + + ) {
const google_protobuf_DescriptorProto_ExtensionRange * r = ext_ranges [ i ] ;
upb_ExtensionRange * r_def = ( upb_ExtensionRange * ) & m - > ext_ranges [ i ] ;
@ -2668,16 +2728,12 @@ static void msgdef_create_nested(
const google_protobuf_EnumDescriptorProto * const * enums =
google_protobuf_DescriptorProto_enum_type ( msg_proto , & n ) ;
m - > nested_enum_count = n ;
m - > nested_enums = symtab_alloc ( ctx , sizeof ( * m - > nested_enums ) * n ) ;
for ( size_t i = 0 ; i < n ; i + + ) {
m - > nested_enum_count = i + 1 ;
create_enumdef ( ctx , m - > full_name , enums [ i ] , m , & m - > nested_enums [ i ] ) ;
}
m - > nested_enums = _upb_EnumDefs_New ( ctx , n , enums , m ) ;
const google_protobuf_FieldDescriptorProto * const * exts =
google_protobuf_DescriptorProto_extension ( msg_proto , & n ) ;
m - > nested_ext_count = n ;
m - > nested_exts = symtab_a lloc( ctx , sizeof ( * m - > nested_exts ) * n ) ;
m - > nested_exts = _upb_FieldDef_A lloc( ctx , n ) ;
for ( size_t i = 0 ; i < n ; i + + ) {
create_fielddef ( ctx , m - > full_name , m , exts [ i ] , & m - > nested_exts [ i ] ,
/* is_extension= */ true ) ;
@ -2687,7 +2743,7 @@ static void msgdef_create_nested(
const google_protobuf_DescriptorProto * const * msgs =
google_protobuf_DescriptorProto_nested_type ( msg_proto , & n ) ;
m - > nested_msg_count = n ;
m - > nested_msgs = symtab_a lloc( ctx , sizeof ( * m - > nested_msgs ) * n ) ;
m - > nested_msgs = _upb_MessageDef_A lloc( ctx , n ) ;
for ( size_t i = 0 ; i < n ; i + + ) {
create_msgdef ( ctx , m - > full_name , msgs [ i ] , m , & m - > nested_msgs [ i ] ) ;
}
@ -2975,18 +3031,15 @@ static void build_filedef(
mutable_weak_deps [ i ] = weak_deps [ i ] ;
}
/* Create enums. */
// Create enums.
enums = google_protobuf_FileDescriptorProto_enum_type ( file_proto , & n ) ;
file - > top_lvl_enum_count = n ;
file - > top_lvl_enums = symtab_alloc ( ctx , sizeof ( * file - > top_lvl_enums ) * n ) ;
for ( i = 0 ; i < n ; i + + ) {
create_enumdef ( ctx , file - > package , enums [ i ] , NULL , & file - > top_lvl_enums [ i ] ) ;
}
file - > top_lvl_enums = _upb_EnumDefs_New ( ctx , n , enums , NULL ) ;
/* Create extensions. */
exts = google_protobuf_FileDescriptorProto_extension ( file_proto , & n ) ;
file - > top_lvl_ext_count = n ;
file - > top_lvl_exts = symtab_a lloc( ctx , sizeof ( * file - > top_lvl_exts ) * n ) ;
file - > top_lvl_exts = _upb_FieldDef_A lloc( ctx , n ) ;
for ( i = 0 ; i < n ; i + + ) {
create_fielddef ( ctx , file - > package , NULL , exts [ i ] , & file - > top_lvl_exts [ i ] ,
/* is_extension= */ true ) ;
@ -2996,7 +3049,7 @@ static void build_filedef(
/* Create messages. */
msgs = google_protobuf_FileDescriptorProto_message_type ( file_proto , & n ) ;
file - > top_lvl_msg_count = n ;
file - > top_lvl_msgs = symtab_a lloc( ctx , sizeof ( * file - > top_lvl_msgs ) * n ) ;
file - > top_lvl_msgs = _upb_MessageDef_A lloc( ctx , n ) ;
for ( i = 0 ; i < n ; i + + ) {
create_msgdef ( ctx , file - > package , msgs [ i ] , NULL , & file - > top_lvl_msgs [ i ] ) ;
}
@ -3004,7 +3057,7 @@ static void build_filedef(
/* Create services. */
services = google_protobuf_FileDescriptorProto_service ( file_proto , & n ) ;
file - > service_count = n ;
file - > services = symtab_a lloc( ctx , sizeof ( * file - > services ) * n ) ;
file - > services = _upb_ServiceDef_A lloc( ctx , n ) ;
for ( i = 0 ; i < n ; i + + ) {
create_service ( ctx , services [ i ] , & file - > services [ i ] ) ;
( ( upb_ServiceDef * ) & file - > services [ i ] ) - > index = i ;
@ -3104,7 +3157,7 @@ static const upb_FileDef* _upb_DefPool_AddFile(
ctx . file = NULL ;
}
} else {
ctx . file = symtab_a lloc( & ctx , sizeof ( * ctx . file ) ) ;
ctx . file = _upb_FileDef_A lloc( & ctx ) ;
build_filedef ( & ctx , ctx . file , file_proto ) ;
upb_strtable_insert ( & s - > files , name . data , name . size ,
pack_def ( ctx . file , UPB_DEFTYPE_FILE ) , ctx . arena ) ;