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