statstypes.cc revision 4b89aa03bb9c817cf2274f2035d613a70c5298eb
1/* 2 * libjingle 3 * Copyright 2014 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include "talk/app/webrtc/statstypes.h" 29 30#include <string.h> 31 32#include "webrtc/base/checks.h" 33 34// TODO(tommi): Could we have a static map of value name -> expected type 35// and use this to DCHECK on correct usage (somewhat strongly typed values)? 36// Alternatively, we could define the names+type in a separate document and 37// generate strongly typed inline C++ code that forces the correct type to be 38// used for a given name at compile time. 39 40using rtc::RefCountedObject; 41 42namespace webrtc { 43namespace { 44 45// The id of StatsReport of type kStatsReportTypeBwe. 46const char kStatsReportVideoBweId[] = "bweforvideo"; 47 48// NOTE: These names need to be consistent with an external 49// specification (W3C Stats Identifiers). 50const char* InternalTypeToString(StatsReport::StatsType type) { 51 switch (type) { 52 case StatsReport::kStatsReportTypeSession: 53 return "googLibjingleSession"; 54 case StatsReport::kStatsReportTypeBwe: 55 return "VideoBwe"; 56 case StatsReport::kStatsReportTypeRemoteSsrc: 57 return "remoteSsrc"; 58 case StatsReport::kStatsReportTypeSsrc: 59 return "ssrc"; 60 case StatsReport::kStatsReportTypeTrack: 61 return "googTrack"; 62 case StatsReport::kStatsReportTypeIceLocalCandidate: 63 return "localcandidate"; 64 case StatsReport::kStatsReportTypeIceRemoteCandidate: 65 return "remotecandidate"; 66 case StatsReport::kStatsReportTypeTransport: 67 return "transport"; 68 case StatsReport::kStatsReportTypeComponent: 69 return "googComponent"; 70 case StatsReport::kStatsReportTypeCandidatePair: 71 return "googCandidatePair"; 72 case StatsReport::kStatsReportTypeCertificate: 73 return "googCertificate"; 74 case StatsReport::kStatsReportTypeDataChannel: 75 return "datachannel"; 76 } 77 DCHECK(false); 78 return nullptr; 79} 80 81class BandwidthEstimationId : public StatsReport::IdBase { 82 public: 83 BandwidthEstimationId() 84 : StatsReport::IdBase(StatsReport::kStatsReportTypeBwe) {} 85 std::string ToString() const override { return kStatsReportVideoBweId; } 86}; 87 88class TypedId : public StatsReport::IdBase { 89 public: 90 TypedId(StatsReport::StatsType type, const std::string& id) 91 : StatsReport::IdBase(type), id_(id) {} 92 93 bool Equals(const IdBase& other) const override { 94 return IdBase::Equals(other) && 95 static_cast<const TypedId&>(other).id_ == id_; 96 } 97 98 std::string ToString() const override { 99 return std::string(InternalTypeToString(type_)) + kSeparator + id_; 100 } 101 102 protected: 103 const std::string id_; 104}; 105 106class TypedIntId : public StatsReport::IdBase { 107 public: 108 TypedIntId(StatsReport::StatsType type, int id) 109 : StatsReport::IdBase(type), id_(id) {} 110 111 bool Equals(const IdBase& other) const override { 112 return IdBase::Equals(other) && 113 static_cast<const TypedIntId&>(other).id_ == id_; 114 } 115 116 std::string ToString() const override { 117 return std::string(InternalTypeToString(type_)) + 118 kSeparator + 119 rtc::ToString<int>(id_); 120 } 121 122 protected: 123 const int id_; 124}; 125 126class IdWithDirection : public TypedId { 127 public: 128 IdWithDirection(StatsReport::StatsType type, const std::string& id, 129 StatsReport::Direction direction) 130 : TypedId(type, id), direction_(direction) {} 131 132 bool Equals(const IdBase& other) const override { 133 return TypedId::Equals(other) && 134 static_cast<const IdWithDirection&>(other).direction_ == direction_; 135 } 136 137 std::string ToString() const override { 138 std::string ret(TypedId::ToString()); 139 ret += kSeparator; 140 ret += direction_ == StatsReport::kSend ? "send" : "recv"; 141 return ret; 142 } 143 144 private: 145 const StatsReport::Direction direction_; 146}; 147 148class CandidateId : public TypedId { 149 public: 150 CandidateId(bool local, const std::string& id) 151 : TypedId(local ? 152 StatsReport::kStatsReportTypeIceLocalCandidate : 153 StatsReport::kStatsReportTypeIceRemoteCandidate, 154 id) { 155 } 156 157 std::string ToString() const override { 158 return "Cand-" + id_; 159 } 160}; 161 162class ComponentId : public StatsReport::IdBase { 163 public: 164 ComponentId(const std::string& content_name, int component) 165 : ComponentId(StatsReport::kStatsReportTypeComponent, content_name, 166 component) {} 167 168 bool Equals(const IdBase& other) const override { 169 return IdBase::Equals(other) && 170 static_cast<const ComponentId&>(other).component_ == component_ && 171 static_cast<const ComponentId&>(other).content_name_ == content_name_; 172 } 173 174 std::string ToString() const override { 175 return ToString("Channel-"); 176 } 177 178 protected: 179 ComponentId(StatsReport::StatsType type, const std::string& content_name, 180 int component) 181 : IdBase(type), 182 content_name_(content_name), 183 component_(component) {} 184 185 std::string ToString(const char* prefix) const { 186 std::string ret(prefix); 187 ret += content_name_; 188 ret += '-'; 189 ret += rtc::ToString<>(component_); 190 return ret; 191 } 192 193 private: 194 const std::string content_name_; 195 const int component_; 196}; 197 198class CandidatePairId : public ComponentId { 199 public: 200 CandidatePairId(const std::string& content_name, int component, int index) 201 : ComponentId(StatsReport::kStatsReportTypeCandidatePair, content_name, 202 component), 203 index_(index) {} 204 205 bool Equals(const IdBase& other) const override { 206 return ComponentId::Equals(other) && 207 static_cast<const CandidatePairId&>(other).index_ == index_; 208 } 209 210 std::string ToString() const override { 211 std::string ret(ComponentId::ToString("Conn-")); 212 ret += '-'; 213 ret += rtc::ToString<>(index_); 214 return ret; 215 } 216 217 private: 218 const int index_; 219}; 220 221} // namespace 222 223StatsReport::IdBase::IdBase(StatsType type) : type_(type) {} 224StatsReport::IdBase::~IdBase() {} 225 226StatsReport::StatsType StatsReport::IdBase::type() const { return type_; } 227 228bool StatsReport::IdBase::Equals(const IdBase& other) const { 229 return other.type_ == type_; 230} 231 232StatsReport::Value::Value(StatsValueName name, int64 value, Type int_type) 233 : name(name), type_(int_type) { 234 DCHECK(type_ == kInt || type_ == kInt64); 235 type_ == kInt ? value_.int_ = static_cast<int>(value) : value_.int64_ = value; 236} 237 238StatsReport::Value::Value(StatsValueName name, float f) 239 : name(name), type_(kFloat) { 240 value_.float_ = f; 241} 242 243StatsReport::Value::Value(StatsValueName name, const std::string& value) 244 : name(name), type_(kString) { 245 value_.string_ = new std::string(value); 246} 247 248StatsReport::Value::Value(StatsValueName name, const char* value) 249 : name(name), type_(kStaticString) { 250 value_.static_string_ = value; 251} 252 253StatsReport::Value::Value(StatsValueName name, bool b) 254 : name(name), type_(kBool) { 255 value_.bool_ = b; 256} 257 258StatsReport::Value::Value(StatsValueName name, const Id& value) 259 : name(name), type_(kId) { 260 value_.id_ = new Id(value); 261} 262 263StatsReport::Value::~Value() { 264 switch (type_) { 265 case kInt: 266 case kInt64: 267 case kFloat: 268 case kBool: 269 case kStaticString: 270 break; 271 case kString: 272 delete value_.string_; 273 break; 274 case kId: 275 delete value_.id_; 276 break; 277 } 278} 279 280bool StatsReport::Value::Equals(const Value& other) const { 281 if (name != other.name) 282 return false; 283 284 // There's a 1:1 relation between a name and a type, so we don't have to 285 // check that. 286 DCHECK_EQ(type_, other.type_); 287 288 switch (type_) { 289 case kInt: 290 return value_.int_ == other.value_.int_; 291 case kInt64: 292 return value_.int64_ == other.value_.int64_; 293 case kFloat: 294 return value_.float_ == other.value_.float_; 295 case kStaticString: { 296#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) 297 if (value_.static_string_ != other.value_.static_string_) { 298 DCHECK(strcmp(value_.static_string_, other.value_.static_string_) != 0) 299 << "Duplicate global?"; 300 } 301#endif 302 return value_.static_string_ == other.value_.static_string_; 303 } 304 case kString: 305 return *value_.string_ == *other.value_.string_; 306 case kBool: 307 return value_.bool_ == other.value_.bool_; 308 case kId: 309 return (*value_.id_)->Equals(*other.value_.id_); 310 } 311 RTC_NOTREACHED(); 312 return false; 313} 314 315bool StatsReport::Value::operator==(const std::string& value) const { 316 return (type_ == kString && value_.string_->compare(value) == 0) || 317 (type_ == kStaticString && value.compare(value_.static_string_) == 0); 318} 319 320bool StatsReport::Value::operator==(const char* value) const { 321 if (type_ == kString) 322 return value_.string_->compare(value) == 0; 323 if (type_ != kStaticString) 324 return false; 325#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) 326 if (value_.static_string_ != value) 327 DCHECK(strcmp(value_.static_string_, value) != 0) << "Duplicate global?"; 328#endif 329 return value == value_.static_string_; 330} 331 332bool StatsReport::Value::operator==(int64 value) const { 333 return type_ == kInt ? value_.int_ == static_cast<int>(value) : 334 (type_ == kInt64 ? value_.int64_ == value : false); 335} 336 337bool StatsReport::Value::operator==(bool value) const { 338 return type_ == kBool && value_.bool_ == value; 339} 340 341bool StatsReport::Value::operator==(float value) const { 342 return type_ == kFloat && value_.float_ == value; 343} 344 345bool StatsReport::Value::operator==(const Id& value) const { 346 return type_ == kId && (*value_.id_)->Equals(value); 347} 348 349int StatsReport::Value::int_val() const { 350 DCHECK(type_ == kInt); 351 return value_.int_; 352} 353 354int64 StatsReport::Value::int64_val() const { 355 DCHECK(type_ == kInt64); 356 return value_.int64_; 357} 358 359float StatsReport::Value::float_val() const { 360 DCHECK(type_ == kFloat); 361 return value_.float_; 362} 363 364const char* StatsReport::Value::static_string_val() const { 365 DCHECK(type_ == kStaticString); 366 return value_.static_string_; 367} 368 369const std::string& StatsReport::Value::string_val() const { 370 DCHECK(type_ == kString); 371 return *value_.string_; 372} 373 374bool StatsReport::Value::bool_val() const { 375 DCHECK(type_ == kBool); 376 return value_.bool_; 377} 378 379const char* StatsReport::Value::display_name() const { 380 switch (name) { 381 case kStatsValueNameAudioOutputLevel: 382 return "audioOutputLevel"; 383 case kStatsValueNameAudioInputLevel: 384 return "audioInputLevel"; 385 case kStatsValueNameBytesSent: 386 return "bytesSent"; 387 case kStatsValueNamePacketsSent: 388 return "packetsSent"; 389 case kStatsValueNameBytesReceived: 390 return "bytesReceived"; 391 case kStatsValueNameLabel: 392 return "label"; 393 case kStatsValueNamePacketsReceived: 394 return "packetsReceived"; 395 case kStatsValueNamePacketsLost: 396 return "packetsLost"; 397 case kStatsValueNameProtocol: 398 return "protocol"; 399 case kStatsValueNameTransportId: 400 return "transportId"; 401 case kStatsValueNameSelectedCandidatePairId: 402 return "selectedCandidatePairId"; 403 case kStatsValueNameSsrc: 404 return "ssrc"; 405 case kStatsValueNameState: 406 return "state"; 407 case kStatsValueNameDataChannelId: 408 return "datachannelid"; 409 410 // 'goog' prefixed constants. 411 case kStatsValueNameActiveConnection: 412 return "googActiveConnection"; 413 case kStatsValueNameActualEncBitrate: 414 return "googActualEncBitrate"; 415 case kStatsValueNameAvailableReceiveBandwidth: 416 return "googAvailableReceiveBandwidth"; 417 case kStatsValueNameAvailableSendBandwidth: 418 return "googAvailableSendBandwidth"; 419 case kStatsValueNameAvgEncodeMs: 420 return "googAvgEncodeMs"; 421 case kStatsValueNameBucketDelay: 422 return "googBucketDelay"; 423 case kStatsValueNameBandwidthLimitedResolution: 424 return "googBandwidthLimitedResolution"; 425 case kStatsValueNameCaptureJitterMs: 426 return "googCaptureJitterMs"; 427 case kStatsValueNameCaptureQueueDelayMsPerS: 428 return "googCaptureQueueDelayMsPerS"; 429 430 // Candidate related attributes. Values are taken from 431 // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*. 432 case kStatsValueNameCandidateIPAddress: 433 return "ipAddress"; 434 case kStatsValueNameCandidateNetworkType: 435 return "networkType"; 436 case kStatsValueNameCandidatePortNumber: 437 return "portNumber"; 438 case kStatsValueNameCandidatePriority: 439 return "priority"; 440 case kStatsValueNameCandidateTransportType: 441 return "transport"; 442 case kStatsValueNameCandidateType: 443 return "candidateType"; 444 445 case kStatsValueNameChannelId: 446 return "googChannelId"; 447 case kStatsValueNameCodecName: 448 return "googCodecName"; 449 case kStatsValueNameComponent: 450 return "googComponent"; 451 case kStatsValueNameContentName: 452 return "googContentName"; 453 case kStatsValueNameCpuLimitedResolution: 454 return "googCpuLimitedResolution"; 455 case kStatsValueNameDecodingCTSG: 456 return "googDecodingCTSG"; 457 case kStatsValueNameDecodingCTN: 458 return "googDecodingCTN"; 459 case kStatsValueNameDecodingNormal: 460 return "googDecodingNormal"; 461 case kStatsValueNameDecodingPLC: 462 return "googDecodingPLC"; 463 case kStatsValueNameDecodingCNG: 464 return "googDecodingCNG"; 465 case kStatsValueNameDecodingPLCCNG: 466 return "googDecodingPLCCNG"; 467 case kStatsValueNameDer: 468 return "googDerBase64"; 469 case kStatsValueNameDtlsCipher: 470 return "dtlsCipher"; 471 case kStatsValueNameEchoCancellationQualityMin: 472 return "googEchoCancellationQualityMin"; 473 case kStatsValueNameEchoDelayMedian: 474 return "googEchoCancellationEchoDelayMedian"; 475 case kStatsValueNameEchoDelayStdDev: 476 return "googEchoCancellationEchoDelayStdDev"; 477 case kStatsValueNameEchoReturnLoss: 478 return "googEchoCancellationReturnLoss"; 479 case kStatsValueNameEchoReturnLossEnhancement: 480 return "googEchoCancellationReturnLossEnhancement"; 481 case kStatsValueNameEncodeUsagePercent: 482 return "googEncodeUsagePercent"; 483 case kStatsValueNameExpandRate: 484 return "googExpandRate"; 485 case kStatsValueNameFingerprint: 486 return "googFingerprint"; 487 case kStatsValueNameFingerprintAlgorithm: 488 return "googFingerprintAlgorithm"; 489 case kStatsValueNameFirsReceived: 490 return "googFirsReceived"; 491 case kStatsValueNameFirsSent: 492 return "googFirsSent"; 493 case kStatsValueNameFrameHeightInput: 494 return "googFrameHeightInput"; 495 case kStatsValueNameFrameHeightReceived: 496 return "googFrameHeightReceived"; 497 case kStatsValueNameFrameHeightSent: 498 return "googFrameHeightSent"; 499 case kStatsValueNameFrameRateReceived: 500 return "googFrameRateReceived"; 501 case kStatsValueNameFrameRateDecoded: 502 return "googFrameRateDecoded"; 503 case kStatsValueNameFrameRateOutput: 504 return "googFrameRateOutput"; 505 case kStatsValueNameDecodeMs: 506 return "googDecodeMs"; 507 case kStatsValueNameMaxDecodeMs: 508 return "googMaxDecodeMs"; 509 case kStatsValueNameCurrentDelayMs: 510 return "googCurrentDelayMs"; 511 case kStatsValueNameTargetDelayMs: 512 return "googTargetDelayMs"; 513 case kStatsValueNameJitterBufferMs: 514 return "googJitterBufferMs"; 515 case kStatsValueNameMinPlayoutDelayMs: 516 return "googMinPlayoutDelayMs"; 517 case kStatsValueNameRenderDelayMs: 518 return "googRenderDelayMs"; 519 case kStatsValueNameCaptureStartNtpTimeMs: 520 return "googCaptureStartNtpTimeMs"; 521 case kStatsValueNameFrameRateInput: 522 return "googFrameRateInput"; 523 case kStatsValueNameFrameRateSent: 524 return "googFrameRateSent"; 525 case kStatsValueNameFrameWidthInput: 526 return "googFrameWidthInput"; 527 case kStatsValueNameFrameWidthReceived: 528 return "googFrameWidthReceived"; 529 case kStatsValueNameFrameWidthSent: 530 return "googFrameWidthSent"; 531 case kStatsValueNameInitiator: 532 return "googInitiator"; 533 case kStatsValueNameIssuerId: 534 return "googIssuerId"; 535 case kStatsValueNameJitterReceived: 536 return "googJitterReceived"; 537 case kStatsValueNameLocalAddress: 538 return "googLocalAddress"; 539 case kStatsValueNameLocalCandidateId: 540 return "localCandidateId"; 541 case kStatsValueNameLocalCandidateType: 542 return "googLocalCandidateType"; 543 case kStatsValueNameLocalCertificateId: 544 return "localCertificateId"; 545 case kStatsValueNameAdaptationChanges: 546 return "googAdaptationChanges"; 547 case kStatsValueNameNacksReceived: 548 return "googNacksReceived"; 549 case kStatsValueNameNacksSent: 550 return "googNacksSent"; 551 case kStatsValueNamePlisReceived: 552 return "googPlisReceived"; 553 case kStatsValueNamePlisSent: 554 return "googPlisSent"; 555 case kStatsValueNamePreferredJitterBufferMs: 556 return "googPreferredJitterBufferMs"; 557 case kStatsValueNameReadable: 558 return "googReadable"; 559 case kStatsValueNameRemoteAddress: 560 return "googRemoteAddress"; 561 case kStatsValueNameRemoteCandidateId: 562 return "remoteCandidateId"; 563 case kStatsValueNameRemoteCandidateType: 564 return "googRemoteCandidateType"; 565 case kStatsValueNameRemoteCertificateId: 566 return "remoteCertificateId"; 567 case kStatsValueNameRetransmitBitrate: 568 return "googRetransmitBitrate"; 569 case kStatsValueNameRtt: 570 return "googRtt"; 571 case kStatsValueNameSecondaryDecodedRate: 572 return "googSecondaryDecodedRate"; 573 case kStatsValueNameSendPacketsDiscarded: 574 return "packetsDiscardedOnSend"; 575 case kStatsValueNameSpeechExpandRate: 576 return "googSpeechExpandRate"; 577 case kStatsValueNameSrtpCipher: 578 return "srtpCipher"; 579 case kStatsValueNameTargetEncBitrate: 580 return "googTargetEncBitrate"; 581 case kStatsValueNameTransmitBitrate: 582 return "googTransmitBitrate"; 583 case kStatsValueNameTransportType: 584 return "googTransportType"; 585 case kStatsValueNameTrackId: 586 return "googTrackId"; 587 case kStatsValueNameTypingNoiseState: 588 return "googTypingNoiseState"; 589 case kStatsValueNameViewLimitedResolution: 590 return "googViewLimitedResolution"; 591 case kStatsValueNameWritable: 592 return "googWritable"; 593 default: 594 DCHECK(false); 595 break; 596 } 597 598 return nullptr; 599} 600 601std::string StatsReport::Value::ToString() const { 602 switch (type_) { 603 case kInt: 604 return rtc::ToString(value_.int_); 605 case kInt64: 606 return rtc::ToString(value_.int64_); 607 case kFloat: 608 return rtc::ToString(value_.float_); 609 case kStaticString: 610 return std::string(value_.static_string_); 611 case kString: 612 return *value_.string_; 613 case kBool: 614 return value_.bool_ ? "true" : "false"; 615 case kId: 616 return (*value_.id_)->ToString(); 617 } 618 RTC_NOTREACHED(); 619 return std::string(); 620} 621 622StatsReport::StatsReport(const Id& id) : id_(id), timestamp_(0.0) { 623 DCHECK(id_.get()); 624} 625 626// static 627StatsReport::Id StatsReport::NewBandwidthEstimationId() { 628 return Id(new RefCountedObject<BandwidthEstimationId>()); 629} 630 631// static 632StatsReport::Id StatsReport::NewTypedId(StatsType type, const std::string& id) { 633 return Id(new RefCountedObject<TypedId>(type, id)); 634} 635 636// static 637StatsReport::Id StatsReport::NewTypedIntId(StatsType type, int id) { 638 return Id(new RefCountedObject<TypedIntId>(type, id)); 639} 640 641// static 642StatsReport::Id StatsReport::NewIdWithDirection( 643 StatsType type, const std::string& id, StatsReport::Direction direction) { 644 return Id(new RefCountedObject<IdWithDirection>(type, id, direction)); 645} 646 647// static 648StatsReport::Id StatsReport::NewCandidateId(bool local, const std::string& id) { 649 return Id(new RefCountedObject<CandidateId>(local, id)); 650} 651 652// static 653StatsReport::Id StatsReport::NewComponentId( 654 const std::string& content_name, int component) { 655 return Id(new RefCountedObject<ComponentId>(content_name, component)); 656} 657 658// static 659StatsReport::Id StatsReport::NewCandidatePairId( 660 const std::string& content_name, int component, int index) { 661 return Id(new RefCountedObject<CandidatePairId>( 662 content_name, component, index)); 663} 664 665const char* StatsReport::TypeToString() const { 666 return InternalTypeToString(id_->type()); 667} 668 669void StatsReport::AddString(StatsReport::StatsValueName name, 670 const std::string& value) { 671 const Value* found = FindValue(name); 672 if (!found || !(*found == value)) 673 values_[name] = ValuePtr(new Value(name, value)); 674} 675 676void StatsReport::AddString(StatsReport::StatsValueName name, 677 const char* value) { 678 const Value* found = FindValue(name); 679 if (!found || !(*found == value)) 680 values_[name] = ValuePtr(new Value(name, value)); 681} 682 683void StatsReport::AddInt64(StatsReport::StatsValueName name, int64 value) { 684 const Value* found = FindValue(name); 685 if (!found || !(*found == value)) 686 values_[name] = ValuePtr(new Value(name, value, Value::kInt64)); 687} 688 689void StatsReport::AddInt(StatsReport::StatsValueName name, int value) { 690 const Value* found = FindValue(name); 691 if (!found || !(*found == static_cast<int64>(value))) 692 values_[name] = ValuePtr(new Value(name, value, Value::kInt)); 693} 694 695void StatsReport::AddFloat(StatsReport::StatsValueName name, float value) { 696 const Value* found = FindValue(name); 697 if (!found || !(*found == value)) 698 values_[name] = ValuePtr(new Value(name, value)); 699} 700 701void StatsReport::AddBoolean(StatsReport::StatsValueName name, bool value) { 702 const Value* found = FindValue(name); 703 if (!found || !(*found == value)) 704 values_[name] = ValuePtr(new Value(name, value)); 705} 706 707void StatsReport::AddId(StatsReport::StatsValueName name, 708 const Id& value) { 709 const Value* found = FindValue(name); 710 if (!found || !(*found == value)) 711 values_[name] = ValuePtr(new Value(name, value)); 712} 713 714const StatsReport::Value* StatsReport::FindValue(StatsValueName name) const { 715 Values::const_iterator it = values_.find(name); 716 return it == values_.end() ? nullptr : it->second.get(); 717} 718 719StatsCollection::StatsCollection() { 720} 721 722StatsCollection::~StatsCollection() { 723 for (auto* r : list_) 724 delete r; 725} 726 727StatsCollection::const_iterator StatsCollection::begin() const { 728 return list_.begin(); 729} 730 731StatsCollection::const_iterator StatsCollection::end() const { 732 return list_.end(); 733} 734 735size_t StatsCollection::size() const { 736 return list_.size(); 737} 738 739StatsReport* StatsCollection::InsertNew(const StatsReport::Id& id) { 740 DCHECK(Find(id) == nullptr); 741 StatsReport* report = new StatsReport(id); 742 list_.push_back(report); 743 return report; 744} 745 746StatsReport* StatsCollection::FindOrAddNew(const StatsReport::Id& id) { 747 StatsReport* ret = Find(id); 748 return ret ? ret : InsertNew(id); 749} 750 751StatsReport* StatsCollection::ReplaceOrAddNew(const StatsReport::Id& id) { 752 DCHECK(id.get()); 753 Container::iterator it = std::find_if(list_.begin(), list_.end(), 754 [&id](const StatsReport* r)->bool { return r->id()->Equals(id); }); 755 if (it != end()) { 756 StatsReport* report = new StatsReport((*it)->id()); 757 delete *it; 758 *it = report; 759 return report; 760 } 761 return InsertNew(id); 762} 763 764// Looks for a report with the given |id|. If one is not found, NULL 765// will be returned. 766StatsReport* StatsCollection::Find(const StatsReport::Id& id) { 767 Container::iterator it = std::find_if(list_.begin(), list_.end(), 768 [&id](const StatsReport* r)->bool { return r->id()->Equals(id); }); 769 return it == list_.end() ? nullptr : *it; 770} 771 772} // namespace webrtc 773