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