Commits

Tuukka Norri  committed 8c19193

NSValue safety, linking
- NSValue's -getValue: doesn't check the size of the given buffer. Wrote a C++ class to resolve this.
- NSNumber's deserialization method now tries to make the resulting NSNumber as small as possible.
- Changed linking to AppKit so that the whole framework is weakly linked, not just the NSApp symbol. There were some problems with the symbol not being available in client applications.

  • Participants
  • Parent commits 4499160

Comments (0)

Files changed (16)

File BaseTen.xcodeproj/project.pbxproj

 		5392053D11AEDB4F000E2BEC /* BXCollectionFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5392053C11AEDB4F000E2BEC /* BXCollectionFunctions.h */; };
 		53937B670EFD097700510DBD /* PGTSInvocationRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 53937B650EFD097700510DBD /* PGTSInvocationRecorder.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		53937B680EFD097700510DBD /* PGTSInvocationRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 53937B660EFD097700510DBD /* PGTSInvocationRecorder.m */; };
+		539506F211CFAFBA0049F36C /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5395061611CFAD680049F36C /* AppKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
+		53950A0811CFBD730049F36C /* NSNumber+BaseTenAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53950A0611CFBD730049F36C /* NSNumber+BaseTenAdditions.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		53950A0911CFBD730049F36C /* NSNumber+BaseTenAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 53950A0711CFBD730049F36C /* NSNumber+BaseTenAdditions.mm */; };
+		53950A0C11CFBDAE0049F36C /* NSValue+BaseTenAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53950A0A11CFBDAE0049F36C /* NSValue+BaseTenAdditions.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		53950A0D11CFBDAE0049F36C /* NSValue+BaseTenAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 53950A0B11CFBDAE0049F36C /* NSValue+BaseTenAdditions.m */; };
+		53950AC711CFD6840049F36C /* BXValueGetter.h in Headers */ = {isa = PBXBuildFile; fileRef = 53950AC511CFD6840049F36C /* BXValueGetter.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		53950AC811CFD6840049F36C /* BXValueGetter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 53950AC611CFD6840049F36C /* BXValueGetter.mm */; };
 		5395E7260E2F77DF006E8441 /* BXPGEntityImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5395E7240E2F77DF006E8441 /* BXPGEntityImporter.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		5395E7270E2F77DF006E8441 /* BXPGEntityImporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5395E7250E2F77DF006E8441 /* BXPGEntityImporter.m */; };
 		539758520E1E86200042120A /* BXDataModelCompiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 539758500E1E86200042120A /* BXDataModelCompiler.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		53933EF409EBD082001D00BB /* BXInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BXInterface.h; path = Sources/BXInterface.h; sourceTree = "<group>"; };
 		53937B650EFD097700510DBD /* PGTSInvocationRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PGTSInvocationRecorder.h; path = Sources/PGTSInvocationRecorder.h; sourceTree = "<group>"; };
 		53937B660EFD097700510DBD /* PGTSInvocationRecorder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PGTSInvocationRecorder.m; path = Sources/PGTSInvocationRecorder.m; sourceTree = "<group>"; };
+		5395061611CFAD680049F36C /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+		53950A0611CFBD730049F36C /* NSNumber+BaseTenAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSNumber+BaseTenAdditions.h"; path = "Sources/NSNumber+BaseTenAdditions.h"; sourceTree = "<group>"; };
+		53950A0711CFBD730049F36C /* NSNumber+BaseTenAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "NSNumber+BaseTenAdditions.mm"; path = "Sources/NSNumber+BaseTenAdditions.mm"; sourceTree = "<group>"; };
+		53950A0A11CFBDAE0049F36C /* NSValue+BaseTenAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSValue+BaseTenAdditions.h"; path = "Sources/NSValue+BaseTenAdditions.h"; sourceTree = "<group>"; };
+		53950A0B11CFBDAE0049F36C /* NSValue+BaseTenAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSValue+BaseTenAdditions.m"; path = "Sources/NSValue+BaseTenAdditions.m"; sourceTree = "<group>"; };
+		53950AC511CFD6840049F36C /* BXValueGetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXValueGetter.h; path = Sources/BXValueGetter.h; sourceTree = "<group>"; };
+		53950AC611CFD6840049F36C /* BXValueGetter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = BXValueGetter.mm; path = Sources/BXValueGetter.mm; sourceTree = "<group>"; };
 		5395E7240E2F77DF006E8441 /* BXPGEntityImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXPGEntityImporter.h; path = Sources/BXPGEntityImporter.h; sourceTree = "<group>"; };
 		5395E7250E2F77DF006E8441 /* BXPGEntityImporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXPGEntityImporter.m; path = Sources/BXPGEntityImporter.m; sourceTree = "<group>"; };
 		539758500E1E86200042120A /* BXDataModelCompiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXDataModelCompiler.h; path = Sources/BXDataModelCompiler.h; sourceTree = "<group>"; };
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				535444090D634A47002A6C47 /* Foundation.framework in Frameworks */,
 				5354440A0D634A47002A6C47 /* libcrypto.dylib in Frameworks */,
-				5354440B0D634A47002A6C47 /* libssl.dylib in Frameworks */,
-				5354440C0D634A47002A6C47 /* Security.framework in Frameworks */,
-				538678D40DE31BA0000C9A78 /* IOKit.framework in Frameworks */,
-				538679880DE31C1D000C9A78 /* libstdc++.6.dylib in Frameworks */,
-				537920580E3F519000423965 /* CoreData.framework in Frameworks */,
-				53D69A880EAE072A00C4C22D /* SystemConfiguration.framework in Frameworks */,
 				535B3E1E1038146500A5FB7E /* libpcre.a in Frameworks */,
 				5314FA1F11CC3B0F000D213B /* libpq.a in Frameworks */,
+				5354440B0D634A47002A6C47 /* libssl.dylib in Frameworks */,
+				538679880DE31C1D000C9A78 /* libstdc++.6.dylib in Frameworks */,
+				539506F211CFAFBA0049F36C /* AppKit.framework in Frameworks */,
+				537920580E3F519000423965 /* CoreData.framework in Frameworks */,
 				53E8522611CE2D7700588B12 /* CoreServices.framework in Frameworks */,
+				535444090D634A47002A6C47 /* Foundation.framework in Frameworks */,
+				538678D40DE31BA0000C9A78 /* IOKit.framework in Frameworks */,
+				5354440C0D634A47002A6C47 /* Security.framework in Frameworks */,
+				53D69A880EAE072A00C4C22D /* SystemConfiguration.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 				53DBE8010B666C3B00C3D20A /* libcrypto.dylib */,
 				53DBE8120B666C7900C3D20A /* libssl.dylib */,
 				538679870DE31C1D000C9A78 /* libstdc++.6.dylib */,
+				5395061611CFAD680049F36C /* AppKit.framework */,
 				D2F7E79907B2D74100F64583 /* CoreData.framework */,
 				53E8522511CE2D7700588B12 /* CoreServices.framework */,
 				0867D69BFE84028FC02AAC07 /* Foundation.framework */,
 			children = (
 				53666CC20E1CD8D20028DBEA /* BXHOM.h */,
 				53666CC30E1CD8D20028DBEA /* BXHOM.m */,
+				53950AC511CFD6840049F36C /* BXValueGetter.h */,
+				53950AC611CFD6840049F36C /* BXValueGetter.mm */,
 				539204D011AEC944000E2BEC /* NSObject+BaseTenAdditions.h */,
 				539204D111AEC944000E2BEC /* NSObject+BaseTenAdditions.m */,
+				53950A0A11CFBDAE0049F36C /* NSValue+BaseTenAdditions.h */,
+				53950A0B11CFBDAE0049F36C /* NSValue+BaseTenAdditions.m */,
+				53950A0611CFBD730049F36C /* NSNumber+BaseTenAdditions.h */,
+				53950A0711CFBD730049F36C /* NSNumber+BaseTenAdditions.mm */,
 				535661CC0F025DD800920008 /* NSURL+BaseTenAdditions.h */,
 				535661CB0F025DD800920008 /* NSURL+BaseTenAdditions.m */,
 				535661CD0F025DD800920008 /* NSArray+BaseTenAdditions.h */,
 				5392053D11AEDB4F000E2BEC /* BXCollectionFunctions.h in Headers */,
 				53F9D04C11B0828900600413 /* PGTSOids.h in Headers */,
 				534F122011CC302E00DC4F62 /* postgresql in Headers */,
+				53950A0811CFBD730049F36C /* NSNumber+BaseTenAdditions.h in Headers */,
+				53950A0C11CFBDAE0049F36C /* NSValue+BaseTenAdditions.h in Headers */,
+				53950AC711CFD6840049F36C /* BXValueGetter.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 				539204DA11AECE07000E2BEC /* BXDictionaryFunctions.m in Sources */,
 				534369C811AFEF8700ADD6C1 /* BXCollectionFunctions.mm in Sources */,
 				53F9D04D11B0828900600413 /* PGTSOids.mm in Sources */,
+				53950A0911CFBD730049F36C /* NSNumber+BaseTenAdditions.mm in Sources */,
+				53950A0D11CFBDAE0049F36C /* NSValue+BaseTenAdditions.m in Sources */,
+				53950AC811CFD6840049F36C /* BXValueGetter.mm in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

File BaseTenAppKit/BaseTenAppKit.xcodeproj/project.pbxproj

 		535444780D634D9C002A6C47 /* BXDatabaseContextAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 53D0D15A0B6F896200D2D101 /* BXDatabaseContextAdditions.m */; };
 		5354447C0D634D9C002A6C47 /* BXPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = 53E9BB090B909EA000DDB9BE /* BXPanel.m */; };
 		5354447D0D634D9C002A6C47 /* BXNetServiceConnector.m in Sources */ = {isa = PBXBuildFile; fileRef = 532D60E00B944D8C0028E90B /* BXNetServiceConnector.m */; };
-		535444800D634D9C002A6C47 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
 		535444820D634D9C002A6C47 /* SecurityInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 531650C30B72040700785454 /* SecurityInterface.framework */; };
 		5355C15311A8744700C5DEAF /* BXAppKitSystemEventNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 5355C15111A8744700C5DEAF /* BXAppKitSystemEventNotifier.h */; };
 		5355C15411A8744700C5DEAF /* BXAppKitSystemEventNotifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 5355C15211A8744700C5DEAF /* BXAppKitSystemEventNotifier.m */; };
+		539505FC11CFAC360049F36C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 539505FB11CFAC360049F36C /* Cocoa.framework */; };
 		53ED303F0E1ACBA80095BE8B /* BaseTen.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5354443E0D634CA4002A6C47 /* BaseTen.framework */; };
 		53F137CD0EB074C400D0F517 /* WaitForNetworkWindow.nib in Resources */ = {isa = PBXBuildFile; fileRef = 53F137CB0EB074C400D0F517 /* WaitForNetworkWindow.nib */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
 		089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
-		1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
 		32DBCF5E0370ADEE00C91783 /* BaseTenAppKit_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BaseTenAppKit_Prefix.pch; path = Sources/BaseTenAppKit_Prefix.pch; sourceTree = "<group>"; };
 		5303D5FF0A39E6CD00917C22 /* BXControllerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXControllerProtocol.h; path = Sources/BXControllerProtocol.h; sourceTree = "<group>"; };
 		531650C30B72040700785454 /* SecurityInterface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SecurityInterface.framework; path = System/Library/Frameworks/SecurityInterface.framework; sourceTree = SDKROOT; };
 		537E484B0A14B7BA00A22080 /* BXSynchronizedArrayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXSynchronizedArrayController.m; path = Sources/BXSynchronizedArrayController.m; sourceTree = "<group>"; };
 		537E48D10A14BFE800A22080 /* BaseTen.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = BaseTen.xcodeproj; path = ../BaseTen.xcodeproj; sourceTree = SOURCE_ROOT; };
 		537E4A6D0A14C82200A22080 /* BaseTenAppKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BaseTenAppKit.h; path = Sources/BaseTenAppKit.h; sourceTree = "<group>"; };
+		539505FB11CFAC360049F36C /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
 		53AE2CB70B1721F2000E6EF1 /* BaseTen.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = BaseTen.icns; path = ../Resources/BaseTen.icns; sourceTree = SOURCE_ROOT; };
 		53D0D1590B6F896200D2D101 /* BXDatabaseContextAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BXDatabaseContextAdditions.h; path = Sources/BXDatabaseContextAdditions.h; sourceTree = "<group>"; };
 		53D0D15A0B6F896200D2D101 /* BXDatabaseContextAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BXDatabaseContextAdditions.m; path = Sources/BXDatabaseContextAdditions.m; sourceTree = "<group>"; };
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				535444800D634D9C002A6C47 /* Cocoa.framework in Frameworks */,
 				535444820D634D9C002A6C47 /* SecurityInterface.framework in Frameworks */,
 				53ED303F0E1ACBA80095BE8B /* BaseTen.framework in Frameworks */,
+				539505FC11CFAC360049F36C /* Cocoa.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 			isa = PBXGroup;
 			children = (
 				537E48D10A14BFE800A22080 /* BaseTen.xcodeproj */,
-				1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */,
+				539505FB11CFAC360049F36C /* Cocoa.framework */,
 				531650C30B72040700785454 /* SecurityInterface.framework */,
 			);
 			name = "External Frameworks and Libraries";

File Sources/BXCollectionFunctions.h

 
 #import <Foundation/Foundation.h>
 #import <BaseTen/BXExport.h>
+#import <BaseTen/BXLogger.h>
+#import <BaseTen/BXValueGetter.h>
 
 
-BX_INTERNAL BOOL FindElement (id collection, id key, void *outValue);
-
+BX_EXPORT NSValue *FindElementValue (id collection, id key);
 
 
 #if defined(__cplusplus)
-namespace BaseTen {
+
+namespace BaseTen {	
+
+	template <typename T>
+	inline BOOL FindElement (id collection, id key, T *outValue)
+	{
+		ExpectR (outValue, NO);
+		
+		BOOL retval = NO;
+		NSValue *value = FindElementValue (collection, key);
+		if (value)
+		{
+			ValueGetter <T> getter;
+			retval = getter (value, outValue);
+		}
+		return retval;
+	}
+
 	
 	template <typename T>
 	inline id ObjectValue (T value)

File Sources/BXCollectionFunctions.mm

 #import "BXLogger.h"
 
 
-BOOL
-FindElement (id collection, id key, void *outValue)
+NSValue *
+FindElementValue (id collection, id key)
 {
-	ExpectR (outValue, NO);
-	ExpectR ([collection respondsToSelector: @selector (objectForKey:)], NO);
-
-	BOOL retval = NO;
-	id value = [collection objectForKey: key];
-	if (value)
+	NSValue *retval = nil;
+	if (collection)
 	{
-		ExpectR ([value isKindOfClass: [NSValue class]], NO);
-		
-		retval = YES;
-		[value getValue: outValue];
+		Expect ([collection respondsToSelector: @selector (objectForKey:)]);
+		retval = [collection objectForKey: key];
+		Expect ([retval isKindOfClass: [NSValue class]]);
 	}
-	
 	return retval;
 }
 

File Sources/BXDatabaseContextDelegateDefaultImplementation.m

 
 #if (TARGET_OS_MAC)
 #import <AppKit/AppKit.h>
+#else
+static id NSApp = nil;
 #endif
-id NSApp WEAK_IMPORT_ATTRIBUTE;
 
 
 

File Sources/BXLogger.h

 	do { if (! (assertion)) { BXLogError (message , ##__VA_ARGS__); BXAssertionDebug (); return; }} while (0)
 #define BXAssertValueReturn(assertion, retval, message, ...) \
 	do { if (! (assertion)) { BXLogError (message , ##__VA_ARGS__); BXAssertionDebug (); return (retval); }} while (0)
+#define BXLogAssertionFailure(message, ...) \
+	do { BXLogError (message , ##__VA_ARGS__); BXAssertionDebug (); } while (0)
 
 #define BXDeprecationLogSpecific(...) \
 	do { BXLogWarning (__VA_ARGS__); BXDeprecationWarning (); } while (0)

File Sources/BXPGModificationHandler.mm

 	}
 	
 	//Send changes.
+	BaseTen::ValueGetter <unichar> getter;
 	for (NSValue *key in [changes keyEnumerator])
     {
+		NSArray* objectIDs = [changes objectForKey: key];
+
 		unichar changeType = '\0';
-		[key getValue: &changeType];		
-		NSArray* objectIDs = [changes objectForKey: key];
+		BOOL status = getter (key, &changeType);
+		ExpectV (status);
 		
 		switch (changeType)
 		{

File Sources/BXValueGetter.h

+//
+// BXValueGetter.h
+// BaseTen
+//
+// Copyright (C) 2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+
+#if defined(__cplusplus)
+#import <Foundation/Foundation.h>
+#import <limits>
+#import <BaseTen/NSValue+BaseTenAdditions.h>
+
+
+namespace BaseTen {
+	
+	class ValueGetterBase {
+		
+		template <typename T>
+		struct NumberType {
+			static CFNumberType const numberType = 0;
+		};
+		
+		template <bool> class Signedness {};
+		template <typename T, bool isIntegral> class Integrality {};
+		template <typename T, bool isSpecialized> class NumericSpecialization {};
+	};
+	
+	
+	
+	template <typename T>
+	class ValueGetter : public ValueGetterBase {
+		
+	public:
+		BOOL operator() (id value, T *outValue);
+	};
+	
+	
+	
+	template <> struct ValueGetterBase::NumberType <char>      { static CFNumberType const numberType = kCFNumberCharType;     };
+	template <> struct ValueGetterBase::NumberType <short>     { static CFNumberType const numberType = kCFNumberShortType;    };
+	template <> struct ValueGetterBase::NumberType <int>       { static CFNumberType const numberType = kCFNumberIntType;      };
+	template <> struct ValueGetterBase::NumberType <long>      { static CFNumberType const numberType = kCFNumberLongType;     };
+	template <> struct ValueGetterBase::NumberType <long long> { static CFNumberType const numberType = kCFNumberLongLongType; };
+	template <> struct ValueGetterBase::NumberType <float>     { static CFNumberType const numberType = kCFNumberFloatType;    };
+	template <> struct ValueGetterBase::NumberType <double>    { static CFNumberType const numberType = kCFNumberDoubleType;   };
+	
+	
+	
+	template <> 
+	class ValueGetterBase::Signedness <true> {
+	public: 
+		typedef intmax_t  integralType;
+	};
+	
+	template <>
+	class ValueGetterBase::Signedness <false> {
+	public:
+		typedef uintmax_t integralType;
+	};
+	
+	
+	
+	template <typename T>
+	class ValueGetterBase::Integrality <T, true> {
+	public:
+		BOOL operator() (id value, T *outValue)
+		{
+			// Support for uintmax_t is missing from NSValue & NSNumber additions.
+			typedef typename Signedness <true>::integralType integralType;
+			//typedef typename Signedness <std::numeric_limits <T>::is_signed>::integralType integralType;
+			
+			BOOL retval = NO;
+			integralType i = 0;
+			
+			if ([value BXGetValue: &i length: sizeof (i) numberType: NumberType <integralType>::numberType encoding: @encode (integralType)])
+			{
+				// Support for uintmax_t is missing from NSValue & NSNumber additions.
+				if ((integralType) std::numeric_limits <T>::min () <= i && (i < 0 || (0 <= i && static_cast <T> (i) <= std::numeric_limits <T>::max ())))
+				//if (std::numeric_limits <T>::min () <= i && i <= std::numeric_limits <T>::max ())
+				{
+					retval = YES;
+					*outValue = i;
+				}
+				else
+				{
+					BXLogAssertionFailure (@"Unable to copy '%@'; value out of bounds.", value);
+				}
+			}
+			else
+			{
+				BXLogAssertionFailure (@"Unable to copy '%@'; type mismatch.", value);
+			}
+			return retval;
+		}
+	};
+	
+	template <typename T>
+	class ValueGetterBase::Integrality <T, false> {
+	public:
+		BOOL operator() (id value, T *outValue)
+		{
+			typedef double fpType;
+			
+			BOOL retval = NO;
+			fpType f = 0.0;
+			
+			if ([value BXGetValue: &f length: sizeof (fpType) numberType: NumberType <fpType>::numberType encoding: @encode (fpType)])
+			{
+				if (abs (f) <= std::numeric_limits <T>::max ())
+				{
+					retval = YES;
+					*outValue = f;
+				}
+				else
+				{
+					BXLogAssertionFailure (@"Unable to copy '%@'; value out of bounds.", value);
+				}
+			}
+			else
+			{
+				BXLogAssertionFailure (@"Unable to copy '%@'; type mismatch.", value);
+			}			
+			return retval;
+		}
+	};
+	
+	
+	
+	template <typename T>
+	class ValueGetterBase::NumericSpecialization <T, true> {
+	public:
+		BOOL operator() (id value, T *outValue)
+		{
+			Integrality <T, std::numeric_limits <T>::is_integer> integrality;
+			return integrality (value, outValue);
+		}
+	};
+	
+	template <typename T>
+	class ValueGetterBase::NumericSpecialization <T, false> {
+	public:
+		BOOL operator() (id value, T *outValue)
+		{
+			BXLogAssertionFailure (@"Unable to copy '%@'; type information unavailable.", value);
+			return NO;
+		}
+	};	
+	
+	
+	
+	template <typename T>
+	BOOL ValueGetter <T>::operator() (id value, T *outValue)
+	{
+		// If the value can be fetched to the given buffer, return immediately.
+		// Otherwise, get the type of T and try to make a larger buffer that is compatible with the type.
+		
+		BOOL retval = NO;
+		if ([value BXGetValue: outValue length: sizeof (T) numberType: NumberType <T>::numberType encoding: @encode (T)])
+			retval = YES;
+		else
+		{
+			NumericSpecialization <T, std::numeric_limits <T>::is_specialized> spec;
+			retval = spec (value, outValue);
+		}
+		return retval;
+	}	
+}
+#endif

File Sources/BXValueGetter.mm

+//
+// BXValueGetter.mm
+// BaseTen
+//
+// Copyright (C) 2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+
+#import "BXValueGetter.h"

File Sources/NSNumber+BaseTenAdditions.h

+//
+// NSNumber+BaseTenAdditions.h
+// BaseTen
+//
+// Copyright (C) 2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface NSNumber (BaseTenAdditions)
+@end

File Sources/NSNumber+BaseTenAdditions.mm

+//
+// NSNumber+BaseTenAdditions.mm
+// BaseTen
+//
+// Copyright (C) 2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import "NSNumber+BaseTenAdditions.h"
+#import "NSValue+BaseTenAdditions.h"
+
+
+@implementation NSNumber (BaseTenAdditions)
+- (size_t) BXValueSize
+{
+	return CFNumberGetByteSize ((CFNumberRef) self);
+}
+
+
+- (BOOL) BXGetValue: (void *) buffer 
+			 length: (size_t) bufferLength
+		 numberType: (CFNumberType) expectedNumberType 
+		   encoding: (const char *) expectedEncoding
+{
+	BOOL retval = NO;
+	
+	if (expectedNumberType)
+		retval = CFNumberGetValue ((CFNumberRef) self, expectedNumberType, buffer);
+	else
+		retval = [super BXGetValue: buffer length: bufferLength numberType: expectedNumberType encoding: expectedEncoding];
+	
+	return retval;
+}
+@end

File Sources/NSValue+BaseTenAdditions.h

+//
+// NSValue+BaseTenAdditions.h
+// BaseTen
+//
+// Copyright (C) 2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface NSValue (BaseTenAdditions)
+- (size_t) BXValueSize;
+- (BOOL) BXGetValue: (void *) buffer 
+			 length: (size_t) bufferLength
+		 numberType: (CFNumberType) expectedNumberType 
+		   encoding: (const char *) expectedEncoding;
+@end

File Sources/NSValue+BaseTenAdditions.m

+//
+// NSValue+BaseTenAdditions.m
+// BaseTen
+//
+// Copyright (C) 2010 Marko Karppinen & Co. LLC.
+//
+// Before using this software, please review the available licensing options
+// by visiting http://www.karppinen.fi/baseten/licensing/ or by contacting
+// us at sales@karppinen.fi. Without an additional license, this software
+// may be distributed only in compliance with the GNU General Public License.
+//
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License, version 2.0,
+// as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+// $Id$
+//
+
+#import "NSValue+BaseTenAdditions.h"
+#import "BXLogger.h"
+
+
+static size_t
+ValueSize (NSValue *value)
+{
+	size_t retval = SIZE_T_MAX;
+	char const * const encoding = [value objCType];
+	ExpectR (encoding, retval);
+	
+	switch (encoding [0])
+	{
+		case 'c':
+			retval = sizeof (signed char);
+			break;
+			
+		case 'i':
+			retval = sizeof (signed int);
+			break;
+			
+		case 's':
+			retval = sizeof (signed short);
+			break;
+			
+		case 'l':
+			retval = sizeof (signed long);
+			break;
+			
+		case 'q':
+			retval = sizeof (signed long long);
+			break;
+			
+		case 'C':
+			retval = sizeof (unsigned char);
+			break;
+			
+		case 'I':
+			retval = sizeof (unsigned int);
+			break;
+			
+		case 'S':
+			retval = sizeof (unsigned short);
+			break;
+			
+		case 'L':
+			retval = sizeof (unsigned long);
+			break;
+			
+		case 'Q':
+			retval = sizeof (unsigned long long);
+			break;
+			
+		case 'f':
+			retval = sizeof (float);
+			break;
+			
+		case 'd':
+			retval = sizeof (double);
+			break;
+			
+		case 'B':
+			retval = sizeof (_Bool);
+			break;
+			
+		case '*':
+			retval = sizeof (char *);
+			break;
+			
+		case '@':
+			retval = sizeof (id);
+			break;
+			
+		case '#':
+			retval = sizeof (Class);
+			break;
+			
+		case ':':
+			retval = sizeof (SEL);
+			break;
+			
+		case '^':
+			retval = sizeof (void *);
+			break;
+			
+		default:
+			BXLogError (@"Unable to calculate size for type encoding '%s'.", encoding);
+			break;
+	}
+	
+	return retval;
+}
+
+
+
+@implementation NSValue (BaseTenAdditions)
+- (size_t) BXValueSize
+{
+	return ValueSize (self);
+}
+
+
+- (BOOL) BXGetValue: (void *) buffer 
+			 length: (size_t) bufferLength
+		 numberType: (CFNumberType) expectedNumberType 
+		   encoding: (const char *) expectedEncoding
+{
+	BOOL retval = NO;
+	if (0 == strcmp (expectedEncoding, [self objCType]))
+	{
+		retval = YES;
+		[self getValue: &buffer];
+	}
+	return retval;
+}
+@end

File Sources/PGTSFoundationObjects.m

 
 
 #import <BaseTen/postgresql/libpq-fe.h>
+#import <limits.h>
 #import "PGTSFoundationObjects.h"
 #import "PGTSConnection.h"
 #import "PGTSConnectionPrivate.h"
 	return [self description];
 }
 
-+ (id) copyForPGTSResultSet: (PGTSResultSet *) set withCharacters: (char const *) value type: (PGTSTypeDescription *) typeInfo
++ (id) copyForPGTSResultSet: (PGTSResultSet *) set withCharacters: (char const * const) value type: (PGTSTypeDescription *) typeInfo
 {
-    return [[NSNumber alloc] initWithLongLong: strtoll (value, NULL, 10)];
+	id retval = nil;
+	if (value)
+	{
+		long long l = strtoll (value, NULL, 10);
+		if (SHRT_MIN <= l && l <= SHRT_MAX)
+			retval = [[NSNumber alloc] initWithShort: l];
+		else if (INT_MIN <= l && l <= INT_MAX)
+			retval = [[NSNumber alloc] initWithInt: l];
+		else if (LONG_MIN <= l && l <= LONG_MAX)
+			retval = [[NSNumber alloc] initWithLong: l];
+		else if (LLONG_MIN <= l && l <= LLONG_MAX)
+			retval = [[NSNumber alloc] initWithLongLong: l];
+		else
+			BXLogError (@"Unable to create NSNumber representation for '%s'.", value);
+	}
+    return retval;
 }
 
 - (id) PGTSExpressionOfType: (NSAttributeType) attrType connection: (PGTSConnection *) connection

File Sources/PGTSOids.mm

 
 #import "PGTSOids.h"
 #import "BXCollectionFunctions.h"
+#import "BXLogger.h"
 
 
 /**
 - (Oid) PGTSOidValue
 {
 	Oid retval = InvalidOid;
-	[self getValue: &retval];
+	BaseTen::ValueGetter <Oid> getter;
+	BOOL status = getter (self, &retval);
+	
+	ExpectR (status, InvalidOid);
 	return retval;
 }
 @end

File Sources/PGTSResultSet.mm

 	int columnIndex = 0;
 	if (! FindElement (mFieldIndexesByName, aName, &columnIndex))
 	{
+		NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
+								  aName, kPGTSFieldnameKey,
+								  self,  kPGTSResultSetKey,
+								  nil];
 		@throw [NSException exceptionWithName: kPGTSFieldNotFoundException reason: nil 
-									 userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
-												aName, kPGTSFieldnameKey,
-												self,  kPGTSResultSetKey,
-												nil]];
+									 userInfo: userInfo];
 	}
 	retval = [self valueForFieldAtIndex: columnIndex row: rowIndex];
     return retval;