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)31absl::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)50absl::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)63absl::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)73absl::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)89ParseTypedParameter<absl::optional<DataRate>>(std::string str) { 90 return ParseOptionalParameter<DataRate>(str); 91 } 92 template <> 93 absl::optional<absl::optional<DataSize>> ParseTypedParameter(std::string str)94ParseTypedParameter<absl::optional<DataSize>>(std::string str) { 95 return ParseOptionalParameter<DataSize>(str); 96 } 97 template <> 98 absl::optional<absl::optional<TimeDelta>> ParseTypedParameter(std::string str)99ParseTypedParameter<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