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