1 /*
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 #include "rtc_base/experiments/field_trial_units.h"
11 
12 #include <stdio.h>
13 
14 #include <limits>
15 #include <string>
16 
17 #include "absl/types/optional.h"
18 
19 // Large enough to fit "seconds", the longest supported unit name.
20 #define RTC_TRIAL_UNIT_LENGTH_STR "7"
21 #define RTC_TRIAL_UNIT_SIZE 8
22 
23 namespace webrtc {
24 namespace {
25 
26 struct ValueWithUnit {
27   double value;
28   std::string unit;
29 };
30 
ParseValueWithUnit(std::string str)31 absl::optional<ValueWithUnit> ParseValueWithUnit(std::string str) {
32   if (str == "inf") {
33     return ValueWithUnit{std::numeric_limits<double>::infinity(), ""};
34   } else if (str == "-inf") {
35     return ValueWithUnit{-std::numeric_limits<double>::infinity(), ""};
36   } else {
37     double double_val;
38     char unit_char[RTC_TRIAL_UNIT_SIZE];
39     unit_char[0] = 0;
40     if (sscanf(str.c_str(), "%lf%" RTC_TRIAL_UNIT_LENGTH_STR "s", &double_val,
41                unit_char) >= 1) {
42       return ValueWithUnit{double_val, unit_char};
43     }
44   }
45   return absl::nullopt;
46 }
47 }  // namespace
48 
49 template <>
ParseTypedParameter(std::string str)50 absl::optional<DataRate> ParseTypedParameter<DataRate>(std::string str) {
51   absl::optional<ValueWithUnit> result = ParseValueWithUnit(str);
52   if (result) {
53     if (result->unit.empty() || result->unit == "kbps") {
54       return DataRate::KilobitsPerSec(result->value);
55     } else if (result->unit == "bps") {
56       return DataRate::BitsPerSec(result->value);
57     }
58   }
59   return absl::nullopt;
60 }
61 
62 template <>
ParseTypedParameter(std::string str)63 absl::optional<DataSize> ParseTypedParameter<DataSize>(std::string str) {
64   absl::optional<ValueWithUnit> result = ParseValueWithUnit(str);
65   if (result) {
66     if (result->unit.empty() || result->unit == "bytes")
67       return DataSize::Bytes(result->value);
68   }
69   return absl::nullopt;
70 }
71 
72 template <>
ParseTypedParameter(std::string str)73 absl::optional<TimeDelta> ParseTypedParameter<TimeDelta>(std::string str) {
74   absl::optional<ValueWithUnit> result = ParseValueWithUnit(str);
75   if (result) {
76     if (result->unit == "s" || result->unit == "seconds") {
77       return TimeDelta::Seconds(result->value);
78     } else if (result->unit == "us") {
79       return TimeDelta::Micros(result->value);
80     } else if (result->unit.empty() || result->unit == "ms") {
81       return TimeDelta::Millis(result->value);
82     }
83   }
84   return absl::nullopt;
85 }
86 
87 template <>
88 absl::optional<absl::optional<DataRate>>
ParseTypedParameter(std::string str)89 ParseTypedParameter<absl::optional<DataRate>>(std::string str) {
90   return ParseOptionalParameter<DataRate>(str);
91 }
92 template <>
93 absl::optional<absl::optional<DataSize>>
ParseTypedParameter(std::string str)94 ParseTypedParameter<absl::optional<DataSize>>(std::string str) {
95   return ParseOptionalParameter<DataSize>(str);
96 }
97 template <>
98 absl::optional<absl::optional<TimeDelta>>
ParseTypedParameter(std::string str)99 ParseTypedParameter<absl::optional<TimeDelta>>(std::string str) {
100   return ParseOptionalParameter<TimeDelta>(str);
101 }
102 
103 template class FieldTrialParameter<DataRate>;
104 template class FieldTrialParameter<DataSize>;
105 template class FieldTrialParameter<TimeDelta>;
106 
107 template class FieldTrialConstrained<DataRate>;
108 template class FieldTrialConstrained<DataSize>;
109 template class FieldTrialConstrained<TimeDelta>;
110 
111 template class FieldTrialOptional<DataRate>;
112 template class FieldTrialOptional<DataSize>;
113 template class FieldTrialOptional<TimeDelta>;
114 }  // namespace webrtc
115