blob: e2660e9d505f1ac3f8f421eeaeb3f65909ae1b20 [file] [log] [blame]
Adam Cozzette501ecec2023-09-26 14:36:20 -07001// Protocol Buffers - Google's data interchange format
2// Copyright 2023 Google LLC. All rights reserved.
Adam Cozzette501ecec2023-09-26 14:36:20 -07003//
Hong Shinb837d172023-11-07 13:24:59 -08004// 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
Adam Cozzette501ecec2023-09-26 14:36:20 -07007
Adam Cozzette12c7bb02023-09-28 12:54:11 -07008#include "upb_generator/file_layout.h"
Adam Cozzette501ecec2023-09-26 14:36:20 -07009
10#include <string>
11#include <unordered_set>
Joshua Habermancf3a6f52023-11-07 12:22:10 -080012#include <vector>
Adam Cozzette501ecec2023-09-26 14:36:20 -070013
14#include "upb/mini_table/internal/extension.h"
Joshua Habermancf3a6f52023-11-07 12:22:10 -080015#include "upb/reflection/def.hpp"
Adam Cozzette12c7bb02023-09-28 12:54:11 -070016#include "upb_generator/common.h"
Adam Cozzette501ecec2023-09-26 14:36:20 -070017
Adam Cozzette12c7bb02023-09-28 12:54:11 -070018namespace upb {
19namespace generator {
Adam Cozzette501ecec2023-09-26 14:36:20 -070020
21const char* kEnumsInit = "enums_layout";
22const char* kExtensionsInit = "extensions_layout";
23const char* kMessagesInit = "messages_layout";
24
Joshua Habermancf3a6f52023-11-07 12:22:10 -080025void AddEnums(upb::MessageDefPtr message, std::vector<upb::EnumDefPtr>* enums,
26 WhichEnums which) {
Adam Cozzette501ecec2023-09-26 14:36:20 -070027 enums->reserve(enums->size() + message.enum_type_count());
28 for (int i = 0; i < message.enum_type_count(); i++) {
Joshua Habermancf3a6f52023-11-07 12:22:10 -080029 upb::EnumDefPtr enum_type = message.enum_type(i);
30 if (which == kAllEnums || enum_type.is_closed()) {
31 enums->push_back(message.enum_type(i));
32 }
Adam Cozzette501ecec2023-09-26 14:36:20 -070033 }
34 for (int i = 0; i < message.nested_message_count(); i++) {
Joshua Habermancf3a6f52023-11-07 12:22:10 -080035 AddEnums(message.nested_message(i), enums, which);
Adam Cozzette501ecec2023-09-26 14:36:20 -070036 }
37}
38
Joshua Habermancf3a6f52023-11-07 12:22:10 -080039std::vector<upb::EnumDefPtr> SortedEnums(upb::FileDefPtr file,
40 WhichEnums which) {
Adam Cozzette501ecec2023-09-26 14:36:20 -070041 std::vector<upb::EnumDefPtr> enums;
42 enums.reserve(file.toplevel_enum_count());
43 for (int i = 0; i < file.toplevel_enum_count(); i++) {
Joshua Habermancf3a6f52023-11-07 12:22:10 -080044 upb::EnumDefPtr top_level_enum = file.toplevel_enum(i);
45 if (which == kAllEnums || top_level_enum.is_closed()) {
46 enums.push_back(file.toplevel_enum(i));
47 }
Adam Cozzette501ecec2023-09-26 14:36:20 -070048 }
49 for (int i = 0; i < file.toplevel_message_count(); i++) {
Joshua Habermancf3a6f52023-11-07 12:22:10 -080050 AddEnums(file.toplevel_message(i), &enums, which);
Adam Cozzette501ecec2023-09-26 14:36:20 -070051 }
52 std::sort(enums.begin(), enums.end(),
53 [](upb::EnumDefPtr a, upb::EnumDefPtr b) {
54 return strcmp(a.full_name(), b.full_name()) < 0;
55 });
56 return enums;
57}
58
59std::vector<uint32_t> SortedUniqueEnumNumbers(upb::EnumDefPtr e) {
60 std::vector<uint32_t> values;
61 values.reserve(e.value_count());
62 for (int i = 0; i < e.value_count(); i++) {
63 values.push_back(static_cast<uint32_t>(e.value(i).number()));
64 }
65 std::sort(values.begin(), values.end());
66 auto last = std::unique(values.begin(), values.end());
67 values.erase(last, values.end());
68 return values;
69}
70
71void AddMessages(upb::MessageDefPtr message,
72 std::vector<upb::MessageDefPtr>* messages) {
73 messages->push_back(message);
74 for (int i = 0; i < message.nested_message_count(); i++) {
75 AddMessages(message.nested_message(i), messages);
76 }
77}
78
79// Ordering must match upb/def.c!
80//
81// The ordering is significant because each upb_MessageDef* will point at the
82// corresponding upb_MiniTable and we just iterate through the list without
83// any search or lookup.
84std::vector<upb::MessageDefPtr> SortedMessages(upb::FileDefPtr file) {
85 std::vector<upb::MessageDefPtr> messages;
86 for (int i = 0; i < file.toplevel_message_count(); i++) {
87 AddMessages(file.toplevel_message(i), &messages);
88 }
89 return messages;
90}
91
92void AddExtensionsFromMessage(upb::MessageDefPtr message,
93 std::vector<upb::FieldDefPtr>* exts) {
94 for (int i = 0; i < message.nested_extension_count(); i++) {
95 exts->push_back(message.nested_extension(i));
96 }
97 for (int i = 0; i < message.nested_message_count(); i++) {
98 AddExtensionsFromMessage(message.nested_message(i), exts);
99 }
100}
101
102// Ordering must match upb/def.c!
103//
104// The ordering is significant because each upb_FieldDef* will point at the
105// corresponding upb_MiniTableExtension and we just iterate through the list
106// without any search or lookup.
107std::vector<upb::FieldDefPtr> SortedExtensions(upb::FileDefPtr file) {
108 std::vector<upb::FieldDefPtr> ret;
109 ret.reserve(file.toplevel_extension_count());
110 for (int i = 0; i < file.toplevel_extension_count(); i++) {
111 ret.push_back(file.toplevel_extension(i));
112 }
113 for (int i = 0; i < file.toplevel_message_count(); i++) {
114 AddExtensionsFromMessage(file.toplevel_message(i), &ret);
115 }
116 return ret;
117}
118
119std::vector<upb::FieldDefPtr> FieldNumberOrder(upb::MessageDefPtr message) {
120 std::vector<upb::FieldDefPtr> fields;
121 fields.reserve(message.field_count());
122 for (int i = 0; i < message.field_count(); i++) {
123 fields.push_back(message.field(i));
124 }
125 std::sort(fields.begin(), fields.end(),
126 [](upb::FieldDefPtr a, upb::FieldDefPtr b) {
127 return a.number() < b.number();
128 });
129 return fields;
130}
131
Adam Cozzette12c7bb02023-09-28 12:54:11 -0700132} // namespace generator
133} // namespace upb