1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
|
/*
* Copyright 2016 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 WEBRTC_API_STATS_RTCSTATS_H_
#define WEBRTC_API_STATS_RTCSTATS_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "webrtc/base/checks.h"
namespace webrtc {
class RTCStatsMemberInterface;
// Abstract base class for RTCStats-derived dictionaries, see
// https://w3c.github.io/webrtc-stats/.
//
// All derived classes must have the following static variable defined:
// static const char kType[];
// It is used as a unique class identifier and a string representation of the
// class type, see https://w3c.github.io/webrtc-stats/#rtcstatstype-str*.
// Use the |WEBRTC_RTCSTATS_IMPL| macro when implementing subclasses, see macro
// for details.
//
// Derived classes list their dictionary members, RTCStatsMember<T>, as public
// fields, allowing the following:
//
// RTCFooStats foo("fooId", GetCurrentTime());
// foo.bar = 42;
// foo.baz = std::vector<std::string>();
// foo.baz->push_back("hello world");
// uint32_t x = *foo.bar;
//
// Pointers to all the members are available with |Members|, allowing iteration:
//
// for (const RTCStatsMemberInterface* member : foo.Members()) {
// printf("%s = %s\n", member->name(), member->ValueToString().c_str());
// }
class RTCStats {
public:
RTCStats(const std::string& id, int64_t timestamp_us)
: id_(id), timestamp_us_(timestamp_us) {}
RTCStats(std::string&& id, int64_t timestamp_us)
: id_(std::move(id)), timestamp_us_(timestamp_us) {}
virtual ~RTCStats() {}
virtual std::unique_ptr<RTCStats> copy() const = 0;
const std::string& id() const { return id_; }
// Time relative to the UNIX epoch (Jan 1, 1970, UTC), in microseconds.
int64_t timestamp_us() const { return timestamp_us_; }
// Returns the static member variable |kType| of the implementing class.
virtual const char* type() const = 0;
// Returns a vector of pointers to all the |RTCStatsMemberInterface| members
// of this class. This allows for iteration of members. For a given class,
// |Members| always returns the same members in the same order.
std::vector<const RTCStatsMemberInterface*> Members() const;
// Checks if the two stats objects are of the same type and have the same
// member values. Timestamps are not compared. These operators are exposed for
// testing.
bool operator==(const RTCStats& other) const;
bool operator!=(const RTCStats& other) const;
// Creates a human readable string representation of the stats object, listing
// all of its members (names and values).
std::string ToString() const;
// Downcasts the stats object to an |RTCStats| subclass |T|. DCHECKs that the
// object is of type |T|.
template<typename T>
const T& cast_to() const {
RTC_DCHECK_EQ(type(), T::kType);
return static_cast<const T&>(*this);
}
protected:
// Gets a vector of all members of this |RTCStats| object, including members
// derived from parent classes. |additional_capacity| is how many more members
// shall be reserved in the vector (so that subclasses can allocate a vector
// with room for both parent and child members without it having to resize).
virtual std::vector<const RTCStatsMemberInterface*>
MembersOfThisObjectAndAncestors(
size_t additional_capacity) const;
std::string const id_;
int64_t timestamp_us_;
};
// All |RTCStats| classes should use these macros.
// |WEBRTC_RTCSTATS_DECL| is placed in a public section of the class definition.
// |WEBRTC_RTCSTATS_IMPL| is placed outside the class definition (in a .cc).
//
// These macros declare (in _DECL) and define (in _IMPL) the static |kType| and
// overrides methods as required by subclasses of |RTCStats|: |copy|, |type| and
// |MembersOfThisObjectAndAncestors|. The |...| argument is a list of addresses
// to each member defined in the implementing class. The list must have at least
// one member.
//
// (Since class names need to be known to implement these methods this cannot be
// part of the base |RTCStats|. While these methods could be implemented using
// templates, that would only work for immediate subclasses. Subclasses of
// subclasses also have to override these methods, resulting in boilerplate
// code. Using a macro avoids this and works for any |RTCStats| class, including
// grandchildren.)
//
// Sample usage:
//
// rtcfoostats.h:
// class RTCFooStats : public RTCStats {
// public:
// WEBRTC_RTCSTATS_DECL();
//
// RTCFooStats(const std::string& id, int64_t timestamp_us);
//
// RTCStatsMember<int32_t> foo;
// RTCStatsMember<int32_t> bar;
// };
//
// rtcfoostats.cc:
// WEBRTC_RTCSTATS_IMPL(RTCFooStats, RTCStats, "foo-stats"
// &foo,
// &bar);
//
// RTCFooStats::RTCFooStats(const std::string& id, int64_t timestamp_us)
// : RTCStats(id, timestamp_us),
// foo("foo"),
// bar("bar") {
// }
//
#define WEBRTC_RTCSTATS_DECL() \
public: \
static const char kType[]; \
\
std::unique_ptr<webrtc::RTCStats> copy() const override; \
const char* type() const override; \
\
protected: \
std::vector<const webrtc::RTCStatsMemberInterface*> \
MembersOfThisObjectAndAncestors( \
size_t local_var_additional_capacity) const override; \
\
public:
#define WEBRTC_RTCSTATS_IMPL(this_class, parent_class, type_str, ...) \
const char this_class::kType[] = type_str; \
\
std::unique_ptr<webrtc::RTCStats> this_class::copy() const { \
return std::unique_ptr<webrtc::RTCStats>(new this_class(*this)); \
} \
\
const char* this_class::type() const { \
return this_class::kType; \
} \
\
std::vector<const webrtc::RTCStatsMemberInterface*> \
this_class::MembersOfThisObjectAndAncestors( \
size_t local_var_additional_capacity) const { \
const webrtc::RTCStatsMemberInterface* local_var_members[] = { \
__VA_ARGS__ \
}; \
size_t local_var_members_count = \
sizeof(local_var_members) / sizeof(local_var_members[0]); \
std::vector<const webrtc::RTCStatsMemberInterface*> local_var_members_vec =\
parent_class::MembersOfThisObjectAndAncestors( \
local_var_members_count + local_var_additional_capacity); \
RTC_DCHECK_GE( \
local_var_members_vec.capacity() - local_var_members_vec.size(), \
local_var_members_count + local_var_additional_capacity); \
local_var_members_vec.insert(local_var_members_vec.end(), \
&local_var_members[0], \
&local_var_members[local_var_members_count]); \
return local_var_members_vec; \
}
// 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>
};
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;
bool is_defined() const { return is_defined_; }
// Type and value comparator. The names are not compared. These operators are
// exposed for testing.
virtual bool operator==(const RTCStatsMemberInterface& other) const = 0;
bool operator!=(const RTCStatsMemberInterface& other) const {
return !(*this == other);
}
virtual std::string ValueToString() const = 0;
template<typename T>
const T& cast_to() const {
RTC_DCHECK_EQ(type(), T::kType);
return static_cast<const T&>(*this);
}
protected:
RTCStatsMemberInterface(const char* name, bool is_defined)
: name_(name), is_defined_(is_defined) {}
const char* const name_;
bool is_defined_;
};
// Template implementation of |RTCStatsMemberInterface|. Every possible |T| is
// specialized in rtcstats.cc, using a different |T| results in a linker error
// (undefined reference to |kType|). The supported types are the ones described
// by |RTCStatsMemberInterface::Type|.
template<typename T>
class RTCStatsMember : public RTCStatsMemberInterface {
public:
static const Type kType;
explicit RTCStatsMember(const char* name)
: RTCStatsMemberInterface(name, false),
value_() {}
RTCStatsMember(const char* name, const T& value)
: RTCStatsMemberInterface(name, true),
value_(value) {}
RTCStatsMember(const char* name, T&& value)
: RTCStatsMemberInterface(name, true),
value_(std::move(value)) {}
explicit RTCStatsMember(const RTCStatsMember<T>& other)
: RTCStatsMemberInterface(other.name_, other.is_defined_),
value_(other.value_) {}
explicit RTCStatsMember(RTCStatsMember<T>&& other)
: RTCStatsMemberInterface(other.name_, other.is_defined_),
value_(std::move(other.value_)) {}
Type type() const override { return kType; }
bool is_sequence() const override;
bool is_string() const override;
bool operator==(const RTCStatsMemberInterface& other) const override {
if (type() != other.type())
return false;
const RTCStatsMember<T>& other_t =
static_cast<const RTCStatsMember<T>&>(other);
if (!is_defined_)
return !other_t.is_defined();
if (!other.is_defined())
return false;
return value_ == other_t.value_;
}
std::string ValueToString() const override;
// Assignment operators.
T& operator=(const T& value) {
value_ = value;
is_defined_ = true;
return value_;
}
T& operator=(const T&& value) {
value_ = std::move(value);
is_defined_ = true;
return value_;
}
T& operator=(const RTCStatsMember<T>& other) {
RTC_DCHECK(other.is_defined_);
value_ = other.is_defined_;
is_defined_ = true;
return value_;
}
// Value getters.
T& operator*() {
RTC_DCHECK(is_defined_);
return value_;
}
const T& operator*() const {
RTC_DCHECK(is_defined_);
return value_;
}
// Value getters, arrow operator.
T* operator->() {
RTC_DCHECK(is_defined_);
return &value_;
}
const T* operator->() const {
RTC_DCHECK(is_defined_);
return &value_;
}
private:
T value_;
};
} // namespace webrtc
#endif // WEBRTC_API_STATS_RTCSTATS_H_
|