Skip to content

Commit 9237761

Browse files
smilesa-maurice
authored andcommitted
Improved OBJ_C_PTR_WRAPPER() macro.
* Added template class to generate a C++ container for an Obj-C object. * Added a macro to generate a named C++ container for an Obj-C object. This simplifies defining a forward declared platform specific class e.g UserInternal as ObjCPointer when compiling for iOS. PiperOrigin-RevId: 264908750
1 parent 6cd357b commit 9237761

26 files changed

+152
-87
lines changed

app/src/app_ios.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@
2222

2323
namespace firebase {
2424

25-
OBJ_C_PTR_WRAPPER(FIRApp);
25+
namespace internal {
26+
OBJ_C_PTR_WRAPPER_NAMED(AppInternal, FIRApp);
27+
} // namespace internal
28+
29+
typedef internal::AppInternal FIRAppPointer;
2630

2731
} // namespace firebase
2832

app/src/app_ios.mm

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ static void PlatformOptionsToAppOptions(FIROptions* platform_options,
225225
App::~App() {
226226
app_common::RemoveApp(this);
227227
if (data_) {
228-
delete static_cast<FIRAppPointer*>(data_);
228+
delete static_cast<internal::AppInternal*>(data_);
229229
data_ = nullptr;
230230
}
231231
}
@@ -249,7 +249,7 @@ static void PlatformOptionsToAppOptions(FIROptions* platform_options,
249249
app = new App();
250250
app->options_ = options;
251251
app->name_ = name;
252-
app->data_ = new FIRAppPointer(platform_app);
252+
app->data_ = new internal::AppInternal(platform_app);
253253
app_common::AddApp(app, &app->init_results_);
254254
}
255255
return app;
@@ -272,11 +272,13 @@ static void PlatformOptionsToAppOptions(FIROptions* platform_options,
272272
void App::SetDefaultConfigPath(const char* path) { }
273273

274274
void App::SetDataCollectionDefaultEnabled(bool enabled) {
275-
static_cast<FIRAppPointer*>(data_)->ptr.dataCollectionDefaultEnabled = (enabled ? YES : NO);
275+
(**static_cast<internal::AppInternal*>(data_)).dataCollectionDefaultEnabled =
276+
(enabled ? YES : NO);
276277
}
277278

278279
bool App::IsDataCollectionDefaultEnabled() const {
279-
return static_cast<FIRAppPointer*>(data_)->ptr.isDataCollectionDefaultEnabled ? true : false;
280+
return (**static_cast<internal::AppInternal*>(data_)).isDataCollectionDefaultEnabled ?
281+
true : false;
280282
}
281283

282284
} // namespace firebase

app/src/util_ios.h

Lines changed: 85 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,11 @@
3030
namespace firebase {
3131
namespace util {
3232

33-
/// Define a simple struct to wrap an Objective-C pointer.
33+
/// Define a class to wrap an Objective-C pointer.
3434
/// Objective-C uses automatic reference counting, we can't just cast them to
35-
/// void* to reference them from platform-independent data structures
36-
/// (like firebase::App's data_ pointer). Instead, we wrap the pointer in this
37-
/// struct, and point our void* at an instance of this struct.
38-
/// It's awkward. A better solution would be welcome.
39-
///
40-
/// Unfortunately, the _Nullable types can't be used with templates,
41-
/// so we use a hokey macro instead.
42-
///
43-
/// OBJ_C_PTR_WRAPPER(MyClass) unwraps to:
44-
/// struct MyClassPointer {
45-
/// MyClassPointer() : ptr(nil) {}
46-
/// explicit MyClassPointer(MyClass *_Nullable ptr) : ptr(ptr) {}
47-
/// ~MyClassPointer() { ptr = nil; }
48-
/// MyClass *_Nullable ptr;
49-
/// };
35+
/// void* or a forward declared C++ class to reference them from
36+
// platform-independent data structures (like firebase::App's data_ pointer).
37+
/// Instead, we wrap the pointer in this class.
5038
///
5139
/// Usage:
5240
///
@@ -56,7 +44,11 @@ namespace util {
5644
/// };
5745
///
5846
/// // .cpp
59-
/// OBJ_C_PTR_WRAPPER(MyObjCClass);
47+
/// typedef ObjCPointer<MyObjCClass> MyObjCClassPointer;
48+
/// // or OBJ_C_PTR_WRAPPER(MyObjCClass);
49+
/// // or OBJ_C_PTR_WRAPPER_NAMED(MyObjCClassPointer, MyObjCClass);
50+
// // OBJ_C_PTR_WRAPPER* define a class rather than a typedef which
51+
// // is useful when defining a forward declared class.
6052
///
6153
/// void Init(MyPlatformIndependentClass* c, MyObjCClass* obj_c) {
6254
/// c->platform_indep_ptr_ = new MyObjCClassPointer(obj_c);
@@ -68,15 +60,73 @@ namespace util {
6860
/// }
6961
///
7062
/// void DoSomething(MyPlatformIndependentClass* c) {
71-
/// [static_cast<MyObjCClassPointer*>(c->platform_indep_ptr_)->ptr fn_name];
63+
/// [static_cast<MyObjCClassPointer*>(
64+
/// c->platform_indep_ptr_)->get() fn_name];
7265
/// }
7366
///
74-
#define OBJ_C_PTR_WRAPPER(type_name) \
75-
struct type_name##Pointer { \
76-
type_name##Pointer() : ptr(nil) {} \
77-
explicit type_name##Pointer(type_name *_Nullable ptr) : ptr(ptr) {} \
78-
~type_name##Pointer() { ptr = nil; } \
79-
type_name *_Nullable ptr; \
67+
template <typename T>
68+
class ObjCPointer {
69+
public:
70+
// Construct with an empty class.
71+
ObjCPointer() : objc_object_(nil) {}
72+
73+
// Construct with a reference to an Obj-C object.
74+
explicit ObjCPointer(T *_Nullable objc_object) : objc_object_(objc_object) {}
75+
76+
// Release the reference to the Obj-C object.
77+
~ObjCPointer() { release(); }
78+
79+
// Determine whether the Obj-C object is valid.
80+
explicit operator bool() const { return get() != nil; }
81+
82+
// Get the Obj-C object.
83+
T *_Nullable operator*() const { return get(); }
84+
85+
// Get the Obj-C object.
86+
T *_Nullable get() const { return objc_object_; }
87+
88+
// Release the reference to the Obj-C object.
89+
T *_Nullable release() {
90+
T *released = objc_object_;
91+
objc_object_ = nil;
92+
return released;
93+
}
94+
95+
// Assign a new Obj-C object.
96+
void reset(T *_Nullable objc_object) { objc_object_ = objc_object; }
97+
98+
// Assign a new Obj-C object.
99+
ObjCPointer &operator=(T *_Nullable objc_object) {
100+
reset(objc_object);
101+
return *this;
102+
}
103+
104+
// Get the Obj-C object from an ObjCPointer if the specified object is
105+
// non-null.
106+
static T *_Nullable SafeGet(const ObjCPointer *_Nullable reference) {
107+
return reference ? reference->get() : nil;
108+
}
109+
110+
private:
111+
/* This should be private */
112+
T *_Nullable objc_object_;
113+
};
114+
115+
// Generate the class named class_name as an alias of ObjCPointer to contain
116+
// the Objective-C type objc_type_name.
117+
#define OBJ_C_PTR_WRAPPER_NAMED(class_name, objc_type_name) \
118+
class class_name : public firebase::util::ObjCPointer<objc_type_name> { \
119+
public: \
120+
class_name() {} \
121+
explicit class_name( \
122+
const firebase::util::ObjCPointer<objc_type_name>& obj) \
123+
: firebase::util::ObjCPointer<objc_type_name>(obj) {} \
124+
explicit class_name(objc_type_name *_Nullable objc_object) \
125+
: firebase::util::ObjCPointer<objc_type_name>(objc_object) {} \
126+
class_name &operator=(objc_type_name *_Nullable objc_object) { \
127+
ObjCPointer<objc_type_name>::operator=(objc_object); \
128+
return *this; \
129+
} \
80130
}
81131

82132
/// Return an std::string created from an NSString pointer.
@@ -138,7 +188,7 @@ typedef BOOL (
138188
// blacklist we keep).
139189
void ForEachAppDelegateClass(void (^block)(Class));
140190

141-
// Convert a string array into an NSMutableArray.
191+
// Convert a string array into an NSMutableArray.
142192
NSMutableArray *StringVectorToNSMutableArray(
143193
const std::vector<std::string> &vector);
144194

@@ -175,7 +225,8 @@ id VariantToId(const Variant &variant);
175225
Variant IdToVariant(id value);
176226

177227
// Converts an NSMutableDictionary mapping id-to-id to a map<Variant, Variant>.
178-
void NSDictionaryToStdMap(NSDictionary *dictionary, std::map<Variant, Variant> *map);
228+
void NSDictionaryToStdMap(NSDictionary *dictionary, // NOLINT
229+
std::map<Variant, Variant> *map);
179230

180231
// Runs a block on the main/UI thread immediately if the current thread is the
181232
// main thread; otherwise, dispatches asynchronously to the main thread.
@@ -269,16 +320,21 @@ NS_ASSUME_NONNULL_END
269320
// setting the existing method implementation on an app delegate. You can use
270321
// this as the type encoding class for ReplaceOrAddMethod, if you are
271322
// modifying methods on an app delegate class.
272-
@interface FIRSAMAppDelegate : UIResponder<UIApplicationDelegate>
323+
@interface FIRSAMAppDelegate : UIResponder <UIApplicationDelegate>
273324
@end
274325

275326
#else
276327

277328
// Define an opaque type for the Obj-C pointer wrapper struct when this header
278329
// is included in plain C++ files.
279-
#define OBJ_C_PTR_WRAPPER(type_name) \
280-
struct type_name##Pointer;
330+
#define OBJ_C_PTR_WRAPPER_NAMED(class_name, objc_type_name) class class_name;
281331

282332
#endif // __OBJC__
283333

334+
// Generate the class definition objc_type_name##Pointer which is a container
335+
// of the Objective-C type objc_type_name.
336+
// For more information, see ObjCPointer.
337+
#define OBJ_C_PTR_WRAPPER(objc_type_name) \
338+
OBJ_C_PTR_WRAPPER_NAMED(objc_type_name##Pointer, objc_type_name)
339+
284340
#endif // FIREBASE_APP_CLIENT_CPP_SRC_UTIL_IOS_H_

auth/src/ios/auth_ios.mm

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,15 @@ explicit ListenerHandleHolder(T handle) : handle(handle) {}
125125

126126
// Platform-specific method to create the wrapped Auth class.
127127
void *CreatePlatformAuth(App *app, void *app_impl) {
128-
FIRApp *fir_app = static_cast<FIRAppPointer *>(app_impl)->ptr;
128+
FIRApp *fir_app = static_cast<FIRAppPointer *>(app_impl)->get();
129129

130130
// Grab the auth for our app.
131131
FIRAuth *auth = [FIRAuth authWithApp:fir_app];
132132
FIREBASE_ASSERT(auth != nullptr);
133133

134134
// Create a FIRAuth* that uses Objective-C's automatic reference counting.
135135
AuthDataIos *auth_impl = new AuthDataIos();
136-
auth_impl->fir_auth.ptr = auth;
136+
auth_impl->fir_auth = auth;
137137
return auth_impl;
138138
}
139139

@@ -149,7 +149,7 @@ void UpdateCurrentUser(AuthData* auth_data) {
149149
FIRCPPAuthListenerHandle* listener_cpp_handle =
150150
[[FIRCPPAuthListenerHandle alloc] init];
151151
listener_cpp_handle.authData = auth_data;
152-
reinterpret_cast<AuthDataIos*>(auth_data->auth_impl)->listener_handle.ptr = listener_cpp_handle;
152+
reinterpret_cast<AuthDataIos*>(auth_data->auth_impl)->listener_handle = listener_cpp_handle;
153153
// Register a listening block that will notify all the C++ listeners on
154154
// auth state change.
155155
FIRAuthStateDidChangeListenerHandle listener_handle =
@@ -192,7 +192,7 @@ void UpdateCurrentUser(AuthData* auth_data) {
192192
void Auth::DestroyPlatformAuth(AuthData *auth_data) {
193193
// Remove references from listener blocks.
194194
AuthDataIos* auth_data_ios = reinterpret_cast<AuthDataIos *>(auth_data->auth_impl);
195-
FIRCPPAuthListenerHandle *listener_cpp_handle = auth_data_ios->listener_handle.ptr;
195+
FIRCPPAuthListenerHandle *listener_cpp_handle = auth_data_ios->listener_handle.get();
196196
@synchronized (listener_cpp_handle) {
197197
listener_cpp_handle.authData = nullptr;
198198
}

auth/src/ios/common_ios.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,8 @@ struct AuthDataIos {
5252

5353
/// Convert from the platform-independent void* to the Obj-C FIRUser pointer.
5454
static inline FIRUser *_Nullable UserImpl(AuthData *_Nonnull auth_data) {
55-
return auth_data->user_impl == nullptr
56-
? nullptr
57-
: static_cast<FIRUserPointer *>(auth_data->user_impl)->ptr;
55+
return FIRUserPointer::SafeGet(
56+
static_cast<FIRUserPointer *>(auth_data->user_impl));
5857
}
5958

6059
/// Release the platform-dependent FIRUser object.
@@ -76,14 +75,14 @@ static inline void SetUserImpl(AuthData *_Nonnull auth_data,
7675

7776
/// Convert from the platform-independent void* to the Obj-C FIRAuth pointer.
7877
static inline FIRAuth *_Nonnull AuthImpl(AuthData *_Nonnull auth_data) {
79-
return static_cast<AuthDataIos *>(auth_data->auth_impl)->fir_auth.ptr;
78+
return static_cast<AuthDataIos *>(auth_data->auth_impl)->fir_auth.get();
8079
}
8180

8281
/// Convert from the void* credential implementation pointer into the Obj-C
8382
/// FIRAuthCredential pointer.
8483
static inline FIRAuthCredential *_Nonnull CredentialFromImpl(
8584
void *_Nonnull impl) {
86-
return static_cast<FIRAuthCredentialPointer *>(impl)->ptr;
85+
return static_cast<FIRAuthCredentialPointer *>(impl)->get();
8786
}
8887

8988
AuthError AuthErrorFromNSError(NSError *_Nullable error);

database/src/ios/data_snapshot_ios.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class DataSnapshotInternal {
111111

112112
private:
113113
#ifdef __OBJC__
114-
FIRDataSnapshot* impl() const { return impl_->ptr; }
114+
FIRDataSnapshot* impl() const { return impl_->get(); }
115115
#endif // __OBJC__
116116

117117
DatabaseInternal* database_;

database/src/ios/data_snapshot_ios.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@
3636

3737
DataSnapshotInternal::DataSnapshotInternal(const DataSnapshotInternal& other)
3838
: database_(other.database_) {
39-
impl_.reset(new FIRDataSnapshotPointer(other.impl_->ptr));
39+
impl_.reset(new FIRDataSnapshotPointer(*other.impl_));
4040
}
4141

4242
DataSnapshotInternal& DataSnapshotInternal::operator=(const DataSnapshotInternal& other) {
4343
database_ = other.database_;
44-
impl_.reset(new FIRDataSnapshotPointer(other.impl_->ptr));
44+
impl_.reset(new FIRDataSnapshotPointer(*other.impl_));
4545
return *this;
4646
}
4747

database/src/ios/database_ios.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,13 @@ class DatabaseInternal {
147147
// Guard access to C++ objects referenced by
148148
// FIRCPPDatabaseQueryCallbackStatePointer.
149149
NSRecursiveLock* query_lock() const {
150-
return query_lock_->ptr;
150+
return query_lock_->get();
151151
}
152152
#endif // __OBJC__
153153

154154
private:
155155
#ifdef __OBJC__
156-
FIRDatabase* impl() const { return impl_->ptr; }
156+
FIRDatabase* impl() const { return impl_->get(); }
157157
#endif // __OBJC__
158158

159159
// The firebase::App that this Database was created with.

database/src/ios/database_ios.mm

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
: app_(app), log_level_(kLogLevelInfo) {
3131
@try {
3232
impl_.reset(new FIRDatabasePointer(
33-
[FIRDatabase databaseForApp:static_cast<FIRAppPointer*>(app->data_)->ptr]));
33+
[FIRDatabase databaseForApp:static_cast<FIRAppPointer*>(app->data_)->get()]));
3434
query_lock_.reset(new NSRecursiveLockPointer([[NSRecursiveLock alloc] init]));
3535
}
3636
@catch (NSException* exception) {
@@ -44,7 +44,7 @@
4444
: app_(app), constructor_url_(url), log_level_(kLogLevelInfo) {
4545
@try {
4646
impl_.reset(new FIRDatabasePointer(
47-
[FIRDatabase databaseForApp:static_cast<FIRAppPointer*>(app->data_)->ptr URL:@(url)]));
47+
[FIRDatabase databaseForApp:static_cast<FIRAppPointer*>(app->data_)->get() URL:@(url)]));
4848
query_lock_.reset(new NSRecursiveLockPointer([[NSRecursiveLock alloc] init]));
4949
}
5050
@catch (NSException* exception) {
@@ -155,7 +155,7 @@ new DatabaseReferenceInternal(const_cast<DatabaseInternal*>(this),
155155
if (value_listeners_by_query_.Unregister(spec, listener)) {
156156
auto found = cleanup_value_listener_lookup_.find(listener);
157157
if (found != cleanup_value_listener_lookup_.end()) {
158-
[found->second.ptr removeAllObservers];
158+
[found->second.get() removeAllObservers];
159159
cleanup_value_listener_lookup_.erase(found);
160160
}
161161
return true;
@@ -196,7 +196,7 @@ new DatabaseReferenceInternal(const_cast<DatabaseInternal*>(this),
196196
if (child_listeners_by_query_.Unregister(spec, listener)) {
197197
auto found = cleanup_child_listener_lookup_.find(listener);
198198
if (found != cleanup_child_listener_lookup_.end()) {
199-
[found->second.ptr removeAllObservers];
199+
[found->second.get() removeAllObservers];
200200
cleanup_child_listener_lookup_.erase(found);
201201
}
202202
return true;

database/src/ios/database_reference_ios.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class DatabaseReferenceInternal : public QueryInternal {
163163

164164
protected:
165165
#ifdef __OBJC__
166-
FIRDatabaseReference* impl() const { return impl_->ptr; }
166+
FIRDatabaseReference* impl() const { return impl_->get(); }
167167
#endif // __OBJC__
168168

169169
private:

0 commit comments

Comments
 (0)