diff options
author | Gil <mcg@google.com> | 2018-01-19 12:27:11 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-19 12:27:11 -0800 |
commit | 39d8252300015c26f1932cff42032613fdb36a09 (patch) | |
tree | 93bb3ab7c476289c4afe6cf91773a60b6f53a94d /Firestore/Source | |
parent | 9f7c094f9f00a6efc0107071f109ef1bc4d7357d (diff) |
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
Diffstat (limited to 'Firestore/Source')
-rw-r--r-- | Firestore/Source/API/FIRGeoPoint.mm (renamed from Firestore/Source/API/FIRGeoPoint.m) | 17 | ||||
-rw-r--r-- | Firestore/Source/Core/FSTTimestamp.mm (renamed from Firestore/Source/Core/FSTTimestamp.m) | 9 | ||||
-rw-r--r-- | Firestore/Source/Local/FSTDocumentReference.h | 4 | ||||
-rw-r--r-- | Firestore/Source/Local/FSTDocumentReference.mm (renamed from Firestore/Source/Local/FSTDocumentReference.m) | 11 | ||||
-rw-r--r-- | Firestore/Source/Local/FSTMemoryMutationQueue.mm (renamed from Firestore/Source/Local/FSTMemoryMutationQueue.m) | 7 | ||||
-rw-r--r-- | Firestore/Source/Model/FSTFieldValue.mm (renamed from Firestore/Source/Model/FSTFieldValue.m) | 72 | ||||
-rw-r--r-- | Firestore/Source/Util/FSTComparison.h | 66 | ||||
-rw-r--r-- | Firestore/Source/Util/FSTComparison.m | 175 |
8 files changed, 89 insertions, 272 deletions
diff --git a/Firestore/Source/API/FIRGeoPoint.m b/Firestore/Source/API/FIRGeoPoint.mm index 72e9e7d..8d89633 100644 --- a/Firestore/Source/API/FIRGeoPoint.m +++ b/Firestore/Source/API/FIRGeoPoint.mm @@ -16,9 +16,14 @@ #import "Firestore/Source/API/FIRGeoPoint+Internal.h" -#import "Firestore/Source/Util/FSTComparison.h" +#import "Firestore/core/src/firebase/firestore/util/comparison.h" + #import "Firestore/Source/Util/FSTUsageValidation.h" +using firebase::firestore::util::DoubleBitwiseEquals; +using firebase::firestore::util::DoubleBitwiseHash; +using firebase::firestore::util::WrapCompare; + NS_ASSUME_NONNULL_BEGIN @implementation FIRGeoPoint @@ -45,11 +50,11 @@ NS_ASSUME_NONNULL_BEGIN } - (NSComparisonResult)compare:(FIRGeoPoint *)other { - NSComparisonResult result = FSTCompareDoubles(self.latitude, other.latitude); + NSComparisonResult result = WrapCompare<double>(self.latitude, other.latitude); if (result != NSOrderedSame) { return result; } else { - return FSTCompareDoubles(self.longitude, other.longitude); + return WrapCompare<double>(self.longitude, other.longitude); } } @@ -67,12 +72,12 @@ NS_ASSUME_NONNULL_BEGIN return NO; } FIRGeoPoint *otherGeoPoint = (FIRGeoPoint *)other; - return FSTDoubleBitwiseEquals(self.latitude, otherGeoPoint.latitude) && - FSTDoubleBitwiseEquals(self.longitude, otherGeoPoint.longitude); + return DoubleBitwiseEquals(self.latitude, otherGeoPoint.latitude) && + DoubleBitwiseEquals(self.longitude, otherGeoPoint.longitude); } - (NSUInteger)hash { - return 31 * FSTDoubleBitwiseHash(self.latitude) + FSTDoubleBitwiseHash(self.longitude); + return 31 * DoubleBitwiseHash(self.latitude) + DoubleBitwiseHash(self.longitude); } /** Implements NSCopying without actually copying because geopoints are immutable. */ diff --git a/Firestore/Source/Core/FSTTimestamp.m b/Firestore/Source/Core/FSTTimestamp.mm index 6d9e314..d2b492a 100644 --- a/Firestore/Source/Core/FSTTimestamp.m +++ b/Firestore/Source/Core/FSTTimestamp.mm @@ -16,8 +16,11 @@ #import "Firestore/Source/Core/FSTTimestamp.h" +#include "Firestore/core/src/firebase/firestore/util/comparison.h" + #import "Firestore/Source/Util/FSTAssert.h" -#import "Firestore/Source/Util/FSTComparison.h" + +using firebase::firestore::util::WrapCompare; NS_ASSUME_NONNULL_BEGIN @@ -110,11 +113,11 @@ static const int kNanosPerSecond = 1000000000; } - (NSComparisonResult)compare:(FSTTimestamp *)other { - NSComparisonResult result = FSTCompareInt64s(self.seconds, other.seconds); + NSComparisonResult result = WrapCompare<int64_t>(self.seconds, other.seconds); if (result != NSOrderedSame) { return result; } - return FSTCompareInt32s(self.nanos, other.nanos); + return WrapCompare<int32_t>(self.nanos, other.nanos); } @end diff --git a/Firestore/Source/Local/FSTDocumentReference.h b/Firestore/Source/Local/FSTDocumentReference.h index eff60e4..04b8416 100644 --- a/Firestore/Source/Local/FSTDocumentReference.h +++ b/Firestore/Source/Local/FSTDocumentReference.h @@ -32,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN @interface FSTDocumentReference : NSObject <NSCopying> /** Initializes the document reference with the given key and ID. */ -- (instancetype)initWithKey:(FSTDocumentKey *)key ID:(int)ID NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithKey:(FSTDocumentKey *)key ID:(int32_t)ID NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @@ -43,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN * The targetID of a referring target or the batchID of a referring mutation batch. (Which this * is depends upon which FSTReferenceSet this reference is a part of.) */ -@property(nonatomic, assign, readonly) int ID; +@property(nonatomic, assign, readonly) int32_t ID; @end diff --git a/Firestore/Source/Local/FSTDocumentReference.m b/Firestore/Source/Local/FSTDocumentReference.mm index 25a5935..4310baa 100644 --- a/Firestore/Source/Local/FSTDocumentReference.m +++ b/Firestore/Source/Local/FSTDocumentReference.mm @@ -16,14 +16,17 @@ #import "Firestore/Source/Local/FSTDocumentReference.h" +#include "Firestore/core/src/firebase/firestore/util/comparison.h" + #import "Firestore/Source/Model/FSTDocumentKey.h" -#import "Firestore/Source/Util/FSTComparison.h" + +using firebase::firestore::util::WrapCompare; NS_ASSUME_NONNULL_BEGIN @implementation FSTDocumentReference -- (instancetype)initWithKey:(FSTDocumentKey *)key ID:(int)ID { +- (instancetype)initWithKey:(FSTDocumentKey *)key ID:(int32_t)ID { self = [super init]; if (self) { _key = key; @@ -67,13 +70,13 @@ const NSComparator FSTDocumentReferenceComparatorByKey = if (result != NSOrderedSame) { return result; } - return FSTCompareInts(left.ID, right.ID); + return WrapCompare<int32_t>(left.ID, right.ID); }; /** Sorts document references by ID then key. */ const NSComparator FSTDocumentReferenceComparatorByID = ^NSComparisonResult(FSTDocumentReference *left, FSTDocumentReference *right) { - NSComparisonResult result = FSTCompareInts(left.ID, right.ID); + NSComparisonResult result = WrapCompare<int32_t>(left.ID, right.ID); if (result != NSOrderedSame) { return result; } diff --git a/Firestore/Source/Local/FSTMemoryMutationQueue.m b/Firestore/Source/Local/FSTMemoryMutationQueue.mm index b155264..702f614 100644 --- a/Firestore/Source/Local/FSTMemoryMutationQueue.m +++ b/Firestore/Source/Local/FSTMemoryMutationQueue.mm @@ -23,10 +23,13 @@ #import "Firestore/Source/Model/FSTMutationBatch.h" #import "Firestore/Source/Model/FSTPath.h" #import "Firestore/Source/Util/FSTAssert.h" -#import "Firestore/Source/Util/FSTComparison.h" NS_ASSUME_NONNULL_BEGIN +static const NSComparator NumberComparator = ^NSComparisonResult(NSNumber *left, NSNumber *right) { + return [left compare:right]; +}; + @interface FSTMemoryMutationQueue () /** @@ -260,7 +263,7 @@ NS_ASSUME_NONNULL_BEGIN // Find unique batchIDs referenced by all documents potentially matching the query. __block FSTImmutableSortedSet<NSNumber *> *uniqueBatchIDs = - [FSTImmutableSortedSet setWithComparator:FSTNumberComparator]; + [FSTImmutableSortedSet setWithComparator:NumberComparator]; FSTDocumentReferenceBlock block = ^(FSTDocumentReference *reference, BOOL *stop) { FSTResourcePath *rowKeyPath = reference.key.path; if (![prefix isPrefixOfPath:rowKeyPath]) { diff --git a/Firestore/Source/Model/FSTFieldValue.m b/Firestore/Source/Model/FSTFieldValue.mm index a6326a7..8ffc98e 100644 --- a/Firestore/Source/Model/FSTFieldValue.m +++ b/Firestore/Source/Model/FSTFieldValue.mm @@ -16,6 +16,9 @@ #import "Firestore/Source/Model/FSTFieldValue.h" +#include "Firestore/core/src/firebase/firestore/util/comparison.h" +#include "Firestore/core/src/firebase/firestore/util/string_apple.h" + #import "Firestore/Source/API/FIRGeoPoint+Internal.h" #import "Firestore/Source/API/FIRSnapshotOptions+Internal.h" #import "Firestore/Source/Core/FSTTimestamp.h" @@ -24,7 +27,14 @@ #import "Firestore/Source/Model/FSTPath.h" #import "Firestore/Source/Util/FSTAssert.h" #import "Firestore/Source/Util/FSTClasses.h" -#import "Firestore/Source/Util/FSTComparison.h" + +using firebase::firestore::util::Comparator; +using firebase::firestore::util::CompareMixedNumber; +using firebase::firestore::util::DoubleBitwiseEquals; +using firebase::firestore::util::DoubleBitwiseHash; +using firebase::firestore::util::MakeStringView; +using firebase::firestore::util::ReverseOrder; +using firebase::firestore::util::WrapCompare; NS_ASSUME_NONNULL_BEGIN @@ -208,7 +218,7 @@ NS_ASSUME_NONNULL_BEGIN - (NSComparisonResult)compare:(FSTFieldValue *)other { if ([other isKindOfClass:[FSTBooleanValue class]]) { - return FSTCompareBools(self.internalValue, ((FSTBooleanValue *)other).internalValue); + return WrapCompare<bool>(self.internalValue, ((FSTBooleanValue *)other).internalValue); } else { return [self defaultCompare:other]; } @@ -231,19 +241,22 @@ NS_ASSUME_NONNULL_BEGIN if ([self isKindOfClass:[FSTDoubleValue class]]) { double thisDouble = ((FSTDoubleValue *)self).internalValue; if ([other isKindOfClass:[FSTDoubleValue class]]) { - return FSTCompareDoubles(thisDouble, ((FSTDoubleValue *)other).internalValue); + return WrapCompare(thisDouble, ((FSTDoubleValue *)other).internalValue); } else { FSTAssert([other isKindOfClass:[FSTIntegerValue class]], @"Unknown number value: %@", other); - return FSTCompareMixed(thisDouble, ((FSTIntegerValue *)other).internalValue); + auto result = CompareMixedNumber(thisDouble, ((FSTIntegerValue *)other).internalValue); + return static_cast<NSComparisonResult>(result); } } else { int64_t thisInt = ((FSTIntegerValue *)self).internalValue; if ([other isKindOfClass:[FSTIntegerValue class]]) { - return FSTCompareInt64s(thisInt, ((FSTIntegerValue *)other).internalValue); + return WrapCompare(thisInt, ((FSTIntegerValue *)other).internalValue); } else { FSTAssert([other isKindOfClass:[FSTDoubleValue class]], @"Unknown number value: %@", other); - return -1 * FSTCompareMixed(((FSTDoubleValue *)other).internalValue, thisInt); + double otherDouble = ((FSTDoubleValue *)other).internalValue; + auto result = ReverseOrder(CompareMixedNumber(otherDouble, thisInt)); + return static_cast<NSComparisonResult>(result); } } } @@ -334,11 +347,11 @@ NS_ASSUME_NONNULL_BEGIN // NOTE: isEqual: should compare NaN equal to itself and -0.0 not equal to 0.0. return [other isKindOfClass:[FSTDoubleValue class]] && - FSTDoubleBitwiseEquals(self.internalValue, ((FSTDoubleValue *)other).internalValue); + DoubleBitwiseEquals(self.internalValue, ((FSTDoubleValue *)other).internalValue); } - (NSUInteger)hash { - return FSTDoubleBitwiseHash(self.internalValue); + return DoubleBitwiseHash(self.internalValue); } // NOTE: compare: is implemented in NumberValue. @@ -347,6 +360,17 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - FSTStringValue +/** + * Specialization of Comparator for NSStrings. + */ +template <> +struct Comparator<NSString *> { + bool operator()(NSString *left, NSString *right) const { + Comparator<absl::string_view> lessThan; + return lessThan(MakeStringView(left), MakeStringView(right)); + } +}; + @interface FSTStringValue () @property(nonatomic, copy, readonly) NSString *internalValue; @end @@ -385,7 +409,7 @@ NS_ASSUME_NONNULL_BEGIN - (NSComparisonResult)compare:(FSTFieldValue *)other { if ([other isKindOfClass:[FSTStringValue class]]) { - return FSTCompareStrings(self.internalValue, ((FSTStringValue *)other).internalValue); + return WrapCompare(self.internalValue, ((FSTStringValue *)other).internalValue); } else { return [self defaultCompare:other]; } @@ -556,6 +580,22 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - FSTBlobValue +static NSComparisonResult CompareBytes(NSData *left, NSData *right) { + NSUInteger minLength = MIN(left.length, right.length); + int result = memcmp(left.bytes, right.bytes, minLength); + if (result < 0) { + return NSOrderedAscending; + } else if (result > 0) { + return NSOrderedDescending; + } else if (left.length < right.length) { + return NSOrderedAscending; + } else if (left.length > right.length) { + return NSOrderedDescending; + } else { + return NSOrderedSame; + } +} + @interface FSTBlobValue () @property(nonatomic, copy, readonly) NSData *internalValue; @end @@ -594,7 +634,7 @@ NS_ASSUME_NONNULL_BEGIN - (NSComparisonResult)compare:(FSTFieldValue *)other { if ([other isKindOfClass:[FSTBlobValue class]]) { - return FSTCompareBytes(self.internalValue, ((FSTBlobValue *)other).internalValue); + return CompareBytes(self.internalValue, ((FSTBlobValue *)other).internalValue); } else { return [self defaultCompare:other]; } @@ -664,6 +704,10 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - FSTObjectValue +static const NSComparator StringComparator = ^NSComparisonResult(NSString *left, NSString *right) { + return WrapCompare(left, right); +}; + @interface FSTObjectValue () @property(nonatomic, strong, readonly) FSTImmutableSortedDictionary<NSString *, FSTFieldValue *> *internalValue; @@ -677,7 +721,7 @@ NS_ASSUME_NONNULL_BEGIN dispatch_once(&onceToken, ^{ FSTImmutableSortedDictionary<NSString *, FSTFieldValue *> *empty = - [FSTImmutableSortedDictionary dictionaryWithComparator:FSTStringComparator]; + [FSTImmutableSortedDictionary dictionaryWithComparator:StringComparator]; sharedEmptyInstance = [[FSTObjectValue alloc] initWithImmutableDictionary:empty]; }); return sharedEmptyInstance; @@ -694,7 +738,7 @@ NS_ASSUME_NONNULL_BEGIN - (id)initWithDictionary:(NSDictionary<NSString *, FSTFieldValue *> *)value { FSTImmutableSortedDictionary<NSString *, FSTFieldValue *> *dictionary = - [FSTImmutableSortedDictionary dictionaryWithDictionary:value comparator:FSTStringComparator]; + [FSTImmutableSortedDictionary dictionaryWithDictionary:value comparator:StringComparator]; return [self initWithImmutableDictionary:dictionary]; } @@ -748,7 +792,7 @@ NS_ASSUME_NONNULL_BEGIN key2 = [enumerator2 nextObject]; } // Only equal if both enumerators are exhausted. - return FSTCompareBools(key1 != nil, key2 != nil); + return WrapCompare(key1 != nil, key2 != nil); } else { return [self defaultCompare:other]; } @@ -876,7 +920,7 @@ NS_ASSUME_NONNULL_BEGIN return cmp; } } - return FSTCompareUIntegers(selfArray.count, otherArray.count); + return WrapCompare<int64_t>(selfArray.count, otherArray.count); } else { return [self defaultCompare:other]; } diff --git a/Firestore/Source/Util/FSTComparison.h b/Firestore/Source/Util/FSTComparison.h deleted file mode 100644 index e6e57e6..0000000 --- a/Firestore/Source/Util/FSTComparison.h +++ /dev/null @@ -1,66 +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 <Foundation/Foundation.h> - -NS_ASSUME_NONNULL_BEGIN - -/** Compares two NSStrings. */ -NSComparisonResult FSTCompareStrings(NSString *left, NSString *right); - -/** Compares two BOOLs. */ -NSComparisonResult FSTCompareBools(BOOL left, BOOL right); - -/** Compares two integers. */ -NSComparisonResult FSTCompareInts(int left, int right); - -/** Compares two int32_t. */ -NSComparisonResult FSTCompareInt32s(int32_t left, int32_t right); - -/** Compares two int64_t. */ -NSComparisonResult FSTCompareInt64s(int64_t left, int64_t right); - -/** Compares two NSUIntegers. */ -NSComparisonResult FSTCompareUIntegers(NSUInteger left, NSUInteger right); - -/** Compares two doubles (using Firestore semantics for NaN). */ -NSComparisonResult FSTCompareDoubles(double left, double right); - -/** Compares a double and an int64_t. */ -NSComparisonResult FSTCompareMixed(double doubleValue, int64_t longValue); - -/** Compare two NSData byte sequences. */ -NSComparisonResult FSTCompareBytes(NSData *left, NSData *right); - -/** A simple NSComparator for comparing NSNumber instances. */ -extern const NSComparator FSTNumberComparator; - -/** A simple NSComparator for comparing NSString instances. */ -extern const NSComparator FSTStringComparator; - -/** - * Compares the bitwise representation of two doubles, but normalizes NaN values. This is - * similar to what the backend and android clients do, including comparing -0.0 as not equal to 0.0. - */ -BOOL FSTDoubleBitwiseEquals(double left, double right); - -/** - * Computes a bitwise hash of a double, but normalizes NaN values, suitable for use when using - * FSTDoublesAreBitwiseEqual for equality. - */ -NSUInteger FSTDoubleBitwiseHash(double d); - -NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Util/FSTComparison.m b/Firestore/Source/Util/FSTComparison.m deleted file mode 100644 index 9c5c3eb..0000000 --- a/Firestore/Source/Util/FSTComparison.m +++ /dev/null @@ -1,175 +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/Util/FSTComparison.h" - -NS_ASSUME_NONNULL_BEGIN - -union DoubleBits { - double d; - uint64_t bits; -}; - -const NSComparator FSTNumberComparator = ^NSComparisonResult(NSNumber *left, NSNumber *right) { - return [left compare:right]; -}; - -const NSComparator FSTStringComparator = ^NSComparisonResult(NSString *left, NSString *right) { - return FSTCompareStrings(left, right); -}; - -NSComparisonResult FSTCompareStrings(NSString *left, NSString *right) { - // NOTE: NSLiteralSearch is necessary to compare the raw character codes. By default, - // precomposed characters are considered equivalent to their decomposed equivalents. - return [left compare:right options:NSLiteralSearch]; -} - -NSComparisonResult FSTCompareBools(BOOL left, BOOL right) { - if (!left) { - return right ? NSOrderedAscending : NSOrderedSame; - } else { - return right ? NSOrderedSame : NSOrderedDescending; - } -} - -NSComparisonResult FSTCompareInts(int left, int right) { - if (left > right) { - return NSOrderedDescending; - } - if (right > left) { - return NSOrderedAscending; - } - return NSOrderedSame; -} - -NSComparisonResult FSTCompareInt32s(int32_t left, int32_t right) { - if (left > right) { - return NSOrderedDescending; - } - if (right > left) { - return NSOrderedAscending; - } - return NSOrderedSame; -} - -NSComparisonResult FSTCompareInt64s(int64_t left, int64_t right) { - if (left > right) { - return NSOrderedDescending; - } - if (right > left) { - return NSOrderedAscending; - } - return NSOrderedSame; -} - -NSComparisonResult FSTCompareUIntegers(NSUInteger left, NSUInteger right) { - if (left > right) { - return NSOrderedDescending; - } - if (right > left) { - return NSOrderedAscending; - } - return NSOrderedSame; -} - -NSComparisonResult FSTCompareDoubles(double left, double right) { - // NaN sorts equal to itself and before any other number. - if (left < right) { - return NSOrderedAscending; - } else if (left > right) { - return NSOrderedDescending; - } else if (left == right) { - return NSOrderedSame; - } else { - // One or both left and right is NaN. - if (isnan(left)) { - return isnan(right) ? NSOrderedSame : NSOrderedAscending; - } else { - return NSOrderedDescending; - } - } -} - -static const double LONG_MIN_VALUE_AS_DOUBLE = (double)LLONG_MIN; -static const double LONG_MAX_VALUE_AS_DOUBLE = (double)LLONG_MAX; - -NSComparisonResult FSTCompareMixed(double doubleValue, int64_t longValue) { - // LLONG_MIN has an exact representation as double, so to check for a value outside the range - // representable by long, we have to check for strictly less than LLONG_MIN. Note that this also - // handles negative infinity. - if (doubleValue < LONG_MIN_VALUE_AS_DOUBLE) { - return NSOrderedAscending; - } - - // LLONG_MAX has no exact representation as double (casting as we've done makes 2^63, which is - // larger than LLONG_MAX), so consider any value greater than or equal to the threshold to be out - // of range. This also handles positive infinity. - if (doubleValue >= LONG_MAX_VALUE_AS_DOUBLE) { - return NSOrderedDescending; - } - - // In Firestore NaN is defined to compare before all other numbers. - if (isnan(doubleValue)) { - return NSOrderedAscending; - } - - int64_t doubleAsLong = (int64_t)doubleValue; - NSComparisonResult cmp = FSTCompareInt64s(doubleAsLong, longValue); - if (cmp != NSOrderedSame) { - return cmp; - } - - // At this point the long representations are equal but this could be due to rounding. - double longAsDouble = (double)longValue; - return FSTCompareDoubles(doubleValue, longAsDouble); -} - -NSComparisonResult FSTCompareBytes(NSData *left, NSData *right) { - NSUInteger minLength = MIN(left.length, right.length); - int result = memcmp(left.bytes, right.bytes, minLength); - if (result < 0) { - return NSOrderedAscending; - } else if (result > 0) { - return NSOrderedDescending; - } else if (left.length < right.length) { - return NSOrderedAscending; - } else if (left.length > right.length) { - return NSOrderedDescending; - } else { - return NSOrderedSame; - } -} - -/** Helper to normalize a double and then return the raw bits as a uint64_t. */ -uint64_t FSTDoubleBits(double d) { - if (isnan(d)) { - d = NAN; - } - union DoubleBits converter = {.d = d}; - return converter.bits; -} - -BOOL FSTDoubleBitwiseEquals(double left, double right) { - return FSTDoubleBits(left) == FSTDoubleBits(right); -} - -NSUInteger FSTDoubleBitwiseHash(double d) { - uint64_t bits = FSTDoubleBits(d); - // Note that x ^ (x >> 32) works fine for both 32 and 64 bit definitions of NSUInteger - return (((NSUInteger)bits) ^ (NSUInteger)(bits >> 32)); -} - -NS_ASSUME_NONNULL_END |