/* * Copyright 2018 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "rtc_base/experiments/field_trial_parser.h" #include #include #include #include #include "rtc_base/logging.h" namespace webrtc { namespace { int FindOrEnd(std::string str, size_t start, char delimiter) { size_t pos = str.find(delimiter, start); pos = (pos == std::string::npos) ? str.length() : pos; return static_cast(pos); } } // namespace FieldTrialParameterInterface::FieldTrialParameterInterface(std::string key) : key_(key) {} FieldTrialParameterInterface::~FieldTrialParameterInterface() = default; std::string FieldTrialParameterInterface::Key() const { return key_; } void ParseFieldTrial( std::initializer_list fields, std::string trial_string) { std::map field_map; for (FieldTrialParameterInterface* field : fields) { field_map[field->Key()] = field; } size_t i = 0; while (i < trial_string.length()) { int val_end = FindOrEnd(trial_string, i, ','); int colon_pos = FindOrEnd(trial_string, i, ':'); int key_end = std::min(val_end, colon_pos); int val_begin = key_end + 1; std::string key = trial_string.substr(i, key_end - i); rtc::Optional opt_value; if (val_end >= val_begin) opt_value = trial_string.substr(val_begin, val_end - val_begin); i = val_end + 1; auto field = field_map.find(key); if (field != field_map.end()) { if (!field->second->Parse(std::move(opt_value))) { RTC_LOG(LS_WARNING) << "Failed to read field with key: '" << key << "' in trial: \"" << trial_string << "\""; } } else { RTC_LOG(LS_INFO) << "No field with key: '" << key << "' (found in trial: \"" << trial_string << "\")"; } } } template <> rtc::Optional ParseTypedParameter(std::string str) { if (str == "true" || str == "1") { return true; } else if (str == "false" || str == "0") { return false; } return rtc::nullopt; } template <> rtc::Optional ParseTypedParameter(std::string str) { double value; if (sscanf(str.c_str(), "%lf", &value) == 1) { return value; } else { return rtc::nullopt; } } template <> rtc::Optional ParseTypedParameter(std::string str) { int value; if (sscanf(str.c_str(), "%i", &value) == 1) { return value; } else { return rtc::nullopt; } } template <> rtc::Optional ParseTypedParameter(std::string str) { return std::move(str); } FieldTrialFlag::FieldTrialFlag(std::string key) : FieldTrialFlag(key, false) {} FieldTrialFlag::FieldTrialFlag(std::string key, bool default_value) : FieldTrialParameterInterface(key), value_(default_value) {} bool FieldTrialFlag::Get() const { return value_; } bool FieldTrialFlag::Parse(rtc::Optional str_value) { // Only set the flag if there is no argument provided. if (str_value) { rtc::Optional opt_value = ParseTypedParameter(*str_value); if (!opt_value) return false; value_ = *opt_value; } else { value_ = true; } return true; } template class FieldTrialParameter; template class FieldTrialParameter; template class FieldTrialParameter; template class FieldTrialParameter; template class FieldTrialOptional; template class FieldTrialOptional; template class FieldTrialOptional; template class FieldTrialOptional; } // namespace webrtc