1 // Copyright (C) 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "icing/schema/property-util.h"
16
17 #include <cstddef>
18 #include <cstdint>
19 #include <string>
20 #include <string_view>
21 #include <vector>
22
23 #include "icing/text_classifier/lib3/utils/base/statusor.h"
24 #include "icing/absl_ports/str_cat.h"
25 #include "icing/absl_ports/str_join.h"
26 #include "icing/proto/document.pb.h"
27
28 namespace icing {
29 namespace lib {
30
31 namespace property_util {
32
ConvertToPropertyExprIndexStr(int index)33 std::string ConvertToPropertyExprIndexStr(int index) {
34 if (index == kWildcardPropertyIndex) {
35 return "";
36 }
37 return absl_ports::StrCat(kLBracket, std::to_string(index), kRBracket);
38 }
39
ConcatenatePropertyPathExpr(std::string_view property_path_expr1,std::string_view property_path_expr2)40 std::string ConcatenatePropertyPathExpr(std::string_view property_path_expr1,
41 std::string_view property_path_expr2) {
42 if (property_path_expr1.empty()) {
43 return std::string(property_path_expr2);
44 }
45 if (property_path_expr2.empty()) {
46 return std::string(property_path_expr1);
47 }
48 return absl_ports::StrCat(property_path_expr1, kPropertyPathSeparator,
49 property_path_expr2);
50 }
51
SplitPropertyPathExpr(std::string_view property_path_expr)52 std::vector<std::string_view> SplitPropertyPathExpr(
53 std::string_view property_path_expr) {
54 return absl_ports::StrSplit(property_path_expr, kPropertyPathSeparator);
55 }
56
ParsePropertyNameExpr(std::string_view property_name_expr)57 PropertyInfo ParsePropertyNameExpr(std::string_view property_name_expr) {
58 size_t l_bracket = property_name_expr.find(kLBracket);
59 if (l_bracket == std::string_view::npos ||
60 l_bracket >= property_name_expr.length()) {
61 return PropertyInfo(std::string(property_name_expr),
62 kWildcardPropertyIndex);
63 }
64 size_t r_bracket = property_name_expr.find(kRBracket, l_bracket);
65 if (r_bracket == std::string_view::npos || r_bracket - l_bracket < 2) {
66 return PropertyInfo(std::string(property_name_expr),
67 kWildcardPropertyIndex);
68 }
69 std::string index_string = std::string(
70 property_name_expr.substr(l_bracket + 1, r_bracket - l_bracket - 1));
71 return PropertyInfo(std::string(property_name_expr.substr(0, l_bracket)),
72 std::stoi(index_string));
73 }
74
ParsePropertyPathExpr(std::string_view property_path_expr)75 std::vector<PropertyInfo> ParsePropertyPathExpr(
76 std::string_view property_path_expr) {
77 std::vector<std::string_view> property_name_exprs =
78 SplitPropertyPathExpr(property_path_expr);
79
80 std::vector<PropertyInfo> property_infos;
81 property_infos.reserve(property_name_exprs.size());
82 for (std::string_view property_name_expr : property_name_exprs) {
83 property_infos.push_back(ParsePropertyNameExpr(property_name_expr));
84 }
85 return property_infos;
86 }
87
IsParentPropertyPath(std::string_view property_path_expr1,std::string_view property_path_expr2)88 bool IsParentPropertyPath(std::string_view property_path_expr1,
89 std::string_view property_path_expr2) {
90 if (property_path_expr2.length() < property_path_expr1.length()) {
91 return false;
92 }
93 if (property_path_expr1 !=
94 property_path_expr2.substr(0, property_path_expr1.length())) {
95 return false;
96 }
97 if (property_path_expr2.length() > property_path_expr1.length() &&
98 property_path_expr2[property_path_expr1.length()] !=
99 kPropertyPathSeparator[0]) {
100 return false;
101 }
102 return true;
103 }
104
GetPropertyProto(const DocumentProto & document,std::string_view property_name)105 const PropertyProto* GetPropertyProto(const DocumentProto& document,
106 std::string_view property_name) {
107 for (const PropertyProto& property : document.properties()) {
108 if (property.name() == property_name) {
109 return &property;
110 }
111 }
112 return nullptr;
113 }
114
115 template <>
116 libtextclassifier3::StatusOr<std::vector<std::string>>
ExtractPropertyValues(const PropertyProto & property)117 ExtractPropertyValues<std::string>(const PropertyProto& property) {
118 return std::vector<std::string>(property.string_values().begin(),
119 property.string_values().end());
120 }
121
122 template <>
123 libtextclassifier3::StatusOr<std::vector<std::string_view>>
ExtractPropertyValues(const PropertyProto & property)124 ExtractPropertyValues<std::string_view>(const PropertyProto& property) {
125 return std::vector<std::string_view>(property.string_values().begin(),
126 property.string_values().end());
127 }
128
129 template <>
130 libtextclassifier3::StatusOr<std::vector<int64_t>>
ExtractPropertyValues(const PropertyProto & property)131 ExtractPropertyValues<int64_t>(const PropertyProto& property) {
132 return std::vector<int64_t>(property.int64_values().begin(),
133 property.int64_values().end());
134 }
135
136 template <>
ExtractPropertyValues(const PropertyProto & property)137 libtextclassifier3::StatusOr<std::vector<double>> ExtractPropertyValues<double>(
138 const PropertyProto& property) {
139 return std::vector<double>(property.double_values().begin(),
140 property.double_values().end());
141 }
142
143 template <>
ExtractPropertyValues(const PropertyProto & property)144 libtextclassifier3::StatusOr<std::vector<bool>> ExtractPropertyValues<bool>(
145 const PropertyProto& property) {
146 return std::vector<bool>(property.boolean_values().begin(),
147 property.boolean_values().end());
148 }
149
150 template <>
151 libtextclassifier3::StatusOr<std::vector<PropertyProto::VectorProto>>
ExtractPropertyValues(const PropertyProto & property)152 ExtractPropertyValues<PropertyProto::VectorProto>(
153 const PropertyProto& property) {
154 return std::vector<PropertyProto::VectorProto>(
155 property.vector_values().begin(), property.vector_values().end());
156 }
157
158 template <>
159 libtextclassifier3::StatusOr<std::vector<PropertyProto::BlobHandleProto>>
ExtractPropertyValues(const PropertyProto & property)160 ExtractPropertyValues<PropertyProto::BlobHandleProto>(
161 const PropertyProto& property) {
162 return std::vector<PropertyProto::BlobHandleProto>(
163 property.blob_handle_values().begin(),
164 property.blob_handle_values().end());
165 }
166
167 } // namespace property_util
168
169 } // namespace lib
170 } // namespace icing
171