aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AddressBook/GTMABAddressBook.m5
-rw-r--r--AppKit/GTMCarbonEvent.m5
-rw-r--r--AppKit/GTMHotKeyTextField.m4
-rw-r--r--AppKit/GTMLargeTypeWindow.m6
-rw-r--r--AppKit/GTMWindowSheetController.m4
-rw-r--r--DebugUtils/GTMTypeCasting.h81
-rw-r--r--Foundation/GTMFileSystemKQueue.m5
-rw-r--r--Foundation/GTMHTTPServer.m4
-rw-r--r--Foundation/GTMObjC2RuntimeTest.m7
-rw-r--r--Foundation/GTMSignalHandler.m3
-rw-r--r--GTM.xcodeproj/project.pbxproj4
-rw-r--r--GTMiPhone.xcodeproj/project.pbxproj2
-rw-r--r--ReleaseNotes.txt3
13 files changed, 119 insertions, 14 deletions
diff --git a/AddressBook/GTMABAddressBook.m b/AddressBook/GTMABAddressBook.m
index 77642db..637494b 100644
--- a/AddressBook/GTMABAddressBook.m
+++ b/AddressBook/GTMABAddressBook.m
@@ -18,6 +18,7 @@
#import "GTMABAddressBook.h"
#import "GTMGarbageCollection.h"
+#import "GTMTypeCasting.h"
#if GTM_IPHONE_SDK
#import <UIKit/UIKit.h>
@@ -811,7 +812,9 @@ typedef struct {
isEqual = [label isEqual:objLabel];
if (isEqual) {
id value = [self valueAtIndex:i];
- id objValue = [(GTMABMultiValue*)object valueAtIndex:i];
+ GTMABMultiValue *multiValueObject
+ = GTM_STATIC_CAST(GTMABMultiValue, object);
+ id objValue = [multiValueObject valueAtIndex:i];
isEqual = [value isEqual:objValue];
}
}
diff --git a/AppKit/GTMCarbonEvent.m b/AppKit/GTMCarbonEvent.m
index 16c46c8..2166331 100644
--- a/AppKit/GTMCarbonEvent.m
+++ b/AppKit/GTMCarbonEvent.m
@@ -19,6 +19,7 @@
#import "GTMCarbonEvent.h"
#import "GTMObjectSingleton.h"
#import "GTMDebugSelectorValidation.h"
+#import "GTMTypeCasting.h"
// Wrapper for all the info we need about a hotkey that we can store in a
// Foundation storage class. We expecct selector to have this signature:
@@ -432,8 +433,8 @@ static OSStatus EventHandler(EventHandlerCallRef inHandler,
EventRef inEvent,
void *inUserData) {
GTMCarbonEvent *event = [GTMCarbonEvent eventWithEvent:inEvent];
- GTMCarbonEventHandler *handler= (GTMCarbonEventHandler *)inUserData;
- check([handler isKindOfClass:[GTMCarbonEventHandler class]]);
+ GTMCarbonEventHandler *handler
+ = GTM_STATIC_CAST(GTMCarbonEventHandler, inUserData);
// First check to see if our delegate cares about this event. If the delegate
// handles it (i.e responds to it and does not return eventNotHandledErr) we
diff --git a/AppKit/GTMHotKeyTextField.m b/AppKit/GTMHotKeyTextField.m
index 864ba54..4524340 100644
--- a/AppKit/GTMHotKeyTextField.m
+++ b/AppKit/GTMHotKeyTextField.m
@@ -21,6 +21,7 @@
#import "GTMSystemVersion.h"
#import "GTMObjectSingleton.h"
#import "GTMNSObject+KeyValueObserving.h"
+#import "GTMTypeCasting.h"
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
typedef struct __TISInputSource* TISInputSourceRef;
@@ -370,7 +371,8 @@ static CFStringRef kGTM_TISPropertyUnicodeKeyLayoutData = NULL;
- (void)textDidChange:(NSNotification *)notification {
// Sanity
- GTMHotKeyFieldEditor *fieldEditor = [notification object];
+ GTMHotKeyFieldEditor *fieldEditor = GTM_STATIC_CAST(GTMHotKeyFieldEditor,
+ [notification object]);
if (![fieldEditor isKindOfClass:[GTMHotKeyFieldEditor class]]) {
_GTMDevLog(@"Field editor not appropriate for field, check window delegate");
return;
diff --git a/AppKit/GTMLargeTypeWindow.m b/AppKit/GTMLargeTypeWindow.m
index dfef15f..de85ec8 100644
--- a/AppKit/GTMLargeTypeWindow.m
+++ b/AppKit/GTMLargeTypeWindow.m
@@ -22,7 +22,7 @@
#import "GTMGeometryUtils.h"
#import "GTMNSBezierPath+RoundRect.h"
#import "GTMMethodCheck.h"
-
+#import "GTMTypeCasting.h"
// How far to inset the text from the edge of the window
static const CGFloat kEdgeInset = 16.0;
@@ -221,7 +221,9 @@ static NSTimeInterval gGTMLargeTypeWindowFadeAnimationDuration = 0.333;
// Give the user some feedback that a copy has occurred
NSTimeInterval dur = [[self class] copyAnimationDuration];
- [(GTMLargeTypeBackgroundView*)[self contentView] animateCopyWithDuration:dur];
+ GTMLargeTypeBackgroundView *view
+ = GTM_STATIC_CAST(GTMLargeTypeBackgroundView, [self contentView]);
+ [view animateCopyWithDuration:dur];
}
- (BOOL)canBecomeKeyWindow {
diff --git a/AppKit/GTMWindowSheetController.m b/AppKit/GTMWindowSheetController.m
index ae14685..59a866d 100644
--- a/AppKit/GTMWindowSheetController.m
+++ b/AppKit/GTMWindowSheetController.m
@@ -19,6 +19,7 @@
#import "GTMWindowSheetController.h"
#import "GTMDefines.h"
+#import "GTMTypeCasting.h"
@interface GTMWSCSheetInfo : NSObject {
@public
@@ -462,7 +463,8 @@ willPositionSheet:(NSWindow*)sheet
}
- (void)notificationHappened:(NSNotification*)notification {
- [self viewDidChangeSize:[notification object]];
+ NSView *view = GTM_STATIC_CAST(NSView, [notification object]);
+ [self viewDidChangeSize:view];
}
- (void)viewDidChangeSize:(NSView*)view {
diff --git a/DebugUtils/GTMTypeCasting.h b/DebugUtils/GTMTypeCasting.h
new file mode 100644
index 0000000..1e9ebb9
--- /dev/null
+++ b/DebugUtils/GTMTypeCasting.h
@@ -0,0 +1,81 @@
+//
+// GTMTypeCasting.h
+//
+// Copyright 2010 Google Inc.
+//
+// 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>
+#import "GTMDefines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// These are some basic macros for making down-casting safer in Objective C.
+// They are loosely based on the same cast types with similar names in C++.
+// A typical usage would look like this:
+//
+// Bar* b = [[Bar alloc] init];
+// Foo* a = GTM_STATIC_CAST(Foo, b);
+//
+// Note that it's GTM_STATIC_CAST(Foo, b) and not GTM_STATIC_CAST(Foo*, b).
+//
+// GTM_STATIC_CAST runs only in debug mode, and will assert if and only if:
+// - object is non nil
+// - [object isKindOfClass:[cls class]] returns nil
+//
+// otherwise it returns object.
+//
+// GTM_DYNAMIC_CAST runs in both debug and release and will return nil if
+// - object is nil
+// - [object isKindOfClass:[cls class]] returns nil
+//
+// otherwise it returns object.
+//
+
+// Support functions for dealing with casting.
+GTM_INLINE id GTMDynamicCastSupport(Class cls, id object) {
+ id value = nil;
+ if (object) {
+ _GTMDevAssert(cls, @"Nil Class");
+ if ([object isKindOfClass:cls]) {
+ value = object;
+ }
+ }
+ return value;
+}
+
+GTM_INLINE id GTMStaticCastSupport(Class cls, id object) {
+ id value = nil;
+ if (object) {
+ value = GTMDynamicCastSupport(cls, object);
+ _GTMDevAssert(value, @"Could not cast %@ to class %@", object, cls);
+ }
+ return value;
+}
+
+#ifndef GTM_STATIC_CAST
+ #ifdef DEBUG
+ #define GTM_STATIC_CAST(type, object) GTMStaticCastSupport([type class], \
+ object)
+ #else
+ #define GTM_STATIC_CAST(type, object) ((type *) (object))
+ #endif
+#endif
+
+#ifndef GTM_DYNAMIC_CAST
+ #define GTM_DYNAMIC_CAST(type, object) GTMDynamicCastSupport([type class], \
+ object)
+#endif
diff --git a/Foundation/GTMFileSystemKQueue.m b/Foundation/GTMFileSystemKQueue.m
index 1db71c1..e423de2 100644
--- a/Foundation/GTMFileSystemKQueue.m
+++ b/Foundation/GTMFileSystemKQueue.m
@@ -20,7 +20,7 @@
#import <unistd.h>
#import "GTMDefines.h"
#import "GTMDebugSelectorValidation.h"
-
+#import "GTMTypeCasting.h"
// File descriptor for the kqueue that will hold all of our file system events.
static int gFileSystemKQueueFileDescriptor = 0;
@@ -118,7 +118,8 @@ static void SocketCallBack(CFSocketRef socketref, CFSocketCallBackType type,
if (kevent(gFileSystemKQueueFileDescriptor, NULL, 0, &event, 1, NULL) == -1) {
_GTMDevLog(@"could not pick up kqueue event. Errno %d", errno); // COV_NF_LINE
} else {
- GTMFileSystemKQueue *fskq = (GTMFileSystemKQueue *)event.udata;
+ GTMFileSystemKQueue *fskq = GTM_STATIC_CAST(GTMFileSystemKQueue,
+ event.udata);
[fskq notify:event.fflags];
}
diff --git a/Foundation/GTMHTTPServer.m b/Foundation/GTMHTTPServer.m
index 7887ade..a514842 100644
--- a/Foundation/GTMHTTPServer.m
+++ b/Foundation/GTMHTTPServer.m
@@ -28,6 +28,7 @@
#import "GTMDebugSelectorValidation.h"
#import "GTMGarbageCollection.h"
#import "GTMDefines.h"
+#import "GTMTypeCasting.h"
@interface GTMHTTPServer (PrivateMethods)
- (void)acceptedConnectionNotification:(NSNotification *)notification;
@@ -283,7 +284,8 @@ startFailed:
}
- (void)dataAvailableNotification:(NSNotification *)notification {
- NSFileHandle *connectionHandle = [notification object];
+ NSFileHandle *connectionHandle = GTM_STATIC_CAST(NSFileHandle,
+ [notification object]);
NSMutableDictionary *connDict = [self lookupConnection:connectionHandle];
if (connDict == nil) return; // we are no longer tracking this one
diff --git a/Foundation/GTMObjC2RuntimeTest.m b/Foundation/GTMObjC2RuntimeTest.m
index 626a625..aa57388 100644
--- a/Foundation/GTMObjC2RuntimeTest.m
+++ b/Foundation/GTMObjC2RuntimeTest.m
@@ -19,8 +19,7 @@
#import "GTMObjC2Runtime.h"
#import "GTMSenTestCase.h"
#import "GTMSystemVersion.h"
-
-
+#import "GTMTypeCasting.h"
#import <string.h>
@@ -94,7 +93,9 @@ AT_REQUIRED
- (void)startedTest:(NSNotification *)notification {
// Logs if we are testing on Tiger or Leopard runtime.
- NSString *testName = [(SenTest*)[[notification object] test] name];
+ SenTestSuiteRun *suiteRun = GTM_STATIC_CAST(SenTestSuiteRun,
+ [notification object]);
+ NSString *testName = [[suiteRun test] name];
NSString *className = NSStringFromClass([GTMObjC2RuntimeTest class]);
if ([testName isEqualToString:className]) {
NSString *runtimeString;
diff --git a/Foundation/GTMSignalHandler.m b/Foundation/GTMSignalHandler.m
index b6cfb70..dd67269 100644
--- a/Foundation/GTMSignalHandler.m
+++ b/Foundation/GTMSignalHandler.m
@@ -18,6 +18,7 @@
#import "GTMSignalHandler.h"
#import "GTMDefines.h"
+#import "GTMTypeCasting.h"
#import <sys/event.h> // for kqueue() and kevent
#import "GTMDebugSelectorValidation.h"
@@ -116,7 +117,7 @@ static void SocketCallBack(CFSocketRef socketref, CFSocketCallBackType type,
if (kevent(gSignalKQueueFileDescriptor, NULL, 0, &event, 1, NULL) == -1) {
_GTMDevLog(@"could not pick up kqueue event. Errno %d", errno); // COV_NF_LINE
} else {
- GTMSignalHandler *handler = (GTMSignalHandler *)event.udata;
+ GTMSignalHandler *handler = GTM_STATIC_CAST(GTMSignalHandler, event.udata);
[handler notify];
}
diff --git a/GTM.xcodeproj/project.pbxproj b/GTM.xcodeproj/project.pbxproj
index 947bda3..2ff56ac 100644
--- a/GTM.xcodeproj/project.pbxproj
+++ b/GTM.xcodeproj/project.pbxproj
@@ -213,6 +213,7 @@
8BEEA90D0DA7446300894774 /* GTMUnitTestingImage.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 8BEEA90A0DA7446300894774 /* GTMUnitTestingImage.tiff */; };
8BEEA90E0DA7446300894774 /* GTMUnitTestingWindow.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 8BEEA90B0DA7446300894774 /* GTMUnitTestingWindow.tiff */; };
8BEEA90F0DA7446300894774 /* GTMUnitTestingView.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 8BEEA90C0DA7446300894774 /* GTMUnitTestingView.tiff */; };
+ 8BF2555310F65B56000490C8 /* GTMTypeCasting.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BF2555110F65B56000490C8 /* GTMTypeCasting.h */; settings = {ATTRIBUTES = (Public, ); }; };
8BF4D2E60FC7073A009ABC3F /* GTMGoogleSearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BF4D2E30FC7073A009ABC3F /* GTMGoogleSearch.h */; settings = {ATTRIBUTES = (Public, ); }; };
8BF4D2E70FC7073A009ABC3F /* GTMGoogleSearch.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BF4D2E40FC7073A009ABC3F /* GTMGoogleSearch.m */; };
8BF4D2E80FC70751009ABC3F /* GTMGoogleSearchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BF4D2E20FC7073A009ABC3F /* GTMGoogleSearchTest.m */; };
@@ -627,6 +628,7 @@
8BEEA90A0DA7446300894774 /* GTMUnitTestingImage.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GTMUnitTestingImage.tiff; sourceTree = "<group>"; };
8BEEA90B0DA7446300894774 /* GTMUnitTestingWindow.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GTMUnitTestingWindow.tiff; sourceTree = "<group>"; };
8BEEA90C0DA7446300894774 /* GTMUnitTestingView.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GTMUnitTestingView.tiff; sourceTree = "<group>"; };
+ 8BF2555110F65B56000490C8 /* GTMTypeCasting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMTypeCasting.h; sourceTree = "<group>"; };
8BF4D2E20FC7073A009ABC3F /* GTMGoogleSearchTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMGoogleSearchTest.m; sourceTree = "<group>"; };
8BF4D2E30FC7073A009ABC3F /* GTMGoogleSearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMGoogleSearch.h; sourceTree = "<group>"; };
8BF4D2E40FC7073A009ABC3F /* GTMGoogleSearch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMGoogleSearch.m; sourceTree = "<group>"; };
@@ -1358,6 +1360,7 @@
F4FF22760D9D47FB003880AC /* DebugUtils */ = {
isa = PBXGroup;
children = (
+ 8BF2555110F65B56000490C8 /* GTMTypeCasting.h */,
F4FF22770D9D4835003880AC /* GTMDebugSelectorValidation.h */,
8B6F31EF0DA347720052CA40 /* GTMMethodCheck.m */,
8B6F31F40DA3489B0052CA40 /* GTMMethodCheck.h */,
@@ -1448,6 +1451,7 @@
8B307FF91056B773006C4C7A /* GTMNSNumber+64Bit.h in Headers */,
F4C6248B109753960069CADD /* GTMIBArray.h in Headers */,
8B158ADE10A8C42000C93125 /* GTMNSAnimation+Duration.h in Headers */,
+ 8BF2555310F65B56000490C8 /* GTMTypeCasting.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/GTMiPhone.xcodeproj/project.pbxproj b/GTMiPhone.xcodeproj/project.pbxproj
index 039b578..a3929a7 100644
--- a/GTMiPhone.xcodeproj/project.pbxproj
+++ b/GTMiPhone.xcodeproj/project.pbxproj
@@ -257,6 +257,7 @@
8BE839870E89C74A00C611B0 /* GTMDebugThreadValidation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMDebugThreadValidation.m; sourceTree = "<group>"; };
8BE839880E89C74A00C611B0 /* GTMDebugThreadValidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMDebugThreadValidation.h; sourceTree = "<group>"; };
8BE83A650E8B059A00C611B0 /* GTMDebugThreadValidationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMDebugThreadValidationTest.m; sourceTree = "<group>"; };
+ 8BF2568E10F673D1000490C8 /* GTMTypeCasting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMTypeCasting.h; sourceTree = "<group>"; };
8BF4D3E00FC72A46009ABC3F /* GTMGoogleSearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMGoogleSearch.h; sourceTree = "<group>"; };
8BF4D3E10FC72A46009ABC3F /* GTMGoogleSearch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMGoogleSearch.m; sourceTree = "<group>"; };
8BF4D3E20FC72A46009ABC3F /* GTMGoogleSearchTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMGoogleSearchTest.m; sourceTree = "<group>"; };
@@ -506,6 +507,7 @@
8BC0479A0DAE928A00C2D1CA /* DebugUtils */ = {
isa = PBXGroup;
children = (
+ 8BF2568E10F673D1000490C8 /* GTMTypeCasting.h */,
8BC0479B0DAE928A00C2D1CA /* GTMDebugSelectorValidation.h */,
8BE83A650E8B059A00C611B0 /* GTMDebugThreadValidationTest.m */,
8BE839870E89C74A00C611B0 /* GTMDebugThreadValidation.m */,
diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt
index ef9dc49..a61862e 100644
--- a/ReleaseNotes.txt
+++ b/ReleaseNotes.txt
@@ -382,6 +382,9 @@ Changes since 1.5.1
- iPhone unit tests now print "Test Case '-[TEST SELECTOR]' started." before
each test.
+- Added GTMTypeCasting.h which gives you safer objective-c casts based on
+ C++ static_cast and dynamic_cast.
+
Release 1.5.1
Changes since 1.5.0