|  | // Protocol Buffers - Google's data interchange format | 
|  | // Copyright 2023 Google LLC.  All rights reserved. | 
|  | // | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file or at | 
|  | // https://developers.google.com/open-source/licenses/bsd | 
|  |  | 
|  | #ifndef GOOGLE_UPB_UPB_GENERATOR_C_NAMES_H__ | 
|  | #define GOOGLE_UPB_UPB_GENERATOR_C_NAMES_H__ | 
|  |  | 
|  | #include <string> | 
|  |  | 
|  | #include "absl/container/flat_hash_map.h" | 
|  | #include "absl/strings/string_view.h" | 
|  |  | 
|  | namespace upb { | 
|  | namespace generator { | 
|  |  | 
|  | // Note: these names are not currently exported, in hopes that no code | 
|  | // generators outside of the protobuf repo will ever use the generated C API. | 
|  |  | 
|  | // Maps: foo/bar/baz.proto -> foo/bar/baz.upb.h | 
|  | std::string CApiHeaderFilename(absl::string_view proto_filename); | 
|  |  | 
|  | // The foo.upb.h file defines far more symbols than we currently enumerate here. | 
|  | // We do the bare minimum by by defining the type name for messages and enums, | 
|  | // which also forms the symbol prefix for associated functions. | 
|  | // | 
|  | //   typedef struct { /* ... */ } <MessageType>; | 
|  | //   typedef enum { <EnumValue> = X, ... } <EnumType>; | 
|  | // | 
|  | // Oneofs and extensions have a base name that forms the prefix for associated | 
|  | // functions. | 
|  |  | 
|  | std::string CApiMessageType(absl::string_view full_name); | 
|  | std::string CApiEnumType(absl::string_view full_name); | 
|  | std::string CApiEnumValueSymbol(absl::string_view full_name); | 
|  | std::string CApiExtensionIdentBase(absl::string_view full_name); | 
|  | std::string CApiOneofIdentBase(absl::string_view full_name); | 
|  |  | 
|  | // Name mangling for individual fields. NameMangler maps each field name to a | 
|  | // mangled name, which tries to avoid collisions with other field accessors. | 
|  | // | 
|  | // For example, a field named "clear_foo" might be renamed to "clear_foo_" if | 
|  | // there is a field named "foo" in the same message. | 
|  | // | 
|  | // This API would be more principled if it generated a full symbol name for each | 
|  | // generated API function, eg. | 
|  | //   mangler.GetSetter("clear_foo") -> "mypkg_MyMessage_set_clear_foo_" | 
|  | //   mangler.GetHazzer("clear_foo") -> "mypkg_MyMessage_has_clear_foo_" | 
|  | // | 
|  | // But that would be a larger and more complicated API. In the long run, we | 
|  | // probably don't want to have other code generators wrapping these APIs, so | 
|  | // it's probably not worth designing a fully principled API. | 
|  |  | 
|  | enum FieldClass { | 
|  | kStringField = 1 << 0, | 
|  | kContainerField = 1 << 1, | 
|  | kOtherField = 1 << 2, | 
|  | }; | 
|  |  | 
|  | class NameMangler { | 
|  | public: | 
|  | explicit NameMangler( | 
|  | const absl::flat_hash_map<std::string, FieldClass>& fields); | 
|  |  | 
|  | std::string ResolveFieldName(absl::string_view name) const { | 
|  | auto it = names_.find(name); | 
|  | return it == names_.end() ? std::string(name) : it->second; | 
|  | } | 
|  |  | 
|  | private: | 
|  | // Maps field_name -> mangled_name.  If a field name is not in the map, it | 
|  | // is not mangled. | 
|  | absl::flat_hash_map<std::string, std::string> names_; | 
|  | }; | 
|  |  | 
|  | // Here we provide functions for building field lists from both C++ and upb | 
|  | // reflection.  They are templated so as to not actually introduce dependencies | 
|  | // on either C++ or upb. | 
|  |  | 
|  | template <class T> | 
|  | absl::flat_hash_map<std::string, FieldClass> GetCppFields(const T* descriptor) { | 
|  | absl::flat_hash_map<std::string, FieldClass> fields; | 
|  | for (int i = 0; i < descriptor->field_count(); ++i) { | 
|  | const auto* field = descriptor->field(i); | 
|  | if (field->is_repeated() || field->is_map()) { | 
|  | fields.emplace(field->name(), kContainerField); | 
|  | } else if (field->cpp_type() == field->CPPTYPE_STRING) { | 
|  | fields.emplace(field->name(), kStringField); | 
|  | } else { | 
|  | fields.emplace(field->name(), kOtherField); | 
|  | } | 
|  | } | 
|  | return fields; | 
|  | } | 
|  |  | 
|  | template <class T> | 
|  | absl::flat_hash_map<std::string, FieldClass> GetUpbFields(const T& msg_def) { | 
|  | absl::flat_hash_map<std::string, FieldClass> fields; | 
|  | for (const auto field : msg_def.fields()) { | 
|  | if (field.IsSequence() || field.IsMap()) { | 
|  | fields.emplace(field.name(), kContainerField); | 
|  | } else if (field.ctype() == decltype(field)::CType::kUpb_CType_String) { | 
|  | fields.emplace(field.name(), kStringField); | 
|  | } else { | 
|  | fields.emplace(field.name(), kOtherField); | 
|  | } | 
|  | } | 
|  | return fields; | 
|  | } | 
|  |  | 
|  | ABSL_CONST_INIT const absl::string_view kRepeatedFieldArrayGetterPostfix = | 
|  | "upb_array"; | 
|  | ABSL_CONST_INIT const absl::string_view | 
|  | kRepeatedFieldMutableArrayGetterPostfix = "mutable_upb_array"; | 
|  |  | 
|  | ABSL_CONST_INIT const absl::string_view kMapGetterPostfix = "upb_map"; | 
|  | ABSL_CONST_INIT const absl::string_view kMutableMapGetterPostfix = | 
|  | "mutable_upb_map"; | 
|  |  | 
|  | }  // namespace generator | 
|  | }  // namespace upb | 
|  |  | 
|  | #endif  // GOOGLE_UPB_UPB_GENERATOR_C_NAMES_H__ |