aboutsummaryrefslogtreecommitdiff
path: root/Foundation
diff options
context:
space:
mode:
authorGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-10-22 19:16:19 +0000
committerGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-10-22 19:16:19 +0000
commit11938e47355bfbf3b81f1ff5b15f1222b83d4f47 (patch)
tree3794c78559472e4b2efe5eabc0e094d7c14a9743 /Foundation
parent90eba8f973c0b77f36dc7084163ff0d43675a1a8 (diff)
- GTM_INLINE will make sure a function gets inlined, and provides a consistent
way for all GTM code to do it. - Added GTMDebugThreadValidation to allow you to enforce the fact that your code must run in the main thread in DEBUG builds. - Updated some internals of the iPhone unittesting so it doesn't double print the test descriptions, file names, or lines numbers of a test failure line. Also includes the test names in the error output. - Changed the xcconfigs so that know it's easier to set different settings at the different levels and not accidentally overwrite settings set at lower levels in the "settings collapse". Also tightened up warnings significantly. - Changed how gtm_unitTestExposedBindingsTestValues works. If you have an implementation of gtm_unitTestExposedBindingsTestValues in your own code you will need to update to the new way of calling. See implementations in GTMNSObject+BindingUnitTesting.m for details. - Added support for grabbing the build number for a particular OS in GTMSystemVersion and easily comparing it to known build numbers, and switched some types from in GTMSystemVersion from "int" to SInt32 to make 64 bit work better. - Added support for SnowLeopard (10A96). We build cleanly with the 10.6 SDKs and all radar checks were updated accordingly. Build All script was also updated to build on SnowLeopard if you have the SDK available. - Turned off building ppc64 GTM because the SnowLeopard SDK currently doesn't have ppc64 support, so SenTestCase isn't defined. This makes it impossible to build the ppc64 10.5 config on SnowLeopard. We have left the setting in the xcconfig for those of you who need it, but have disabled it in the GTM project settings. - Turned on stack smashing protection on the debug builds for all Leopard and above. - Added ability to easily do leak checking by defining the GTM_ENABLE_LEAKS environment variable. It isn't on by default because several of Apple's frameworks leak. You can work around these false positives by using the GTM_LEAKS_SYMBOLS_TO_IGNORE environment variable. Also if you turn on leaks make sure to turn off zombies by defining the GTM_DISABLE_ZOMBIES variable, otherwise every memory allocation you do will look like a leak.
Diffstat (limited to 'Foundation')
-rw-r--r--Foundation/GTMBase64.m7
-rw-r--r--Foundation/GTMCalculatedRange.m2
-rw-r--r--Foundation/GTMGarbageCollection.h14
-rw-r--r--Foundation/GTMGeometryUtils.h64
-rw-r--r--Foundation/GTMGetURLHandler.m270
-rw-r--r--Foundation/GTMHTTPFetcher.m19
-rw-r--r--Foundation/GTMHTTPFetcherTest.m79
-rw-r--r--Foundation/GTMNSAppleEventDescriptor+Foundation.m5
-rw-r--r--Foundation/GTMNSAppleEventDescriptor+Handler.m2
-rw-r--r--Foundation/GTMNSAppleScript+Handler.h2
-rw-r--r--Foundation/GTMNSAppleScript+Handler.m19
-rw-r--r--Foundation/GTMNSAppleScript+HandlerTest.m20
-rw-r--r--Foundation/GTMNSDictionary+URLArguments.m2
-rw-r--r--Foundation/GTMNSString+XML.m2
-rw-r--r--Foundation/GTMObjC2Runtime.m12
-rw-r--r--Foundation/GTMObjC2RuntimeTest.m54
-rw-r--r--Foundation/GTMProgressMonitorInputStreamTest.m15
-rw-r--r--Foundation/GTMRegex.m17
-rw-r--r--Foundation/GTMScriptRunner.m1
-rw-r--r--Foundation/GTMScriptRunnerTest.m24
-rw-r--r--Foundation/GTMStackTrace.h7
-rw-r--r--Foundation/GTMStackTrace.m40
-rw-r--r--Foundation/GTMStackTraceTest.m19
-rw-r--r--Foundation/GTMSystemVersion.h39
-rw-r--r--Foundation/GTMSystemVersion.m120
-rw-r--r--Foundation/GTMSystemVersionTest.m53
-rw-r--r--Foundation/GTMValidatingContainers.h19
-rw-r--r--Foundation/GTMValidatingContainers.m38
28 files changed, 503 insertions, 462 deletions
diff --git a/Foundation/GTMBase64.m b/Foundation/GTMBase64.m
index 03914fd..5cbcfa7 100644
--- a/Foundation/GTMBase64.m
+++ b/Foundation/GTMBase64.m
@@ -153,7 +153,7 @@ static const char kWebSafeBase64DecodeChars[] = {
// YES if the character is a whitespace character.
// NO if the character is not a whitespace character.
//
-FOUNDATION_STATIC_INLINE BOOL IsSpace(unsigned char c) {
+GTM_INLINE BOOL IsSpace(unsigned char c) {
// we use our own mapping here because we don't want anything w/ locale
// support.
static BOOL kSpaces[256] = {
@@ -192,8 +192,7 @@ FOUNDATION_STATIC_INLINE BOOL IsSpace(unsigned char c) {
// Returns:
// The guessed encoded length for a source length
//
-FOUNDATION_STATIC_INLINE NSUInteger CalcEncodedLength(NSUInteger srcLen,
- BOOL padded) {
+GTM_INLINE NSUInteger CalcEncodedLength(NSUInteger srcLen, BOOL padded) {
NSUInteger intermediate_result = 8 * srcLen + 5;
NSUInteger len = intermediate_result / 6;
if (padded) {
@@ -209,7 +208,7 @@ FOUNDATION_STATIC_INLINE NSUInteger CalcEncodedLength(NSUInteger srcLen,
// Returns:
// The guessed decoded length for a source length
//
-FOUNDATION_STATIC_INLINE NSUInteger GuessDecodedLength(NSUInteger srcLen) {
+GTM_INLINE NSUInteger GuessDecodedLength(NSUInteger srcLen) {
return (srcLen + 3) / 4 * 3;
}
diff --git a/Foundation/GTMCalculatedRange.m b/Foundation/GTMCalculatedRange.m
index 218b811..ef49d83 100644
--- a/Foundation/GTMCalculatedRange.m
+++ b/Foundation/GTMCalculatedRange.m
@@ -30,7 +30,7 @@
- (CGFloat)position;
@end
-CG_INLINE BOOL FPEqual(CGFloat a, CGFloat b) {
+GTM_INLINE BOOL FPEqual(CGFloat a, CGFloat b) {
return (fpclassify(a - b) == FP_ZERO);
}
diff --git a/Foundation/GTMGarbageCollection.h b/Foundation/GTMGarbageCollection.h
index 7f2873c..b29a13b 100644
--- a/Foundation/GTMGarbageCollection.h
+++ b/Foundation/GTMGarbageCollection.h
@@ -33,13 +33,13 @@
// but there may be a reason the you want to make something collectable
// but not autoreleased, especially in pure GC code where you don't
// want to bother with the nop autorelease.
-FOUNDATION_STATIC_INLINE id GTMNSMakeCollectable(CFTypeRef cf) {
+GTM_INLINE id GTMNSMakeCollectable(CFTypeRef cf) {
return NSMakeCollectable(cf);
}
// GTMNSMakeUncollectable is for global maps, etc. that we don't
// want released ever. You should still retain these in non-gc code.
-FOUNDATION_STATIC_INLINE void GTMNSMakeUncollectable(id object) {
+GTM_INLINE void GTMNSMakeUncollectable(id object) {
[[NSGarbageCollector defaultCollector] disableCollectorForPointer:object];
}
@@ -48,21 +48,21 @@ FOUNDATION_STATIC_INLINE void GTMNSMakeUncollectable(id object) {
// There are some places where GC doesn't work w/ things w/in Apple's
// frameworks, so this is here so GTM unittests and detect it, and not run
// individual tests to work around bugs in Apple's frameworks.
-FOUNDATION_STATIC_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
+GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
return ([NSGarbageCollector defaultCollector] != nil);
}
#else
-FOUNDATION_STATIC_INLINE id GTMNSMakeCollectable(CFTypeRef cf) {
+GTM_INLINE id GTMNSMakeCollectable(CFTypeRef cf) {
// NSMakeCollectable handles NULLs just fine and returns nil as expected.
return (id)cf;
}
-FOUNDATION_STATIC_INLINE void GTMNSMakeUncollectable(id object) {
+GTM_INLINE void GTMNSMakeUncollectable(id object) {
}
-FOUNDATION_STATIC_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
+GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
return NO;
}
@@ -71,7 +71,7 @@ FOUNDATION_STATIC_INLINE BOOL GTMIsGarbageCollectionEnabled(void) {
// GTMCFAutorelease makes a CF object collectable in GC mode, or adds it
// to the autorelease pool in non-GC mode. Either way it is taken care
// of.
-FOUNDATION_STATIC_INLINE id GTMCFAutorelease(CFTypeRef cf) {
+GTM_INLINE id GTMCFAutorelease(CFTypeRef cf) {
return [GTMNSMakeCollectable(cf) autorelease];
}
diff --git a/Foundation/GTMGeometryUtils.h b/Foundation/GTMGeometryUtils.h
index 855b97f..c3d6b1a 100644
--- a/Foundation/GTMGeometryUtils.h
+++ b/Foundation/GTMGeometryUtils.h
@@ -52,7 +52,7 @@ typedef NSUInteger GTMRectAlignment;
//
// Returns:
// point located in the middle of min X side of rect
-CG_INLINE CGPoint GTMCGMidMinX(CGRect rect) {
+GTM_INLINE CGPoint GTMCGMidMinX(CGRect rect) {
return CGPointMake(CGRectGetMinX(rect), CGRectGetMidY(rect));
}
@@ -63,7 +63,7 @@ CG_INLINE CGPoint GTMCGMidMinX(CGRect rect) {
//
// Returns:
// point located in the middle of max X side of rect
-CG_INLINE CGPoint GTMCGMidMaxX(CGRect rect) {
+GTM_INLINE CGPoint GTMCGMidMaxX(CGRect rect) {
return CGPointMake(CGRectGetMaxX(rect), CGRectGetMidY(rect));
}
@@ -74,7 +74,7 @@ CG_INLINE CGPoint GTMCGMidMaxX(CGRect rect) {
//
// Returns:
// point located in the middle of max Y side of rect
-CG_INLINE CGPoint GTMCGMidMaxY(CGRect rect) {
+GTM_INLINE CGPoint GTMCGMidMaxY(CGRect rect) {
return CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
}
@@ -85,7 +85,7 @@ CG_INLINE CGPoint GTMCGMidMaxY(CGRect rect) {
//
// Returns:
// point located in the middle of min Y side of rect
-CG_INLINE CGPoint GTMCGMidMinY(CGRect rect) {
+GTM_INLINE CGPoint GTMCGMidMinY(CGRect rect) {
return CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
}
@@ -96,7 +96,7 @@ CG_INLINE CGPoint GTMCGMidMinY(CGRect rect) {
//
// Returns:
// point located in the center of rect
-CG_INLINE CGPoint GTMCGCenter(CGRect rect) {
+GTM_INLINE CGPoint GTMCGCenter(CGRect rect) {
return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
}
@@ -110,7 +110,7 @@ CG_INLINE CGPoint GTMCGCenter(CGRect rect) {
//
// Returns:
// size of rectangle
-CG_INLINE CGSize GTMCGRectSize(CGRect rect) {
+GTM_INLINE CGSize GTMCGRectSize(CGRect rect) {
return CGSizeMake(CGRectGetWidth(rect), CGRectGetHeight(rect));
}
@@ -121,7 +121,7 @@ CG_INLINE CGSize GTMCGRectSize(CGRect rect) {
//
// Returns:
// rectangle of size (origin 0,0)
-CG_INLINE CGRect GTMCGRectOfSize(CGSize size) {
+GTM_INLINE CGRect GTMCGRectOfSize(CGSize size) {
return CGRectMake(0.0f, 0.0f, size.width, size.height);
}
@@ -137,7 +137,7 @@ CG_INLINE CGRect GTMCGRectOfSize(CGSize size) {
//
// Returns:
// Converted Rect
-CG_INLINE CGRect GTMCGRectScale(CGRect inRect, CGFloat xScale, CGFloat yScale) {
+GTM_INLINE CGRect GTMCGRectScale(CGRect inRect, CGFloat xScale, CGFloat yScale) {
return CGRectMake(inRect.origin.x, inRect.origin.y,
inRect.size.width * xScale, inRect.size.height * yScale);
}
@@ -171,7 +171,7 @@ CGRect GTMCGScaleRectangleToSize(CGRect scalee, CGSize size,
//
// Returns:
// Distance
-CG_INLINE CGFloat GTMCGDistanceBetweenPoints(CGPoint pt1, CGPoint pt2) {
+GTM_INLINE CGFloat GTMCGDistanceBetweenPoints(CGPoint pt1, CGPoint pt2) {
CGFloat dX = pt1.x - pt2.x;
CGFloat dY = pt1.y - pt2.y;
#if CGFLOAT_IS_DOUBLE
@@ -200,7 +200,7 @@ CG_INLINE CGFloat GTMCGDistanceBetweenPoints(CGPoint pt1, CGPoint pt2) {
//
// Returns:
// Converted NSPoint
-CG_INLINE NSPoint GTMCGPointToNSPoint(CGPoint inPoint) {
+GTM_INLINE NSPoint GTMCGPointToNSPoint(CGPoint inPoint) {
_GTMCompileAssert(sizeof(NSPoint) == sizeof(CGPoint), NSPoint_and_CGPoint_must_be_the_same_size);
union convertUnion {NSPoint ns; CGPoint cg;};
return ((union convertUnion *)&inPoint)->ns;
@@ -216,7 +216,7 @@ CG_INLINE NSPoint GTMCGPointToNSPoint(CGPoint inPoint) {
//
// Returns:
// Converted CGPoint
-CG_INLINE CGPoint GTMNSPointToCGPoint(NSPoint inPoint) {
+GTM_INLINE CGPoint GTMNSPointToCGPoint(NSPoint inPoint) {
_GTMCompileAssert(sizeof(NSPoint) == sizeof(CGPoint), NSPoint_and_CGPoint_must_be_the_same_size);
union convertUnion {NSPoint ns; CGPoint cg;};
return ((union convertUnion *)&inPoint)->cg;
@@ -235,7 +235,7 @@ CG_INLINE CGPoint GTMNSPointToCGPoint(NSPoint inPoint) {
//
// Returns:
// Converted NSRect
-CG_INLINE NSRect GTMCGRectToNSRect(CGRect inRect) {
+GTM_INLINE NSRect GTMCGRectToNSRect(CGRect inRect) {
_GTMCompileAssert(sizeof(NSRect) == sizeof(CGRect), NSRect_and_CGRect_must_be_the_same_size);
union convertUnion {NSRect ns; CGRect cg;};
return ((union convertUnion *)&inRect)->ns;
@@ -251,7 +251,7 @@ CG_INLINE NSRect GTMCGRectToNSRect(CGRect inRect) {
//
// Returns:
// Converted CGRect
-CG_INLINE CGRect GTMNSRectToCGRect(NSRect inRect) {
+GTM_INLINE CGRect GTMNSRectToCGRect(NSRect inRect) {
_GTMCompileAssert(sizeof(NSRect) == sizeof(CGRect), NSRect_and_CGRect_must_be_the_same_size);
union convertUnion {NSRect ns; CGRect cg;};
return ((union convertUnion *)&inRect)->cg;
@@ -268,7 +268,7 @@ CG_INLINE CGRect GTMNSRectToCGRect(NSRect inRect) {
//
// Returns:
// Converted NSSize
-CG_INLINE NSSize GTMCGSizeToNSSize(CGSize inSize) {
+GTM_INLINE NSSize GTMCGSizeToNSSize(CGSize inSize) {
_GTMCompileAssert(sizeof(NSSize) == sizeof(CGSize), NSSize_and_CGSize_must_be_the_same_size);
union convertUnion {NSSize ns; CGSize cg;};
return ((union convertUnion *)&inSize)->ns;
@@ -281,7 +281,7 @@ CG_INLINE NSSize GTMCGSizeToNSSize(CGSize inSize) {
//
// Returns:
// Converted CGSize
-CG_INLINE CGSize GTMNSSizeToCGSize(NSSize inSize) {
+GTM_INLINE CGSize GTMNSSizeToCGSize(NSSize inSize) {
_GTMCompileAssert(sizeof(NSSize) == sizeof(CGSize), NSSize_and_CGSize_must_be_the_same_size);
union convertUnion {NSSize ns; CGSize cg;};
return ((union convertUnion *)&inSize)->cg;
@@ -297,7 +297,7 @@ CG_INLINE CGSize GTMNSSizeToCGSize(NSSize inSize) {
//
// Returns:
// point located in the middle of min X side of rect
-CG_INLINE NSPoint GTMNSMidMinX(NSRect rect) {
+GTM_INLINE NSPoint GTMNSMidMinX(NSRect rect) {
return NSMakePoint(NSMinX(rect), NSMidY(rect));
}
@@ -308,7 +308,7 @@ CG_INLINE NSPoint GTMNSMidMinX(NSRect rect) {
//
// Returns:
// point located in the middle of max X side of rect
-CG_INLINE NSPoint GTMNSMidMaxX(NSRect rect) {
+GTM_INLINE NSPoint GTMNSMidMaxX(NSRect rect) {
return NSMakePoint(NSMaxX(rect), NSMidY(rect));
}
@@ -319,7 +319,7 @@ CG_INLINE NSPoint GTMNSMidMaxX(NSRect rect) {
//
// Returns:
// point located in the middle of max Y side of rect
-CG_INLINE NSPoint GTMNSMidMaxY(NSRect rect) {
+GTM_INLINE NSPoint GTMNSMidMaxY(NSRect rect) {
return NSMakePoint(NSMidX(rect), NSMaxY(rect));
}
@@ -330,7 +330,7 @@ CG_INLINE NSPoint GTMNSMidMaxY(NSRect rect) {
//
// Returns:
// point located in the middle of min Y side of rect
-CG_INLINE NSPoint GTMNSMidMinY(NSRect rect) {
+GTM_INLINE NSPoint GTMNSMidMinY(NSRect rect) {
return NSMakePoint(NSMidX(rect), NSMinY(rect));
}
@@ -341,7 +341,7 @@ CG_INLINE NSPoint GTMNSMidMinY(NSRect rect) {
//
// Returns:
// point located in the center of rect
-CG_INLINE NSPoint GTMNSCenter(NSRect rect) {
+GTM_INLINE NSPoint GTMNSCenter(NSRect rect) {
return NSMakePoint(NSMidX(rect), NSMidY(rect));
}
@@ -355,7 +355,7 @@ CG_INLINE NSPoint GTMNSCenter(NSRect rect) {
//
// Returns:
// size of rectangle
-CG_INLINE NSSize GTMNSRectSize(NSRect rect) {
+GTM_INLINE NSSize GTMNSRectSize(NSRect rect) {
return NSMakeSize(NSWidth(rect), NSHeight(rect));
}
@@ -366,7 +366,7 @@ CG_INLINE NSSize GTMNSRectSize(NSRect rect) {
//
// Returns:
// rectangle of size (origin 0,0)
-CG_INLINE NSRect GTMNSRectOfSize(NSSize size) {
+GTM_INLINE NSRect GTMNSRectOfSize(NSSize size) {
return NSMakeRect(0.0f, 0.0f, size.width, size.height);
}
@@ -382,7 +382,7 @@ CG_INLINE NSRect GTMNSRectOfSize(NSSize size) {
//
// Returns:
// Converted Rect
-CG_INLINE NSRect GTMNSRectScale(NSRect inRect, CGFloat xScale, CGFloat yScale) {
+GTM_INLINE NSRect GTMNSRectScale(NSRect inRect, CGFloat xScale, CGFloat yScale) {
return NSMakeRect(inRect.origin.x, inRect.origin.y,
inRect.size.width * xScale, inRect.size.height * yScale);
}
@@ -392,8 +392,8 @@ CG_INLINE NSRect GTMNSRectScale(NSRect inRect, CGFloat xScale, CGFloat yScale) {
// Args:
// alignee - rect to be aligned
// aligner - rect to be aligned from
-CG_INLINE NSRect GTMNSAlignRectangles(NSRect alignee, NSRect aligner,
- GTMRectAlignment alignment) {
+GTM_INLINE NSRect GTMNSAlignRectangles(NSRect alignee, NSRect aligner,
+ GTMRectAlignment alignment) {
return GTMCGRectToNSRect(GTMCGAlignRectangles(GTMNSRectToCGRect(alignee),
GTMNSRectToCGRect(aligner),
alignment));
@@ -406,10 +406,10 @@ CG_INLINE NSRect GTMNSAlignRectangles(NSRect alignee, NSRect aligner,
// scaler - rect to scale to
// scaling - way to scale the rectangle
// alignment - way to align the scaled rectangle
-CG_INLINE NSRect GTMNSScaleRectToRect(NSRect scalee,
- NSRect scaler,
- GTMScaling scaling,
- GTMRectAlignment alignment) {
+GTM_INLINE NSRect GTMNSScaleRectToRect(NSRect scalee,
+ NSRect scaler,
+ GTMScaling scaling,
+ GTMRectAlignment alignment) {
return GTMCGRectToNSRect(
GTMCGAlignRectangles(
@@ -426,8 +426,8 @@ CG_INLINE NSRect GTMNSScaleRectToRect(NSRect scalee,
// scalee - rect to be scaled
// size - size to scale to
// scaling - way to scale the rectangle
-CG_INLINE NSRect GTMNSScaleRectangleToSize(NSRect scalee, NSSize size,
- GTMScaling scaling) {
+GTM_INLINE NSRect GTMNSScaleRectangleToSize(NSRect scalee, NSSize size,
+ GTMScaling scaling) {
return GTMCGRectToNSRect(GTMCGScaleRectangleToSize(GTMNSRectToCGRect(scalee),
GTMNSSizeToCGSize(size),
scaling));
@@ -444,7 +444,7 @@ CG_INLINE NSRect GTMNSScaleRectangleToSize(NSRect scalee, NSSize size,
//
// Returns:
// Distance
-CG_INLINE CGFloat GTMNSDistanceBetweenPoints(NSPoint pt1, NSPoint pt2) {
+GTM_INLINE CGFloat GTMNSDistanceBetweenPoints(NSPoint pt1, NSPoint pt2) {
return GTMCGDistanceBetweenPoints(GTMNSPointToCGPoint(pt1),
GTMNSPointToCGPoint(pt2));
}
diff --git a/Foundation/GTMGetURLHandler.m b/Foundation/GTMGetURLHandler.m
deleted file mode 100644
index 30d516f..0000000
--- a/Foundation/GTMGetURLHandler.m
+++ /dev/null
@@ -1,270 +0,0 @@
-//
-// GTMGetURLHandler.m
-//
-// Copyright 2008 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.
-//
-
-// Add this class to your app to have get URL handled almost automatically for
-// you. For each entry in your CFBundleURLTypes dictionaries, add a new
-// key/object pair of GTMBundleURLClass/the name of the class you want
-// to have handle the scheme(s).
-// Then have that class respond to the class method:
-// + (BOOL)gtm_openURL:(NSURL*)url
-// and voila, it will just work.
-// Note that in Debug mode we will do extensive testing to make sure that this
-// is all hooked up correctly, and will spew out to the console if we
-// find anything amiss.
-//
-// Example plist entry
-// ...
-//
-// <key>CFBundleURLTypes</key>
-// <array>
-// <dict>
-// <key>CFBundleURLName</key>
-// <string>Google Suggestion URL</string>
-// <key>GTMBundleURLClass</key>
-// <string>GoogleSuggestURLHandler</string>
-// <key>CFBundleURLSchemes</key>
-// <array>
-// <string>googlesuggest</string>
-// <string>googlesuggestextreme</string>
-// </array>
-// </dict>
-// </array>
-//
-//
-// Example implementation
-// @interface GoogleSuggestURLHandler
-// @end
-// @implementation GoogleSuggestURLHandler
-// + (BOOL)gtm_openURL:(NSURL*)url {
-// NSLog(@"%@", url);
-// }
-// @end
-
-#import <Foundation/Foundation.h>
-#import "GTMGarbageCollection.h"
-#import "GTMNSAppleEventDescriptor+Foundation.h"
-#import "GTMMethodCheck.h"
-
-static NSString *const kGTMBundleURLClassKey = @"GTMBundleURLClass";
-// A variety of constants Apple really should have defined somewhere to
-// allow the compiler to find your typos.
-static NSString *const kGTMCFBundleURLSchemesKey = @"CFBundleURLSchemes";
-static NSString *const kGTMCFBundleURLNameKey = @"CFBundleURLName";
-static NSString *const kGTMCFBundleTypeRoleKey = @"CFBundleTypeRole";
-static NSString *const kGTMCFBundleURLTypesKey = @"CFBundleURLTypes";
-static NSString *const kGTMCFBundleViewerRole = @"Viewer";
-static NSString *const kGTMCFBundleEditorRole = @"Editor";
-
-// Set this macro elsewhere is you want to force the
-// bundle checks on/off. They are nice for debugging
-// problems, but shouldn't be required in a release version
-// unless you are paranoid about your users messing with your
-// Info.plist
-#ifndef GTM_CHECK_BUNDLE_URL_CLASSES
-#define GTM_CHECK_BUNDLE_URL_CLASSES DEBUG
-#endif // GTM_CHECK_BUNDLE_URL_CLASSES
-
-@protocol GTMGetURLHandlerProtocol
-+ (BOOL)gtm_openURL:(NSURL*)url;
-@end
-
-@interface GTMGetURLHandler : NSObject {
- NSArray *urlTypes_;
-}
-- (id)initWithTypes:(NSArray*)urlTypes;
-- (void)getUrl:(NSAppleEventDescriptor *)event
-withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
-- (void)addError:(OSStatus)error
- withDescription:(NSString*)string
- toDescriptor:(NSAppleEventDescriptor *)desc;
-+ (id)handlerForBundle:(NSBundle *)bundle;
-@end
-
-@implementation GTMGetURLHandler
-GTM_METHOD_CHECK(NSNumber, gtm_appleEventDescriptor);
-GTM_METHOD_CHECK(NSString, gtm_appleEventDescriptor);
-
-+ (void)load {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSBundle *bundle = [NSBundle mainBundle];
- GTMGetURLHandler *handler = [GTMGetURLHandler handlerForBundle:bundle];
- if (handler) {
- [handler retain];
- GTMNSMakeUncollectable(handler);
- NSAppleEventManager *man = [NSAppleEventManager sharedAppleEventManager];
- [man setEventHandler:handler
- andSelector:@selector(getUrl:withReplyEvent:)
- forEventClass:kInternetEventClass
- andEventID:kAEGetURL];
- }
- [pool release];
-}
-
-+ (id)handlerForBundle:(NSBundle *)bundle {
- GTMGetURLHandler *handler = nil;
- NSArray *urlTypes = [bundle objectForInfoDictionaryKey:kGTMCFBundleURLTypesKey];
- if (urlTypes) {
- handler = [[[GTMGetURLHandler alloc] initWithTypes:urlTypes] autorelease];
- } else {
- _GTMDevLog(@"If you don't have CFBundleURLTypes in your plist, you may want"
- @" to remove GTMGetURLHandler.m from your project");
- }
- return handler;
-}
-
-- (id)initWithTypes:(NSArray*)urlTypes {
- if ((self = [super init])) {
- urlTypes_ = [urlTypes retain];
-#if GTM_CHECK_BUNDLE_URL_CLASSES
- // Some debug handling to check to make sure we can handle the
- // classes properly.
- NSEnumerator *enumerator = [urlTypes_ objectEnumerator];
- NSDictionary *urlType;
- while ((urlType = [enumerator nextObject])) {
- NSString *className = [urlType objectForKey:kGTMBundleURLClassKey];
- if ([className length]) {
- Class cls = NSClassFromString(className);
- if (cls) {
- if (![cls respondsToSelector:@selector(gtm_openURL:)]) {
- _GTMDevLog(@"Class %@ for URL handler %@ "
- "(URL schemes: %@) doesn't respond to openURL:",
- className,
- [urlType objectForKey:kGTMCFBundleURLNameKey],
- [urlType objectForKey:kGTMCFBundleURLSchemesKey]);
- }
- } else {
- _GTMDevLog(@"Unable to get class %@ for URL handler %@ "
- "(URL schemes: %@)",
- className,
- [urlType objectForKey:kGTMCFBundleURLNameKey],
- [urlType objectForKey:kGTMCFBundleURLSchemesKey]);
- }
- } else {
- NSString *role = [urlType objectForKey:kGTMCFBundleTypeRoleKey];
- if ([role caseInsensitiveCompare:kGTMCFBundleViewerRole] == NSOrderedSame ||
- [role caseInsensitiveCompare:kGTMCFBundleEditorRole] == NSOrderedSame) {
- _GTMDevLog(@"Missing %@ for URL handler %@ "
- "(URL schemes: %@)",
- kGTMBundleURLClassKey,
- [urlType objectForKey:kGTMCFBundleURLNameKey],
- [urlType objectForKey:kGTMCFBundleURLSchemesKey]);
- }
- }
- }
-#endif // GTM_CHECK_BUNDLE_URL_CLASSES
- }
- return self;
-}
-
-- (void)dealloc {
- [urlTypes_ release];
- [super dealloc];
-}
-
-- (NSURL*)extractURLFromEvent:(NSAppleEventDescriptor*)event
- withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
- NSAppleEventDescriptor *desc
- = [event paramDescriptorForKeyword:keyDirectObject];
- NSString *urlstring = [desc stringValue];
- NSURL *url = [NSURL URLWithString:urlstring];
- if (!url) {
- [self addError:errAECoercionFail
- withDescription:@"Unable to extract url from key direct object."
- toDescriptor:replyEvent];
- }
- return url;
-}
-
-- (Class)getClassForScheme:(NSString *)scheme
- withReplyEvent:(NSAppleEventDescriptor*)replyEvent {
- NSEnumerator *typeEnumerator = [urlTypes_ objectEnumerator];
- NSDictionary *urlType;
- Class cls = nil;
- NSString *typeScheme = nil;
- while (!typeScheme && (urlType = [typeEnumerator nextObject])) {
- NSArray *schemes = [urlType objectForKey:kGTMCFBundleURLSchemesKey];
- NSEnumerator *schemeEnumerator = [schemes objectEnumerator];
- while ((typeScheme = [schemeEnumerator nextObject])) {
- if ([typeScheme caseInsensitiveCompare:scheme] == NSOrderedSame) {
- break;
- }
- }
- }
- if (typeScheme) {
- NSString *class = [urlType objectForKey:kGTMBundleURLClassKey];
- if (class) {
- cls = NSClassFromString(class);
- }
- if (!cls) {
- NSString *errorString
- = [NSString stringWithFormat:@"Unable to instantiate class for "
- "%@:%@ for scheme:%@.",
- kGTMBundleURLClassKey, class, typeScheme];
- [self addError:errAECorruptData
- withDescription:errorString
- toDescriptor:replyEvent];
- }
- } else {
- NSString *errorString
- = [NSString stringWithFormat:@"Unable to find handler for scheme %@.",
- scheme];
- [self addError:errAECorruptData
- withDescription:errorString
- toDescriptor:replyEvent];
- }
- return cls;
-}
-
-- (void)getUrl:(NSAppleEventDescriptor *)event
-withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
- NSURL *url = [self extractURLFromEvent:event withReplyEvent:replyEvent];
- if (!url) {
- return;
- }
- NSString *scheme = [url scheme];
- Class cls = [self getClassForScheme:scheme withReplyEvent:replyEvent];
- if (!cls) {
- return;
- }
- BOOL wasGood = [cls gtm_openURL:url];
- if (!wasGood) {
- NSString *errorString
- = [NSString stringWithFormat:@"[%@ gtm_openURL:] failed to handle %@",
- NSStringFromClass(cls), url];
- [self addError:errAEEventNotHandled
- withDescription:errorString
- toDescriptor:replyEvent];
- }
-}
-
-- (void)addError:(OSStatus)error
- withDescription:(NSString*)string
- toDescriptor:(NSAppleEventDescriptor *)desc {
- NSAppleEventDescriptor *errorDesc = nil;
- if (error != noErr) {
- NSNumber *errNum = [NSNumber numberWithLong:error];
- errorDesc = [errNum gtm_appleEventDescriptor];
- [desc setParamDescriptor:errorDesc forKeyword:keyErrorNumber];
- }
- if (string) {
- errorDesc = [string gtm_appleEventDescriptor];
- [desc setParamDescriptor:errorDesc forKeyword:keyErrorString];
- }
-}
-@end
-
diff --git a/Foundation/GTMHTTPFetcher.m b/Foundation/GTMHTTPFetcher.m
index 614f3ad..bc93bab 100644
--- a/Foundation/GTMHTTPFetcher.m
+++ b/Foundation/GTMHTTPFetcher.m
@@ -21,6 +21,7 @@
#import "GTMHTTPFetcher.h"
#import "GTMDebugSelectorValidation.h"
#import "GTMGarbageCollection.h"
+#import "GTMSystemVersion.h"
@interface GTMHTTPFetcher (GTMHTTPFetcherLoggingInternal)
- (void)logFetchWithError:(NSError *)error;
@@ -1129,13 +1130,9 @@ CannotBeginFetch:
NSString *scheme = [theURL scheme];
NSString *domain = nil;
- if ([host isEqual:@"localhost"]) {
- // the domain stored into NSHTTPCookies for localhost is "localhost.local"
- domain = @"localhost.local";
- } else {
- if (host) {
- domain = [@"." stringByAppendingString:host];
- }
+
+ if (host) {
+ domain = [[@"." stringByAppendingString:host] lowercaseString];
}
NSUInteger numberOfCookies = [cookieStorageArray count];
@@ -1143,11 +1140,17 @@ CannotBeginFetch:
NSHTTPCookie *storedCookie = [cookieStorageArray objectAtIndex:idx];
- NSString *cookieDomain = [storedCookie domain];
+ NSString *cookieDomain = [[storedCookie domain] lowercaseString];
NSString *cookiePath = [storedCookie path];
BOOL cookieIsSecure = [storedCookie isSecure];
BOOL domainIsOK = [domain hasSuffix:cookieDomain];
+ if (!domainIsOK && [domain hasSuffix:@"localhost"]) {
+ // On Leopard and below, localhost Cookies always come back
+ // with a domain of localhost.local. On SnowLeopard they come
+ // back as just localhost.
+ domainIsOK = [@".localhost.local" hasSuffix:cookieDomain];
+ }
BOOL pathIsOK = [cookiePath isEqual:@"/"] || [path hasPrefix:cookiePath];
BOOL secureIsOK = (!cookieIsSecure) || [scheme isEqual:@"https"];
diff --git a/Foundation/GTMHTTPFetcherTest.m b/Foundation/GTMHTTPFetcherTest.m
index 3c461e0..a541d1f 100644
--- a/Foundation/GTMHTTPFetcherTest.m
+++ b/Foundation/GTMHTTPFetcherTest.m
@@ -19,6 +19,7 @@
#import "GTMSenTestCase.h"
#import "GTMHTTPFetcher.h"
#import "GTMTestHTTPServer.h"
+#import "GTMUnitTestDevLog.h"
@interface GTMHTTPFetcherTest : GTMTestCase {
// these ivars are checked after fetches, and are reset by resetFetchResponse
@@ -97,7 +98,7 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
- (void)tearDown {
[testServer_ release];
testServer_ = nil;
-
+
[self resetFetchResponse];
[fetchHistory_ release];
@@ -136,24 +137,24 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
responseHeaders = [(NSHTTPURLResponse *)fetchedResponse_ allHeaderFields];
NSString *cookiesSetString = [responseHeaders objectForKey:@"Set-Cookie"];
NSString *cookieExpected = [NSString stringWithFormat:@"TestCookie=%@",
- kValidFileName];
+ kValidFileName];
STAssertEqualObjects(cookiesSetString, cookieExpected, @"Unexpected cookie");
// test properties
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
- @"val1", @"key1", @"val2", @"key2", nil];
+ @"val1", @"key1", @"val2", @"key2", nil];
[fetcher setProperties:dict];
STAssertEqualObjects([fetcher properties], dict, @"properties as dictionary");
STAssertEqualObjects([fetcher propertyForKey:@"key2"], @"val2",
- @"single property");
+ @"single property");
NSDictionary *dict2 = [NSDictionary dictionaryWithObjectsAndKeys:
- @"valx1", @"key1", @"val3", @"key3", nil];
+ @"valx1", @"key1", @"val3", @"key3", nil];
[fetcher setProperty:@"valx1" forKey:@"key1"];
[fetcher setProperty:nil forKey:@"key2"];
[fetcher setProperty:@"val3" forKey:@"key3"];
STAssertEqualObjects([fetcher properties], dict2, @"property changes");
-
+
// make a copy of the fetched data to compare with our next fetch from the
// cache
NSData *originalFetchedData = [[fetchedData_ copy] autorelease];
@@ -161,7 +162,7 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
// Now fetch again so the "If modified since" header will be set (because
// we're calling setFetchHistory: below) and caching ON, and verify that we
// got a good data from the cache, along with a "Not modified" status
-
+
[self resetFetchResponse];
[self doFetchWithURLString:urlString cachingDatedData:YES];
@@ -196,19 +197,19 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
[fetchHistory_ removeAllObjects];
[self doFetchWithURLString:urlString cachingDatedData:NO];
-
+
STAssertEqualObjects(fetchedData_, originalFetchedData,
@"cache data mismatch");
-
+
[self resetFetchResponse];
[self doFetchWithURLString:urlString cachingDatedData:NO];
-
+
STAssertNotNil(fetchedData_, @"");
STAssertEquals([fetchedData_ length], (NSUInteger)0, @"unexpected data");
STAssertEquals(fetchedStatus_, (NSInteger)kGTMHTTPFetcherStatusNotModified,
@"fetching data expected status 304, instead got %d", fetchedStatus_);
STAssertNil(fetcherError_, @"unexpected error: %@", fetcherError_);
-
+
}
- (void)testBogusFetch {
@@ -221,29 +222,29 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
if (fetchedStatus_ == kServiceUnavailableStatus) {
// some proxies give a "service unavailable" error for bogus fetches
} else {
-
+
if (fetchedData_) {
NSString *str = [[[NSString alloc] initWithData:fetchedData_
encoding:NSUTF8StringEncoding] autorelease];
STAssertNil(fetchedData_, @"fetched unexpected data: %@", str);
}
-
+
STAssertNotNil(fetcherError_, @"failed to receive fetching error");
STAssertEquals(fetchedStatus_, (NSInteger)0,
@"fetching data expected no status from no response, instead got %d",
fetchedStatus_);
}
-
+
// fetch with a specific status code from our http server
[self resetFetchResponse];
-
+
NSString *invalidWebPageFile =
[kValidFileName stringByAppendingString:@"?status=400"];
NSString *statusUrlString =
[self fileURLStringToTestFileName:invalidWebPageFile];
-
+
[self doFetchWithURLString:statusUrlString cachingDatedData:NO];
-
+
STAssertNotNil(fetchedData_, @"fetch lacked data with error info");
STAssertNil(fetcherError_, @"expected bad status but got an error");
STAssertEquals(fetchedStatus_, (NSInteger)400,
@@ -258,7 +259,7 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
SEL countRetriesSel = @selector(countRetriesFetcher:willRetry:forError:);
SEL fixRequestSel = @selector(fixRequestFetcher:willRetry:forError:);
-
+
//
// test: retry until timeout, then expect failure with status message
//
@@ -310,6 +311,44 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
STAssertEquals([fetcher retryCount], 1U, @"retry count unexpected");
}
+- (void)testNilFetch {
+ GTMHTTPFetcher *fetcher = [[GTMHTTPFetcher alloc] init];
+ [GTMUnitTestDevLog expectString:@"beginFetchWithDelegate requires a request"];
+ BOOL wasGood = [fetcher beginFetchWithDelegate:nil
+ didFinishSelector:NULL
+ didFailSelector:NULL];
+ STAssertFalse(wasGood, nil);
+}
+
+- (void)testCookies {
+ // This is checking part one of
+ // rdar://6293862 NSHTTPCookie cookieWithProperties doesn't work with
+ // NSHTTPCookieOriginURL key
+ NSString *urlString = @"http://www.apple.com/index.html";
+ NSURL *url = [NSURL URLWithString:@"http://www.apple.com/index.html"];
+
+ NSDictionary *properties = [NSDictionary dictionaryWithObjectsAndKeys:
+ url, NSHTTPCookieOriginURL,
+ @"testCookies", NSHTTPCookieName,
+ @"1", NSHTTPCookieValue,
+ nil];
+ NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:properties];
+
+ STAssertNil(cookie, nil);
+
+ // This is checking part two of
+ // rdar://6293862 NSHTTPCookie cookieWithProperties doesn't work with
+ // NSHTTPCookieOriginURL key
+ properties = [NSDictionary dictionaryWithObjectsAndKeys:
+ urlString, NSHTTPCookieOriginURL,
+ @"testCookies", NSHTTPCookieName,
+ @"1", NSHTTPCookieValue,
+ nil];
+ cookie = [NSHTTPCookie cookieWithProperties:properties];
+
+ STAssertNil(cookie, nil);
+}
+
#pragma mark -
- (GTMHTTPFetcher *)doFetchWithURLString:(NSString *)urlString
@@ -327,7 +366,7 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
retrySelector:(SEL)retrySel
maxRetryInterval:(NSTimeInterval)maxRetryInterval
userData:(id)userData {
-
+
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *req = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringCacheData
@@ -387,7 +426,7 @@ static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
// return a localhost:port URL for the test file
NSString *urlString = [NSString stringWithFormat:@"http://localhost:%d/%@",
- [testServer_ port], name];
+ [testServer_ port], name];
// we exclude the "?status=" that would indicate that the URL
// should cause a retryable error
diff --git a/Foundation/GTMNSAppleEventDescriptor+Foundation.m b/Foundation/GTMNSAppleEventDescriptor+Foundation.m
index deb375f..14f256d 100644
--- a/Foundation/GTMNSAppleEventDescriptor+Foundation.m
+++ b/Foundation/GTMNSAppleEventDescriptor+Foundation.m
@@ -507,13 +507,12 @@ static NSMutableDictionary *gTypeMap = nil;
BOOL isGood = YES;
AppleEvent replyEvent = { typeNull, NULL };
OSStatus err = AESendMessage([self aeDesc], &replyEvent, mode, timeout * 60);
+ NSAppleEventDescriptor *replyDesc
+ = [[[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&replyEvent] autorelease];
if (err) {
isGood = NO;
_GTMDevLog(@"Unable to send message: %@ %d", self, err);
- replyEvent.descriptorType = typeNull;
- replyEvent.dataHandle = NULL;
}
- NSAppleEventDescriptor *replyDesc = [[[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&replyEvent] autorelease];
if (isGood) {
NSAppleEventDescriptor *errorDesc = [replyDesc descriptorForKeyword:keyErrorNumber];
if (errorDesc && [errorDesc int32Value]) {
diff --git a/Foundation/GTMNSAppleEventDescriptor+Handler.m b/Foundation/GTMNSAppleEventDescriptor+Handler.m
index da0197b..76b6e85 100644
--- a/Foundation/GTMNSAppleEventDescriptor+Handler.m
+++ b/Foundation/GTMNSAppleEventDescriptor+Handler.m
@@ -22,7 +22,7 @@
#import <Carbon/Carbon.h>
@implementation NSAppleEventDescriptor (GTMAppleEventDescriptorHandlerAdditions)
-GTM_METHOD_CHECK(NSProcessInfo, gtm_appleEventDescriptor); // COV_NF_LINE
+GTM_METHOD_CHECK(NSProcessInfo, gtm_appleEventDescriptor);
+ (id)gtm_descriptorWithPositionalHandler:(NSString*)handler
parametersArray:(NSArray*)params {
diff --git a/Foundation/GTMNSAppleScript+Handler.h b/Foundation/GTMNSAppleScript+Handler.h
index 2c38f36..e63eaee 100644
--- a/Foundation/GTMNSAppleScript+Handler.h
+++ b/Foundation/GTMNSAppleScript+Handler.h
@@ -21,7 +21,7 @@
// :::WARNING::: NSAppleScript and Garbage Collect (GC)
//
-// As of 10.5.4 (and below) Apple has bugs in NSAppleScript when running with
+// As of 10.5.5 (and below) Apple has bugs in NSAppleScript when running with
// GC; ie-things crash that have nothing to do w/ this or your code. See
// http://rails.wincent.com/issues/640 for a good amount of detail about the
// problems and simple cases that show it.
diff --git a/Foundation/GTMNSAppleScript+Handler.m b/Foundation/GTMNSAppleScript+Handler.m
index ec6f5d0..592aca6 100644
--- a/Foundation/GTMNSAppleScript+Handler.m
+++ b/Foundation/GTMNSAppleScript+Handler.m
@@ -22,6 +22,7 @@
#import "GTMNSAppleEventDescriptor+Handler.h"
#import "GTMFourCharCode.h"
#import "GTMMethodCheck.h"
+#import "GTMDebugThreadValidation.h"
// Some private methods that we need to call
@interface NSAppleScript (NSPrivate)
@@ -70,9 +71,9 @@
@end
@implementation NSAppleScript(GTMAppleScriptHandlerAdditions)
-GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_descriptorWithPositionalHandler:parametersArray:); // COV_NF_LINE
-GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_descriptorWithLabeledHandler:labels:parameters:count:); // COV_NF_LINE
-GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:); // COV_NF_LINE
+GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_descriptorWithPositionalHandler:parametersArray:);
+GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_descriptorWithLabeledHandler:labels:parameters:count:);
+GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
+ (void)load {
DescType types[] = {
@@ -104,6 +105,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
- (NSAppleEventDescriptor *)gtm_executeAppleEvent:(NSAppleEventDescriptor *)event
error:(NSDictionary **)error {
+ GTMAssertRunningOnMainThread();
if (![self isCompiled]) {
if (![self compileAndReturnError:error]) {
return nil;
@@ -225,7 +227,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
desc = [[[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&result]
autorelease];
} else {
- _GTMDevLog(@"Unable to coerce script %d", error); // COV_NF_LINE
+ _GTMDevLog(@"Unable to coerce script %d", error);
}
return desc;
}
@@ -247,7 +249,8 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
- (void)forwardInvocation:(NSInvocation *)invocation {
SEL sel = [invocation selector];
- NSMutableString *handlerName = [NSStringFromSelector(sel) mutableCopy];
+ NSMutableString *handlerName
+ = [[NSStringFromSelector(sel) mutableCopy] autorelease];
NSUInteger handlerOrigLength = [handlerName length];
[handlerName replaceOccurrencesOfString:@":"
withString:@""
@@ -285,6 +288,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
}
- (NSAppleEventDescriptor*)gtm_valueDescriptorForProperty:(id)property {
+ GTMAssertRunningOnMainThread();
OSAError error = paramErr;
NSAppleEventDescriptor *desc = nil;
NSAppleEventDescriptor *propertyName
@@ -335,6 +339,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
}
- (NSSet*)gtm_scriptHandlers {
+ GTMAssertRunningOnMainThread();
AEDescList names = { typeNull, NULL };
NSArray *array = nil;
ComponentInstance component;
@@ -353,6 +358,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
}
- (NSSet*)gtm_scriptProperties {
+ GTMAssertRunningOnMainThread();
AEDescList names = { typeNull, NULL };
NSArray *array = nil;
ComponentInstance component;
@@ -371,6 +377,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
}
- (OSAID)gtm_genericID:(OSAID)osaID forComponent:(ComponentInstance)component {
+ GTMAssertRunningOnMainThread();
ComponentInstance genericComponent = [NSAppleScript _defaultScriptingComponent];
OSAID exactID = osaID;
OSAError error = OSARealToGenericID(genericComponent, &exactID, component);
@@ -383,6 +390,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
- (NSAppleEventDescriptor*)descForScriptID:(OSAID)osaID
component:(ComponentInstance)component {
+ GTMAssertRunningOnMainThread();
NSAppleEventDescriptor *desc = nil;
// If we have a script, return a typeGTMOSAID, otherwise convert it to
// it's default AEDesc using OSACoerceToDesc with typeWildCard.
@@ -422,6 +430,7 @@ GTM_METHOD_CHECK(NSAppleEventDescriptor, gtm_registerSelector:forTypes:count:);
}
- (OSAID)gtm_realIDAndComponent:(ComponentInstance*)component {
+ GTMAssertRunningOnMainThread();
if (![self isCompiled]) {
NSDictionary *error;
if (![self compileAndReturnError:&error]) {
diff --git a/Foundation/GTMNSAppleScript+HandlerTest.m b/Foundation/GTMNSAppleScript+HandlerTest.m
index d4bb9bc..102332e 100644
--- a/Foundation/GTMNSAppleScript+HandlerTest.m
+++ b/Foundation/GTMNSAppleScript+HandlerTest.m
@@ -36,11 +36,11 @@
// GTMNSAppleScript+Handler.h for more details, but we disable them to avoid
// the tests failing (crashing) when it's Apple's bug. Please bump the system
// check as appropriate when new systems are tested. Currently broken on
- // 10.5.4 and below. Radar 6126682.
- long major, minor, bugfix;
+ // 10.5.5 and below. Radar 6126682.
+ SInt32 major, minor, bugfix;
[GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugfix];
if (!(GTMIsGarbageCollectionEnabled()
- && major <= 10 && minor <= 5 && bugfix <= 4)) {
+ && major <= 10 && minor <= 5 && bugfix <= 5)) {
[super invokeTest];
} else {
NSLog(@"--- %@ NOT run because of GC incompatibilites ---", [self name]);
@@ -286,6 +286,12 @@
@"testadd",
@"testgetscript",
nil];
+ if ([GTMSystemVersion isBuildEqualTo:kGTMSystemBuild10_6_0_WWDC]) {
+ // Workaround for bug in SnowLeopard
+ // rdar://66688601 OSAGetHandlersNames returns names in camelcase instead
+ // of smallcaps.
+ handlers = [handlers valueForKey:@"lowercaseString"];
+ }
STAssertEqualObjects(handlers, expected, @"Unexpected handlers?");
}
@@ -345,13 +351,19 @@
[GTMFourCharCode fourCharCodeWithFourCharCode:pASWeeks],
[GTMFourCharCode fourCharCodeWithFourCharCode:pTextItemDelimiters],
// Applescript properties should be pASSeconds, but
- // on 10.5.4 it is actually using cSeconds.
+ // on 10.5.4/10.5.5 it is actually using cSeconds.
// Radar 6132696 Applescript root level property is cSeconds
// instead of pASSeconds
[GTMFourCharCode fourCharCodeWithFourCharCode:cSeconds],
[GTMFourCharCode fourCharCodeWithFourCharCode:pASHours],
[GTMFourCharCode fourCharCodeWithFourCharCode:pASTab],
nil];
+ if ([GTMSystemVersion isBuildEqualTo:kGTMSystemBuild10_6_0_WWDC]) {
+ // Workaround for bug in SnowLeopard
+ // rdar://6289077 OSAGetPropertyNames returns names in camelcase instead
+ // of lowercase.
+ properties = [properties valueForKey:@"lowercaseString"];
+ }
STAssertEqualObjects(properties, expected, @"Unexpected properties?");
id value = [script gtm_valueForProperty:@"testScriptProperty"];
STAssertEqualObjects(value, [NSNumber numberWithInt:5], @"bad property?");
diff --git a/Foundation/GTMNSDictionary+URLArguments.m b/Foundation/GTMNSDictionary+URLArguments.m
index 9b3d67e..d67572c 100644
--- a/Foundation/GTMNSDictionary+URLArguments.m
+++ b/Foundation/GTMNSDictionary+URLArguments.m
@@ -22,7 +22,7 @@
@implementation NSDictionary (GTMNSDictionaryURLArgumentsAdditions)
-GTM_METHOD_CHECK(NSString, gtm_stringByEscapingForURLArgument); // COV_NF_LINE
+GTM_METHOD_CHECK(NSString, gtm_stringByEscapingForURLArgument);
- (NSString *)gtm_httpArgumentsString {
NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:[self count]];
diff --git a/Foundation/GTMNSString+XML.m b/Foundation/GTMNSString+XML.m
index 909a8f1..0e16ddb 100644
--- a/Foundation/GTMNSString+XML.m
+++ b/Foundation/GTMNSString+XML.m
@@ -40,7 +40,7 @@ static NSString *gXMLEntityList[] = {
@"&gt;",
};
-FOUNDATION_STATIC_INLINE GTMXMLCharMode XMLModeForUnichar(UniChar c) {
+GTM_INLINE GTMXMLCharMode XMLModeForUnichar(UniChar c) {
// Per XML spec Section 2.2 Characters
// ( http://www.w3.org/TR/REC-xml/#charsets )
diff --git a/Foundation/GTMObjC2Runtime.m b/Foundation/GTMObjC2Runtime.m
index df3c9ca..ba0cb74 100644
--- a/Foundation/GTMObjC2Runtime.m
+++ b/Foundation/GTMObjC2Runtime.m
@@ -108,8 +108,16 @@ IMP method_setImplementation(Method method, IMP imp) {
// because it seems odd that this API won't accept nil for method considering
// all the other apis will accept nil args.
// If this does get fixed, remember to enable the unit tests.
- IMP oldImp = method->method_imp;
- method->method_imp = imp;
+ // This method works differently on SnowLeopard than
+ // on Leopard. If you pass in a nil for IMP on SnowLeopard
+ // it doesn't change anything. On Leopard it will. Since
+ // attempting to change a sel to nil is probably an error
+ // we follow the SnowLeopard way of doing things.
+ IMP oldImp = NULL;
+ if (imp) {
+ oldImp = method->method_imp;
+ method->method_imp = imp;
+ }
return oldImp;
}
diff --git a/Foundation/GTMObjC2RuntimeTest.m b/Foundation/GTMObjC2RuntimeTest.m
index 6fb5bdf..1bc0ee3 100644
--- a/Foundation/GTMObjC2RuntimeTest.m
+++ b/Foundation/GTMObjC2RuntimeTest.m
@@ -18,6 +18,10 @@
#import "GTMObjC2Runtime.h"
#import "GTMSenTestCase.h"
+#import "GTMSystemVersion.h"
+
+
+
#import <string.h>
@protocol GTMObjC2Runtime_TestProtocol
@@ -270,11 +274,6 @@ AT_REQUIRED
}
- (void)test_method_setImplementation {
- // Nil Checks
- // This case intentionally not tested. Passing nil to method_setImplementation
- // on Leopard crashes. It does on Tiger as well.
- // STAssertNULL(method_setImplementation(nil, nil), nil);
-
// Standard use check
GTMObjC2Runtime_TestClass *test = [[GTMObjC2Runtime_TestClass alloc] init];
Method *list = class_copyMethodList(cls_, nil);
@@ -297,12 +296,45 @@ AT_REQUIRED
STAssertNotEquals(oldImp, newImp, nil);
// test nils
- oldImp = method_setImplementation(list[0], nil);
- STAssertNotNULL(oldImp, nil);
-
- newImp = method_setImplementation(list[0], oldImp);
- STAssertNULL(newImp, nil);
-
+ // Apparently it was a bug that we could call setImplementation with a nil
+ // so we now test to make sure that setting to nil works as expected on
+ // all systems.
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ // Built for less then leopard gives us the behaviors we defined...
+ // (doesn't take nil)
+ IMP nullImp = method_setImplementation(list[0], nil);
+ STAssertNULL(nullImp, nil);
+ IMP testImp = method_setImplementation(list[0], newImp);
+ STAssertEquals(testImp, oldImp, nil);
+#else
+ // Built for leopard or later means we get the os runtime behavior...
+ if ([GTMSystemVersion isLeopard]) {
+ // (takes nil)
+ oldImp = method_setImplementation(list[0], nil);
+ STAssertNotNULL(oldImp, nil);
+ newImp = method_setImplementation(list[0], oldImp);
+ STAssertNULL(newImp, nil);
+ } else {
+ // (doesn't take nil)
+ IMP nullImp = method_setImplementation(list[0], nil);
+ STAssertNULL(nullImp, nil);
+ IMP testImp = method_setImplementation(list[0], newImp);
+ STAssertEquals(testImp, oldImp, nil);
+ }
+#endif
+
+ // This case intentionally not tested. Passing nil to method_setImplementation
+ // on Leopard crashes. It does on Tiger as well. Half works on SnowLeopard.
+ // We made our Tiger implementation the same as the SnowLeopard
+ // implementation.
+ // Logged as radar 5572981.
+ if (![GTMSystemVersion isLeopard]) {
+ STAssertNULL(method_setImplementation(nil, nil), nil);
+ }
+ if ([GTMSystemVersion isBuildGreaterThan:kGTMSystemBuild10_6_0_WWDC]) {
+ STAssertNULL(method_setImplementation(nil, newImp), nil);
+ }
+
[test release];
free(list);
}
diff --git a/Foundation/GTMProgressMonitorInputStreamTest.m b/Foundation/GTMProgressMonitorInputStreamTest.m
index 1d0d1aa..69d331a 100644
--- a/Foundation/GTMProgressMonitorInputStreamTest.m
+++ b/Foundation/GTMProgressMonitorInputStreamTest.m
@@ -19,7 +19,7 @@
#import "GTMSenTestCase.h"
#import "GTMProgressMonitorInputStream.h"
#import "GTMUnitTestDevLog.h"
-
+#import "GTMSystemVersion.h"
@interface GTMProgressMonitorInputStreamTest : GTMTestCase
@end
@@ -111,10 +111,15 @@ static const unsigned long long kSourceDataByteCount = (10000*10);
[monStream setDelegate:nil];
STAssertNil([monStream delegate], nil);
- // error (we get unknown error before we open things)
-
- NSError *err = [monStream streamError];
- STAssertEqualObjects([err domain], @"NSUnknownErrorDomain", nil);
+ if (![GTMSystemVersion isBuildEqualTo:kGTMSystemBuild10_6_0_WWDC]) {
+ // error (we get unknown error before we open things)
+ // This was changed on SnowLeopard.
+ // rdar://689714 Calling streamError on unopened stream no longer returns
+ // error
+ // was filed to check this behaviour.
+ NSError *err = [monStream streamError];
+ STAssertEqualObjects([err domain], @"NSUnknownErrorDomain", nil);
+ }
// status and properties
diff --git a/Foundation/GTMRegex.m b/Foundation/GTMRegex.m
index 33c5b25..71d5050 100644
--- a/Foundation/GTMRegex.m
+++ b/Foundation/GTMRegex.m
@@ -444,13 +444,16 @@ static NSString *const kReplacementPattern =
NSString *result = @"internal error";
// size the buffer we need
- size_t len = regerror(errCode, &regexData_, nil, 0);
- char buffer[len];
- // fetch the error
- if (len == regerror(errCode, &regexData_, buffer, len)) {
- NSString *generatedError = [NSString stringWithUTF8String:buffer];
- if (generatedError)
- result = generatedError;
+ size_t len = regerror(errCode, &regexData_, NULL, 0);
+ char *buffer = (char*)malloc(sizeof(char) * len);
+ if (buffer) {
+ // fetch the error
+ if (len == regerror(errCode, &regexData_, buffer, len)) {
+ NSString *generatedError = [NSString stringWithUTF8String:buffer];
+ if (generatedError)
+ result = generatedError;
+ }
+ free(buffer);
}
return result;
}
diff --git a/Foundation/GTMScriptRunner.m b/Foundation/GTMScriptRunner.m
index 8a76c4a..fce6915 100644
--- a/Foundation/GTMScriptRunner.m
+++ b/Foundation/GTMScriptRunner.m
@@ -72,6 +72,7 @@ static BOOL LaunchNSTaskCatchingExceptions(NSTask *task);
}
- (void)dealloc {
+ [environment_ release];
[interpreter_ release];
[interpreterArgs_ release];
[super dealloc];
diff --git a/Foundation/GTMScriptRunnerTest.m b/Foundation/GTMScriptRunnerTest.m
index 9545045..3d74b9e 100644
--- a/Foundation/GTMScriptRunnerTest.m
+++ b/Foundation/GTMScriptRunnerTest.m
@@ -183,12 +183,13 @@
GTMScriptRunner *sr = [GTMScriptRunner runner];
STAssertNotNil(sr, @"Script runner must not be nil");
NSString *output = nil;
-
+ NSString *error = nil;
STAssertNil([sr environment], @"should start w/ empty env");
- output = [sr run:@"/usr/bin/env | wc -l"];
+ output = [sr run:@"/usr/bin/env | wc -l" standardError:&error];
int numVars = [output intValue];
- STAssertGreaterThan(numVars, 0, @"numVars should be positive");
+ STAssertGreaterThan(numVars, 0,
+ @"numVars should be positive. StdErr %@", error);
// By default the environment is wiped clean, however shells often add a few
// of their own env vars after things have been wiped. For example, sh will
// add about 3 env vars (PWD, _, and SHLVL).
@@ -197,15 +198,14 @@
NSDictionary *newEnv = [NSDictionary dictionaryWithObject:@"bar"
forKey:@"foo"];
[sr setEnvironment:newEnv];
-
- output = [sr run:@"/usr/bin/env | wc -l"];
+ output = [sr run:@"/usr/bin/env | wc -l" standardError:&error];
STAssertEquals([output intValue], numVars + 1,
- @"should have one more env var now");
+ @"should have one more env var now. StdErr %@", error);
[sr setEnvironment:nil];
- output = [sr run:@"/usr/bin/env | wc -l"];
+ output = [sr run:@"/usr/bin/env | wc -l" standardError:&error];
STAssertEquals([output intValue], numVars,
- @"should be back down to %d vars", numVars);
+ @"should be back down to %d vars. StdErr:%@", numVars, error);
NSMutableDictionary *currVars
= [[[[NSProcessInfo processInfo] environment] mutableCopy] autorelease];
@@ -216,9 +216,11 @@
[currVars setObject:@"/usr/bin/env" forKey:@"_"];
[sr setEnvironment:currVars];
- output = [sr run:@"/usr/bin/env | wc -l"];
- STAssertEquals([output intValue], (int)[currVars count],
- @"should be back down to %d vars", numVars);
+ output = [sr run:@"/usr/bin/env | /usr/bin/sort" standardError:&error];
+ NSArray *lineArray = [output componentsSeparatedByString:@"\n"];
+ STAssertEquals([lineArray count], [currVars count],
+ @"StdErr:%@\nCurrentEnvironment:\n%@\nExpected environment:\n%@",
+ error, output, currVars);
}
- (void)testDescription {
diff --git a/Foundation/GTMStackTrace.h b/Foundation/GTMStackTrace.h
index a77ca93..3b6965d 100644
--- a/Foundation/GTMStackTrace.h
+++ b/Foundation/GTMStackTrace.h
@@ -17,6 +17,7 @@
//
#include <CoreFoundation/CoreFoundation.h>
+#import "GTMDefines.h"
#ifdef __cplusplus
extern "C" {
@@ -66,7 +67,7 @@ NSString *GTMStackTrace(void);
// Returns:
// The number of program counters actually added to outPcs.
//
-int GTMGetStackProgramCounters(void *outPcs[], int count);
+NSUInteger GTMGetStackProgramCounters(void *outPcs[], NSUInteger count);
// Returns an array of GTMAddressDescriptors from the current thread's stack.
// *** You should probably use GTMStackTrace() instead of this function ***
@@ -84,8 +85,8 @@ int GTMGetStackProgramCounters(void *outPcs[], int count);
// Returns:
// The number of program counters actually added to outPcs.
//
-int GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
- int count);
+NSUInteger GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
+ NSUInteger count);
#ifdef __cplusplus
}
#endif
diff --git a/Foundation/GTMStackTrace.m b/Foundation/GTMStackTrace.m
index a7198dc..8a14bcf 100644
--- a/Foundation/GTMStackTrace.m
+++ b/Foundation/GTMStackTrace.m
@@ -42,7 +42,7 @@ struct GTMClassDescription {
#pragma mark Private utility functions
-static struct GTMClassDescription *GTMClassDescriptions(int *total_count) {
+static struct GTMClassDescription *GTMClassDescriptions(NSUInteger *total_count) {
int class_count = objc_getClassList(nil, 0);
struct GTMClassDescription *class_descs
= calloc(class_count, sizeof(struct GTMClassDescription));
@@ -74,9 +74,9 @@ static struct GTMClassDescription *GTMClassDescriptions(int *total_count) {
}
static void GTMFreeClassDescriptions(struct GTMClassDescription *class_descs,
- int count) {
- if (!class_descs || count < 0) return;
- for (int i = 0; i < count; ++i) {
+ NSUInteger count) {
+ if (!class_descs) return;
+ for (NSUInteger i = 0; i < count; ++i) {
if (class_descs[i].instance_methods) {
free(class_descs[i].instance_methods);
}
@@ -95,7 +95,7 @@ static void GTMFreeClassDescriptions(struct GTMClassDescription *class_descs,
// great on i386, but PPC requires a little more work because the PC (or link
// register) isn't always stored on the stack.
//
-int GTMGetStackProgramCounters(void *outPcs[], int count) {
+NSUInteger GTMGetStackProgramCounters(void *outPcs[], NSUInteger count) {
if (!outPcs || (count < 1)) return 0;
struct GTMStackFrame *fp;
@@ -108,7 +108,7 @@ int GTMGetStackProgramCounters(void *outPcs[], int count) {
#error architecture not supported
#endif
- int level = 0;
+ NSUInteger level = 0;
while (level < count) {
if (fp == NULL) {
level--;
@@ -122,15 +122,15 @@ int GTMGetStackProgramCounters(void *outPcs[], int count) {
return level;
}
-int GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
- int count) {
- if (count < 1) return 0;
+NSUInteger GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
+ NSUInteger count) {
+ if (count < 1 || !outDescs) return 0;
void **pcs = calloc(count, sizeof(void*));
if (!pcs) return 0;
- int newSize = GTMGetStackProgramCounters(pcs, count);
- int class_desc_count;
+ NSUInteger newSize = GTMGetStackProgramCounters(pcs, count);
+ NSUInteger class_desc_count;
// Get our obj-c class descriptions. This is expensive, so we do it once
// at the top. We go through this because dladdr doesn't work with
@@ -139,7 +139,7 @@ int GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
= GTMClassDescriptions(&class_desc_count);
// Iterate through the stack.
- for (int i = 0; i < newSize; ++i) {
+ for (NSUInteger i = 0; i < newSize; ++i) {
const char *class_name = NULL;
Boolean is_class_method = FALSE;
size_t smallest_diff = SIZE_MAX;
@@ -147,9 +147,9 @@ int GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
currDesc->address = pcs[i];
Method best_method = NULL;
// Iterate through all the classes we know of.
- for (int j = 0; j < class_desc_count; ++j) {
+ for (NSUInteger j = 0; j < class_desc_count; ++j) {
// First check the class methods.
- for (unsigned int k = 0; k < class_descs[j].class_method_count; ++k) {
+ for (NSUInteger k = 0; k < class_descs[j].class_method_count; ++k) {
IMP imp = method_getImplementation(class_descs[j].class_methods[k]);
if (imp <= (IMP)currDesc->address) {
size_t diff = (size_t)currDesc->address - (size_t)imp;
@@ -162,7 +162,7 @@ int GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
}
}
// Then check the instance methods.
- for (unsigned int k = 0; k < class_descs[j].instance_method_count; ++k) {
+ for (NSUInteger k = 0; k < class_descs[j].instance_method_count; ++k) {
IMP imp = method_getImplementation(class_descs[j].instance_methods[k]);
if (imp <= (IMP)currDesc->address) {
size_t diff = (size_t)currDesc->address - (size_t)imp;
@@ -194,6 +194,7 @@ int GTMGetStackAddressDescriptors(struct GTMAddressDescriptor outDescs[],
currDesc->filename = info.dli_fname;
}
GTMFreeClassDescriptions(class_descs, class_desc_count);
+ free(pcs);
return newSize;
}
@@ -201,17 +202,16 @@ NSString *GTMStackTrace(void) {
// The maximum number of stack frames that we will walk. We limit this so
// that super-duper recursive functions (or bugs) don't send us for an
// infinite loop.
- const int kMaxStackTraceDepth = 100;
- struct GTMAddressDescriptor descs[kMaxStackTraceDepth];
- int depth = kMaxStackTraceDepth;
+ struct GTMAddressDescriptor descs[100];
+ size_t depth = sizeof(descs) / sizeof(struct GTMAddressDescriptor);
depth = GTMGetStackAddressDescriptors(descs, depth);
NSMutableString *trace = [NSMutableString string];
// Start at the second item so that GTMStackTrace and it's utility calls (of
// which there is currently 1) is not included in the output.
- const int kTracesToStrip = 2;
- for (int i = kTracesToStrip; i < depth; i++) {
+ const size_t kTracesToStrip = 2;
+ for (size_t i = kTracesToStrip; i < depth; i++) {
if (descs[i].class_name) {
[trace appendFormat:@"#%-2d 0x%08lx %s[%s %s] (%s)\n",
i - kTracesToStrip, descs[i].address,
diff --git a/Foundation/GTMStackTraceTest.m b/Foundation/GTMStackTraceTest.m
index dd92fe9..dc5ea57 100644
--- a/Foundation/GTMStackTraceTest.m
+++ b/Foundation/GTMStackTraceTest.m
@@ -47,11 +47,12 @@
- (void)testProgramCountersBasic {
void *pcs[10];
- int depth = 10;
+ NSUInteger depth = 10;
depth = GTMGetStackProgramCounters(pcs, depth);
- STAssertGreaterThan(depth, 3, @"stack trace must have > 3 lines");
- STAssertLessThanOrEqual(depth, 10, @"stack trace must have < 10 lines");
+ STAssertGreaterThan(depth, (NSUInteger)3, @"stack trace must have > 3 lines");
+ STAssertLessThanOrEqual(depth, (NSUInteger)10,
+ @"stack trace must have < 10 lines");
// pcs is an array of program counters from the stack. pcs[0] should match
// the call into GTMGetStackProgramCounters, which is tough for us to check.
@@ -63,19 +64,19 @@
- (void)testProgramCountersMore {
void *pcs0[0];
- int depth0 = 0;
+ NSUInteger depth0 = 0;
depth0 = GTMGetStackProgramCounters(pcs0, depth0);
- STAssertEquals(depth0, 0, @"stack trace must have 0 lines");
+ STAssertEquals(depth0, (NSUInteger)0, @"stack trace must have 0 lines");
void *pcs1[1];
- int depth1 = 1;
+ NSUInteger depth1 = 1;
depth1 = GTMGetStackProgramCounters(pcs1, depth1);
- STAssertEquals(depth1, 1, @"stack trace must have 1 lines");
+ STAssertEquals(depth1, (NSUInteger)1, @"stack trace must have 1 lines");
void *pcs2[2];
- int depth2 = 2;
+ NSUInteger depth2 = 2;
depth2 = GTMGetStackProgramCounters(pcs2, depth2);
- STAssertEquals(depth2, 2, @"stack trace must have 2 lines");
+ STAssertEquals(depth2, (NSUInteger)2, @"stack trace must have 2 lines");
void *current_pc = __builtin_return_address(0);
STAssertEquals(pcs2[1], current_pc, @"pcs[1] should equal the current PC");
}
diff --git a/Foundation/GTMSystemVersion.h b/Foundation/GTMSystemVersion.h
index 0f19596..959d2af 100644
--- a/Foundation/GTMSystemVersion.h
+++ b/Foundation/GTMSystemVersion.h
@@ -23,7 +23,20 @@
@interface GTMSystemVersion : NSObject
// Returns the current system version major.minor.bugFix
-+ (void)getMajor:(long*)major minor:(long*)minor bugFix:(long*)bugFix;
++ (void)getMajor:(SInt32*)major minor:(SInt32*)minor bugFix:(SInt32*)bugFix;
+
+// Returns the build number of the OS. Useful when looking for bug fixes
+// in new OSes which all have a set system version.
+// eg 10.5.5's build number is 9F33. Easy way to check the build number
+// is to choose "About this Mac" from the Apple menu and click on the version
+// number.
++ (NSString*)build;
+
++ (BOOL)isBuildLessThan:(NSString*)build;
++ (BOOL)isBuildLessThanOrEqualTo:(NSString*)build;
++ (BOOL)isBuildGreaterThan:(NSString*)build;
++ (BOOL)isBuildGreaterThanOrEqualTo:(NSString*)build;
++ (BOOL)isBuildEqualTo:(NSString *)build;
#if GTM_MACOS_SDK
// Returns YES if running on 10.3, NO otherwise.
@@ -35,6 +48,9 @@
// Returns YES if running on 10.5, NO otherwise.
+ (BOOL)isLeopard;
+// Returns YES if running on 10.6, NO otherwise.
++ (BOOL)isSnowLeopard;
+
// Returns a YES/NO if the system is 10.3 or better
+ (BOOL)isPantherOrGreater;
@@ -43,6 +59,27 @@
// Returns a YES/NO if the system is 10.5 or better
+ (BOOL)isLeopardOrGreater;
+
+// Returns a YES/NO if the system is 10.6 or better
++ (BOOL)isSnowLeopardOrGreater;
#endif // GTM_MACOS_SDK
+// Returns one of the achitecture strings below. Note that this is the
+// architecture that we are currently running as, not the hardware architecture.
++ (NSString *)runtimeArchitecture;
@end
+
+// Architecture Strings
+// TODO: Should probably break iPhone up into iPhone_ARM and iPhone_Simulator
+// but haven't found a need yet.
+extern NSString *const kGTMArch_iPhone;
+extern NSString *const kGTMArch_ppc;
+extern NSString *const kGTMArch_ppc64;
+extern NSString *const kGTMArch_x86_64;
+extern NSString *const kGTMArch_i386;
+
+// System Build Number constants
+extern NSString *const kGTMSystemBuild10_5_5;
+extern NSString *const kGTMSystemBuild10_6_0_WWDC;
+
+
diff --git a/Foundation/GTMSystemVersion.m b/Foundation/GTMSystemVersion.m
index da767ae..868f6b8 100644
--- a/Foundation/GTMSystemVersion.m
+++ b/Foundation/GTMSystemVersion.m
@@ -17,6 +17,7 @@
//
#import "GTMSystemVersion.h"
+#import "GTMGarbageCollection.h"
#if GTM_MACOS_SDK
#import <Carbon/Carbon.h>
#endif
@@ -24,6 +25,18 @@
static SInt32 sGTMSystemVersionMajor = 0;
static SInt32 sGTMSystemVersionMinor = 0;
static SInt32 sGTMSystemVersionBugFix = 0;
+static NSString *sBuild = nil;
+
+NSString *const kGTMArch_iPhone = @"iPhone";
+NSString *const kGTMArch_ppc = @"ppc";
+NSString *const kGTMArch_ppc64 = @"ppc64";
+NSString *const kGTMArch_x86_64 = @"x86_64";
+NSString *const kGTMArch_i386 = @"i386";
+
+static NSString *const kSystemVersionPlistPath = @"/System/Library/CoreServices/SystemVersion.plist";
+
+NSString *const kGTMSystemBuild10_5_5 = @"9F33";
+NSString *const kGTMSystemBuild10_6_0_WWDC = @"10A96";
@implementation GTMSystemVersion
+ (void)initialize {
@@ -51,9 +64,9 @@ static SInt32 sGTMSystemVersionBugFix = 0;
// Note that this code will return x.9.9 for any system rev parts that are
// greater than 9 (i.e., 10.10.10 will be 10.9.9). This shouldn't ever be a
// problem as the code above takes care of 10.4+.
- int msb = (binaryCodedDec & 0x0000F000L) >> 12;
+ SInt32 msb = (binaryCodedDec & 0x0000F000L) >> 12;
msb *= 10;
- int lsb = (binaryCodedDec & 0x00000F00L) >> 8;
+ SInt32 lsb = (binaryCodedDec & 0x00000F00L) >> 8;
sGTMSystemVersionMajor = msb + lsb;
sGTMSystemVersionMinor = (binaryCodedDec & 0x000000F0L) >> 4;
sGTMSystemVersionBugFix = (binaryCodedDec & 0x0000000FL);
@@ -61,14 +74,17 @@ static SInt32 sGTMSystemVersionBugFix = 0;
#else // GTM_MACOS_SDK
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSDictionary *systemVersionPlist = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
+ NSDictionary *systemVersionPlist
+ = [NSDictionary dictionaryWithContentsOfFile:kSystemVersionPlistPath];
NSString *version = [systemVersionPlist objectForKey:@"ProductVersion"];
_GTMDevAssert(version, @"Unable to get version");
NSArray *versionInfo = [version componentsSeparatedByString:@"."];
NSUInteger length = [versionInfo count];
- _GTMDevAssert(length > 1 && length < 4, @"Unparseable version %@", version);
+ _GTMDevAssert(length > 1 && length < 4,
+ @"Unparseable version %@", version);
sGTMSystemVersionMajor = [[versionInfo objectAtIndex:0] intValue];
- _GTMDevAssert(sGTMSystemVersionMajor != 0, @"Unknown version for %@", version);
+ _GTMDevAssert(sGTMSystemVersionMajor != 0,
+ @"Unknown version for %@", version);
sGTMSystemVersionMinor = [[versionInfo objectAtIndex:1] intValue];
if (length == 3) {
sGTMSystemVersionBugFix = [[versionInfo objectAtIndex:2] intValue];
@@ -78,7 +94,7 @@ static SInt32 sGTMSystemVersionBugFix = 0;
}
}
-+ (void)getMajor:(long*)major minor:(long*)minor bugFix:(long*)bugFix {
++ (void)getMajor:(SInt32*)major minor:(SInt32*)minor bugFix:(SInt32*)bugFix {
if (major) {
*major = sGTMSystemVersionMajor;
}
@@ -90,6 +106,57 @@ static SInt32 sGTMSystemVersionBugFix = 0;
}
}
++ (NSString*)build {
+ @synchronized(self) {
+ // Not cached at initialization time because we don't expect "real"
+ // software to want this, and it costs a bit to get at startup.
+ // This will mainly be for unit test cases.
+ if (!sBuild) {
+ NSDictionary *systemVersionPlist
+ = [NSDictionary dictionaryWithContentsOfFile:kSystemVersionPlistPath];
+ sBuild = [[systemVersionPlist objectForKey:@"ProductBuildVersion"] retain];
+ GTMNSMakeUncollectable(sBuild);
+ _GTMDevAssert(sBuild, @"Unable to get build version");
+ }
+ }
+ return sBuild;
+}
+
++ (BOOL)isBuildLessThan:(NSString*)build {
+ NSComparisonResult result
+ = [[self build] compare:build
+ options:NSNumericSearch | NSCaseInsensitiveSearch];
+ return result == NSOrderedAscending;
+}
+
++ (BOOL)isBuildLessThanOrEqualTo:(NSString*)build {
+ NSComparisonResult result
+ = [[self build] compare:build
+ options:NSNumericSearch | NSCaseInsensitiveSearch];
+ return result != NSOrderedDescending;
+}
+
++ (BOOL)isBuildGreaterThan:(NSString*)build {
+ NSComparisonResult result
+ = [[self build] compare:build
+ options:NSNumericSearch | NSCaseInsensitiveSearch];
+ return result == NSOrderedDescending;
+}
+
++ (BOOL)isBuildGreaterThanOrEqualTo:(NSString*)build {
+ NSComparisonResult result
+ = [[self build] compare:build
+ options:NSNumericSearch | NSCaseInsensitiveSearch];
+ return result != NSOrderedAscending;
+}
+
++ (BOOL)isBuildEqualTo:(NSString *)build {
+ NSComparisonResult result
+ = [[self build] compare:build
+ options:NSNumericSearch | NSCaseInsensitiveSearch];
+ return result == NSOrderedSame;
+}
+
#if GTM_MACOS_SDK
+ (BOOL)isPanther {
return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 3;
@@ -103,6 +170,10 @@ static SInt32 sGTMSystemVersionBugFix = 0;
return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 5;
}
++ (BOOL)isSnowLeopard {
+ return sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor == 6;
+}
+
+ (BOOL)isPantherOrGreater {
return (sGTMSystemVersionMajor > 10) ||
(sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 3);
@@ -118,6 +189,43 @@ static SInt32 sGTMSystemVersionBugFix = 0;
(sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 5);
}
++ (BOOL)isSnowLeopardOrGreater {
+ return (sGTMSystemVersionMajor > 10) ||
+ (sGTMSystemVersionMajor == 10 && sGTMSystemVersionMinor >= 6);
+}
+
#endif // GTM_MACOS_SDK
++ (NSString *)runtimeArchitecture {
+ NSString *architecture = nil;
+#if GTM_IPHONE_SDK
+ architecture = kGTMArch_iPhone;
+#else // !GTM_IPHONE_SDK
+ // In reading arch(3) you'd thing this would work:
+ //
+ // const NXArchInfo *localInfo = NXGetLocalArchInfo();
+ // _GTMDevAssert(localInfo && localInfo->name, @"Couldn't get NXArchInfo");
+ // const NXArchInfo *genericInfo = NXGetArchInfoFromCpuType(localInfo->cputype, 0);
+ // _GTMDevAssert(genericInfo && genericInfo->name, @"Couldn't get generic NXArchInfo");
+ // extensions[0] = [NSString stringWithFormat:@".%s", genericInfo->name];
+ //
+ // but on 64bit it returns the same things as on 32bit, so...
+#if __POWERPC__
+#if __LP64__
+ architecture = kGTMArch_ppc64;
+#else // !__LP64__
+ architecture = kGTMArch_ppc;
+#endif // __LP64__
+#else // !__POWERPC__
+#if __LP64__
+ architecture = kGTMArch_x86_64;
+#else // !__LP64__
+ architecture = kGTMArch_i386;
+#endif // __LP64__
+#endif // !__POWERPC__
+
+#endif // GTM_IPHONE_SDK
+ return architecture;
+}
+
@end
diff --git a/Foundation/GTMSystemVersionTest.m b/Foundation/GTMSystemVersionTest.m
index e95a33d..b6952da 100644
--- a/Foundation/GTMSystemVersionTest.m
+++ b/Foundation/GTMSystemVersionTest.m
@@ -24,9 +24,9 @@
@implementation GTMSystemVersionTest
- (void)testBasics {
- long major;
- long minor;
- long bugFix;
+ SInt32 major;
+ SInt32 minor;
+ SInt32 bugFix;
[GTMSystemVersion getMajor:nil minor:nil bugFix:nil];
[GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
@@ -37,17 +37,54 @@
BOOL isPanther = (major == 10) && (minor == 3);
BOOL isTiger = (major == 10) && (minor == 4);
BOOL isLeopard = (major == 10) && (minor == 5);
- BOOL isLater = (major > 10) || ((major == 10) && (minor > 5));
+ BOOL isSnowLeopard = (major == 10) && (minor == 6);
+
+ BOOL isLater = (major > 10) || ((major == 10) && (minor > 6));
STAssertEquals([GTMSystemVersion isPanther], isPanther, nil);
STAssertEquals([GTMSystemVersion isPantherOrGreater],
- (BOOL)(isPanther || isTiger || isLeopard || isLater), nil);
+ (BOOL)(isPanther || isTiger
+ || isLeopard || isSnowLeopard || isLater), nil);
STAssertEquals([GTMSystemVersion isTiger], isTiger, nil);
STAssertEquals([GTMSystemVersion isTigerOrGreater],
- (BOOL)(isTiger || isLeopard || isLater), nil);
+ (BOOL)(isTiger || isLeopard || isSnowLeopard || isLater), nil);
STAssertEquals([GTMSystemVersion isLeopard], isLeopard, nil);
STAssertEquals([GTMSystemVersion isLeopardOrGreater],
- (BOOL)(isLeopard || isLater), nil);
-#endif
+ (BOOL)(isLeopard || isSnowLeopard || isLater), nil);
+ STAssertEquals([GTMSystemVersion isSnowLeopard], isSnowLeopard, nil);
+ STAssertEquals([GTMSystemVersion isSnowLeopardOrGreater],
+ (BOOL)(isSnowLeopard || isLater), nil);
+#endif
+}
+
+- (void)testRuntimeArchitecture {
+ // Not sure how to test this short of recoding it and verifying.
+ // This at least executes the code for me.
+ STAssertNotNil([GTMSystemVersion runtimeArchitecture], nil);
}
+- (void)testBuild {
+ // Not sure how to test this short of coding up a large fragile table.
+ // This at least executes the code for me.
+ NSString *systemVersion = [GTMSystemVersion build];
+ STAssertNotEquals([systemVersion length], (NSUInteger)0, nil);
+
+ NSString *smallVersion = @"1A00";
+ NSString *largeVersion = @"100Z100";
+ STAssertTrue([GTMSystemVersion isBuildGreaterThan:smallVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildGreaterThan:systemVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildGreaterThan:largeVersion], nil);
+ STAssertTrue([GTMSystemVersion isBuildGreaterThanOrEqualTo:smallVersion], nil);
+ STAssertTrue([GTMSystemVersion isBuildGreaterThanOrEqualTo:systemVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildGreaterThanOrEqualTo:largeVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildEqualTo:smallVersion], nil);
+ STAssertTrue([GTMSystemVersion isBuildEqualTo:systemVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildEqualTo:largeVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildLessThanOrEqualTo:smallVersion], nil);
+ STAssertTrue([GTMSystemVersion isBuildLessThanOrEqualTo:systemVersion], nil);
+ STAssertTrue([GTMSystemVersion isBuildLessThanOrEqualTo:largeVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildLessThan:smallVersion], nil);
+ STAssertFalse([GTMSystemVersion isBuildLessThan:systemVersion], nil);
+ STAssertTrue([GTMSystemVersion isBuildLessThan:largeVersion], nil);
+
+}
@end
diff --git a/Foundation/GTMValidatingContainers.h b/Foundation/GTMValidatingContainers.h
index 1b11f1b..e53b541 100644
--- a/Foundation/GTMValidatingContainers.h
+++ b/Foundation/GTMValidatingContainers.h
@@ -33,7 +33,7 @@
// GTMValidatingArray *array = [GTMValidatingArray validatingArrayWithTarget:target
// selector:selector];
// [array addObject:@"foo"]; // Will be good
-// [array addObject:[NSNumber numberWithInt:2]; // Will fail
+// [array addObject:[NSNumber numberWithInt:2]]; // Will fail
//
// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and
// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens
@@ -84,18 +84,19 @@ void _GTMValidateContainerContainsMemberOfClass(id container, Class cls);
void _GTMValidateContainerConformsToProtocol(id container, Protocol *prot);
void _GTMValidateContainerItemsRespondToSelector(id container, SEL sel);
#else
-inline void _GTMValidateContainer(id container, id target, SEL selector) {
+GTM_INLINE void _GTMValidateContainer(id container, id target, SEL selector) {
}
-inline void _GTMValidateContainerContainsKindOfClass(id container, Class cls) {
+GTM_INLINE void _GTMValidateContainerContainsKindOfClass(id container,
+ Class cls) {
}
-inline void _GTMValidateContainerContainsMemberOfClass(id container,
- Class cls) {
+GTM_INLINE void _GTMValidateContainerContainsMemberOfClass(id container,
+ Class cls) {
}
-inline void _GTMValidateContainerConformsToProtocol(id container,
- Protocol *prot) {
+GTM_INLINE void _GTMValidateContainerConformsToProtocol(id container,
+ Protocol *prot) {
}
-inline void _GTMValidateContainerItemsRespondToSelector(id container,
- SEL sel) {
+GTM_INLINE void _GTMValidateContainerItemsRespondToSelector(id container,
+ SEL sel) {
}
#endif
diff --git a/Foundation/GTMValidatingContainers.m b/Foundation/GTMValidatingContainers.m
index f46ba3f..3b31356 100644
--- a/Foundation/GTMValidatingContainers.m
+++ b/Foundation/GTMValidatingContainers.m
@@ -34,10 +34,10 @@
#import <objc/objc-runtime.h>
#endif // GTM_IPHONE_SDK
-static inline BOOL VerifyObjectWithTargetAndSelectorForContainer(id anObject,
- id target,
- SEL selector,
- id container) {
+GTM_INLINE BOOL VerifyObjectWithTargetAndSelectorForContainer(id anObject,
+ id target,
+ SEL selector,
+ id container) {
// We must take care here, since Intel leaves junk in high bytes of return
// register for predicates that return BOOL.
// For details see:
@@ -59,7 +59,7 @@ static inline BOOL VerifyObjectWithTargetAndSelectorForContainer(id anObject,
return isGood;
}
-static inline void VerifySelectorOnTarget(SEL sel, id target) {
+GTM_INLINE void VerifySelectorOnTarget(SEL sel, id target) {
GTMAssertSelectorNilOrImplementedWithReturnTypeAndArguments(target,
sel,
@encode(BOOL),
@@ -207,7 +207,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
- (id)initValidatingWithCapacity:(NSUInteger)capacity
target:(id)target
selector:(SEL)sel {
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return [[NSMutableArray alloc] initWithCapacity:capacity];
}
#endif // GTM_CONTAINERS_VALIDATE
@@ -282,7 +284,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
- (id)initValidatingWithCapacity:(NSUInteger)capacity
target:(id)target
selector:(SEL)sel {
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return [[NSMutableDictionary alloc] initWithCapacity:capacity];
}
@@ -359,7 +363,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
- (id)initValidatingWithCapacity:(NSUInteger)capacity
target:(id)target
selector:(SEL)sel {
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return [[NSMutableSet alloc] initWithCapacity:capacity];
}
#endif // GTM_CONTAINERS_VALIDATE
@@ -384,7 +390,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
}
return self;
#else // GTM_CONTAINERS_VALIDATE
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return nil;
#endif // GTM_CONTAINERS_VALIDATE
}
@@ -411,7 +419,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
}
return self;
#else // GTM_CONTAINERS_VALIDATE
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return nil;
#endif // GTM_CONTAINERS_VALIDATE
}
@@ -438,7 +448,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
}
return self;
#else // GTM_CONTAINERS_VALIDATE
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return nil;
#endif // GTM_CONTAINERS_VALIDATE
}
@@ -465,7 +477,9 @@ void _GTMValidateContainer(id container, id target, SEL selector) {
}
return self;
#else // GTM_CONTAINERS_VALIDATE
- [self release];
+ if ((self = [super init])) {
+ [self release];
+ }
return nil;
#endif // GTM_CONTAINERS_VALIDATE
}