webrtc/rtc_base/experiments/field_trial_parser.cc
Sebastian Jansson 9eb38866cd Adds field trial parser.
Bug: webrtc:9346
Change-Id: Ibd07a1753feaa40d4be4d465d61f55bc8a8a9325
Reviewed-on: https://webrtc-review.googlesource.com/80263
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23615}
2018-06-14 16:02:38 +00:00

134 lines
3.9 KiB
C++

/*
* 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 <algorithm>
#include <map>
#include <type_traits>
#include <utility>
#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<int>(pos);
}
} // namespace
FieldTrialParameterInterface::FieldTrialParameterInterface(std::string key)
: key_(key) {}
FieldTrialParameterInterface::~FieldTrialParameterInterface() = default;
std::string FieldTrialParameterInterface::Key() const {
return key_;
}
void ParseFieldTrial(
std::initializer_list<FieldTrialParameterInterface*> fields,
std::string trial_string) {
std::map<std::string, FieldTrialParameterInterface*> 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<std::string> 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<bool> ParseTypedParameter<bool>(std::string str) {
if (str == "true" || str == "1") {
return true;
} else if (str == "false" || str == "0") {
return false;
}
return rtc::nullopt;
}
template <>
rtc::Optional<double> ParseTypedParameter<double>(std::string str) {
double value;
if (sscanf(str.c_str(), "%lf", &value) == 1) {
return value;
} else {
return rtc::nullopt;
}
}
template <>
rtc::Optional<int> ParseTypedParameter<int>(std::string str) {
int value;
if (sscanf(str.c_str(), "%i", &value) == 1) {
return value;
} else {
return rtc::nullopt;
}
}
template <>
rtc::Optional<std::string> ParseTypedParameter<std::string>(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<std::string> str_value) {
// Only set the flag if there is no argument provided.
if (str_value) {
rtc::Optional<bool> opt_value = ParseTypedParameter<bool>(*str_value);
if (!opt_value)
return false;
value_ = *opt_value;
} else {
value_ = true;
}
return true;
}
template class FieldTrialParameter<bool>;
template class FieldTrialParameter<double>;
template class FieldTrialParameter<int>;
template class FieldTrialParameter<std::string>;
template class FieldTrialOptional<double>;
template class FieldTrialOptional<int>;
template class FieldTrialOptional<bool>;
template class FieldTrialOptional<std::string>;
} // namespace webrtc