blob: ff00b90f36ef227696ae24bbc1b11400c28867a4 [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>
15#include <string>
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020016#include "absl/types/optional.h"
Sebastian Jansson9eb38862018-06-14 16:47:42 +020017
18// Field trial parser functionality. Provides funcitonality to parse field trial
19// argument strings in key:value format. Each parameter is described using
20// key:value, parameters are separated with a ,. Values can't include the comma
21// character, since there's no quote facility. For most types, white space is
22// ignored. Parameters are declared with a given type for which an
23// implementation of ParseTypedParameter should be provided. The
24// ParseTypedParameter implementation is given whatever is between the : and the
25// ,. FieldTrialOptional will use nullopt if the key is provided without :.
26
27// Example string: "my_optional,my_int:3,my_string:hello"
28
29// For further description of usage and behavior, see the examples in the unit
30// tests.
31
32namespace webrtc {
33class FieldTrialParameterInterface {
34 public:
35 virtual ~FieldTrialParameterInterface();
36
37 protected:
38 explicit FieldTrialParameterInterface(std::string key);
39 friend void ParseFieldTrial(
40 std::initializer_list<FieldTrialParameterInterface*> fields,
41 std::string raw_string);
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020042 virtual bool Parse(absl::optional<std::string> str_value) = 0;
Sebastian Jansson9eb38862018-06-14 16:47:42 +020043 std::string Key() const;
44
45 private:
46 const std::string key_;
47};
48
49// ParseFieldTrial function parses the given string and fills the given fields
50// with extrated values if available.
51void ParseFieldTrial(
52 std::initializer_list<FieldTrialParameterInterface*> fields,
53 std::string raw_string);
54
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020055// Specialize this in code file for custom types. Should return absl::nullopt if
Sebastian Jansson9eb38862018-06-14 16:47:42 +020056// the given string cannot be properly parsed.
57template <typename T>
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020058absl::optional<T> ParseTypedParameter(std::string);
Sebastian Jansson9eb38862018-06-14 16:47:42 +020059
60// This class uses the ParseTypedParameter function to implement a parameter
61// implementation with an enforced default value.
62template <typename T>
63class FieldTrialParameter : public FieldTrialParameterInterface {
64 public:
65 FieldTrialParameter(std::string key, T default_value)
66 : FieldTrialParameterInterface(key), value_(default_value) {}
67 T Get() const { return value_; }
68 operator T() const { return Get(); }
69
70 protected:
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020071 bool Parse(absl::optional<std::string> str_value) override {
Sebastian Jansson9eb38862018-06-14 16:47:42 +020072 if (str_value) {
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020073 absl::optional<T> value = ParseTypedParameter<T>(*str_value);
Sebastian Jansson9eb38862018-06-14 16:47:42 +020074 if (value.has_value()) {
75 value_ = value.value();
76 return true;
77 }
78 }
79 return false;
80 }
81
82 private:
83 T value_;
84};
85
86// This class uses the ParseTypedParameter function to implement an optional
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020087// parameter implementation that can default to absl::nullopt.
Sebastian Jansson9eb38862018-06-14 16:47:42 +020088template <typename T>
89class FieldTrialOptional : public FieldTrialParameterInterface {
90 public:
91 explicit FieldTrialOptional(std::string key)
92 : FieldTrialParameterInterface(key) {}
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020093 FieldTrialOptional(std::string key, absl::optional<T> default_value)
Sebastian Jansson9eb38862018-06-14 16:47:42 +020094 : FieldTrialParameterInterface(key), value_(default_value) {}
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020095 absl::optional<T> Get() const { return value_; }
Sebastian Jansson9eb38862018-06-14 16:47:42 +020096
97 protected:
Danil Chapovalov0a1d1892018-06-21 11:48:25 +020098 bool Parse(absl::optional<std::string> str_value) override {
Sebastian Jansson9eb38862018-06-14 16:47:42 +020099 if (str_value) {
Danil Chapovalov0a1d1892018-06-21 11:48:25 +0200100 absl::optional<T> value = ParseTypedParameter<T>(*str_value);
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200101 if (!value.has_value())
102 return false;
103 value_ = value.value();
104 } else {
Danil Chapovalov0a1d1892018-06-21 11:48:25 +0200105 value_ = absl::nullopt;
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200106 }
107 return true;
108 }
109
110 private:
Danil Chapovalov0a1d1892018-06-21 11:48:25 +0200111 absl::optional<T> value_;
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200112};
113
114// Equivalent to a FieldTrialParameter<bool> in the case that both key and value
115// are present. If key is missing, evaluates to false. If key is present, but no
116// explicit value is provided, the flag evaluates to true.
117class FieldTrialFlag : public FieldTrialParameterInterface {
118 public:
119 explicit FieldTrialFlag(std::string key);
120 FieldTrialFlag(std::string key, bool default_value);
121 bool Get() const;
122
123 protected:
Danil Chapovalov0a1d1892018-06-21 11:48:25 +0200124 bool Parse(absl::optional<std::string> str_value) override;
Sebastian Jansson9eb38862018-06-14 16:47:42 +0200125
126 private:
127 bool value_;
128};
129
130// Accepts true, false, else parsed with sscanf %i, true if != 0.
131extern template class FieldTrialParameter<bool>;
132// Interpreted using sscanf %lf.
133extern template class FieldTrialParameter<double>;
134// Interpreted using sscanf %i.
135extern template class FieldTrialParameter<int>;
136// Using the given value as is.
137extern template class FieldTrialParameter<std::string>;
138
139extern template class FieldTrialOptional<double>;
140extern template class FieldTrialOptional<int>;
141extern template class FieldTrialOptional<bool>;
142extern template class FieldTrialOptional<std::string>;
143
144} // namespace webrtc
145
146#endif // RTC_BASE_EXPERIMENTS_FIELD_TRIAL_PARSER_H_