xref: /aosp_15_r20/external/libtextclassifier/native/utils/flatbuffers/reflection.cc (revision 993b0882672172b81d12fad7a7ac0c3e5c824a12)
1*993b0882SAndroid Build Coastguard Worker /*
2*993b0882SAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*993b0882SAndroid Build Coastguard Worker  *
4*993b0882SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*993b0882SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*993b0882SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*993b0882SAndroid Build Coastguard Worker  *
8*993b0882SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*993b0882SAndroid Build Coastguard Worker  *
10*993b0882SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*993b0882SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*993b0882SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*993b0882SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*993b0882SAndroid Build Coastguard Worker  * limitations under the License.
15*993b0882SAndroid Build Coastguard Worker  */
16*993b0882SAndroid Build Coastguard Worker 
17*993b0882SAndroid Build Coastguard Worker #include "utils/flatbuffers/reflection.h"
18*993b0882SAndroid Build Coastguard Worker 
19*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3 {
20*993b0882SAndroid Build Coastguard Worker 
GetFieldOrNull(const reflection::Object * type,const StringPiece field_name)21*993b0882SAndroid Build Coastguard Worker const reflection::Field* GetFieldOrNull(const reflection::Object* type,
22*993b0882SAndroid Build Coastguard Worker                                         const StringPiece field_name) {
23*993b0882SAndroid Build Coastguard Worker   TC3_CHECK(type != nullptr && type->fields() != nullptr);
24*993b0882SAndroid Build Coastguard Worker   return type->fields()->LookupByKey(field_name.data());
25*993b0882SAndroid Build Coastguard Worker }
26*993b0882SAndroid Build Coastguard Worker 
GetFieldOrNull(const reflection::Object * type,const int field_offset)27*993b0882SAndroid Build Coastguard Worker const reflection::Field* GetFieldOrNull(const reflection::Object* type,
28*993b0882SAndroid Build Coastguard Worker                                         const int field_offset) {
29*993b0882SAndroid Build Coastguard Worker   if (type->fields() == nullptr) {
30*993b0882SAndroid Build Coastguard Worker     return nullptr;
31*993b0882SAndroid Build Coastguard Worker   }
32*993b0882SAndroid Build Coastguard Worker   for (const reflection::Field* field : *type->fields()) {
33*993b0882SAndroid Build Coastguard Worker     if (field->offset() == field_offset) {
34*993b0882SAndroid Build Coastguard Worker       return field;
35*993b0882SAndroid Build Coastguard Worker     }
36*993b0882SAndroid Build Coastguard Worker   }
37*993b0882SAndroid Build Coastguard Worker   return nullptr;
38*993b0882SAndroid Build Coastguard Worker }
39*993b0882SAndroid Build Coastguard Worker 
GetFieldOrNull(const reflection::Object * type,const StringPiece field_name,const int field_offset)40*993b0882SAndroid Build Coastguard Worker const reflection::Field* GetFieldOrNull(const reflection::Object* type,
41*993b0882SAndroid Build Coastguard Worker                                         const StringPiece field_name,
42*993b0882SAndroid Build Coastguard Worker                                         const int field_offset) {
43*993b0882SAndroid Build Coastguard Worker   // Lookup by name might be faster as the fields are sorted by name in the
44*993b0882SAndroid Build Coastguard Worker   // schema data, so try that first.
45*993b0882SAndroid Build Coastguard Worker   if (!field_name.empty()) {
46*993b0882SAndroid Build Coastguard Worker     return GetFieldOrNull(type, field_name.data());
47*993b0882SAndroid Build Coastguard Worker   }
48*993b0882SAndroid Build Coastguard Worker   return GetFieldOrNull(type, field_offset);
49*993b0882SAndroid Build Coastguard Worker }
50*993b0882SAndroid Build Coastguard Worker 
GetFieldOrNull(const reflection::Object * type,const FlatbufferField * field)51*993b0882SAndroid Build Coastguard Worker const reflection::Field* GetFieldOrNull(const reflection::Object* type,
52*993b0882SAndroid Build Coastguard Worker                                         const FlatbufferField* field) {
53*993b0882SAndroid Build Coastguard Worker   TC3_CHECK(type != nullptr && field != nullptr);
54*993b0882SAndroid Build Coastguard Worker   if (field->field_name() == nullptr) {
55*993b0882SAndroid Build Coastguard Worker     return GetFieldOrNull(type, field->field_offset());
56*993b0882SAndroid Build Coastguard Worker   }
57*993b0882SAndroid Build Coastguard Worker   return GetFieldOrNull(
58*993b0882SAndroid Build Coastguard Worker       type,
59*993b0882SAndroid Build Coastguard Worker       StringPiece(field->field_name()->data(), field->field_name()->size()),
60*993b0882SAndroid Build Coastguard Worker       field->field_offset());
61*993b0882SAndroid Build Coastguard Worker }
62*993b0882SAndroid Build Coastguard Worker 
GetFieldOrNull(const reflection::Object * type,const FlatbufferFieldT * field)63*993b0882SAndroid Build Coastguard Worker const reflection::Field* GetFieldOrNull(const reflection::Object* type,
64*993b0882SAndroid Build Coastguard Worker                                         const FlatbufferFieldT* field) {
65*993b0882SAndroid Build Coastguard Worker   TC3_CHECK(type != nullptr && field != nullptr);
66*993b0882SAndroid Build Coastguard Worker   return GetFieldOrNull(type, field->field_name, field->field_offset);
67*993b0882SAndroid Build Coastguard Worker }
68*993b0882SAndroid Build Coastguard Worker 
TypeForName(const reflection::Schema * schema,const StringPiece type_name)69*993b0882SAndroid Build Coastguard Worker const reflection::Object* TypeForName(const reflection::Schema* schema,
70*993b0882SAndroid Build Coastguard Worker                                       const StringPiece type_name) {
71*993b0882SAndroid Build Coastguard Worker   for (const reflection::Object* object : *schema->objects()) {
72*993b0882SAndroid Build Coastguard Worker     if (type_name.Equals(object->name()->str())) {
73*993b0882SAndroid Build Coastguard Worker       return object;
74*993b0882SAndroid Build Coastguard Worker     }
75*993b0882SAndroid Build Coastguard Worker   }
76*993b0882SAndroid Build Coastguard Worker   return nullptr;
77*993b0882SAndroid Build Coastguard Worker }
78*993b0882SAndroid Build Coastguard Worker 
TypeIdForObject(const reflection::Schema * schema,const reflection::Object * type)79*993b0882SAndroid Build Coastguard Worker Optional<int> TypeIdForObject(const reflection::Schema* schema,
80*993b0882SAndroid Build Coastguard Worker                               const reflection::Object* type) {
81*993b0882SAndroid Build Coastguard Worker   for (int i = 0; i < schema->objects()->size(); i++) {
82*993b0882SAndroid Build Coastguard Worker     if (schema->objects()->Get(i) == type) {
83*993b0882SAndroid Build Coastguard Worker       return Optional<int>(i);
84*993b0882SAndroid Build Coastguard Worker     }
85*993b0882SAndroid Build Coastguard Worker   }
86*993b0882SAndroid Build Coastguard Worker   return Optional<int>();
87*993b0882SAndroid Build Coastguard Worker }
88*993b0882SAndroid Build Coastguard Worker 
TypeIdForName(const reflection::Schema * schema,const StringPiece type_name)89*993b0882SAndroid Build Coastguard Worker Optional<int> TypeIdForName(const reflection::Schema* schema,
90*993b0882SAndroid Build Coastguard Worker                             const StringPiece type_name) {
91*993b0882SAndroid Build Coastguard Worker   for (int i = 0; i < schema->objects()->size(); i++) {
92*993b0882SAndroid Build Coastguard Worker     if (type_name.Equals(schema->objects()->Get(i)->name()->str())) {
93*993b0882SAndroid Build Coastguard Worker       return Optional<int>(i);
94*993b0882SAndroid Build Coastguard Worker     }
95*993b0882SAndroid Build Coastguard Worker   }
96*993b0882SAndroid Build Coastguard Worker   return Optional<int>();
97*993b0882SAndroid Build Coastguard Worker }
98*993b0882SAndroid Build Coastguard Worker 
SwapFieldNamesForOffsetsInPath(const reflection::Schema * schema,FlatbufferFieldPathT * path)99*993b0882SAndroid Build Coastguard Worker bool SwapFieldNamesForOffsetsInPath(const reflection::Schema* schema,
100*993b0882SAndroid Build Coastguard Worker                                     FlatbufferFieldPathT* path) {
101*993b0882SAndroid Build Coastguard Worker   if (schema == nullptr || !schema->root_table()) {
102*993b0882SAndroid Build Coastguard Worker     TC3_LOG(ERROR) << "Empty schema provided.";
103*993b0882SAndroid Build Coastguard Worker     return false;
104*993b0882SAndroid Build Coastguard Worker   }
105*993b0882SAndroid Build Coastguard Worker 
106*993b0882SAndroid Build Coastguard Worker   reflection::Object const* type = schema->root_table();
107*993b0882SAndroid Build Coastguard Worker   for (int i = 0; i < path->field.size(); i++) {
108*993b0882SAndroid Build Coastguard Worker     const reflection::Field* field = GetFieldOrNull(type, path->field[i].get());
109*993b0882SAndroid Build Coastguard Worker     if (field == nullptr) {
110*993b0882SAndroid Build Coastguard Worker       TC3_LOG(ERROR) << "Could not find field: " << path->field[i]->field_name;
111*993b0882SAndroid Build Coastguard Worker       return false;
112*993b0882SAndroid Build Coastguard Worker     }
113*993b0882SAndroid Build Coastguard Worker     path->field[i]->field_name.clear();
114*993b0882SAndroid Build Coastguard Worker     path->field[i]->field_offset = field->offset();
115*993b0882SAndroid Build Coastguard Worker 
116*993b0882SAndroid Build Coastguard Worker     // Descend.
117*993b0882SAndroid Build Coastguard Worker     if (i < path->field.size() - 1) {
118*993b0882SAndroid Build Coastguard Worker       if (field->type()->base_type() != reflection::Obj) {
119*993b0882SAndroid Build Coastguard Worker         TC3_LOG(ERROR) << "Field: " << field->name()->str()
120*993b0882SAndroid Build Coastguard Worker                        << " is not of type `Object`.";
121*993b0882SAndroid Build Coastguard Worker         return false;
122*993b0882SAndroid Build Coastguard Worker       }
123*993b0882SAndroid Build Coastguard Worker       type = schema->objects()->Get(field->type()->index());
124*993b0882SAndroid Build Coastguard Worker     }
125*993b0882SAndroid Build Coastguard Worker   }
126*993b0882SAndroid Build Coastguard Worker   return true;
127*993b0882SAndroid Build Coastguard Worker }
128*993b0882SAndroid Build Coastguard Worker 
ParseEnumValue(const reflection::Schema * schema,const reflection::Type * type,StringPiece value)129*993b0882SAndroid Build Coastguard Worker Variant ParseEnumValue(const reflection::Schema* schema,
130*993b0882SAndroid Build Coastguard Worker                        const reflection::Type* type, StringPiece value) {
131*993b0882SAndroid Build Coastguard Worker   TC3_DCHECK(IsEnum(type));
132*993b0882SAndroid Build Coastguard Worker   TC3_CHECK_NE(schema->enums(), nullptr);
133*993b0882SAndroid Build Coastguard Worker   const auto* enum_values = schema->enums()->Get(type->index())->values();
134*993b0882SAndroid Build Coastguard Worker   if (enum_values == nullptr) {
135*993b0882SAndroid Build Coastguard Worker     TC3_LOG(ERROR) << "Enum has no specified values.";
136*993b0882SAndroid Build Coastguard Worker     return Variant();
137*993b0882SAndroid Build Coastguard Worker   }
138*993b0882SAndroid Build Coastguard Worker   for (const reflection::EnumVal* enum_value : *enum_values) {
139*993b0882SAndroid Build Coastguard Worker     if (value.Equals(StringPiece(enum_value->name()->c_str(),
140*993b0882SAndroid Build Coastguard Worker                                  enum_value->name()->size()))) {
141*993b0882SAndroid Build Coastguard Worker       const int64 value = enum_value->value();
142*993b0882SAndroid Build Coastguard Worker       switch (type->base_type()) {
143*993b0882SAndroid Build Coastguard Worker         case reflection::BaseType::Byte:
144*993b0882SAndroid Build Coastguard Worker           return Variant(static_cast<int8>(value));
145*993b0882SAndroid Build Coastguard Worker         case reflection::BaseType::UByte:
146*993b0882SAndroid Build Coastguard Worker           return Variant(static_cast<uint8>(value));
147*993b0882SAndroid Build Coastguard Worker         case reflection::BaseType::Short:
148*993b0882SAndroid Build Coastguard Worker           return Variant(static_cast<int16>(value));
149*993b0882SAndroid Build Coastguard Worker         case reflection::BaseType::UShort:
150*993b0882SAndroid Build Coastguard Worker           return Variant(static_cast<uint16>(value));
151*993b0882SAndroid Build Coastguard Worker         case reflection::BaseType::Int:
152*993b0882SAndroid Build Coastguard Worker           return Variant(static_cast<int32>(value));
153*993b0882SAndroid Build Coastguard Worker         case reflection::BaseType::UInt:
154*993b0882SAndroid Build Coastguard Worker           return Variant(static_cast<uint32>(value));
155*993b0882SAndroid Build Coastguard Worker         case reflection::BaseType::Long:
156*993b0882SAndroid Build Coastguard Worker           return Variant(value);
157*993b0882SAndroid Build Coastguard Worker         case reflection::BaseType::ULong:
158*993b0882SAndroid Build Coastguard Worker           return Variant(static_cast<uint64>(value));
159*993b0882SAndroid Build Coastguard Worker         default:
160*993b0882SAndroid Build Coastguard Worker           break;
161*993b0882SAndroid Build Coastguard Worker       }
162*993b0882SAndroid Build Coastguard Worker     }
163*993b0882SAndroid Build Coastguard Worker   }
164*993b0882SAndroid Build Coastguard Worker   return Variant();
165*993b0882SAndroid Build Coastguard Worker }
166*993b0882SAndroid Build Coastguard Worker 
167*993b0882SAndroid Build Coastguard Worker }  // namespace libtextclassifier3
168