123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- /*
- * Copyright 2018 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
- #ifndef RTC_BASE_EXPERIMENTS_FIELD_TRIAL_PARSER_H_
- #define RTC_BASE_EXPERIMENTS_FIELD_TRIAL_PARSER_H_
- #include <stdint.h>
- #include <initializer_list>
- #include <map>
- #include <set>
- #include <string>
- #include <vector>
- #include "absl/types/optional.h"
- // Field trial parser functionality. Provides funcitonality to parse field trial
- // argument strings in key:value format. Each parameter is described using
- // key:value, parameters are separated with a ,. Values can't include the comma
- // character, since there's no quote facility. For most types, white space is
- // ignored. Parameters are declared with a given type for which an
- // implementation of ParseTypedParameter should be provided. The
- // ParseTypedParameter implementation is given whatever is between the : and the
- // ,. If the key is provided without : a FieldTrialOptional will use nullopt.
- // Example string: "my_optional,my_int:3,my_string:hello"
- // For further description of usage and behavior, see the examples in the unit
- // tests.
- namespace webrtc {
- class FieldTrialParameterInterface {
- public:
- virtual ~FieldTrialParameterInterface();
- std::string key() const { return key_; }
- protected:
- // Protected to allow implementations to provide assignment and copy.
- FieldTrialParameterInterface(const FieldTrialParameterInterface&) = default;
- FieldTrialParameterInterface& operator=(const FieldTrialParameterInterface&) =
- default;
- explicit FieldTrialParameterInterface(std::string key);
- friend void ParseFieldTrial(
- std::initializer_list<FieldTrialParameterInterface*> fields,
- std::string raw_string);
- void MarkAsUsed() { used_ = true; }
- virtual bool Parse(absl::optional<std::string> str_value) = 0;
- virtual void ParseDone() {}
- std::vector<FieldTrialParameterInterface*> sub_parameters_;
- private:
- std::string key_;
- bool used_ = false;
- };
- // ParseFieldTrial function parses the given string and fills the given fields
- // with extracted values if available.
- void ParseFieldTrial(
- std::initializer_list<FieldTrialParameterInterface*> fields,
- std::string raw_string);
- // Specialize this in code file for custom types. Should return absl::nullopt if
- // the given string cannot be properly parsed.
- template <typename T>
- absl::optional<T> ParseTypedParameter(std::string);
- // This class uses the ParseTypedParameter function to implement a parameter
- // implementation with an enforced default value.
- template <typename T>
- class FieldTrialParameter : public FieldTrialParameterInterface {
- public:
- FieldTrialParameter(std::string key, T default_value)
- : FieldTrialParameterInterface(key), value_(default_value) {}
- T Get() const { return value_; }
- operator T() const { return Get(); }
- const T* operator->() const { return &value_; }
- void SetForTest(T value) { value_ = value; }
- protected:
- bool Parse(absl::optional<std::string> str_value) override {
- if (str_value) {
- absl::optional<T> value = ParseTypedParameter<T>(*str_value);
- if (value.has_value()) {
- value_ = value.value();
- return true;
- }
- }
- return false;
- }
- private:
- T value_;
- };
- // This class uses the ParseTypedParameter function to implement a parameter
- // implementation with an enforced default value and a range constraint. Values
- // outside the configured range will be ignored.
- template <typename T>
- class FieldTrialConstrained : public FieldTrialParameterInterface {
- public:
- FieldTrialConstrained(std::string key,
- T default_value,
- absl::optional<T> lower_limit,
- absl::optional<T> upper_limit)
- : FieldTrialParameterInterface(key),
- value_(default_value),
- lower_limit_(lower_limit),
- upper_limit_(upper_limit) {}
- T Get() const { return value_; }
- operator T() const { return Get(); }
- const T* operator->() const { return &value_; }
- protected:
- bool Parse(absl::optional<std::string> str_value) override {
- if (str_value) {
- absl::optional<T> value = ParseTypedParameter<T>(*str_value);
- if (value && (!lower_limit_ || *value >= *lower_limit_) &&
- (!upper_limit_ || *value <= *upper_limit_)) {
- value_ = *value;
- return true;
- }
- }
- return false;
- }
- private:
- T value_;
- absl::optional<T> lower_limit_;
- absl::optional<T> upper_limit_;
- };
- class AbstractFieldTrialEnum : public FieldTrialParameterInterface {
- public:
- AbstractFieldTrialEnum(std::string key,
- int default_value,
- std::map<std::string, int> mapping);
- ~AbstractFieldTrialEnum() override;
- AbstractFieldTrialEnum(const AbstractFieldTrialEnum&);
- protected:
- bool Parse(absl::optional<std::string> str_value) override;
- protected:
- int value_;
- std::map<std::string, int> enum_mapping_;
- std::set<int> valid_values_;
- };
- // The FieldTrialEnum class can be used to quickly define a parser for a
- // specific enum. It handles values provided as integers and as strings if a
- // mapping is provided.
- template <typename T>
- class FieldTrialEnum : public AbstractFieldTrialEnum {
- public:
- FieldTrialEnum(std::string key,
- T default_value,
- std::map<std::string, T> mapping)
- : AbstractFieldTrialEnum(key,
- static_cast<int>(default_value),
- ToIntMap(mapping)) {}
- T Get() const { return static_cast<T>(value_); }
- operator T() const { return Get(); }
- private:
- static std::map<std::string, int> ToIntMap(std::map<std::string, T> mapping) {
- std::map<std::string, int> res;
- for (const auto& it : mapping)
- res[it.first] = static_cast<int>(it.second);
- return res;
- }
- };
- // This class uses the ParseTypedParameter function to implement an optional
- // parameter implementation that can default to absl::nullopt.
- template <typename T>
- class FieldTrialOptional : public FieldTrialParameterInterface {
- public:
- explicit FieldTrialOptional(std::string key)
- : FieldTrialParameterInterface(key) {}
- FieldTrialOptional(std::string key, absl::optional<T> default_value)
- : FieldTrialParameterInterface(key), value_(default_value) {}
- absl::optional<T> GetOptional() const { return value_; }
- const T& Value() const { return value_.value(); }
- const T& operator*() const { return value_.value(); }
- const T* operator->() const { return &value_.value(); }
- explicit operator bool() const { return value_.has_value(); }
- protected:
- bool Parse(absl::optional<std::string> str_value) override {
- if (str_value) {
- absl::optional<T> value = ParseTypedParameter<T>(*str_value);
- if (!value.has_value())
- return false;
- value_ = value.value();
- } else {
- value_ = absl::nullopt;
- }
- return true;
- }
- private:
- absl::optional<T> value_;
- };
- // Equivalent to a FieldTrialParameter<bool> in the case that both key and value
- // are present. If key is missing, evaluates to false. If key is present, but no
- // explicit value is provided, the flag evaluates to true.
- class FieldTrialFlag : public FieldTrialParameterInterface {
- public:
- explicit FieldTrialFlag(std::string key);
- FieldTrialFlag(std::string key, bool default_value);
- bool Get() const;
- operator bool() const;
- protected:
- bool Parse(absl::optional<std::string> str_value) override;
- private:
- bool value_;
- };
- template <typename T>
- absl::optional<absl::optional<T>> ParseOptionalParameter(std::string str) {
- if (str.empty())
- return absl::optional<T>();
- auto parsed = ParseTypedParameter<T>(str);
- if (parsed.has_value())
- return parsed;
- return absl::nullopt;
- }
- template <>
- absl::optional<bool> ParseTypedParameter<bool>(std::string str);
- template <>
- absl::optional<double> ParseTypedParameter<double>(std::string str);
- template <>
- absl::optional<int> ParseTypedParameter<int>(std::string str);
- template <>
- absl::optional<unsigned> ParseTypedParameter<unsigned>(std::string str);
- template <>
- absl::optional<std::string> ParseTypedParameter<std::string>(std::string str);
- template <>
- absl::optional<absl::optional<bool>> ParseTypedParameter<absl::optional<bool>>(
- std::string str);
- template <>
- absl::optional<absl::optional<int>> ParseTypedParameter<absl::optional<int>>(
- std::string str);
- template <>
- absl::optional<absl::optional<unsigned>>
- ParseTypedParameter<absl::optional<unsigned>>(std::string str);
- template <>
- absl::optional<absl::optional<double>>
- ParseTypedParameter<absl::optional<double>>(std::string str);
- // Accepts true, false, else parsed with sscanf %i, true if != 0.
- extern template class FieldTrialParameter<bool>;
- // Interpreted using sscanf %lf.
- extern template class FieldTrialParameter<double>;
- // Interpreted using sscanf %i.
- extern template class FieldTrialParameter<int>;
- // Interpreted using sscanf %u.
- extern template class FieldTrialParameter<unsigned>;
- // Using the given value as is.
- extern template class FieldTrialParameter<std::string>;
- extern template class FieldTrialConstrained<double>;
- extern template class FieldTrialConstrained<int>;
- extern template class FieldTrialConstrained<unsigned>;
- extern template class FieldTrialOptional<double>;
- extern template class FieldTrialOptional<int>;
- extern template class FieldTrialOptional<unsigned>;
- extern template class FieldTrialOptional<bool>;
- extern template class FieldTrialOptional<std::string>;
- } // namespace webrtc
- #endif // RTC_BASE_EXPERIMENTS_FIELD_TRIAL_PARSER_H_
|