From 39d8252300015c26f1932cff42032613fdb36a09 Mon Sep 17 00:00:00 2001 From: Gil Date: Fri, 19 Jan 2018 12:27:11 -0800 Subject: Port comparison to C++ (#678) This reimplements our comparison functions as C++ Comparators and then provides compatibility shims for interoperating with existing Objective-C usage. A few specialized comparators aren't suitable for porting but only have a single usage (e.g. CompareBytes for comparing NSData * instances). In these cases I've moved them into the caller. * Use int32_t for typeof(ID) in FSTDocumentReference * Migrate callers of FSTComparison.h to Objective-C++ * Port comparison to C++ * Migrate usages of FSTComparison.h to C++ equivalents * Remove FSTComparison --- Firestore/Source/Core/FSTTimestamp.m | 122 --------------------------------- Firestore/Source/Core/FSTTimestamp.mm | 125 ++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 122 deletions(-) delete mode 100644 Firestore/Source/Core/FSTTimestamp.m create mode 100644 Firestore/Source/Core/FSTTimestamp.mm (limited to 'Firestore/Source/Core') diff --git a/Firestore/Source/Core/FSTTimestamp.m b/Firestore/Source/Core/FSTTimestamp.m deleted file mode 100644 index 6d9e314..0000000 --- a/Firestore/Source/Core/FSTTimestamp.m +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "Firestore/Source/Core/FSTTimestamp.h" - -#import "Firestore/Source/Util/FSTAssert.h" -#import "Firestore/Source/Util/FSTComparison.h" - -NS_ASSUME_NONNULL_BEGIN - -static const int kNanosPerSecond = 1000000000; - -@implementation FSTTimestamp - -#pragma mark - Constructors - -+ (instancetype)timestamp { - return [FSTTimestamp timestampWithDate:[NSDate date]]; -} - -+ (instancetype)timestampWithDate:(NSDate *)date { - double secondsDouble; - double fraction = modf(date.timeIntervalSince1970, &secondsDouble); - // GCP Timestamps always have non-negative nanos. - if (fraction < 0) { - fraction += 1.0; - secondsDouble -= 1.0; - } - int64_t seconds = (int64_t)secondsDouble; - int32_t nanos = (int32_t)(fraction * kNanosPerSecond); - return [[FSTTimestamp alloc] initWithSeconds:seconds nanos:nanos]; -} - -- (instancetype)initWithSeconds:(int64_t)seconds nanos:(int32_t)nanos { - self = [super init]; - if (self) { - FSTAssert(nanos >= 0, @"timestamp nanoseconds out of range: %d", nanos); - FSTAssert(nanos < 1e9, @"timestamp nanoseconds out of range: %d", nanos); - // Midnight at the beginning of 1/1/1 is the earliest timestamp Firestore supports. - FSTAssert(seconds >= -62135596800L, @"timestamp seconds out of range: %lld", seconds); - // This will break in the year 10,000. - FSTAssert(seconds < 253402300800L, @"timestamp seconds out of range: %lld", seconds); - - _seconds = seconds; - _nanos = nanos; - } - return self; -} - -#pragma mark - NSObject methods - -- (BOOL)isEqual:(id)object { - if (self == object) { - return YES; - } - if (![object isKindOfClass:[FSTTimestamp class]]) { - return NO; - } - return [self isEqualToTimestamp:(FSTTimestamp *)object]; -} - -- (NSUInteger)hash { - return (NSUInteger)((self.seconds >> 32) ^ self.seconds ^ self.nanos); -} - -- (NSString *)description { - return [NSString - stringWithFormat:@"", self.seconds, self.nanos]; -} - -/** Implements NSCopying without actually copying because timestamps are immutable. */ -- (id)copyWithZone:(NSZone *_Nullable)zone { - return self; -} - -#pragma mark - Public methods - -- (NSDate *)approximateDateValue { - NSTimeInterval interval = (NSTimeInterval)self.seconds + ((NSTimeInterval)self.nanos) / 1e9; - return [NSDate dateWithTimeIntervalSince1970:interval]; -} - -- (BOOL)isEqualToTimestamp:(FSTTimestamp *)other { - return [self compare:other] == NSOrderedSame; -} - -- (NSString *)ISO8601String { - NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; - formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss"; - formatter.timeZone = [NSTimeZone timeZoneWithName:@"UTC"]; - NSDate *secondsDate = [NSDate dateWithTimeIntervalSince1970:self.seconds]; - NSString *secondsString = [formatter stringFromDate:secondsDate]; - FSTAssert(secondsString.length == 19, @"Invalid ISO string: %@", secondsString); - - NSString *nanosString = [NSString stringWithFormat:@"%09d", self.nanos]; - return [NSString stringWithFormat:@"%@.%@Z", secondsString, nanosString]; -} - -- (NSComparisonResult)compare:(FSTTimestamp *)other { - NSComparisonResult result = FSTCompareInt64s(self.seconds, other.seconds); - if (result != NSOrderedSame) { - return result; - } - return FSTCompareInt32s(self.nanos, other.nanos); -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Core/FSTTimestamp.mm b/Firestore/Source/Core/FSTTimestamp.mm new file mode 100644 index 0000000..d2b492a --- /dev/null +++ b/Firestore/Source/Core/FSTTimestamp.mm @@ -0,0 +1,125 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Firestore/Source/Core/FSTTimestamp.h" + +#include "Firestore/core/src/firebase/firestore/util/comparison.h" + +#import "Firestore/Source/Util/FSTAssert.h" + +using firebase::firestore::util::WrapCompare; + +NS_ASSUME_NONNULL_BEGIN + +static const int kNanosPerSecond = 1000000000; + +@implementation FSTTimestamp + +#pragma mark - Constructors + ++ (instancetype)timestamp { + return [FSTTimestamp timestampWithDate:[NSDate date]]; +} + ++ (instancetype)timestampWithDate:(NSDate *)date { + double secondsDouble; + double fraction = modf(date.timeIntervalSince1970, &secondsDouble); + // GCP Timestamps always have non-negative nanos. + if (fraction < 0) { + fraction += 1.0; + secondsDouble -= 1.0; + } + int64_t seconds = (int64_t)secondsDouble; + int32_t nanos = (int32_t)(fraction * kNanosPerSecond); + return [[FSTTimestamp alloc] initWithSeconds:seconds nanos:nanos]; +} + +- (instancetype)initWithSeconds:(int64_t)seconds nanos:(int32_t)nanos { + self = [super init]; + if (self) { + FSTAssert(nanos >= 0, @"timestamp nanoseconds out of range: %d", nanos); + FSTAssert(nanos < 1e9, @"timestamp nanoseconds out of range: %d", nanos); + // Midnight at the beginning of 1/1/1 is the earliest timestamp Firestore supports. + FSTAssert(seconds >= -62135596800L, @"timestamp seconds out of range: %lld", seconds); + // This will break in the year 10,000. + FSTAssert(seconds < 253402300800L, @"timestamp seconds out of range: %lld", seconds); + + _seconds = seconds; + _nanos = nanos; + } + return self; +} + +#pragma mark - NSObject methods + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[FSTTimestamp class]]) { + return NO; + } + return [self isEqualToTimestamp:(FSTTimestamp *)object]; +} + +- (NSUInteger)hash { + return (NSUInteger)((self.seconds >> 32) ^ self.seconds ^ self.nanos); +} + +- (NSString *)description { + return [NSString + stringWithFormat:@"", self.seconds, self.nanos]; +} + +/** Implements NSCopying without actually copying because timestamps are immutable. */ +- (id)copyWithZone:(NSZone *_Nullable)zone { + return self; +} + +#pragma mark - Public methods + +- (NSDate *)approximateDateValue { + NSTimeInterval interval = (NSTimeInterval)self.seconds + ((NSTimeInterval)self.nanos) / 1e9; + return [NSDate dateWithTimeIntervalSince1970:interval]; +} + +- (BOOL)isEqualToTimestamp:(FSTTimestamp *)other { + return [self compare:other] == NSOrderedSame; +} + +- (NSString *)ISO8601String { + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss"; + formatter.timeZone = [NSTimeZone timeZoneWithName:@"UTC"]; + NSDate *secondsDate = [NSDate dateWithTimeIntervalSince1970:self.seconds]; + NSString *secondsString = [formatter stringFromDate:secondsDate]; + FSTAssert(secondsString.length == 19, @"Invalid ISO string: %@", secondsString); + + NSString *nanosString = [NSString stringWithFormat:@"%09d", self.nanos]; + return [NSString stringWithFormat:@"%@.%@Z", secondsString, nanosString]; +} + +- (NSComparisonResult)compare:(FSTTimestamp *)other { + NSComparisonResult result = WrapCompare(self.seconds, other.seconds); + if (result != NSOrderedSame) { + return result; + } + return WrapCompare(self.nanos, other.nanos); +} + +@end + +NS_ASSUME_NONNULL_END -- cgit v1.2.3