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 #ifndef LIBTEXTCLASSIFIER_UTILS_GRAMMAR_SEMANTICS_VALUE_H_ 18*993b0882SAndroid Build Coastguard Worker #define LIBTEXTCLASSIFIER_UTILS_GRAMMAR_SEMANTICS_VALUE_H_ 19*993b0882SAndroid Build Coastguard Worker 20*993b0882SAndroid Build Coastguard Worker #include "utils/base/arena.h" 21*993b0882SAndroid Build Coastguard Worker #include "utils/base/logging.h" 22*993b0882SAndroid Build Coastguard Worker #include "utils/flatbuffers/mutable.h" 23*993b0882SAndroid Build Coastguard Worker #include "utils/flatbuffers/reflection.h" 24*993b0882SAndroid Build Coastguard Worker #include "utils/strings/stringpiece.h" 25*993b0882SAndroid Build Coastguard Worker #include "utils/utf8/unicodetext.h" 26*993b0882SAndroid Build Coastguard Worker #include "flatbuffers/base.h" 27*993b0882SAndroid Build Coastguard Worker #include "flatbuffers/reflection.h" 28*993b0882SAndroid Build Coastguard Worker 29*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3::grammar { 30*993b0882SAndroid Build Coastguard Worker 31*993b0882SAndroid Build Coastguard Worker // A semantic value as a typed, arena-allocated flatbuffer. 32*993b0882SAndroid Build Coastguard Worker // This denotes the possible results of the evaluation of a semantic expression. 33*993b0882SAndroid Build Coastguard Worker class SemanticValue { 34*993b0882SAndroid Build Coastguard Worker public: 35*993b0882SAndroid Build Coastguard Worker // Creates an arena allocated semantic value. 36*993b0882SAndroid Build Coastguard Worker template <typename T> Create(const T value,UnsafeArena * arena)37*993b0882SAndroid Build Coastguard Worker static const SemanticValue* Create(const T value, UnsafeArena* arena) { 38*993b0882SAndroid Build Coastguard Worker static_assert(!std::is_pointer<T>() && std::is_scalar<T>()); 39*993b0882SAndroid Build Coastguard Worker if (char* buffer = reinterpret_cast<char*>( 40*993b0882SAndroid Build Coastguard Worker arena->AllocAligned(sizeof(T), alignof(T)))) { 41*993b0882SAndroid Build Coastguard Worker flatbuffers::WriteScalar<T>(buffer, value); 42*993b0882SAndroid Build Coastguard Worker return arena->AllocAndInit<SemanticValue>( 43*993b0882SAndroid Build Coastguard Worker libtextclassifier3::flatbuffers_base_type<T>::value, 44*993b0882SAndroid Build Coastguard Worker StringPiece(buffer, sizeof(T))); 45*993b0882SAndroid Build Coastguard Worker } 46*993b0882SAndroid Build Coastguard Worker return nullptr; 47*993b0882SAndroid Build Coastguard Worker } 48*993b0882SAndroid Build Coastguard Worker 49*993b0882SAndroid Build Coastguard Worker template <> Create(const StringPiece value,UnsafeArena * arena)50*993b0882SAndroid Build Coastguard Worker const SemanticValue* Create(const StringPiece value, UnsafeArena* arena) { 51*993b0882SAndroid Build Coastguard Worker return arena->AllocAndInit<SemanticValue>(reflection::BaseType::String, 52*993b0882SAndroid Build Coastguard Worker value); 53*993b0882SAndroid Build Coastguard Worker } 54*993b0882SAndroid Build Coastguard Worker 55*993b0882SAndroid Build Coastguard Worker template <> Create(const UnicodeText value,UnsafeArena * arena)56*993b0882SAndroid Build Coastguard Worker const SemanticValue* Create(const UnicodeText value, UnsafeArena* arena) { 57*993b0882SAndroid Build Coastguard Worker return arena->AllocAndInit<SemanticValue>( 58*993b0882SAndroid Build Coastguard Worker reflection::BaseType::String, 59*993b0882SAndroid Build Coastguard Worker StringPiece(value.data(), value.size_bytes())); 60*993b0882SAndroid Build Coastguard Worker } 61*993b0882SAndroid Build Coastguard Worker 62*993b0882SAndroid Build Coastguard Worker template <> Create(const MutableFlatbuffer * value,UnsafeArena * arena)63*993b0882SAndroid Build Coastguard Worker const SemanticValue* Create(const MutableFlatbuffer* value, 64*993b0882SAndroid Build Coastguard Worker UnsafeArena* arena) { 65*993b0882SAndroid Build Coastguard Worker const std::string buffer = value->Serialize(); 66*993b0882SAndroid Build Coastguard Worker return Create( 67*993b0882SAndroid Build Coastguard Worker value->type(), 68*993b0882SAndroid Build Coastguard Worker StringPiece(arena->Memdup(buffer.data(), buffer.size()), buffer.size()), 69*993b0882SAndroid Build Coastguard Worker arena); 70*993b0882SAndroid Build Coastguard Worker } 71*993b0882SAndroid Build Coastguard Worker Create(const reflection::Object * type,const StringPiece data,UnsafeArena * arena)72*993b0882SAndroid Build Coastguard Worker static const SemanticValue* Create(const reflection::Object* type, 73*993b0882SAndroid Build Coastguard Worker const StringPiece data, 74*993b0882SAndroid Build Coastguard Worker UnsafeArena* arena) { 75*993b0882SAndroid Build Coastguard Worker return arena->AllocAndInit<SemanticValue>(type, data); 76*993b0882SAndroid Build Coastguard Worker } 77*993b0882SAndroid Build Coastguard Worker Create(const reflection::BaseType base_type,const StringPiece data,UnsafeArena * arena)78*993b0882SAndroid Build Coastguard Worker static const SemanticValue* Create(const reflection::BaseType base_type, 79*993b0882SAndroid Build Coastguard Worker const StringPiece data, 80*993b0882SAndroid Build Coastguard Worker UnsafeArena* arena) { 81*993b0882SAndroid Build Coastguard Worker return arena->AllocAndInit<SemanticValue>(base_type, data); 82*993b0882SAndroid Build Coastguard Worker } 83*993b0882SAndroid Build Coastguard Worker 84*993b0882SAndroid Build Coastguard Worker template <typename T> Create(const reflection::BaseType base_type,const T value,UnsafeArena * arena)85*993b0882SAndroid Build Coastguard Worker static const SemanticValue* Create(const reflection::BaseType base_type, 86*993b0882SAndroid Build Coastguard Worker const T value, UnsafeArena* arena) { 87*993b0882SAndroid Build Coastguard Worker switch (base_type) { 88*993b0882SAndroid Build Coastguard Worker case reflection::BaseType::Bool: 89*993b0882SAndroid Build Coastguard Worker return Create( 90*993b0882SAndroid Build Coastguard Worker static_cast< 91*993b0882SAndroid Build Coastguard Worker flatbuffers_cpp_type<reflection::BaseType::Bool>::value>(value), 92*993b0882SAndroid Build Coastguard Worker arena); 93*993b0882SAndroid Build Coastguard Worker case reflection::BaseType::Byte: 94*993b0882SAndroid Build Coastguard Worker return Create( 95*993b0882SAndroid Build Coastguard Worker static_cast< 96*993b0882SAndroid Build Coastguard Worker flatbuffers_cpp_type<reflection::BaseType::Byte>::value>(value), 97*993b0882SAndroid Build Coastguard Worker arena); 98*993b0882SAndroid Build Coastguard Worker case reflection::BaseType::UByte: 99*993b0882SAndroid Build Coastguard Worker return Create( 100*993b0882SAndroid Build Coastguard Worker static_cast< 101*993b0882SAndroid Build Coastguard Worker flatbuffers_cpp_type<reflection::BaseType::UByte>::value>( 102*993b0882SAndroid Build Coastguard Worker value), 103*993b0882SAndroid Build Coastguard Worker arena); 104*993b0882SAndroid Build Coastguard Worker case reflection::BaseType::Short: 105*993b0882SAndroid Build Coastguard Worker return Create( 106*993b0882SAndroid Build Coastguard Worker static_cast< 107*993b0882SAndroid Build Coastguard Worker flatbuffers_cpp_type<reflection::BaseType::Short>::value>( 108*993b0882SAndroid Build Coastguard Worker value), 109*993b0882SAndroid Build Coastguard Worker arena); 110*993b0882SAndroid Build Coastguard Worker case reflection::BaseType::UShort: 111*993b0882SAndroid Build Coastguard Worker return Create( 112*993b0882SAndroid Build Coastguard Worker static_cast< 113*993b0882SAndroid Build Coastguard Worker flatbuffers_cpp_type<reflection::BaseType::UShort>::value>( 114*993b0882SAndroid Build Coastguard Worker value), 115*993b0882SAndroid Build Coastguard Worker arena); 116*993b0882SAndroid Build Coastguard Worker case reflection::BaseType::Int: 117*993b0882SAndroid Build Coastguard Worker return Create( 118*993b0882SAndroid Build Coastguard Worker static_cast<flatbuffers_cpp_type<reflection::BaseType::Int>::value>( 119*993b0882SAndroid Build Coastguard Worker value), 120*993b0882SAndroid Build Coastguard Worker arena); 121*993b0882SAndroid Build Coastguard Worker case reflection::BaseType::UInt: 122*993b0882SAndroid Build Coastguard Worker return Create( 123*993b0882SAndroid Build Coastguard Worker static_cast< 124*993b0882SAndroid Build Coastguard Worker flatbuffers_cpp_type<reflection::BaseType::UInt>::value>(value), 125*993b0882SAndroid Build Coastguard Worker arena); 126*993b0882SAndroid Build Coastguard Worker case reflection::BaseType::Long: 127*993b0882SAndroid Build Coastguard Worker return Create( 128*993b0882SAndroid Build Coastguard Worker static_cast< 129*993b0882SAndroid Build Coastguard Worker flatbuffers_cpp_type<reflection::BaseType::Long>::value>(value), 130*993b0882SAndroid Build Coastguard Worker arena); 131*993b0882SAndroid Build Coastguard Worker case reflection::BaseType::ULong: 132*993b0882SAndroid Build Coastguard Worker return Create( 133*993b0882SAndroid Build Coastguard Worker static_cast< 134*993b0882SAndroid Build Coastguard Worker flatbuffers_cpp_type<reflection::BaseType::ULong>::value>( 135*993b0882SAndroid Build Coastguard Worker value), 136*993b0882SAndroid Build Coastguard Worker arena); 137*993b0882SAndroid Build Coastguard Worker case reflection::BaseType::Float: 138*993b0882SAndroid Build Coastguard Worker return Create( 139*993b0882SAndroid Build Coastguard Worker static_cast< 140*993b0882SAndroid Build Coastguard Worker flatbuffers_cpp_type<reflection::BaseType::Float>::value>( 141*993b0882SAndroid Build Coastguard Worker value), 142*993b0882SAndroid Build Coastguard Worker arena); 143*993b0882SAndroid Build Coastguard Worker case reflection::BaseType::Double: 144*993b0882SAndroid Build Coastguard Worker return Create( 145*993b0882SAndroid Build Coastguard Worker static_cast< 146*993b0882SAndroid Build Coastguard Worker flatbuffers_cpp_type<reflection::BaseType::Double>::value>( 147*993b0882SAndroid Build Coastguard Worker value), 148*993b0882SAndroid Build Coastguard Worker arena); 149*993b0882SAndroid Build Coastguard Worker default: { 150*993b0882SAndroid Build Coastguard Worker TC3_LOG(ERROR) << "Unhandled type: " << base_type; 151*993b0882SAndroid Build Coastguard Worker return nullptr; 152*993b0882SAndroid Build Coastguard Worker } 153*993b0882SAndroid Build Coastguard Worker } 154*993b0882SAndroid Build Coastguard Worker } 155*993b0882SAndroid Build Coastguard Worker SemanticValue(const reflection::BaseType base_type,const StringPiece data)156*993b0882SAndroid Build Coastguard Worker explicit SemanticValue(const reflection::BaseType base_type, 157*993b0882SAndroid Build Coastguard Worker const StringPiece data) 158*993b0882SAndroid Build Coastguard Worker : base_type_(base_type), type_(nullptr), data_(data) {} SemanticValue(const reflection::Object * type,const StringPiece data)159*993b0882SAndroid Build Coastguard Worker explicit SemanticValue(const reflection::Object* type, const StringPiece data) 160*993b0882SAndroid Build Coastguard Worker : base_type_(reflection::BaseType::Obj), type_(type), data_(data) {} 161*993b0882SAndroid Build Coastguard Worker 162*993b0882SAndroid Build Coastguard Worker template <typename T> Has()163*993b0882SAndroid Build Coastguard Worker bool Has() const { 164*993b0882SAndroid Build Coastguard Worker return base_type_ == libtextclassifier3::flatbuffers_base_type<T>::value; 165*993b0882SAndroid Build Coastguard Worker } 166*993b0882SAndroid Build Coastguard Worker 167*993b0882SAndroid Build Coastguard Worker template <> 168*993b0882SAndroid Build Coastguard Worker bool Has<flatbuffers::Table>() const { 169*993b0882SAndroid Build Coastguard Worker return base_type_ == reflection::BaseType::Obj; 170*993b0882SAndroid Build Coastguard Worker } 171*993b0882SAndroid Build Coastguard Worker 172*993b0882SAndroid Build Coastguard Worker template <typename T = flatbuffers::Table> Table()173*993b0882SAndroid Build Coastguard Worker const T* Table() const { 174*993b0882SAndroid Build Coastguard Worker TC3_CHECK(Has<flatbuffers::Table>()); 175*993b0882SAndroid Build Coastguard Worker return flatbuffers::GetRoot<T>( 176*993b0882SAndroid Build Coastguard Worker reinterpret_cast<const unsigned char*>(data_.data())); 177*993b0882SAndroid Build Coastguard Worker } 178*993b0882SAndroid Build Coastguard Worker 179*993b0882SAndroid Build Coastguard Worker template <typename T> Value()180*993b0882SAndroid Build Coastguard Worker const T Value() const { 181*993b0882SAndroid Build Coastguard Worker TC3_CHECK(Has<T>()); 182*993b0882SAndroid Build Coastguard Worker return flatbuffers::ReadScalar<T>(data_.data()); 183*993b0882SAndroid Build Coastguard Worker } 184*993b0882SAndroid Build Coastguard Worker 185*993b0882SAndroid Build Coastguard Worker template <> 186*993b0882SAndroid Build Coastguard Worker const StringPiece Value<StringPiece>() const { 187*993b0882SAndroid Build Coastguard Worker TC3_CHECK(Has<StringPiece>()); 188*993b0882SAndroid Build Coastguard Worker return data_; 189*993b0882SAndroid Build Coastguard Worker } 190*993b0882SAndroid Build Coastguard Worker 191*993b0882SAndroid Build Coastguard Worker template <> 192*993b0882SAndroid Build Coastguard Worker const std::string Value<std::string>() const { 193*993b0882SAndroid Build Coastguard Worker TC3_CHECK(Has<StringPiece>()); 194*993b0882SAndroid Build Coastguard Worker return data_.ToString(); 195*993b0882SAndroid Build Coastguard Worker } 196*993b0882SAndroid Build Coastguard Worker 197*993b0882SAndroid Build Coastguard Worker template <> 198*993b0882SAndroid Build Coastguard Worker const UnicodeText Value<UnicodeText>() const { 199*993b0882SAndroid Build Coastguard Worker TC3_CHECK(Has<StringPiece>()); 200*993b0882SAndroid Build Coastguard Worker return UTF8ToUnicodeText(data_, /*do_copy=*/false); 201*993b0882SAndroid Build Coastguard Worker } 202*993b0882SAndroid Build Coastguard Worker base_type()203*993b0882SAndroid Build Coastguard Worker const reflection::BaseType base_type() const { return base_type_; } type()204*993b0882SAndroid Build Coastguard Worker const reflection::Object* type() const { return type_; } 205*993b0882SAndroid Build Coastguard Worker 206*993b0882SAndroid Build Coastguard Worker private: 207*993b0882SAndroid Build Coastguard Worker // The base type. 208*993b0882SAndroid Build Coastguard Worker const reflection::BaseType base_type_; 209*993b0882SAndroid Build Coastguard Worker 210*993b0882SAndroid Build Coastguard Worker // The object type of the value. 211*993b0882SAndroid Build Coastguard Worker const reflection::Object* type_; 212*993b0882SAndroid Build Coastguard Worker 213*993b0882SAndroid Build Coastguard Worker StringPiece data_; 214*993b0882SAndroid Build Coastguard Worker }; 215*993b0882SAndroid Build Coastguard Worker 216*993b0882SAndroid Build Coastguard Worker } // namespace libtextclassifier3::grammar 217*993b0882SAndroid Build Coastguard Worker 218*993b0882SAndroid Build Coastguard Worker #endif // LIBTEXTCLASSIFIER_UTILS_GRAMMAR_SEMANTICS_VALUE_H_ 219