• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2023 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 #ifndef ICING_QUERY_ADVANCED_QUERY_PARSER_PENDING_VALUE_H_
15 #define ICING_QUERY_ADVANCED_QUERY_PARSER_PENDING_VALUE_H_
16 
17 #include <memory>
18 #include <string>
19 #include <utility>
20 #include <vector>
21 
22 #include "icing/text_classifier/lib3/utils/base/status.h"
23 #include "icing/absl_ports/str_cat.h"
24 #include "icing/index/iterator/doc-hit-info-iterator.h"
25 #include "icing/util/status-macros.h"
26 
27 namespace icing {
28 namespace lib {
29 
30 enum class DataType {
31   kNone,
32   kLong,
33   kText,
34   kString,
35   kStringList,
36   kDocumentIterator,
37 };
38 
39 struct QueryTerm {
40   std::string term;
41   std::string_view raw_term;
42   bool is_prefix_val;
43 };
44 
45 // A holder for intermediate results when processing child nodes.
46 struct PendingValue {
CreateStringPendingValuePendingValue47   static PendingValue CreateStringPendingValue(QueryTerm str) {
48     return PendingValue(std::move(str), DataType::kString);
49   }
50 
CreateTextPendingValuePendingValue51   static PendingValue CreateTextPendingValue(QueryTerm text) {
52     return PendingValue(std::move(text), DataType::kText);
53   }
54 
PendingValuePendingValue55   PendingValue() : data_type_(DataType::kNone) {}
56 
PendingValuePendingValue57   explicit PendingValue(std::unique_ptr<DocHitInfoIterator> iterator)
58       : iterator_(std::move(iterator)),
59         data_type_(DataType::kDocumentIterator) {}
60 
PendingValuePendingValue61   explicit PendingValue(std::vector<std::string> string_lists)
62       : string_vals_(std::move(string_lists)),
63         data_type_(DataType::kStringList) {}
64 
65   PendingValue(const PendingValue&) = delete;
66   PendingValue(PendingValue&&) = default;
67 
68   PendingValue& operator=(const PendingValue&) = delete;
69   PendingValue& operator=(PendingValue&&) = default;
70 
71   // Placeholder is used to indicate where the children of a particular node
72   // begin.
is_placeholderPendingValue73   bool is_placeholder() const { return data_type_ == DataType::kNone; }
74 
75   libtextclassifier3::StatusOr<std::unique_ptr<DocHitInfoIterator>>
iteratorPendingValue76   iterator() && {
77     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kDocumentIterator));
78     return std::move(iterator_);
79   }
80 
string_valsPendingValue81   libtextclassifier3::StatusOr<const std::vector<std::string>*> string_vals()
82       const& {
83     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kStringList));
84     return &string_vals_;
85   }
string_valsPendingValue86   libtextclassifier3::StatusOr<std::vector<std::string>> string_vals() && {
87     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kStringList));
88     return std::move(string_vals_);
89   }
90 
string_valPendingValue91   libtextclassifier3::StatusOr<const QueryTerm*> string_val() const& {
92     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kString));
93     return &query_term_;
94   }
string_valPendingValue95   libtextclassifier3::StatusOr<QueryTerm> string_val() && {
96     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kString));
97     return std::move(query_term_);
98   }
99 
text_valPendingValue100   libtextclassifier3::StatusOr<const QueryTerm*> text_val() const& {
101     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kText));
102     return &query_term_;
103   }
text_valPendingValue104   libtextclassifier3::StatusOr<QueryTerm> text_val() && {
105     ICING_RETURN_IF_ERROR(CheckDataType(DataType::kText));
106     return std::move(query_term_);
107   }
108 
long_valPendingValue109   libtextclassifier3::StatusOr<int64_t> long_val() {
110     ICING_RETURN_IF_ERROR(ParseInt());
111     return long_val_;
112   }
113 
114   // Attempts to interpret the value as an int. A pending value can be parsed as
115   // an int under two circumstances:
116   //   1. It holds a kText value which can be parsed to an int
117   //   2. It holds a kLong value
118   // If #1 is true, then the parsed value will be stored in long_value and
119   // data_type will be updated to kLong.
120   // RETURNS:
121   //   - OK, if able to successfully parse the value into a long
122   //   - INVALID_ARGUMENT if the value could not be parsed as a long
123   libtextclassifier3::Status ParseInt();
124 
data_typePendingValue125   DataType data_type() const { return data_type_; }
126 
127  private:
PendingValuePendingValue128   explicit PendingValue(QueryTerm query_term, DataType data_type)
129       : query_term_(std::move(query_term)), data_type_(data_type) {}
130 
CheckDataTypePendingValue131   libtextclassifier3::Status CheckDataType(DataType required_data_type) const {
132     if (data_type_ == required_data_type) {
133       return libtextclassifier3::Status::OK;
134     }
135     return absl_ports::InvalidArgumentError(
136         absl_ports::StrCat("Unable to retrieve value of type '",
137                            std::to_string(static_cast<int>(required_data_type)),
138                            "' from pending value of type '",
139                            std::to_string(static_cast<int>(data_type_)), "'"));
140   }
141 
142   // iterator_ will be populated when data_type_ is kDocumentIterator.
143   std::unique_ptr<DocHitInfoIterator> iterator_;
144 
145   // string_vals_ will be populated when data_type_ kStringList.
146   std::vector<std::string> string_vals_;
147 
148   // query_term_ will be populated when data_type_ is kString or kText
149   QueryTerm query_term_;
150 
151   // long_val_ will be populated when data_type_ is kLong - after a successful
152   // call to ParseInt.
153   int64_t long_val_;
154   DataType data_type_;
155 };
156 
157 }  // namespace lib
158 }  // namespace icing
159 
160 #endif  // ICING_QUERY_ADVANCED_QUERY_PARSER_PENDING_VALUE_H_
161