| // Copyright 2021 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef RUNTIME_PROBE_FIELD_CONVERTER_H_ |
| #define RUNTIME_PROBE_FIELD_CONVERTER_H_ |
| |
| #include <cstdint> |
| #include <memory> |
| #include <string> |
| |
| #include <pcrecpp.h> |
| |
| #include <base/strings/string_piece.h> |
| #include <base/values.h> |
| #include <gtest/gtest.h> |
| |
| #include "runtime_probe/utils/type_utils.h" |
| |
| namespace runtime_probe { |
| |
| enum class ValidatorOperator : uint8_t { |
| NOP = 0, |
| RE, // Regular Expression match |
| EQ, // EQual to |
| NE, // Not Equal to |
| GT, // Greater Than |
| GE, // Greater than or Euqal to |
| LT, // Less Than |
| LE, // Less than or Equal to |
| |
| NUM_OP, |
| }; |
| |
| // Base class of field converter. |
| // |
| // Each derived class should implement one and only one constructor |
| // FieldConverter(const std::string& validate_rule). |
| class FieldConverter { |
| public: |
| enum class ReturnCode { |
| OK = 0, |
| FIELD_NOT_FOUND = 1, |
| // Failed to convert the field |
| INCOMPATIBLE_VALUE = 2, |
| // The operator is not supported by this converter |
| UNSUPPORTED_OPERATOR = 3, |
| // Field value is invalid |
| INVALID_VALUE = 4, |
| }; |
| |
| // Try to find |field_name| in |dict_value|, and convert it to expected type. |
| // |
| // @return |ReturnCode| to indicate success or reason of failure. |
| virtual ReturnCode Convert(const std::string& field_name, |
| base::Value* dict_value) const = 0; |
| |
| // Check if value of |field_name| in dict_value is valid. |
| // |
| // @return |ReturnCode| to indicate success or reason of failure. |
| virtual ReturnCode Validate(const std::string& field_name, |
| base::Value* dict_value) const = 0; |
| |
| virtual std::string ToString() const = 0; |
| |
| virtual ~FieldConverter() = default; |
| }; |
| |
| // Convert a field to string. |
| // |
| // Supported validators: |
| // - "!re <Perl-compatible regular expression>" |
| // - "!eq <expected string>" |
| // - "!ne <unexpected string>" |
| class StringFieldConverter : public FieldConverter { |
| public: |
| ReturnCode Convert(const std::string& field_name, |
| base::Value* dict_value) const override; |
| |
| ReturnCode Validate(const std::string& field_name, |
| base::Value* dict_value) const override; |
| |
| std::string ToString() const override; |
| |
| static std::unique_ptr<StringFieldConverter> Build( |
| const base::StringPiece& validate_rule); |
| |
| StringFieldConverter(ValidatorOperator op, const base::StringPiece& operand) |
| : operator_(op), operand_(operand) { |
| if (op == ValidatorOperator::RE) { |
| // pcrecpp::RE constructor will always succeed, but might set "error()" if |
| // the pattern is invalid. This will be checked in |Build()|. |
| regex_ = std::make_unique<pcrecpp::RE>(std::string(operand)); |
| } |
| } |
| |
| private: |
| ValidatorOperator operator_; |
| std::string operand_; |
| std::unique_ptr<pcrecpp::RE> regex_; |
| |
| FRIEND_TEST(StringFieldConverterTest, TestValidateRule); |
| }; |
| |
| // Numeric Field Converters convert a field into a numeric type. |
| // The logic of these fields are very similar. To allow implementing common |
| // logic with template, helper function |StringToOperand| and type alias |
| // |OperandType| is defined. |OperandType| is the type of |operand_| member |
| // variable. And |StringToOperand| converts a string to |OperandType| value |
| // and return true on success. |
| |
| // Convert a field to integer. |
| // |
| // However, heximal value is not allowed, please use |HexFieldConverter| |
| // instead. |
| // |
| // Supported validators: |
| // - "!eq <integer>" |
| // - "!ne <integer>" |
| // - "!gt <integer>" |
| // - "!ge <integer>" |
| // - "!lt <integer>" |
| // - "!le <integer>" |
| class IntegerFieldConverter : public FieldConverter { |
| public: |
| using FieldConverter::FieldConverter; |
| using OperandType = int; |
| |
| ReturnCode Convert(const std::string& field_name, |
| base::Value* dict_value) const override; |
| |
| ReturnCode Validate(const std::string& field_name, |
| base::Value* dict_value) const override; |
| |
| std::string ToString() const override; |
| |
| static std::unique_ptr<IntegerFieldConverter> Build( |
| const base::StringPiece& validate_rule); |
| |
| IntegerFieldConverter(ValidatorOperator op, OperandType operand) |
| : operator_(op), operand_(operand) {} |
| |
| static bool StringToOperand(base::StringPiece s, OperandType* output) { |
| return StringToInt(s, output); |
| } |
| |
| private: |
| ValidatorOperator operator_; |
| OperandType operand_; |
| |
| FRIEND_TEST(IntegerFieldConverterTest, TestValidateRule); |
| }; |
| |
| // Convert a hex string field to integer. |
| // |
| // If the original field is string, this class assumes it is base 16. |
| // Otherwise, if the field is already a number (int or double), the behavior wil |
| // be identical to |IntegerFieldConverter|. |
| // |
| // Supported validators: same as |IntegerFieldConverter| |
| class HexFieldConverter : public FieldConverter { |
| public: |
| using FieldConverter::FieldConverter; |
| using OperandType = int64_t; |
| |
| ReturnCode Convert(const std::string& field_name, |
| base::Value* dict_value) const override; |
| |
| ReturnCode Validate(const std::string& field_name, |
| base::Value* dict_value) const override; |
| |
| std::string ToString() const override; |
| |
| static std::unique_ptr<HexFieldConverter> Build( |
| const base::StringPiece& validate_rule); |
| |
| HexFieldConverter(ValidatorOperator op, OperandType operand) |
| : operator_(op), operand_(operand) {} |
| |
| static bool StringToOperand(base::StringPiece s, OperandType* output) { |
| return HexStringToInt64(s, output); |
| } |
| |
| private: |
| ValidatorOperator operator_; |
| OperandType operand_; |
| |
| FRIEND_TEST(HexFieldConverterTest, TestValidateRule); |
| }; |
| |
| // Convert a field to double. |
| // |
| // Supported validators: same as |IntegerFieldConverter|, except the operand |
| // could be double. |
| class DoubleFieldConverter : public FieldConverter { |
| public: |
| using FieldConverter::FieldConverter; |
| using OperandType = double; |
| |
| ReturnCode Convert(const std::string& field_name, |
| base::Value* dict_value) const override; |
| |
| ReturnCode Validate(const std::string& field_name, |
| base::Value* dict_value) const override; |
| |
| std::string ToString() const override; |
| |
| static std::unique_ptr<DoubleFieldConverter> Build( |
| const base::StringPiece& validate_rule); |
| |
| DoubleFieldConverter(ValidatorOperator op, OperandType operand) |
| : operator_(op), operand_(operand) {} |
| |
| static bool StringToOperand(base::StringPiece s, OperandType* output) { |
| return StringToDouble(s, output); |
| } |
| |
| private: |
| ValidatorOperator operator_; |
| OperandType operand_; |
| |
| FRIEND_TEST(DoubleFieldConverterTest, TestValidateRule); |
| }; |
| |
| } // namespace runtime_probe |
| |
| #endif // RUNTIME_PROBE_FIELD_CONVERTER_H_ |