blob: 24058b50bd23bb45656383ccfd67223b5a9b3fb9 [file] [log] [blame]
Sebastian Jansson55251c32019-08-08 11:14:51 +02001/*
2 * Copyright (c) 2019 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/struct_parameters_parser.h"
11
Sebastian Jansson55251c32019-08-08 11:14:51 +020012#include "rtc_base/logging.h"
Sebastian Jansson55251c32019-08-08 11:14:51 +020013
14namespace webrtc {
Sebastian Jansson55251c32019-08-08 11:14:51 +020015namespace {
16size_t FindOrEnd(absl::string_view str, size_t start, char delimiter) {
17 size_t pos = str.find(delimiter, start);
18 pos = (pos == std::string::npos) ? str.length() : pos;
19 return pos;
20}
21} // namespace
22
Sebastian Jansson0ee80082019-08-14 13:16:26 +020023namespace struct_parser_impl {
24namespace {
25inline void StringEncode(std::string* target, bool val) {
26 *target += rtc::ToString(val);
27}
28inline void StringEncode(std::string* target, double val) {
29 *target += rtc::ToString(val);
30}
31inline void StringEncode(std::string* target, int val) {
32 *target += rtc::ToString(val);
33}
34inline void StringEncode(std::string* target, DataRate val) {
35 *target += webrtc::ToString(val);
36}
37inline void StringEncode(std::string* target, DataSize val) {
38 *target += webrtc::ToString(val);
39}
40inline void StringEncode(std::string* target, TimeDelta val) {
41 *target += webrtc::ToString(val);
42}
43
44template <typename T>
45inline void StringEncode(std::string* sb, absl::optional<T> val) {
46 if (val)
47 StringEncode(sb, *val);
48}
49} // namespace
50template <typename T>
51bool TypedParser<T>::Parse(absl::string_view src, void* target) {
52 auto parsed = ParseTypedParameter<T>(std::string(src));
53 if (parsed.has_value())
54 *reinterpret_cast<T*>(target) = *parsed;
55 return parsed.has_value();
56}
57template <typename T>
58void TypedParser<T>::Encode(const void* src, std::string* target) {
59 StringEncode(target, *reinterpret_cast<const T*>(src));
60}
61
62template class TypedParser<bool>;
63template class TypedParser<double>;
64template class TypedParser<int>;
65template class TypedParser<absl::optional<double>>;
66template class TypedParser<absl::optional<int>>;
67
68template class TypedParser<DataRate>;
69template class TypedParser<DataSize>;
70template class TypedParser<TimeDelta>;
71template class TypedParser<absl::optional<DataRate>>;
72template class TypedParser<absl::optional<DataSize>>;
73template class TypedParser<absl::optional<TimeDelta>>;
74} // namespace struct_parser_impl
75
76StructParametersParser::StructParametersParser(
77 std::vector<struct_parser_impl::MemberParameter> members)
78 : members_(std::move(members)) {}
79
80void StructParametersParser::Parse(absl::string_view src) {
Sebastian Jansson55251c32019-08-08 11:14:51 +020081 size_t i = 0;
Sebastian Jansson0ee80082019-08-14 13:16:26 +020082 while (i < src.length()) {
83 size_t val_end = FindOrEnd(src, i, ',');
84 size_t colon_pos = FindOrEnd(src, i, ':');
Sebastian Jansson55251c32019-08-08 11:14:51 +020085 size_t key_end = std::min(val_end, colon_pos);
86 size_t val_begin = key_end + 1u;
Sebastian Jansson0ee80082019-08-14 13:16:26 +020087 absl::string_view key(src.substr(i, key_end - i));
Sebastian Jansson55251c32019-08-08 11:14:51 +020088 absl::string_view opt_value;
89 if (val_end >= val_begin)
Sebastian Jansson0ee80082019-08-14 13:16:26 +020090 opt_value = src.substr(val_begin, val_end - val_begin);
Sebastian Jansson55251c32019-08-08 11:14:51 +020091 i = val_end + 1u;
Sebastian Jansson0ee80082019-08-14 13:16:26 +020092 bool found = false;
93 for (auto& member : members_) {
94 if (key == member.key) {
95 found = true;
96 if (!member.parser.parse(opt_value, member.member_ptr)) {
97 RTC_LOG(LS_WARNING) << "Failed to read field with key: '" << key
98 << "' in trial: \"" << src << "\"";
99 }
100 break;
Sebastian Jansson55251c32019-08-08 11:14:51 +0200101 }
Sebastian Jansson0ee80082019-08-14 13:16:26 +0200102 }
103 if (!found) {
Sebastian Jansson55251c32019-08-08 11:14:51 +0200104 RTC_LOG(LS_INFO) << "No field with key: '" << key
Sebastian Jansson0ee80082019-08-14 13:16:26 +0200105 << "' (found in trial: \"" << src << "\")";
Sebastian Jansson55251c32019-08-08 11:14:51 +0200106 }
107 }
108}
109
Sebastian Jansson0ee80082019-08-14 13:16:26 +0200110std::string StructParametersParser::Encode() const {
111 std::string res;
Sebastian Jansson55251c32019-08-08 11:14:51 +0200112 bool first = true;
Sebastian Jansson0ee80082019-08-14 13:16:26 +0200113 for (const auto& member : members_) {
Sebastian Jansson55251c32019-08-08 11:14:51 +0200114 if (!first)
Sebastian Jansson0ee80082019-08-14 13:16:26 +0200115 res += ",";
116 res += member.key;
117 res += ":";
118 member.parser.encode(member.member_ptr, &res);
Sebastian Jansson55251c32019-08-08 11:14:51 +0200119 first = false;
120 }
Sebastian Jansson0ee80082019-08-14 13:16:26 +0200121 return res;
Sebastian Jansson55251c32019-08-08 11:14:51 +0200122}
Sebastian Jansson55251c32019-08-08 11:14:51 +0200123
124} // namespace webrtc