Move RTCStatsMember+Interface to a separate file.
Pure move CL. Avoids circular dependency in a future CL.
Bug: webrtc:15164
Change-Id: Ide423be95db30b7f3cfaea946e18e12980175f2b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/333920
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41496}
diff --git a/api/BUILD.gn b/api/BUILD.gn
index 341b39c..f09b353 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -773,6 +773,7 @@
sources = [
"stats/rtc_stats.h",
"stats/rtc_stats_collector_callback.h",
+ "stats/rtc_stats_member.h",
"stats/rtc_stats_report.h",
"stats/rtcstats_objects.h",
]
diff --git a/api/stats/rtc_stats.h b/api/stats/rtc_stats.h
index 6cc39a3..d71b10d 100644
--- a/api/stats/rtc_stats.h
+++ b/api/stats/rtc_stats.h
@@ -20,7 +20,7 @@
#include <utility>
#include <vector>
-#include "absl/types/optional.h"
+#include "api/stats/rtc_stats_member.h"
#include "api/units/timestamp.h"
#include "rtc_base/checks.h"
#include "rtc_base/system/rtc_export.h"
@@ -28,8 +28,6 @@
namespace webrtc {
-class RTCStatsMemberInterface;
-
// Abstract base class for RTCStats-derived dictionaries, see
// https://w3c.github.io/webrtc-stats/.
//
@@ -206,185 +204,6 @@
return parent_class::MembersOfThisObjectAndAncestors(0); \
}
-// Interface for `RTCStats` members, which have a name and a value of a type
-// defined in a subclass. Only the types listed in `Type` are supported, these
-// are implemented by `RTCStatsMember<T>`. The value of a member may be
-// undefined, the value can only be read if `is_defined`.
-class RTCStatsMemberInterface {
- public:
- // Member value types.
- enum Type {
- kBool, // bool
- kInt32, // int32_t
- kUint32, // uint32_t
- kInt64, // int64_t
- kUint64, // uint64_t
- kDouble, // double
- kString, // std::string
-
- kSequenceBool, // std::vector<bool>
- kSequenceInt32, // std::vector<int32_t>
- kSequenceUint32, // std::vector<uint32_t>
- kSequenceInt64, // std::vector<int64_t>
- kSequenceUint64, // std::vector<uint64_t>
- kSequenceDouble, // std::vector<double>
- kSequenceString, // std::vector<std::string>
-
- kMapStringUint64, // std::map<std::string, uint64_t>
- kMapStringDouble, // std::map<std::string, double>
- };
-
- virtual ~RTCStatsMemberInterface() {}
-
- const char* name() const { return name_; }
- virtual Type type() const = 0;
- virtual bool is_sequence() const = 0;
- virtual bool is_string() const = 0;
- virtual bool is_defined() const = 0;
- // Type and value comparator. The names are not compared. These operators are
- // exposed for testing.
- bool operator==(const RTCStatsMemberInterface& other) const {
- return IsEqual(other);
- }
- bool operator!=(const RTCStatsMemberInterface& other) const {
- return !(*this == other);
- }
- virtual std::string ValueToString() const = 0;
- // This is the same as ValueToString except for kInt64 and kUint64 types,
- // where the value is represented as a double instead of as an integer.
- // Since JSON stores numbers as floating point numbers, very large integers
- // cannot be accurately represented, so we prefer to display them as doubles
- // instead.
- virtual std::string ValueToJson() const = 0;
-
- template <typename T>
- const T& cast_to() const {
- RTC_DCHECK_EQ(type(), T::StaticType());
- return static_cast<const T&>(*this);
- }
-
- protected:
- explicit RTCStatsMemberInterface(const char* name) : name_(name) {}
-
- virtual bool IsEqual(const RTCStatsMemberInterface& other) const = 0;
-
- const char* const name_;
-};
-
-// Template implementation of `RTCStatsMemberInterface`.
-// The supported types are the ones described by
-// `RTCStatsMemberInterface::Type`.
-template <typename T>
-class RTCStatsMember : public RTCStatsMemberInterface {
- public:
- explicit RTCStatsMember(const char* name)
- : RTCStatsMemberInterface(name), value_() {}
- RTCStatsMember(const char* name, const T& value)
- : RTCStatsMemberInterface(name), value_(value) {}
- RTCStatsMember(const char* name, T&& value)
- : RTCStatsMemberInterface(name), value_(std::move(value)) {}
- explicit RTCStatsMember(const RTCStatsMember<T>& other)
- : RTCStatsMemberInterface(other.name_), value_(other.value_) {}
- explicit RTCStatsMember(RTCStatsMember<T>&& other)
- : RTCStatsMemberInterface(other.name_), value_(std::move(other.value_)) {}
-
- static Type StaticType();
- Type type() const override { return StaticType(); }
- bool is_sequence() const override;
- bool is_string() const override;
- bool is_defined() const override { return value_.has_value(); }
- std::string ValueToString() const override;
- std::string ValueToJson() const override;
-
- template <typename U>
- inline T ValueOrDefault(U default_value) const {
- return value_.value_or(default_value);
- }
-
- // Assignment operators.
- T& operator=(const T& value) {
- value_ = value;
- return value_.value();
- }
- T& operator=(const T&& value) {
- value_ = std::move(value);
- return value_.value();
- }
-
- // Getter methods that look the same as absl::optional<T>. Please prefer these
- // in order to unblock replacing RTCStatsMember<T> with absl::optional<T> in
- // the future (https://crbug.com/webrtc/15164).
- bool has_value() const { return value_.has_value(); }
- const T& value() const { return value_.value(); }
- T& value() { return value_.value(); }
- T& operator*() {
- RTC_DCHECK(value_);
- return *value_;
- }
- const T& operator*() const {
- RTC_DCHECK(value_);
- return *value_;
- }
- T* operator->() {
- RTC_DCHECK(value_);
- return &(*value_);
- }
- const T* operator->() const {
- RTC_DCHECK(value_);
- return &(*value_);
- }
-
- protected:
- bool IsEqual(const RTCStatsMemberInterface& other) const override {
- if (type() != other.type())
- return false;
- const RTCStatsMember<T>& other_t =
- static_cast<const RTCStatsMember<T>&>(other);
- return value_ == other_t.value_;
- }
-
- private:
- absl::optional<T> value_;
-};
-
-namespace rtc_stats_internal {
-
-typedef std::map<std::string, uint64_t> MapStringUint64;
-typedef std::map<std::string, double> MapStringDouble;
-
-} // namespace rtc_stats_internal
-
-#define WEBRTC_DECLARE_RTCSTATSMEMBER(T) \
- template <> \
- RTC_EXPORT RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType(); \
- template <> \
- RTC_EXPORT bool RTCStatsMember<T>::is_sequence() const; \
- template <> \
- RTC_EXPORT bool RTCStatsMember<T>::is_string() const; \
- template <> \
- RTC_EXPORT std::string RTCStatsMember<T>::ValueToString() const; \
- template <> \
- RTC_EXPORT std::string RTCStatsMember<T>::ValueToJson() const; \
- extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) \
- RTCStatsMember<T>
-
-WEBRTC_DECLARE_RTCSTATSMEMBER(bool);
-WEBRTC_DECLARE_RTCSTATSMEMBER(int32_t);
-WEBRTC_DECLARE_RTCSTATSMEMBER(uint32_t);
-WEBRTC_DECLARE_RTCSTATSMEMBER(int64_t);
-WEBRTC_DECLARE_RTCSTATSMEMBER(uint64_t);
-WEBRTC_DECLARE_RTCSTATSMEMBER(double);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::string);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<bool>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int32_t>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint32_t>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int64_t>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint64_t>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<double>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<std::string>);
-WEBRTC_DECLARE_RTCSTATSMEMBER(rtc_stats_internal::MapStringUint64);
-WEBRTC_DECLARE_RTCSTATSMEMBER(rtc_stats_internal::MapStringDouble);
-
} // namespace webrtc
#endif // API_STATS_RTC_STATS_H_
diff --git a/api/stats/rtc_stats_member.h b/api/stats/rtc_stats_member.h
new file mode 100644
index 0000000..09e3836
--- /dev/null
+++ b/api/stats/rtc_stats_member.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#ifndef API_STATS_RTC_STATS_MEMBER_H_
+#define API_STATS_RTC_STATS_MEMBER_H_
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/system/rtc_export.h"
+#include "rtc_base/system/rtc_export_template.h"
+
+namespace webrtc {
+
+// Interface for `RTCStats` members, which have a name and a value of a type
+// defined in a subclass. Only the types listed in `Type` are supported, these
+// are implemented by `RTCStatsMember<T>`. The value of a member may be
+// undefined, the value can only be read if `is_defined`.
+class RTCStatsMemberInterface {
+ public:
+ // Member value types.
+ enum Type {
+ kBool, // bool
+ kInt32, // int32_t
+ kUint32, // uint32_t
+ kInt64, // int64_t
+ kUint64, // uint64_t
+ kDouble, // double
+ kString, // std::string
+
+ kSequenceBool, // std::vector<bool>
+ kSequenceInt32, // std::vector<int32_t>
+ kSequenceUint32, // std::vector<uint32_t>
+ kSequenceInt64, // std::vector<int64_t>
+ kSequenceUint64, // std::vector<uint64_t>
+ kSequenceDouble, // std::vector<double>
+ kSequenceString, // std::vector<std::string>
+
+ kMapStringUint64, // std::map<std::string, uint64_t>
+ kMapStringDouble, // std::map<std::string, double>
+ };
+
+ virtual ~RTCStatsMemberInterface() {}
+
+ const char* name() const { return name_; }
+ virtual Type type() const = 0;
+ virtual bool is_sequence() const = 0;
+ virtual bool is_string() const = 0;
+ virtual bool is_defined() const = 0;
+ // Type and value comparator. The names are not compared. These operators are
+ // exposed for testing.
+ bool operator==(const RTCStatsMemberInterface& other) const {
+ return IsEqual(other);
+ }
+ bool operator!=(const RTCStatsMemberInterface& other) const {
+ return !(*this == other);
+ }
+ virtual std::string ValueToString() const = 0;
+ // This is the same as ValueToString except for kInt64 and kUint64 types,
+ // where the value is represented as a double instead of as an integer.
+ // Since JSON stores numbers as floating point numbers, very large integers
+ // cannot be accurately represented, so we prefer to display them as doubles
+ // instead.
+ virtual std::string ValueToJson() const = 0;
+
+ template <typename T>
+ const T& cast_to() const {
+ RTC_DCHECK_EQ(type(), T::StaticType());
+ return static_cast<const T&>(*this);
+ }
+
+ protected:
+ explicit RTCStatsMemberInterface(const char* name) : name_(name) {}
+
+ virtual bool IsEqual(const RTCStatsMemberInterface& other) const = 0;
+
+ const char* const name_;
+};
+
+// Template implementation of `RTCStatsMemberInterface`.
+// The supported types are the ones described by
+// `RTCStatsMemberInterface::Type`.
+template <typename T>
+class RTCStatsMember : public RTCStatsMemberInterface {
+ public:
+ explicit RTCStatsMember(const char* name)
+ : RTCStatsMemberInterface(name), value_() {}
+ RTCStatsMember(const char* name, const T& value)
+ : RTCStatsMemberInterface(name), value_(value) {}
+ RTCStatsMember(const char* name, T&& value)
+ : RTCStatsMemberInterface(name), value_(std::move(value)) {}
+ explicit RTCStatsMember(const RTCStatsMember<T>& other)
+ : RTCStatsMemberInterface(other.name_), value_(other.value_) {}
+ explicit RTCStatsMember(RTCStatsMember<T>&& other)
+ : RTCStatsMemberInterface(other.name_), value_(std::move(other.value_)) {}
+
+ static Type StaticType();
+ Type type() const override { return StaticType(); }
+ bool is_sequence() const override;
+ bool is_string() const override;
+ bool is_defined() const override { return value_.has_value(); }
+ std::string ValueToString() const override;
+ std::string ValueToJson() const override;
+
+ template <typename U>
+ inline T ValueOrDefault(U default_value) const {
+ return value_.value_or(default_value);
+ }
+
+ // Assignment operators.
+ T& operator=(const T& value) {
+ value_ = value;
+ return value_.value();
+ }
+ T& operator=(const T&& value) {
+ value_ = std::move(value);
+ return value_.value();
+ }
+
+ // Getter methods that look the same as absl::optional<T>. Please prefer these
+ // in order to unblock replacing RTCStatsMember<T> with absl::optional<T> in
+ // the future (https://crbug.com/webrtc/15164).
+ bool has_value() const { return value_.has_value(); }
+ const T& value() const { return value_.value(); }
+ T& value() { return value_.value(); }
+ T& operator*() {
+ RTC_DCHECK(value_);
+ return *value_;
+ }
+ const T& operator*() const {
+ RTC_DCHECK(value_);
+ return *value_;
+ }
+ T* operator->() {
+ RTC_DCHECK(value_);
+ return &(*value_);
+ }
+ const T* operator->() const {
+ RTC_DCHECK(value_);
+ return &(*value_);
+ }
+
+ protected:
+ bool IsEqual(const RTCStatsMemberInterface& other) const override {
+ if (type() != other.type())
+ return false;
+ const RTCStatsMember<T>& other_t =
+ static_cast<const RTCStatsMember<T>&>(other);
+ return value_ == other_t.value_;
+ }
+
+ private:
+ absl::optional<T> value_;
+};
+
+namespace rtc_stats_internal {
+
+typedef std::map<std::string, uint64_t> MapStringUint64;
+typedef std::map<std::string, double> MapStringDouble;
+
+} // namespace rtc_stats_internal
+
+#define WEBRTC_DECLARE_RTCSTATSMEMBER(T) \
+ template <> \
+ RTC_EXPORT RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType(); \
+ template <> \
+ RTC_EXPORT bool RTCStatsMember<T>::is_sequence() const; \
+ template <> \
+ RTC_EXPORT bool RTCStatsMember<T>::is_string() const; \
+ template <> \
+ RTC_EXPORT std::string RTCStatsMember<T>::ValueToString() const; \
+ template <> \
+ RTC_EXPORT std::string RTCStatsMember<T>::ValueToJson() const; \
+ extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT) \
+ RTCStatsMember<T>
+
+WEBRTC_DECLARE_RTCSTATSMEMBER(bool);
+WEBRTC_DECLARE_RTCSTATSMEMBER(int32_t);
+WEBRTC_DECLARE_RTCSTATSMEMBER(uint32_t);
+WEBRTC_DECLARE_RTCSTATSMEMBER(int64_t);
+WEBRTC_DECLARE_RTCSTATSMEMBER(uint64_t);
+WEBRTC_DECLARE_RTCSTATSMEMBER(double);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::string);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<bool>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int32_t>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint32_t>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int64_t>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint64_t>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<double>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<std::string>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(rtc_stats_internal::MapStringUint64);
+WEBRTC_DECLARE_RTCSTATSMEMBER(rtc_stats_internal::MapStringDouble);
+
+} // namespace webrtc
+
+#endif // API_STATS_RTC_STATS_MEMBER_H_
diff --git a/stats/BUILD.gn b/stats/BUILD.gn
index b2a0c20..5890149 100644
--- a/stats/BUILD.gn
+++ b/stats/BUILD.gn
@@ -17,6 +17,7 @@
cflags = []
sources = [
"rtc_stats.cc",
+ "rtc_stats_member.cc",
"rtc_stats_report.cc",
"rtcstats_objects.cc",
]
diff --git a/stats/rtc_stats.cc b/stats/rtc_stats.cc
index 25bde28..21e5d05f 100644
--- a/stats/rtc_stats.cc
+++ b/stats/rtc_stats.cc
@@ -12,112 +12,10 @@
#include <cstdio>
-#include "rtc_base/arraysize.h"
-#include "rtc_base/string_encode.h"
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
-namespace {
-
-// Produces "[a,b,c]". Works for non-vector `RTCStatsMemberInterface::Type`
-// types.
-template <typename T>
-std::string VectorToString(const std::vector<T>& vector) {
- rtc::StringBuilder sb;
- sb << "[";
- const char* separator = "";
- for (const T& element : vector) {
- sb << separator << rtc::ToString(element);
- separator = ",";
- }
- sb << "]";
- return sb.Release();
-}
-
-// This overload is required because std::vector<bool> range loops don't
-// return references but objects, causing -Wrange-loop-analysis diagnostics.
-std::string VectorToString(const std::vector<bool>& vector) {
- rtc::StringBuilder sb;
- sb << "[";
- const char* separator = "";
- for (bool element : vector) {
- sb << separator << rtc::ToString(element);
- separator = ",";
- }
- sb << "]";
- return sb.Release();
-}
-
-// Produces "[\"a\",\"b\",\"c\"]". Works for vectors of both const char* and
-// std::string element types.
-template <typename T>
-std::string VectorOfStringsToString(const std::vector<T>& strings) {
- rtc::StringBuilder sb;
- sb << "[";
- const char* separator = "";
- for (const T& element : strings) {
- sb << separator << "\"" << rtc::ToString(element) << "\"";
- separator = ",";
- }
- sb << "]";
- return sb.Release();
-}
-
-template <typename T>
-std::string MapToString(const std::map<std::string, T>& map) {
- rtc::StringBuilder sb;
- sb << "{";
- const char* separator = "";
- for (const auto& element : map) {
- sb << separator << rtc::ToString(element.first) << ":"
- << rtc::ToString(element.second);
- separator = ",";
- }
- sb << "}";
- return sb.Release();
-}
-
-template <typename T>
-std::string ToStringAsDouble(const T value) {
- // JSON represents numbers as floating point numbers with about 15 decimal
- // digits of precision.
- char buf[32];
- const int len = std::snprintf(&buf[0], arraysize(buf), "%.16g",
- static_cast<double>(value));
- RTC_DCHECK_LE(len, arraysize(buf));
- return std::string(&buf[0], len);
-}
-
-template <typename T>
-std::string VectorToStringAsDouble(const std::vector<T>& vector) {
- rtc::StringBuilder sb;
- sb << "[";
- const char* separator = "";
- for (const T& element : vector) {
- sb << separator << ToStringAsDouble<T>(element);
- separator = ",";
- }
- sb << "]";
- return sb.Release();
-}
-
-template <typename T>
-std::string MapToStringAsDouble(const std::map<std::string, T>& map) {
- rtc::StringBuilder sb;
- sb << "{";
- const char* separator = "";
- for (const auto& element : map) {
- sb << separator << "\"" << rtc::ToString(element.first)
- << "\":" << ToStringAsDouble(element.second);
- separator = ",";
- }
- sb << "}";
- return sb.Release();
-}
-
-} // namespace
-
bool RTCStats::operator==(const RTCStats& other) const {
if (type() != other.type() || id() != other.id())
return false;
@@ -172,126 +70,4 @@
return members;
}
-#define WEBRTC_DEFINE_RTCSTATSMEMBER(T, type, is_seq, is_str, to_str, to_json) \
- template <> \
- RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType() { \
- return type; \
- } \
- template <> \
- bool RTCStatsMember<T>::is_sequence() const { \
- return is_seq; \
- } \
- template <> \
- bool RTCStatsMember<T>::is_string() const { \
- return is_str; \
- } \
- template <> \
- std::string RTCStatsMember<T>::ValueToString() const { \
- RTC_DCHECK(value_.has_value()); \
- return to_str; \
- } \
- template <> \
- std::string RTCStatsMember<T>::ValueToJson() const { \
- RTC_DCHECK(value_.has_value()); \
- return to_json; \
- } \
- template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT) RTCStatsMember<T>
-
-WEBRTC_DEFINE_RTCSTATSMEMBER(bool,
- kBool,
- false,
- false,
- rtc::ToString(*value_),
- rtc::ToString(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(int32_t,
- kInt32,
- false,
- false,
- rtc::ToString(*value_),
- rtc::ToString(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(uint32_t,
- kUint32,
- false,
- false,
- rtc::ToString(*value_),
- rtc::ToString(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(int64_t,
- kInt64,
- false,
- false,
- rtc::ToString(*value_),
- ToStringAsDouble(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(uint64_t,
- kUint64,
- false,
- false,
- rtc::ToString(*value_),
- ToStringAsDouble(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(double,
- kDouble,
- false,
- false,
- rtc::ToString(*value_),
- ToStringAsDouble(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::string,
- kString,
- false,
- true,
- *value_,
- *value_);
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<bool>,
- kSequenceBool,
- true,
- false,
- VectorToString(*value_),
- VectorToString(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int32_t>,
- kSequenceInt32,
- true,
- false,
- VectorToString(*value_),
- VectorToString(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint32_t>,
- kSequenceUint32,
- true,
- false,
- VectorToString(*value_),
- VectorToString(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int64_t>,
- kSequenceInt64,
- true,
- false,
- VectorToString(*value_),
- VectorToStringAsDouble(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint64_t>,
- kSequenceUint64,
- true,
- false,
- VectorToString(*value_),
- VectorToStringAsDouble(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<double>,
- kSequenceDouble,
- true,
- false,
- VectorToString(*value_),
- VectorToStringAsDouble(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<std::string>,
- kSequenceString,
- true,
- false,
- VectorOfStringsToString(*value_),
- VectorOfStringsToString(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(rtc_stats_internal::MapStringUint64,
- kMapStringUint64,
- false,
- false,
- MapToString(*value_),
- MapToStringAsDouble(*value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(rtc_stats_internal::MapStringDouble,
- kMapStringDouble,
- false,
- false,
- MapToString(*value_),
- MapToStringAsDouble(*value_));
-
} // namespace webrtc
diff --git a/stats/rtc_stats_member.cc b/stats/rtc_stats_member.cc
new file mode 100644
index 0000000..d7a3f6c
--- /dev/null
+++ b/stats/rtc_stats_member.cc
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2023 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 "api/stats/rtc_stats_member.h"
+
+#include "rtc_base/arraysize.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace webrtc {
+
+namespace {
+
+// Produces "[a,b,c]". Works for non-vector `RTCStatsMemberInterface::Type`
+// types.
+template <typename T>
+std::string VectorToString(const std::vector<T>& vector) {
+ rtc::StringBuilder sb;
+ sb << "[";
+ const char* separator = "";
+ for (const T& element : vector) {
+ sb << separator << rtc::ToString(element);
+ separator = ",";
+ }
+ sb << "]";
+ return sb.Release();
+}
+
+// This overload is required because std::vector<bool> range loops don't
+// return references but objects, causing -Wrange-loop-analysis diagnostics.
+std::string VectorToString(const std::vector<bool>& vector) {
+ rtc::StringBuilder sb;
+ sb << "[";
+ const char* separator = "";
+ for (bool element : vector) {
+ sb << separator << rtc::ToString(element);
+ separator = ",";
+ }
+ sb << "]";
+ return sb.Release();
+}
+
+// Produces "[\"a\",\"b\",\"c\"]". Works for vectors of both const char* and
+// std::string element types.
+template <typename T>
+std::string VectorOfStringsToString(const std::vector<T>& strings) {
+ rtc::StringBuilder sb;
+ sb << "[";
+ const char* separator = "";
+ for (const T& element : strings) {
+ sb << separator << "\"" << rtc::ToString(element) << "\"";
+ separator = ",";
+ }
+ sb << "]";
+ return sb.Release();
+}
+
+template <typename T>
+std::string MapToString(const std::map<std::string, T>& map) {
+ rtc::StringBuilder sb;
+ sb << "{";
+ const char* separator = "";
+ for (const auto& element : map) {
+ sb << separator << rtc::ToString(element.first) << ":"
+ << rtc::ToString(element.second);
+ separator = ",";
+ }
+ sb << "}";
+ return sb.Release();
+}
+
+template <typename T>
+std::string ToStringAsDouble(const T value) {
+ // JSON represents numbers as floating point numbers with about 15 decimal
+ // digits of precision.
+ char buf[32];
+ const int len = std::snprintf(&buf[0], arraysize(buf), "%.16g",
+ static_cast<double>(value));
+ RTC_DCHECK_LE(len, arraysize(buf));
+ return std::string(&buf[0], len);
+}
+
+template <typename T>
+std::string VectorToStringAsDouble(const std::vector<T>& vector) {
+ rtc::StringBuilder sb;
+ sb << "[";
+ const char* separator = "";
+ for (const T& element : vector) {
+ sb << separator << ToStringAsDouble<T>(element);
+ separator = ",";
+ }
+ sb << "]";
+ return sb.Release();
+}
+
+template <typename T>
+std::string MapToStringAsDouble(const std::map<std::string, T>& map) {
+ rtc::StringBuilder sb;
+ sb << "{";
+ const char* separator = "";
+ for (const auto& element : map) {
+ sb << separator << "\"" << rtc::ToString(element.first)
+ << "\":" << ToStringAsDouble(element.second);
+ separator = ",";
+ }
+ sb << "}";
+ return sb.Release();
+}
+
+} // namespace
+
+#define WEBRTC_DEFINE_RTCSTATSMEMBER(T, type, is_seq, is_str, to_str, to_json) \
+ template <> \
+ RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType() { \
+ return type; \
+ } \
+ template <> \
+ bool RTCStatsMember<T>::is_sequence() const { \
+ return is_seq; \
+ } \
+ template <> \
+ bool RTCStatsMember<T>::is_string() const { \
+ return is_str; \
+ } \
+ template <> \
+ std::string RTCStatsMember<T>::ValueToString() const { \
+ RTC_DCHECK(value_.has_value()); \
+ return to_str; \
+ } \
+ template <> \
+ std::string RTCStatsMember<T>::ValueToJson() const { \
+ RTC_DCHECK(value_.has_value()); \
+ return to_json; \
+ } \
+ template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT) RTCStatsMember<T>
+
+WEBRTC_DEFINE_RTCSTATSMEMBER(bool,
+ kBool,
+ false,
+ false,
+ rtc::ToString(*value_),
+ rtc::ToString(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(int32_t,
+ kInt32,
+ false,
+ false,
+ rtc::ToString(*value_),
+ rtc::ToString(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(uint32_t,
+ kUint32,
+ false,
+ false,
+ rtc::ToString(*value_),
+ rtc::ToString(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(int64_t,
+ kInt64,
+ false,
+ false,
+ rtc::ToString(*value_),
+ ToStringAsDouble(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(uint64_t,
+ kUint64,
+ false,
+ false,
+ rtc::ToString(*value_),
+ ToStringAsDouble(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(double,
+ kDouble,
+ false,
+ false,
+ rtc::ToString(*value_),
+ ToStringAsDouble(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::string,
+ kString,
+ false,
+ true,
+ *value_,
+ *value_);
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<bool>,
+ kSequenceBool,
+ true,
+ false,
+ VectorToString(*value_),
+ VectorToString(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int32_t>,
+ kSequenceInt32,
+ true,
+ false,
+ VectorToString(*value_),
+ VectorToString(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint32_t>,
+ kSequenceUint32,
+ true,
+ false,
+ VectorToString(*value_),
+ VectorToString(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int64_t>,
+ kSequenceInt64,
+ true,
+ false,
+ VectorToString(*value_),
+ VectorToStringAsDouble(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint64_t>,
+ kSequenceUint64,
+ true,
+ false,
+ VectorToString(*value_),
+ VectorToStringAsDouble(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<double>,
+ kSequenceDouble,
+ true,
+ false,
+ VectorToString(*value_),
+ VectorToStringAsDouble(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<std::string>,
+ kSequenceString,
+ true,
+ false,
+ VectorOfStringsToString(*value_),
+ VectorOfStringsToString(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(rtc_stats_internal::MapStringUint64,
+ kMapStringUint64,
+ false,
+ false,
+ MapToString(*value_),
+ MapToStringAsDouble(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(rtc_stats_internal::MapStringDouble,
+ kMapStringDouble,
+ false,
+ false,
+ MapToString(*value_),
+ MapToStringAsDouble(*value_));
+
+} // namespace webrtc