| /* | |
| * 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, or NSDictionary of NSString keys to | |
| NSNumber values.*/ | |
| NSObject *ValueFromStatsAttribute(const Attribute &attribute) { | |
| if (!attribute.has_value()) { | |
| return nil; | |
| } | |
| if (attribute.holds_alternative<bool>()) { | |
| return [NSNumber numberWithBool:attribute.get<bool>()]; | |
| } else if (attribute.holds_alternative<int32_t>()) { | |
| return [NSNumber numberWithInt:attribute.get<int32_t>()]; | |
| } else if (attribute.holds_alternative<uint32_t>()) { | |
| return [NSNumber numberWithUnsignedInt:attribute.get<uint32_t>()]; | |
| } else if (attribute.holds_alternative<int64_t>()) { | |
| return [NSNumber numberWithLong:attribute.get<int64_t>()]; | |
| } else if (attribute.holds_alternative<uint64_t>()) { | |
| return [NSNumber numberWithUnsignedLong:attribute.get<uint64_t>()]; | |
| } else if (attribute.holds_alternative<double>()) { | |
| return [NSNumber numberWithDouble:attribute.get<double>()]; | |
| } else if (attribute.holds_alternative<std::string>()) { | |
| return [NSString stringForStdString:attribute.get<std::string>()]; | |
| } else if (attribute.holds_alternative<std::vector<bool>>()) { | |
| std::vector<bool> sequence = attribute.get<std::vector<bool>>(); | |
| NSMutableArray *array = [NSMutableArray arrayWithCapacity:sequence.size()]; | |
| for (auto item : sequence) { | |
| [array addObject:[NSNumber numberWithBool:item]]; | |
| } | |
| return [array copy]; | |
| } else if (attribute.holds_alternative<std::vector<int32_t>>()) { | |
| std::vector<int32_t> sequence = attribute.get<std::vector<int32_t>>(); | |
| NSMutableArray<NSNumber *> *array = | |
| [NSMutableArray arrayWithCapacity:sequence.size()]; | |
| for (const auto &item : sequence) { | |
| [array addObject:[NSNumber numberWithInt:item]]; | |
| } | |
| return [array copy]; | |
| } else if (attribute.holds_alternative<std::vector<uint32_t>>()) { | |
| std::vector<uint32_t> sequence = attribute.get<std::vector<uint32_t>>(); | |
| NSMutableArray<NSNumber *> *array = | |
| [NSMutableArray arrayWithCapacity:sequence.size()]; | |
| for (const auto &item : sequence) { | |
| [array addObject:[NSNumber numberWithUnsignedInt:item]]; | |
| } | |
| return [array copy]; | |
| } else if (attribute.holds_alternative<std::vector<int64_t>>()) { | |
| std::vector<int64_t> sequence = attribute.get<std::vector<int64_t>>(); | |
| NSMutableArray<NSNumber *> *array = | |
| [NSMutableArray arrayWithCapacity:sequence.size()]; | |
| for (const auto &item : sequence) { | |
| [array addObject:[NSNumber numberWithLong:item]]; | |
| } | |
| return [array copy]; | |
| } else if (attribute.holds_alternative<std::vector<uint64_t>>()) { | |
| std::vector<uint64_t> sequence = attribute.get<std::vector<uint64_t>>(); | |
| NSMutableArray<NSNumber *> *array = | |
| [NSMutableArray arrayWithCapacity:sequence.size()]; | |
| for (const auto &item : sequence) { | |
| [array addObject:[NSNumber numberWithUnsignedLong:item]]; | |
| } | |
| return [array copy]; | |
| } else if (attribute.holds_alternative<std::vector<double>>()) { | |
| std::vector<double> sequence = attribute.get<std::vector<double>>(); | |
| NSMutableArray<NSNumber *> *array = | |
| [NSMutableArray arrayWithCapacity:sequence.size()]; | |
| for (const auto &item : sequence) { | |
| [array addObject:[NSNumber numberWithDouble:item]]; | |
| } | |
| return [array copy]; | |
| } else if (attribute.holds_alternative<std::vector<std::string>>()) { | |
| std::vector<std::string> sequence = | |
| attribute.get<std::vector<std::string>>(); | |
| NSMutableArray<NSString *> *array = | |
| [NSMutableArray arrayWithCapacity:sequence.size()]; | |
| for (const auto &item : sequence) { | |
| [array addObject:[NSString stringForStdString:item]]; | |
| } | |
| return [array copy]; | |
| } else if (attribute.holds_alternative<std::map<std::string, uint64_t>>()) { | |
| std::map<std::string, uint64_t> map = | |
| attribute.get<std::map<std::string, uint64_t>>(); | |
| NSMutableDictionary<NSString *, NSNumber *> *dictionary = | |
| [NSMutableDictionary dictionaryWithCapacity:map.size()]; | |
| for (const auto &item : map) { | |
| dictionary[[NSString stringForStdString:item.first]] = @(item.second); | |
| } | |
| return [dictionary copy]; | |
| } else if (attribute.holds_alternative<std::map<std::string, double>>()) { | |
| std::map<std::string, double> map = | |
| attribute.get<std::map<std::string, double>>(); | |
| NSMutableDictionary<NSString *, NSNumber *> *dictionary = | |
| [NSMutableDictionary dictionaryWithCapacity:map.size()]; | |
| for (const auto &item : map) { | |
| dictionary[[NSString stringForStdString:item.first]] = @(item.second); | |
| } | |
| return [dictionary copy]; | |
| } | |
| RTC_DCHECK_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 { | |
| self = [super init]; | |
| if (self) { | |
| _id = [NSString stringForStdString:statistics.id()]; | |
| _timestamp_us = statistics.timestamp().us(); | |
| _type = [NSString stringWithCString:statistics.type() | |
| encoding:NSUTF8StringEncoding]; | |
| const std::vector<webrtc::Attribute> attributes = statistics.Attributes(); | |
| NSMutableDictionary<NSString *, NSObject *> *values = | |
| [NSMutableDictionary dictionaryWithCapacity:attributes.size()]; | |
| for (const auto &attribute : attributes) { | |
| NSObject *value = ValueFromStatsAttribute(attribute); | |
| if (value) { | |
| NSString *name = [NSString stringWithCString:attribute.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 { | |
| self = [super init]; | |
| if (self) { | |
| _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 |