blob: a385ccfc167c24b7e115a4da646a7a535e034a9e [file] [log] [blame]
Sebastian Jansson9eb38862018-06-14 16:47:42 +02001/*
2 * Copyright 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10#ifndef RTC_BASE_EXPERIMENTS_FIELD_TRIAL_PARSER_H_
11#define RTC_BASE_EXPERIMENTS_FIELD_TRIAL_PARSER_H_
12
13#include <stdint.h>
14#include <initializer_list>
Sebastian Jansson2c74d852018-06-26 10:30:16 +020015#include <map>
16#include <set>
Sebastian Jansson9eb38862018-06-14 16:47:42 +020017#include <string>
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020018#include "absl/types/optional.h"
Sebastian Jansson9eb38862018-06-14 16:47:42 +020019
20// Field trial parser functionality. Provides funcitonality to parse field trial
21// argument strings in key:value format. Each parameter is described using
22// key:value, parameters are separated with a ,. Values can't include the comma
23// character, since there's no quote facility. For most types, white space is
24// ignored. Parameters are declared with a given type for which an
25// implementation of ParseTypedParameter should be provided. The
26// ParseTypedParameter implementation is given whatever is between the : and the
27// ,. FieldTrialOptional will use nullopt if the key is provided without :.
28
29// Example string: "my_optional,my_int:3,my_string:hello"
30
31// For further description of usage and behavior, see the examples in the unit
32// tests.
33
34namespace webrtc {
35class FieldTrialParameterInterface {
36 public:
37 virtual ~FieldTrialParameterInterface();
38
39 protected:
40 explicit FieldTrialParameterInterface(std::string key);
41 friend void ParseFieldTrial(
42 std::initializer_list<FieldTrialParameterInterface*> fields,
43 std::string raw_string);
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020044 virtual bool Parse(absl::optional<std::string> str_value) = 0;
Sebastian Jansson9eb38862018-06-14 16:47:42 +020045 std::string Key() const;
46
47 private:
48 const std::string key_;
49};
50
51// ParseFieldTrial function parses the given string and fills the given fields
52// with extrated values if available.
53void ParseFieldTrial(
54 std::initializer_list<FieldTrialParameterInterface*> fields,
55 std::string raw_string);
56
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020057// Specialize this in code file for custom types. Should return absl::nullopt if
Sebastian Jansson9eb38862018-06-14 16:47:42 +020058// the given string cannot be properly parsed.
59template <typename T>
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020060absl::optional<T> ParseTypedParameter(std::string);
Sebastian Jansson9eb38862018-06-14 16:47:42 +020061
62// This class uses the ParseTypedParameter function to implement a parameter
63// implementation with an enforced default value.
64template <typename T>
65class FieldTrialParameter : public FieldTrialParameterInterface {
66 public:
67 FieldTrialParameter(std::string key, T default_value)
68 : FieldTrialParameterInterface(key), value_(default_value) {}
69 T Get() const { return value_; }
70 operator T() const { return Get(); }
71
72 protected:
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020073 bool Parse(absl::optional<std::string> str_value) override {
Sebastian Jansson9eb38862018-06-14 16:47:42 +020074 if (str_value) {
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020075 absl::optional<T> value = ParseTypedParameter<T>(*str_value);
Sebastian Jansson9eb38862018-06-14 16:47:42 +020076 if (value.has_value()) {
77 value_ = value.value();
78 return true;
79 }
80 }
81 return false;
82 }
83
84 private:
85 T value_;
86};
87
Sebastian Jansson2c74d852018-06-26 10:30:16 +020088class AbstractFieldTrialEnum : public FieldTrialParameterInterface {
89 public:
90 AbstractFieldTrialEnum(std::string key,
91 int default_value,
92 std::map<std::string, int> mapping);
93 ~AbstractFieldTrialEnum() override;
94 AbstractFieldTrialEnum(const AbstractFieldTrialEnum&);
95
96 protected:
97 bool Parse(absl::optional<std::string> str_value) override;
98
99 protected:
100 int value_;
101 std::map<std::string, int> enum_mapping_;
102 std::set<int> valid_values_;
103};
104
105// The FieldTrialEnum class can be used to quickly define a parser for a
106// specific enum. It handles values provided as integers and as strings if a
107// mapping is provided.
108template <typename T>
109class FieldTrialEnum : public AbstractFieldTrialEnum {
110 public:
111 FieldTrialEnum(std::string key,
112 T default_value,
113 std::map<std::string, T> mapping)
114 : AbstractFieldTrialEnum(key,
115 static_cast<int>(default_value),
116 ToIntMap(mapping)) {}
117 T Get() const { return static_cast<T>(value_); }
118 operator T() const { return Get(); }
119
120 private:
121 static std::map<std::string, int> ToIntMap(std::map<std::string, T> mapping) {
122 std::map<std::string, int> res;
123 for (const auto& it : mapping)
124 res[it.first] = static_cast<int>(it.second);
125 return res;
126 }
127};
128
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200129// This class uses the ParseTypedParameter function to implement an optional
Danil Chapovalov0a1d1892018-06-21 11:48:25 +0200130// parameter implementation that can default to absl::nullopt.
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200131template <typename T>
132class FieldTrialOptional : public FieldTrialParameterInterface {
133 public:
134 explicit FieldTrialOptional(std::string key)
135 : FieldTrialParameterInterface(key) {}
Danil Chapovalov0a1d1892018-06-21 11:48:25 +0200136 FieldTrialOptional(std::string key, absl::optional<T> default_value)
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200137 : FieldTrialParameterInterface(key), value_(default_value) {}
Danil Chapovalov0a1d1892018-06-21 11:48:25 +0200138 absl::optional<T> Get() const { return value_; }
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200139
140 protected:
Danil Chapovalov0a1d1892018-06-21 11:48:25 +0200141 bool Parse(absl::optional<std::string> str_value) override {
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200142 if (str_value) {
Danil Chapovalov0a1d1892018-06-21 11:48:25 +0200143 absl::optional<T> value = ParseTypedParameter<T>(*str_value);
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200144 if (!value.has_value())
145 return false;
146 value_ = value.value();
147 } else {
Danil Chapovalov0a1d1892018-06-21 11:48:25 +0200148 value_ = absl::nullopt;
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200149 }
150 return true;
151 }
152
153 private:
Danil Chapovalov0a1d1892018-06-21 11:48:25 +0200154 absl::optional<T> value_;
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200155};
156
157// Equivalent to a FieldTrialParameter<bool> in the case that both key and value
158// are present. If key is missing, evaluates to false. If key is present, but no
159// explicit value is provided, the flag evaluates to true.
160class FieldTrialFlag : public FieldTrialParameterInterface {
161 public:
162 explicit FieldTrialFlag(std::string key);
163 FieldTrialFlag(std::string key, bool default_value);
164 bool Get() const;
165
166 protected:
Danil Chapovalov0a1d1892018-06-21 11:48:25 +0200167 bool Parse(absl::optional<std::string> str_value) override;
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200168
169 private:
170 bool value_;
171};
172
173// Accepts true, false, else parsed with sscanf %i, true if != 0.
174extern template class FieldTrialParameter<bool>;
175// Interpreted using sscanf %lf.
176extern template class FieldTrialParameter<double>;
177// Interpreted using sscanf %i.
178extern template class FieldTrialParameter<int>;
179// Using the given value as is.
180extern template class FieldTrialParameter<std::string>;
181
182extern template class FieldTrialOptional<double>;
183extern template class FieldTrialOptional<int>;
184extern template class FieldTrialOptional<bool>;
185extern template class FieldTrialOptional<std::string>;
186
187} // namespace webrtc
188
189#endif // RTC_BASE_EXPERIMENTS_FIELD_TRIAL_PARSER_H_