OLD | NEW |
| (Empty) |
1 /* | |
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_RTCSTATS_H_ | |
12 #define WEBRTC_API_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 | |
22 namespace webrtc { | |
23 | |
24 class 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 // } | |
50 class 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 | |
94 // All |RTCStats| classes should use this macro in a public section of the class | |
95 // definition. | |
96 // | |
97 // This macro declares the static |kType| and overrides methods as required by | |
98 // subclasses of |RTCStats|: |copy|, |type|, and | |
99 // |MembersOfThisObjectAndAncestors|. The |...| argument is a list of addresses | |
100 // to each member defined in the implementing class (list cannot be empty, must | |
101 // have at least one new member). | |
102 // | |
103 // (Since class names need to be known to implement these methods this cannot be | |
104 // part of the base |RTCStats|. While these methods could be implemented using | |
105 // templates, that would only work for immediate subclasses. Subclasses of | |
106 // subclasses also have to override these methods, resulting in boilerplate | |
107 // code. Using a macro avoids this and works for any |RTCStats| class, including | |
108 // grandchildren.) | |
109 // | |
110 // Sample usage: | |
111 // | |
112 // rtcfoostats.h: | |
113 // class RTCFooStats : public RTCStats { | |
114 // public: | |
115 // RTCFooStats(const std::string& id, int64_t timestamp_us) | |
116 // : RTCStats(id, timestamp_us), | |
117 // foo("foo"), | |
118 // bar("bar") { | |
119 // } | |
120 // | |
121 // WEBRTC_RTCSTATS_IMPL(RTCStats, RTCFooStats, | |
122 // &foo, | |
123 // &bar); | |
124 // | |
125 // RTCStatsMember<int32_t> foo; | |
126 // RTCStatsMember<int32_t> bar; | |
127 // }; | |
128 // | |
129 // rtcfoostats.cc: | |
130 // const char RTCFooStats::kType[] = "foo-stats"; | |
131 // | |
132 #define WEBRTC_RTCSTATS_IMPL(parent_class, this_class, ...) \ | |
133 public: \ | |
134 static const char kType[]; \ | |
135 std::unique_ptr<webrtc::RTCStats> copy() const override { \ | |
136 return std::unique_ptr<webrtc::RTCStats>(new this_class(*this)); \ | |
137 } \ | |
138 const char* type() const override { return this_class::kType; } \ | |
139 protected: \ | |
140 std::vector<const webrtc::RTCStatsMemberInterface*> \ | |
141 MembersOfThisObjectAndAncestors( \ | |
142 size_t local_var_additional_capacity) const override { \ | |
143 const webrtc::RTCStatsMemberInterface* local_var_members[] = { \ | |
144 __VA_ARGS__ \ | |
145 }; \ | |
146 size_t local_var_members_count = \ | |
147 sizeof(local_var_members) / sizeof(local_var_members[0]); \ | |
148 std::vector<const webrtc::RTCStatsMemberInterface*> local_var_members_vec =\ | |
149 parent_class::MembersOfThisObjectAndAncestors( \ | |
150 local_var_members_count + local_var_additional_capacity); \ | |
151 RTC_DCHECK_GE( \ | |
152 local_var_members_vec.capacity() - local_var_members_vec.size(), \ | |
153 local_var_members_count + local_var_additional_capacity); \ | |
154 local_var_members_vec.insert(local_var_members_vec.end(), \ | |
155 &local_var_members[0], \ | |
156 &local_var_members[local_var_members_count]); \ | |
157 return local_var_members_vec; \ | |
158 } \ | |
159 public: | |
160 | |
161 // Interface for |RTCStats| members, which have a name and a value of a type | |
162 // defined in a subclass. Only the types listed in |Type| are supported, these | |
163 // are implemented by |RTCStatsMember<T>|. The value of a member may be | |
164 // undefined, the value can only be read if |is_defined|. | |
165 class RTCStatsMemberInterface { | |
166 public: | |
167 // Member value types. | |
168 enum Type { | |
169 kInt32, // int32_t | |
170 kUint32, // uint32_t | |
171 kInt64, // int64_t | |
172 kUint64, // uint64_t | |
173 kDouble, // double | |
174 kStaticString, // const char* | |
175 kString, // std::string | |
176 | |
177 kSequenceInt32, // std::vector<int32_t> | |
178 kSequenceUint32, // std::vector<uint32_t> | |
179 kSequenceInt64, // std::vector<int64_t> | |
180 kSequenceUint64, // std::vector<uint64_t> | |
181 kSequenceDouble, // std::vector<double> | |
182 kSequenceStaticString, // std::vector<const char*> | |
183 kSequenceString, // std::vector<std::string> | |
184 }; | |
185 | |
186 virtual ~RTCStatsMemberInterface() {} | |
187 | |
188 const char* name() const { return name_; } | |
189 virtual Type type() const = 0; | |
190 virtual bool is_sequence() const = 0; | |
191 virtual bool is_string() const = 0; | |
192 bool is_defined() const { return is_defined_; } | |
193 virtual std::string ValueToString() const = 0; | |
194 | |
195 template<typename T> | |
196 const T& cast_to() const { | |
197 RTC_DCHECK_EQ(type(), T::kType); | |
198 return static_cast<const T&>(*this); | |
199 } | |
200 | |
201 protected: | |
202 RTCStatsMemberInterface(const char* name, bool is_defined) | |
203 : name_(name), is_defined_(is_defined) {} | |
204 | |
205 const char* const name_; | |
206 bool is_defined_; | |
207 }; | |
208 | |
209 // Template implementation of |RTCStatsMemberInterface|. Every possible |T| is | |
210 // specialized in rtcstats.cc, using a different |T| results in a linker error | |
211 // (undefined reference to |kType|). The supported types are the ones described | |
212 // by |RTCStatsMemberInterface::Type|. | |
213 template<typename T> | |
214 class RTCStatsMember : public RTCStatsMemberInterface { | |
215 public: | |
216 static const Type kType; | |
217 | |
218 explicit RTCStatsMember(const char* name) | |
219 : RTCStatsMemberInterface(name, false), | |
220 value_() {} | |
221 RTCStatsMember(const char* name, const T& value) | |
222 : RTCStatsMemberInterface(name, true), | |
223 value_(value) {} | |
224 RTCStatsMember(const char* name, T&& value) | |
225 : RTCStatsMemberInterface(name, true), | |
226 value_(std::move(value)) {} | |
227 explicit RTCStatsMember(const RTCStatsMember<T>& other) | |
228 : RTCStatsMemberInterface(other.name_, other.is_defined_), | |
229 value_(other.value_) {} | |
230 explicit RTCStatsMember(RTCStatsMember<T>&& other) | |
231 : RTCStatsMemberInterface(other.name_, other.is_defined_), | |
232 value_(std::move(other.value_)) {} | |
233 | |
234 Type type() const override { return kType; } | |
235 bool is_sequence() const override; | |
236 bool is_string() const override; | |
237 std::string ValueToString() const override; | |
238 | |
239 // Assignment operators. | |
240 T& operator=(const T& value) { | |
241 value_ = value; | |
242 is_defined_ = true; | |
243 return value_; | |
244 } | |
245 T& operator=(const T&& value) { | |
246 value_ = std::move(value); | |
247 is_defined_ = true; | |
248 return value_; | |
249 } | |
250 T& operator=(const RTCStatsMember<T>& other) { | |
251 RTC_DCHECK(other.is_defined_); | |
252 value_ = other.is_defined_; | |
253 is_defined_ = true; | |
254 return value_; | |
255 } | |
256 | |
257 // Value getters. | |
258 T& operator*() { | |
259 RTC_DCHECK(is_defined_); | |
260 return value_; | |
261 } | |
262 const T& operator*() const { | |
263 RTC_DCHECK(is_defined_); | |
264 return value_; | |
265 } | |
266 | |
267 // Value getters, arrow operator. | |
268 T* operator->() { | |
269 RTC_DCHECK(is_defined_); | |
270 return &value_; | |
271 } | |
272 const T* operator->() const { | |
273 RTC_DCHECK(is_defined_); | |
274 return &value_; | |
275 } | |
276 | |
277 private: | |
278 T value_; | |
279 }; | |
280 | |
281 } // namespace webrtc | |
282 | |
283 #endif // WEBRTC_API_RTCSTATS_H_ | |
OLD | NEW |