/* * Copyright 2019 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. */ #import "RTCStatisticsReport+Private.h" #include "helpers/NSString+StdString.h" #include "rtc_base/checks.h" namespace webrtc { /** Converts a single value to a suitable NSNumber, NSString or NSArray containing NSNumbers or NSStrings.*/ NSObject *ValueFromStatsMember(const RTCStatsMemberInterface *member) { if (member->is_defined()) { switch (member->type()) { case RTCStatsMemberInterface::kBool: return [NSNumber numberWithBool:*member->cast_to>()]; case RTCStatsMemberInterface::kInt32: return [NSNumber numberWithInt:*member->cast_to>()]; case RTCStatsMemberInterface::kUint32: return [NSNumber numberWithUnsignedInt:*member->cast_to>()]; case RTCStatsMemberInterface::kInt64: return [NSNumber numberWithLong:*member->cast_to>()]; case RTCStatsMemberInterface::kUint64: return [NSNumber numberWithUnsignedLong:*member->cast_to>()]; case RTCStatsMemberInterface::kDouble: return [NSNumber numberWithDouble:*member->cast_to>()]; case RTCStatsMemberInterface::kString: return [NSString stringForStdString:*member->cast_to>()]; case RTCStatsMemberInterface::kSequenceBool: { std::vector sequence = *member->cast_to>>(); NSMutableArray *array = [NSMutableArray arrayWithCapacity:sequence.size()]; for (const auto &item : sequence) { [array addObject:[NSNumber numberWithBool:item]]; } return [array copy]; } case RTCStatsMemberInterface::kSequenceInt32: { std::vector sequence = *member->cast_to>>(); NSMutableArray *array = [NSMutableArray arrayWithCapacity:sequence.size()]; for (const auto &item : sequence) { [array addObject:[NSNumber numberWithInt:item]]; } return [array copy]; } case RTCStatsMemberInterface::kSequenceUint32: { std::vector sequence = *member->cast_to>>(); NSMutableArray *array = [NSMutableArray arrayWithCapacity:sequence.size()]; for (const auto &item : sequence) { [array addObject:[NSNumber numberWithUnsignedInt:item]]; } return [array copy]; } case RTCStatsMemberInterface::kSequenceInt64: { std::vector sequence = *member->cast_to>>(); NSMutableArray *array = [NSMutableArray arrayWithCapacity:sequence.size()]; for (const auto &item : sequence) { [array addObject:[NSNumber numberWithLong:item]]; } return [array copy]; } case RTCStatsMemberInterface::kSequenceUint64: { std::vector sequence = *member->cast_to>>(); NSMutableArray *array = [NSMutableArray arrayWithCapacity:sequence.size()]; for (const auto &item : sequence) { [array addObject:[NSNumber numberWithUnsignedLong:item]]; } return [array copy]; } case RTCStatsMemberInterface::kSequenceDouble: { std::vector sequence = *member->cast_to>>(); NSMutableArray *array = [NSMutableArray arrayWithCapacity:sequence.size()]; for (const auto &item : sequence) { [array addObject:[NSNumber numberWithDouble:item]]; } return [array copy]; } case RTCStatsMemberInterface::kSequenceString: { std::vector sequence = *member->cast_to>>(); NSMutableArray *array = [NSMutableArray arrayWithCapacity:sequence.size()]; for (const auto &item : sequence) { [array addObject:[NSString stringForStdString:item]]; } return [array copy]; } default: RTC_NOTREACHED(); } } return nil; } } // namespace webrtc @implementation RTC_OBJC_TYPE (RTCStatistics) @synthesize id = _id; @synthesize timestamp_us = _timestamp_us; @synthesize type = _type; @synthesize values = _values; - (instancetype)initWithStatistics:(const webrtc::RTCStats &)statistics { if (self = [super init]) { _id = [NSString stringForStdString:statistics.id()]; _timestamp_us = statistics.timestamp_us(); _type = [NSString stringWithCString:statistics.type() encoding:NSUTF8StringEncoding]; NSMutableDictionary *values = [NSMutableDictionary dictionary]; for (const webrtc::RTCStatsMemberInterface *member : statistics.Members()) { NSObject *value = ValueFromStatsMember(member); if (value) { NSString *name = [NSString stringWithCString:member->name() encoding:NSUTF8StringEncoding]; RTC_DCHECK(name.length > 0); RTC_DCHECK(!values[name]); values[name] = value; } } _values = [values copy]; } return self; } - (NSString *)description { return [NSString stringWithFormat:@"id = %@, type = %@, timestamp = %.0f, values = %@", self.id, self.type, self.timestamp_us, self.values]; } @end @implementation RTC_OBJC_TYPE (RTCStatisticsReport) @synthesize timestamp_us = _timestamp_us; @synthesize statistics = _statistics; - (NSString *)description { return [NSString stringWithFormat:@"timestamp = %.0f, statistics = %@", self.timestamp_us, self.statistics]; } @end @implementation RTC_OBJC_TYPE (RTCStatisticsReport) (Private) - (instancetype)initWithReport : (const webrtc::RTCStatsReport &)report { if (self = [super init]) { _timestamp_us = report.timestamp_us(); NSMutableDictionary *statisticsById = [NSMutableDictionary dictionaryWithCapacity:report.size()]; for (const auto &stat : report) { RTC_OBJC_TYPE(RTCStatistics) *statistics = [[RTC_OBJC_TYPE(RTCStatistics) alloc] initWithStatistics:stat]; statisticsById[statistics.id] = statistics; } _statistics = [statisticsById copy]; } return self; } @end