blob: 69175483021a748d8e4accd3239c4aa5ff256d79 [file] [log] [blame]
hbos74e1a4f2016-09-15 23:33:01 -07001/*
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;
65 // Returns a vector of pointers to all the RTCStatsMemberInterface members of
66 // this class. This allows for iteration of members.
67 std::vector<const RTCStatsMemberInterface*> Members() const;
68
69 // Creates a human readable string representation of the report, listing all
70 // of its members (names and values).
71 std::string ToString() const;
72
73 // Downcasts the stats object to an |RTCStats| subclass |T|. DCHECKs that the
74 // object is of type |T|.
75 template<typename T>
76 const T& cast_to() const {
77 RTC_DCHECK_EQ(type(), T::kType);
78 return static_cast<const T&>(*this);
79 }
80
81 protected:
82 // Gets a vector of all members of this |RTCStats| object, including members
83 // derived from parent classes. |additional_capacity| is how many more members
84 // shall be reserved in the vector (so that subclasses can allocate a vector
85 // with room for both parent and child members without it having to resize).
86 virtual std::vector<const RTCStatsMemberInterface*>
87 MembersOfThisObjectAndAncestors(
88 size_t additional_capacity) const;
89
90 std::string const id_;
91 int64_t timestamp_us_;
92};
93
hbosfc5e0502016-10-06 02:06:10 -070094// All |RTCStats| classes should use these macros.
95// |WEBRTC_RTCSTATS_DECL| is placed in a public section of the class definition.
96// |WEBRTC_RTCSTATS_IMPL| is placed outside the class definition (in a .cc).
hbos74e1a4f2016-09-15 23:33:01 -070097//
hbosfc5e0502016-10-06 02:06:10 -070098// These macros declare (in _DECL) and define (in _IMPL) the static |kType| and
99// overrides methods as required by subclasses of |RTCStats|: |copy|, |type| and
hbos74e1a4f2016-09-15 23:33:01 -0700100// |MembersOfThisObjectAndAncestors|. The |...| argument is a list of addresses
hbosfc5e0502016-10-06 02:06:10 -0700101// to each member defined in the implementing class. The list must have at least
102// one member.
hbos74e1a4f2016-09-15 23:33:01 -0700103//
104// (Since class names need to be known to implement these methods this cannot be
105// part of the base |RTCStats|. While these methods could be implemented using
106// templates, that would only work for immediate subclasses. Subclasses of
107// subclasses also have to override these methods, resulting in boilerplate
108// code. Using a macro avoids this and works for any |RTCStats| class, including
109// grandchildren.)
110//
111// Sample usage:
112//
113// rtcfoostats.h:
114// class RTCFooStats : public RTCStats {
115// public:
hbosfc5e0502016-10-06 02:06:10 -0700116// WEBRTC_RTCSTATS_DECL();
hbos74e1a4f2016-09-15 23:33:01 -0700117//
hbosfc5e0502016-10-06 02:06:10 -0700118// RTCFooStats(const std::string& id, int64_t timestamp_us);
hbos74e1a4f2016-09-15 23:33:01 -0700119//
120// RTCStatsMember<int32_t> foo;
121// RTCStatsMember<int32_t> bar;
122// };
123//
124// rtcfoostats.cc:
hbosfc5e0502016-10-06 02:06:10 -0700125// WEBRTC_RTCSTATS_IMPL(RTCFooStats, RTCStats, "foo-stats"
126// &foo,
127// &bar);
hbos74e1a4f2016-09-15 23:33:01 -0700128//
hbosfc5e0502016-10-06 02:06:10 -0700129// RTCFooStats::RTCFooStats(const std::string& id, int64_t timestamp_us)
130// : RTCStats(id, timestamp_us),
131// foo("foo"),
132// bar("bar") {
133// }
134//
135#define WEBRTC_RTCSTATS_DECL() \
hbos74e1a4f2016-09-15 23:33:01 -0700136 public: \
137 static const char kType[]; \
hbosfc5e0502016-10-06 02:06:10 -0700138 \
139 std::unique_ptr<webrtc::RTCStats> copy() const override; \
140 const char* type() const override; \
141 \
hbos74e1a4f2016-09-15 23:33:01 -0700142 protected: \
143 std::vector<const webrtc::RTCStatsMemberInterface*> \
144 MembersOfThisObjectAndAncestors( \
hbosfc5e0502016-10-06 02:06:10 -0700145 size_t local_var_additional_capacity) const override; \
146 \
147 public:
148
149#define WEBRTC_RTCSTATS_IMPL(this_class, parent_class, type_str, ...) \
150 const char this_class::kType[] = type_str; \
151 \
152 std::unique_ptr<webrtc::RTCStats> this_class::copy() const { \
153 return std::unique_ptr<webrtc::RTCStats>(new this_class(*this)); \
154 } \
155 \
156 const char* this_class::type() const { \
157 return this_class::kType; \
158 } \
159 \
160 std::vector<const webrtc::RTCStatsMemberInterface*> \
161 this_class::MembersOfThisObjectAndAncestors( \
162 size_t local_var_additional_capacity) const { \
hbos74e1a4f2016-09-15 23:33:01 -0700163 const webrtc::RTCStatsMemberInterface* local_var_members[] = { \
164 __VA_ARGS__ \
165 }; \
166 size_t local_var_members_count = \
167 sizeof(local_var_members) / sizeof(local_var_members[0]); \
168 std::vector<const webrtc::RTCStatsMemberInterface*> local_var_members_vec =\
169 parent_class::MembersOfThisObjectAndAncestors( \
170 local_var_members_count + local_var_additional_capacity); \
171 RTC_DCHECK_GE( \
172 local_var_members_vec.capacity() - local_var_members_vec.size(), \
173 local_var_members_count + local_var_additional_capacity); \
174 local_var_members_vec.insert(local_var_members_vec.end(), \
175 &local_var_members[0], \
176 &local_var_members[local_var_members_count]); \
177 return local_var_members_vec; \
hbosfc5e0502016-10-06 02:06:10 -0700178 }
hbos74e1a4f2016-09-15 23:33:01 -0700179
180// Interface for |RTCStats| members, which have a name and a value of a type
181// defined in a subclass. Only the types listed in |Type| are supported, these
182// are implemented by |RTCStatsMember<T>|. The value of a member may be
183// undefined, the value can only be read if |is_defined|.
184class RTCStatsMemberInterface {
185 public:
186 // Member value types.
187 enum Type {
hbosb20f3872016-10-04 14:37:11 -0700188 kBool, // bool
hbos74e1a4f2016-09-15 23:33:01 -0700189 kInt32, // int32_t
190 kUint32, // uint32_t
191 kInt64, // int64_t
192 kUint64, // uint64_t
193 kDouble, // double
194 kString, // std::string
195
hbosb20f3872016-10-04 14:37:11 -0700196 kSequenceBool, // std::vector<bool>
hbos74e1a4f2016-09-15 23:33:01 -0700197 kSequenceInt32, // std::vector<int32_t>
198 kSequenceUint32, // std::vector<uint32_t>
199 kSequenceInt64, // std::vector<int64_t>
200 kSequenceUint64, // std::vector<uint64_t>
201 kSequenceDouble, // std::vector<double>
202 kSequenceString, // std::vector<std::string>
203 };
204
205 virtual ~RTCStatsMemberInterface() {}
206
207 const char* name() const { return name_; }
208 virtual Type type() const = 0;
209 virtual bool is_sequence() const = 0;
210 virtual bool is_string() const = 0;
211 bool is_defined() const { return is_defined_; }
212 virtual std::string ValueToString() const = 0;
213
214 template<typename T>
215 const T& cast_to() const {
216 RTC_DCHECK_EQ(type(), T::kType);
217 return static_cast<const T&>(*this);
218 }
219
220 protected:
221 RTCStatsMemberInterface(const char* name, bool is_defined)
222 : name_(name), is_defined_(is_defined) {}
223
224 const char* const name_;
225 bool is_defined_;
226};
227
228// Template implementation of |RTCStatsMemberInterface|. Every possible |T| is
229// specialized in rtcstats.cc, using a different |T| results in a linker error
230// (undefined reference to |kType|). The supported types are the ones described
231// by |RTCStatsMemberInterface::Type|.
232template<typename T>
233class RTCStatsMember : public RTCStatsMemberInterface {
234 public:
235 static const Type kType;
236
237 explicit RTCStatsMember(const char* name)
238 : RTCStatsMemberInterface(name, false),
239 value_() {}
240 RTCStatsMember(const char* name, const T& value)
241 : RTCStatsMemberInterface(name, true),
242 value_(value) {}
243 RTCStatsMember(const char* name, T&& value)
244 : RTCStatsMemberInterface(name, true),
245 value_(std::move(value)) {}
246 explicit RTCStatsMember(const RTCStatsMember<T>& other)
247 : RTCStatsMemberInterface(other.name_, other.is_defined_),
248 value_(other.value_) {}
249 explicit RTCStatsMember(RTCStatsMember<T>&& other)
250 : RTCStatsMemberInterface(other.name_, other.is_defined_),
251 value_(std::move(other.value_)) {}
252
253 Type type() const override { return kType; }
254 bool is_sequence() const override;
255 bool is_string() const override;
256 std::string ValueToString() const override;
257
258 // Assignment operators.
259 T& operator=(const T& value) {
260 value_ = value;
261 is_defined_ = true;
262 return value_;
263 }
264 T& operator=(const T&& value) {
265 value_ = std::move(value);
266 is_defined_ = true;
267 return value_;
268 }
269 T& operator=(const RTCStatsMember<T>& other) {
270 RTC_DCHECK(other.is_defined_);
271 value_ = other.is_defined_;
272 is_defined_ = true;
273 return value_;
274 }
275
276 // Value getters.
277 T& operator*() {
278 RTC_DCHECK(is_defined_);
279 return value_;
280 }
281 const T& operator*() const {
282 RTC_DCHECK(is_defined_);
283 return value_;
284 }
285
286 // Value getters, arrow operator.
287 T* operator->() {
288 RTC_DCHECK(is_defined_);
289 return &value_;
290 }
291 const T* operator->() const {
292 RTC_DCHECK(is_defined_);
293 return &value_;
294 }
295
296 private:
297 T value_;
298};
299
300} // namespace webrtc
301
302#endif // WEBRTC_API_STATS_RTCSTATS_H_