From 7459be46ffb27bc95e155a1b267f91093f1a62b0 Mon Sep 17 00:00:00 2001 From: Gil Date: Mon, 27 Nov 2017 21:00:18 -0800 Subject: Port autoid to C++ and remove FSTUtil (#475) * Port autoid to C++ * Reimplement FSTUtil on top of firestore::CreateAutoId directly * Migrate FSTUtil callers to directly use firestore::CreateAutoId * Remove FSTUtil --- Firestore/CMakeLists.txt | 3 + .../Example/Firestore.xcodeproj/project.pbxproj | 24 ++++- .../Example/Tests/Util/FSTIntegrationTestCase.mm | 9 +- Firestore/Example/Tests/Util/FSTUtilTests.m | 35 ------- Firestore/Source/API/FIRCollectionReference.m | 113 -------------------- Firestore/Source/API/FIRCollectionReference.mm | 114 +++++++++++++++++++++ Firestore/Source/Util/FSTUsageValidation.h | 8 ++ Firestore/Source/Util/FSTUtil.h | 28 ----- Firestore/Source/Util/FSTUtil.m | 38 ------- Firestore/src/core/util/CMakeLists.txt | 22 ++++ Firestore/src/core/util/autoid.cc | 52 ++++++++++ Firestore/src/core/util/autoid.h | 29 ++++++ Firestore/test/core/util/CMakeLists.txt | 22 ++++ Firestore/test/core/util/autoid_test.cc | 34 ++++++ 14 files changed, 310 insertions(+), 221 deletions(-) delete mode 100644 Firestore/Example/Tests/Util/FSTUtilTests.m delete mode 100644 Firestore/Source/API/FIRCollectionReference.m create mode 100644 Firestore/Source/API/FIRCollectionReference.mm delete mode 100644 Firestore/Source/Util/FSTUtil.h delete mode 100644 Firestore/Source/Util/FSTUtil.m create mode 100644 Firestore/src/core/util/CMakeLists.txt create mode 100644 Firestore/src/core/util/autoid.cc create mode 100644 Firestore/src/core/util/autoid.h create mode 100644 Firestore/test/core/util/CMakeLists.txt create mode 100644 Firestore/test/core/util/autoid_test.cc diff --git a/Firestore/CMakeLists.txt b/Firestore/CMakeLists.txt index 4274056..119af5e 100644 --- a/Firestore/CMakeLists.txt +++ b/Firestore/CMakeLists.txt @@ -16,3 +16,6 @@ include(${PROJECT_SOURCE_DIR}/cmake/external/googletest.cmake) add_subdirectory(src/support) add_subdirectory(test/support) + +add_subdirectory(src/core/util) +add_subdirectory(test/core/util) diff --git a/Firestore/Example/Firestore.xcodeproj/project.pbxproj b/Firestore/Example/Firestore.xcodeproj/project.pbxproj index 034a96e..f56af4c 100644 --- a/Firestore/Example/Firestore.xcodeproj/project.pbxproj +++ b/Firestore/Example/Firestore.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ /* Begin PBXBuildFile section */ 3B843E4C1F3A182900548890 /* remote_store_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 3B843E4A1F3930A400548890 /* remote_store_spec_test.json */; }; 5463926E1FBEDE28005031AA /* secure_random_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5463926D1FBEDE28005031AA /* secure_random_test.cc */; }; + 5471DCF91FBF99AC00656CD3 /* autoid_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5471DCF71FBF99A300656CD3 /* autoid_test.cc */; }; 54764FAB1FAA0C320085E60A /* string_util_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54764FAA1FAA0C320085E60A /* string_util_test.cc */; }; 54764FAF1FAA21B90085E60A /* FSTGoogleTestTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 54764FAE1FAA21B90085E60A /* FSTGoogleTestTests.mm */; }; 5491BC721FB44593008B3588 /* FSTIntegrationTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5491BC711FB44593008B3588 /* FSTIntegrationTestCase.mm */; }; @@ -135,7 +136,6 @@ DE51B1FF1F0D493A0013853F /* FSTAssertTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DE51B1861F0D48AC0013853F /* FSTAssertTests.m */; }; DE51B2001F0D493A0013853F /* FSTComparisonTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DE51B1871F0D48AC0013853F /* FSTComparisonTests.m */; }; DE51B2011F0D493E0013853F /* FSTHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DE51B1891F0D48AC0013853F /* FSTHelpers.m */; }; - DE51B2021F0D493E0013853F /* FSTUtilTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DE51B18A1F0D48AC0013853F /* FSTUtilTests.m */; }; F104BBD69BC3F0796E3A77C1 /* Pods_Firestore_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69F6A10DBD6187489481CD76 /* Pods_Firestore_Tests.framework */; }; /* End PBXBuildFile section */ @@ -185,6 +185,7 @@ 42491D7DC8C8CD245CC22B93 /* Pods-SwiftBuildTest.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftBuildTest.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftBuildTest/Pods-SwiftBuildTest.debug.xcconfig"; sourceTree = ""; }; 4EBC5F5ABE1FD097EFE5E224 /* Pods-Firestore_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Example/Pods-Firestore_Example.release.xcconfig"; sourceTree = ""; }; 5463926D1FBEDE28005031AA /* secure_random_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = secure_random_test.cc; path = ../../test/support/secure_random_test.cc; sourceTree = ""; }; + 5471DCF71FBF99A300656CD3 /* autoid_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = autoid_test.cc; path = ../../test/core/util/autoid_test.cc; sourceTree = ""; }; 54764FAA1FAA0C320085E60A /* string_util_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = string_util_test.cc; path = ../../Port/string_util_test.cc; sourceTree = ""; }; 54764FAE1FAA21B90085E60A /* FSTGoogleTestTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = FSTGoogleTestTests.mm; path = GoogleTest/FSTGoogleTestTests.mm; sourceTree = ""; }; 5491BC711FB44593008B3588 /* FSTIntegrationTestCase.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTIntegrationTestCase.mm; sourceTree = ""; }; @@ -281,7 +282,6 @@ DE51B1871F0D48AC0013853F /* FSTComparisonTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSTComparisonTests.m; sourceTree = ""; }; DE51B1881F0D48AC0013853F /* FSTHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSTHelpers.h; sourceTree = ""; }; DE51B1891F0D48AC0013853F /* FSTHelpers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSTHelpers.m; sourceTree = ""; }; - DE51B18A1F0D48AC0013853F /* FSTUtilTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSTUtilTests.m; sourceTree = ""; }; DE51B1941F0D48AC0013853F /* FSTLevelDBSpecTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSTLevelDBSpecTests.m; sourceTree = ""; }; DE51B1951F0D48AC0013853F /* FSTMemorySpecTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FSTMemorySpecTests.m; sourceTree = ""; }; DE51B1961F0D48AC0013853F /* FSTMockDatastore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FSTMockDatastore.h; sourceTree = ""; }; @@ -374,9 +374,26 @@ name = support; sourceTree = ""; }; + 5471DCFA1FBF99B100656CD3 /* core */ = { + isa = PBXGroup; + children = ( + 5471DCFB1FBF99B800656CD3 /* util */, + ); + name = core; + sourceTree = ""; + }; + 5471DCFB1FBF99B800656CD3 /* util */ = { + isa = PBXGroup; + children = ( + 5471DCF71FBF99A300656CD3 /* autoid_test.cc */, + ); + name = util; + sourceTree = ""; + }; 54764FAC1FAA0C390085E60A /* GoogleTests */ = { isa = PBXGroup; children = ( + 5471DCFA1FBF99B100656CD3 /* core */, 54764FAD1FAA0C650085E60A /* Port */, 5463926F1FBEDE2F005031AA /* support */, 54764FAE1FAA21B90085E60A /* FSTGoogleTestTests.mm */, @@ -595,7 +612,6 @@ DE51B1871F0D48AC0013853F /* FSTComparisonTests.m */, DE51B1881F0D48AC0013853F /* FSTHelpers.h */, DE51B1891F0D48AC0013853F /* FSTHelpers.m */, - DE51B18A1F0D48AC0013853F /* FSTUtilTests.m */, 54E9282A1F339CAD00C1953E /* XCTestCase+Await.h */, 54E9282B1F339CAD00C1953E /* XCTestCase+Await.m */, D5B259DAA9149B80D6245B57 /* FSTTestDispatchQueue.h */, @@ -1163,11 +1179,11 @@ DE51B1E11F0D490D0013853F /* FSTMemoryRemoteDocumentCacheTests.m in Sources */, DE51B1FF1F0D493A0013853F /* FSTAssertTests.m in Sources */, DE51B1D31F0D48CD0013853F /* FSTViewSnapshotTest.m in Sources */, - DE51B2021F0D493E0013853F /* FSTUtilTests.m in Sources */, DE51B1F91F0D491F0013853F /* FSTWatchChangeTests.m in Sources */, DE51B1F81F0D491F0013853F /* FSTWatchChange+Testing.m in Sources */, DE51B1EB1F0D490D0013853F /* FSTWriteGroupTests.mm in Sources */, DE51B2011F0D493E0013853F /* FSTHelpers.m in Sources */, + 5471DCF91FBF99AC00656CD3 /* autoid_test.cc in Sources */, DE51B1F61F0D491B0013853F /* FSTSerializerBetaTests.m in Sources */, DE51B1F01F0D49140013853F /* FSTFieldValueTests.m in Sources */, 5491BC721FB44593008B3588 /* FSTIntegrationTestCase.mm in Sources */, diff --git a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm index 47d6e76..2c29bf0 100644 --- a/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm +++ b/Firestore/Example/Tests/Util/FSTIntegrationTestCase.mm @@ -21,12 +21,13 @@ #import #import +#include "Firestore/src/core/util/autoid.h" + #import "Firestore/Source/API/FIRFirestore+Internal.h" #import "Firestore/Source/Auth/FSTEmptyCredentialsProvider.h" #import "Firestore/Source/Local/FSTLevelDB.h" #import "Firestore/Source/Model/FSTDatabaseID.h" #import "Firestore/Source/Util/FSTDispatchQueue.h" -#import "Firestore/Source/Util/FSTUtil.h" #import "Firestore/Example/Tests/Util/FSTEventAccumulator.h" #import "Firestore/Example/Tests/Util/FSTTestDispatchQueue.h" @@ -164,7 +165,8 @@ NS_ASSUME_NONNULL_BEGIN } - (NSString *)documentPath { - return [@"test-collection/" stringByAppendingString:[FSTUtil autoID]]; + std::string autoId = firestore::CreateAutoId(); + return [NSString stringWithFormat:@"test-collection/%s", autoId.c_str()]; } - (FIRDocumentReference *)documentRef { @@ -172,7 +174,8 @@ NS_ASSUME_NONNULL_BEGIN } - (FIRCollectionReference *)collectionRef { - NSString *collectionName = [@"test-collection-" stringByAppendingString:[FSTUtil autoID]]; + std::string autoId = firestore::CreateAutoId(); + NSString *collectionName = [NSString stringWithFormat:@"test-collection-%s", autoId.c_str()]; return [self.db collectionWithPath:collectionName]; } diff --git a/Firestore/Example/Tests/Util/FSTUtilTests.m b/Firestore/Example/Tests/Util/FSTUtilTests.m deleted file mode 100644 index d59ed7a..0000000 --- a/Firestore/Example/Tests/Util/FSTUtilTests.m +++ /dev/null @@ -1,35 +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/FSTUtil.h" - -#import - -@interface FSTUtilTests : XCTestCase -@end - -@implementation FSTUtilTests - -- (void)testAutoID { - NSString *autoID = [FSTUtil autoID]; - XCTAssertEqual([autoID length], 20); - for (NSUInteger i = 0; i < 20; i++) { - unichar c = [autoID characterAtIndex:i]; - XCTAssert(c >= ' ' && c <= '~', @"Should be printable ascii characters."); - } -} - -@end diff --git a/Firestore/Source/API/FIRCollectionReference.m b/Firestore/Source/API/FIRCollectionReference.m deleted file mode 100644 index f90bff5..0000000 --- a/Firestore/Source/API/FIRCollectionReference.m +++ /dev/null @@ -1,113 +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 "FIRCollectionReference.h" - -#import "Firestore/Source/API/FIRDocumentReference+Internal.h" -#import "Firestore/Source/API/FIRQuery+Internal.h" -#import "Firestore/Source/API/FIRQuery_Init.h" -#import "Firestore/Source/Core/FSTQuery.h" -#import "Firestore/Source/Model/FSTDocumentKey.h" -#import "Firestore/Source/Model/FSTPath.h" -#import "Firestore/Source/Util/FSTAssert.h" -#import "Firestore/Source/Util/FSTUsageValidation.h" -#import "Firestore/Source/Util/FSTUtil.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FIRCollectionReference () -- (instancetype)initWithPath:(FSTResourcePath *)path - firestore:(FIRFirestore *)firestore NS_DESIGNATED_INITIALIZER; - -// Mark the super class designated initializer unavailable. -- (instancetype)initWithQuery:(FSTQuery *)query - firestore:(FIRFirestore *)firestore - __attribute__((unavailable("Use the initWithPath constructor of FIRCollectionReference."))); -@end - -@implementation FIRCollectionReference (Internal) -+ (instancetype)referenceWithPath:(FSTResourcePath *)path firestore:(FIRFirestore *)firestore { - return [[FIRCollectionReference alloc] initWithPath:path firestore:firestore]; -} -@end - -@implementation FIRCollectionReference - -- (instancetype)initWithPath:(FSTResourcePath *)path firestore:(FIRFirestore *)firestore { - if (path.length % 2 != 1) { - FSTThrowInvalidArgument( - @"Invalid collection reference. Collection references must have an odd " - "number of segments, but %@ has %d", - path.canonicalString, path.length); - } - self = [super initWithQuery:[FSTQuery queryWithPath:path] firestore:firestore]; - return self; -} - -// Override the designated initializer from the super class. -- (instancetype)initWithQuery:(FSTQuery *)query firestore:(FIRFirestore *)firestore { - FSTFail(@"Use FIRCollectionReference initWithPath: initializer."); -} - -- (NSString *)collectionID { - return [self.query.path lastSegment]; -} - -- (FIRDocumentReference *_Nullable)parent { - FSTResourcePath *parentPath = [self.query.path pathByRemovingLastSegment]; - if (parentPath.isEmpty) { - return nil; - } else { - FSTDocumentKey *key = [FSTDocumentKey keyWithPath:parentPath]; - return [FIRDocumentReference referenceWithKey:key firestore:self.firestore]; - } -} - -- (NSString *)path { - return [self.query.path canonicalString]; -} - -- (FIRDocumentReference *)documentWithPath:(NSString *)documentPath { - if (!documentPath) { - FSTThrowInvalidArgument(@"Document path cannot be nil."); - } - FSTResourcePath *subPath = [FSTResourcePath pathWithString:documentPath]; - FSTResourcePath *path = [self.query.path pathByAppendingPath:subPath]; - return [FIRDocumentReference referenceWithPath:path firestore:self.firestore]; -} - -- (FIRDocumentReference *)addDocumentWithData:(NSDictionary *)data { - return [self addDocumentWithData:data completion:nil]; -} - -- (FIRDocumentReference *)addDocumentWithData:(NSDictionary *)data - completion: - (nullable void (^)(NSError *_Nullable error))completion { - FIRDocumentReference *docRef = [self documentWithAutoID]; - [docRef setData:data completion:completion]; - return docRef; -} - -- (FIRDocumentReference *)documentWithAutoID { - NSString *autoID = [FSTUtil autoID]; - FSTDocumentKey *key = - [FSTDocumentKey keyWithPath:[self.query.path pathByAppendingSegment:autoID]]; - return [FIRDocumentReference referenceWithKey:key firestore:self.firestore]; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/API/FIRCollectionReference.mm b/Firestore/Source/API/FIRCollectionReference.mm new file mode 100644 index 0000000..7b487c6 --- /dev/null +++ b/Firestore/Source/API/FIRCollectionReference.mm @@ -0,0 +1,114 @@ +/* + * 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 "FIRCollectionReference.h" + +#include "Firestore/src/core/util/autoid.h" + +#import "Firestore/Source/API/FIRDocumentReference+Internal.h" +#import "Firestore/Source/API/FIRQuery+Internal.h" +#import "Firestore/Source/API/FIRQuery_Init.h" +#import "Firestore/Source/Core/FSTQuery.h" +#import "Firestore/Source/Model/FSTDocumentKey.h" +#import "Firestore/Source/Model/FSTPath.h" +#import "Firestore/Source/Util/FSTAssert.h" +#import "Firestore/Source/Util/FSTUsageValidation.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRCollectionReference () +- (instancetype)initWithPath:(FSTResourcePath *)path + firestore:(FIRFirestore *)firestore NS_DESIGNATED_INITIALIZER; + +// Mark the super class designated initializer unavailable. +- (instancetype)initWithQuery:(FSTQuery *)query + firestore:(FIRFirestore *)firestore + __attribute__((unavailable("Use the initWithPath constructor of FIRCollectionReference."))); +@end + +@implementation FIRCollectionReference (Internal) ++ (instancetype)referenceWithPath:(FSTResourcePath *)path firestore:(FIRFirestore *)firestore { + return [[FIRCollectionReference alloc] initWithPath:path firestore:firestore]; +} +@end + +@implementation FIRCollectionReference + +- (instancetype)initWithPath:(FSTResourcePath *)path firestore:(FIRFirestore *)firestore { + if (path.length % 2 != 1) { + FSTThrowInvalidArgument( + @"Invalid collection reference. Collection references must have an odd " + "number of segments, but %@ has %d", + path.canonicalString, path.length); + } + self = [super initWithQuery:[FSTQuery queryWithPath:path] firestore:firestore]; + return self; +} + +// Override the designated initializer from the super class. +- (instancetype)initWithQuery:(FSTQuery *)query firestore:(FIRFirestore *)firestore { + FSTFail(@"Use FIRCollectionReference initWithPath: initializer."); +} + +- (NSString *)collectionID { + return [self.query.path lastSegment]; +} + +- (FIRDocumentReference *_Nullable)parent { + FSTResourcePath *parentPath = [self.query.path pathByRemovingLastSegment]; + if (parentPath.isEmpty) { + return nil; + } else { + FSTDocumentKey *key = [FSTDocumentKey keyWithPath:parentPath]; + return [FIRDocumentReference referenceWithKey:key firestore:self.firestore]; + } +} + +- (NSString *)path { + return [self.query.path canonicalString]; +} + +- (FIRDocumentReference *)documentWithPath:(NSString *)documentPath { + if (!documentPath) { + FSTThrowInvalidArgument(@"Document path cannot be nil."); + } + FSTResourcePath *subPath = [FSTResourcePath pathWithString:documentPath]; + FSTResourcePath *path = [self.query.path pathByAppendingPath:subPath]; + return [FIRDocumentReference referenceWithPath:path firestore:self.firestore]; +} + +- (FIRDocumentReference *)addDocumentWithData:(NSDictionary *)data { + return [self addDocumentWithData:data completion:nil]; +} + +- (FIRDocumentReference *)addDocumentWithData:(NSDictionary *)data + completion: + (nullable void (^)(NSError *_Nullable error))completion { + FIRDocumentReference *docRef = [self documentWithAutoID]; + [docRef setData:data completion:completion]; + return docRef; +} + +- (FIRDocumentReference *)documentWithAutoID { + NSString *autoID = [NSString stringWithUTF8String:firestore::CreateAutoId().c_str()]; + FSTDocumentKey *key = + [FSTDocumentKey keyWithPath:[self.query.path pathByAppendingSegment:autoID]]; + return [FIRDocumentReference referenceWithKey:key firestore:self.firestore]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Util/FSTUsageValidation.h b/Firestore/Source/Util/FSTUsageValidation.h index a80dafa..34a3d64 100644 --- a/Firestore/Source/Util/FSTUsageValidation.h +++ b/Firestore/Source/Util/FSTUsageValidation.h @@ -18,6 +18,10 @@ NS_ASSUME_NONNULL_BEGIN +#if __cplusplus +extern "C" { +#endif + /** Helper for creating a general exception for invalid usage of an API. */ NSException *FSTInvalidUsage(NSString *exceptionName, NSString *format, ...); @@ -42,4 +46,8 @@ NSException *FSTInvalidUsage(NSString *exceptionName, NSString *format, ...); @throw FSTInvalidUsage(@"FIRInvalidArgumentException", format, ##__VA_ARGS__); \ } while (0) +#if __cplusplus +} // extern "C" +#endif + NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Util/FSTUtil.h b/Firestore/Source/Util/FSTUtil.h deleted file mode 100644 index 230c72a..0000000 --- a/Firestore/Source/Util/FSTUtil.h +++ /dev/null @@ -1,28 +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 - -NS_ASSUME_NONNULL_BEGIN - -@interface FSTUtil : NSObject - -/** Generates a random ID suitable for use as a document ID. */ -+ (NSString *)autoID; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Util/FSTUtil.m b/Firestore/Source/Util/FSTUtil.m deleted file mode 100644 index 47a8821..0000000 --- a/Firestore/Source/Util/FSTUtil.m +++ /dev/null @@ -1,38 +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/FSTUtil.h" - -NS_ASSUME_NONNULL_BEGIN - -static const int kAutoIDLength = 20; -static NSString *const kAutoIDAlphabet = - @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - -@implementation FSTUtil - -+ (NSString *)autoID { - unichar autoID[kAutoIDLength]; - for (int i = 0; i < kAutoIDLength; i++) { - uint32_t randIndex = arc4random_uniform((uint32_t)kAutoIDAlphabet.length); - autoID[i] = [kAutoIDAlphabet characterAtIndex:randIndex]; - } - return [NSString stringWithCharacters:autoID length:kAutoIDLength]; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/src/core/util/CMakeLists.txt b/Firestore/src/core/util/CMakeLists.txt new file mode 100644 index 0000000..6b08d8e --- /dev/null +++ b/Firestore/src/core/util/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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. + +add_library( + firestore_core_util + autoid.cc +) +target_link_libraries( + firestore_core_util + firestore_support +) diff --git a/Firestore/src/core/util/autoid.cc b/Firestore/src/core/util/autoid.cc new file mode 100644 index 0000000..762bbcc --- /dev/null +++ b/Firestore/src/core/util/autoid.cc @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#include "Firestore/src/core/util/autoid.h" + +#include +#include + +#include "Firestore/src/support/secure_random.h" + +namespace { + +const int kAutoIdLength = 20; +const char kAutoIdAlphabet[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + +firestore::SecureRandom shared_random; + +} // namespace + +namespace firestore { + +std::string CreateAutoId() { + std::string auto_id; + auto_id.reserve(kAutoIdLength); + + // -2 here because: + // * sizeof(kAutoIdAlphabet) includes the trailing null terminator + // * uniform_int_distribution is inclusive on both sizes + std::uniform_int_distribution letters(0, sizeof(kAutoIdAlphabet) - 2); + + for (int i = 0; i < kAutoIdLength; i++) { + int rand_index = letters(shared_random); + auto_id.append(1, kAutoIdAlphabet[rand_index]); + } + return auto_id; +} + +} // namespace firestore diff --git a/Firestore/src/core/util/autoid.h b/Firestore/src/core/util/autoid.h new file mode 100644 index 0000000..13486af --- /dev/null +++ b/Firestore/src/core/util/autoid.h @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#ifndef FIRESTORE_SRC_CORE_UTIL_AUTOID_H_ +#define FIRESTORE_SRC_CORE_UTIL_AUTOID_H_ + +#include + +namespace firestore { + +// Generates a random ID suitable for use as a document ID. +std::string CreateAutoId(); + +} // namespace firestore + +#endif // FIRESTORE_SRC_CORE_UTIL_AUTOID_H_ diff --git a/Firestore/test/core/util/CMakeLists.txt b/Firestore/test/core/util/CMakeLists.txt new file mode 100644 index 0000000..1989c0e --- /dev/null +++ b/Firestore/test/core/util/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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. + +cc_test( + firestore_core_util_test + autoid_test.cc +) +target_link_libraries( + firestore_core_util_test + firestore_core_util +) diff --git a/Firestore/test/core/util/autoid_test.cc b/Firestore/test/core/util/autoid_test.cc new file mode 100644 index 0000000..c936194 --- /dev/null +++ b/Firestore/test/core/util/autoid_test.cc @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#include "Firestore/src/core/util/autoid.h" + +#include + +#include "gtest/gtest.h" + +TEST(AutoId, IsSane) { + for (int i = 0; i < 50; i++) { + std::string auto_id = firestore::CreateAutoId(); + EXPECT_EQ(20, auto_id.length()); + for (int pos = 0; pos < 20; pos++) { + char c = auto_id[pos]; + EXPECT_TRUE(isalpha(c) || isdigit(c)) + << "Should be printable ascii character: '" << c << "' in \"" << auto_id + << "\""; + } + } +} -- cgit v1.2.3