1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC. All rights reserved.
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
8 #include "upb_generator/file_layout.h"
11 #include <unordered_set>
14 #include "upb/reflection/def.hpp"
15 #include "upb_generator/common.h"
20 const char* kEnumsInit
= "enums_layout";
21 const char* kExtensionsInit
= "extensions_layout";
22 const char* kMessagesInit
= "messages_layout";
24 void AddEnums(upb::MessageDefPtr message
, std::vector
<upb::EnumDefPtr
>* enums
,
26 enums
->reserve(enums
->size() + message
.enum_type_count());
27 for (int i
= 0; i
< message
.enum_type_count(); i
++) {
28 upb::EnumDefPtr enum_type
= message
.enum_type(i
);
29 if (which
== kAllEnums
|| enum_type
.is_closed()) {
30 enums
->push_back(message
.enum_type(i
));
33 for (int i
= 0; i
< message
.nested_message_count(); i
++) {
34 AddEnums(message
.nested_message(i
), enums
, which
);
38 std::vector
<upb::EnumDefPtr
> SortedEnums(upb::FileDefPtr file
,
40 std::vector
<upb::EnumDefPtr
> enums
;
41 enums
.reserve(file
.toplevel_enum_count());
42 for (int i
= 0; i
< file
.toplevel_enum_count(); i
++) {
43 upb::EnumDefPtr top_level_enum
= file
.toplevel_enum(i
);
44 if (which
== kAllEnums
|| top_level_enum
.is_closed()) {
45 enums
.push_back(file
.toplevel_enum(i
));
48 for (int i
= 0; i
< file
.toplevel_message_count(); i
++) {
49 AddEnums(file
.toplevel_message(i
), &enums
, which
);
51 std::sort(enums
.begin(), enums
.end(),
52 [](upb::EnumDefPtr a
, upb::EnumDefPtr b
) {
53 return strcmp(a
.full_name(), b
.full_name()) < 0;
58 std::vector
<uint32_t> SortedUniqueEnumNumbers(upb::EnumDefPtr e
) {
59 std::vector
<uint32_t> values
;
60 values
.reserve(e
.value_count());
61 for (int i
= 0; i
< e
.value_count(); i
++) {
62 values
.push_back(static_cast<uint32_t>(e
.value(i
).number()));
64 std::sort(values
.begin(), values
.end());
65 auto last
= std::unique(values
.begin(), values
.end());
66 values
.erase(last
, values
.end());
70 void AddMessages(upb::MessageDefPtr message
,
71 std::vector
<upb::MessageDefPtr
>* messages
) {
72 messages
->push_back(message
);
73 for (int i
= 0; i
< message
.nested_message_count(); i
++) {
74 AddMessages(message
.nested_message(i
), messages
);
78 // Ordering must match upb/def.c!
80 // The ordering is significant because each upb_MessageDef* will point at the
81 // corresponding upb_MiniTable and we just iterate through the list without
82 // any search or lookup.
83 std::vector
<upb::MessageDefPtr
> SortedMessages(upb::FileDefPtr file
) {
84 std::vector
<upb::MessageDefPtr
> messages
;
85 for (int i
= 0; i
< file
.toplevel_message_count(); i
++) {
86 AddMessages(file
.toplevel_message(i
), &messages
);
91 void AddExtensionsFromMessage(upb::MessageDefPtr message
,
92 std::vector
<upb::FieldDefPtr
>* exts
) {
93 for (int i
= 0; i
< message
.nested_extension_count(); i
++) {
94 exts
->push_back(message
.nested_extension(i
));
96 for (int i
= 0; i
< message
.nested_message_count(); i
++) {
97 AddExtensionsFromMessage(message
.nested_message(i
), exts
);
101 // Ordering must match upb/def.c!
103 // The ordering is significant because each upb_FieldDef* will point at the
104 // corresponding upb_MiniTableExtension and we just iterate through the list
105 // without any search or lookup.
106 std::vector
<upb::FieldDefPtr
> SortedExtensions(upb::FileDefPtr file
) {
107 std::vector
<upb::FieldDefPtr
> ret
;
108 ret
.reserve(file
.toplevel_extension_count());
109 for (int i
= 0; i
< file
.toplevel_extension_count(); i
++) {
110 ret
.push_back(file
.toplevel_extension(i
));
112 for (int i
= 0; i
< file
.toplevel_message_count(); i
++) {
113 AddExtensionsFromMessage(file
.toplevel_message(i
), &ret
);
118 std::vector
<upb::FieldDefPtr
> FieldNumberOrder(upb::MessageDefPtr message
) {
119 std::vector
<upb::FieldDefPtr
> fields
;
120 fields
.reserve(message
.field_count());
121 for (int i
= 0; i
< message
.field_count(); i
++) {
122 fields
.push_back(message
.field(i
));
124 std::sort(fields
.begin(), fields
.end(),
125 [](upb::FieldDefPtr a
, upb::FieldDefPtr b
) {
126 return a
.number() < b
.number();
131 } // namespace generator