Initial Cocoa (Objective-C) API.
authorJens Alfke <jens@mooseyard.com>
Thu Sep 24 21:47:06 2009 -0700 (2009-09-24)
changeset 6f2cd752db494
parent 5 4c10b7956435
child 7 2e44bc2caefe
Initial Cocoa (Objective-C) API.
Ottoman.xcodeproj/project.pbxproj
bindings/Cocoa/MYOttoman.h
bindings/Cocoa/MYOttoman.mm
bindings/Cocoa/MYOttoman_internal.h
bindings/Cocoa/MYOttoman_test.m
bindings/Cocoa/MYVersionDictionary.h
bindings/Cocoa/MYVersionDictionary.mm
     1.1 --- a/Ottoman.xcodeproj/project.pbxproj	Thu Sep 24 21:46:17 2009 -0700
     1.2 +++ b/Ottoman.xcodeproj/project.pbxproj	Thu Sep 24 21:47:06 2009 -0700
     1.3 @@ -8,6 +8,11 @@
     1.4  
     1.5  /* Begin PBXBuildFile section */
     1.6  		27156CAA104C9C44009EBD39 /* gtest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27156CA9104C9C44009EBD39 /* gtest.framework */; };
     1.7 +		2754DD87106BCBCF00365FAA /* MYOttoman_test.m in Sources */ = {isa = PBXBuildFile; fileRef = 2754DD86106BCBCF00365FAA /* MYOttoman_test.m */; };
     1.8 +		2754DDC5106BD20A00365FAA /* Test.m in Sources */ = {isa = PBXBuildFile; fileRef = 2754DDC4106BD20A00365FAA /* Test.m */; };
     1.9 +		2754DDEE106BD3BD00365FAA /* Logging.m in Sources */ = {isa = PBXBuildFile; fileRef = 2754DDED106BD3BD00365FAA /* Logging.m */; };
    1.10 +		2754DDF3106BD3D300365FAA /* ExceptionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 2754DDF2106BD3D300365FAA /* ExceptionUtils.m */; };
    1.11 +		2754DE2D106BD65600365FAA /* CollectionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 2754DE2C106BD65600365FAA /* CollectionUtils.m */; };
    1.12  		27603901105AC81200D931A7 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27603900105AC81200D931A7 /* CoreFoundation.framework */; };
    1.13  		276E5BCD1066D13D008A2171 /* Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 276E5BC41066D13D008A2171 /* Base.cpp */; };
    1.14  		276E5BCE1066D13D008A2171 /* Chunk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 276E5BC51066D13D008A2171 /* Chunk.cpp */; };
    1.15 @@ -41,8 +46,21 @@
    1.16  		276E5CC4106731C7008A2171 /* File.h in Headers */ = {isa = PBXBuildFile; fileRef = 276E5BBD1066D135008A2171 /* File.h */; };
    1.17  		276E5CC5106731C8008A2171 /* Ottoman.h in Headers */ = {isa = PBXBuildFile; fileRef = 276E5BC11066D135008A2171 /* Ottoman.h */; };
    1.18  		276E5CC6106731C8008A2171 /* VersionDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 276E5BC21066D135008A2171 /* VersionDictionary.h */; };
    1.19 +		276E5D141067D2AD008A2171 /* MYOttoman.mm in Sources */ = {isa = PBXBuildFile; fileRef = 276E5D0A1067D24A008A2171 /* MYOttoman.mm */; };
    1.20 +		276E5D151067D2B2008A2171 /* libOttoman.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 276E5CAE1067315D008A2171 /* libOttoman.a */; };
    1.21 +		276E5D2E1067F86E008A2171 /* MYVersionDictionary.mm in Sources */ = {isa = PBXBuildFile; fileRef = 276E5D2D1067F86E008A2171 /* MYVersionDictionary.mm */; };
    1.22  /* End PBXBuildFile section */
    1.23  
    1.24 +/* Begin PBXContainerItemProxy section */
    1.25 +		276E5D7810692FA7008A2171 /* PBXContainerItemProxy */ = {
    1.26 +			isa = PBXContainerItemProxy;
    1.27 +			containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
    1.28 +			proxyType = 1;
    1.29 +			remoteGlobalIDString = 276E5CAD1067315D008A2171;
    1.30 +			remoteInfo = "Static Library";
    1.31 +		};
    1.32 +/* End PBXContainerItemProxy section */
    1.33 +
    1.34  /* Begin PBXCopyFilesBuildPhase section */
    1.35  		8DD76F690486A84900D96B5E /* CopyFiles */ = {
    1.36  			isa = PBXCopyFilesBuildPhase;
    1.37 @@ -57,6 +75,15 @@
    1.38  
    1.39  /* Begin PBXFileReference section */
    1.40  		27156CA9104C9C44009EBD39 /* gtest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = gtest.framework; path = /Library/Frameworks/gtest.framework; sourceTree = "<absolute>"; };
    1.41 +		2754DD86106BCBCF00365FAA /* MYOttoman_test.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MYOttoman_test.m; sourceTree = "<group>"; };
    1.42 +		2754DDC3106BD20A00365FAA /* Test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Test.h; sourceTree = "<group>"; };
    1.43 +		2754DDC4106BD20A00365FAA /* Test.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Test.m; sourceTree = "<group>"; };
    1.44 +		2754DDEC106BD3BD00365FAA /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Logging.h; sourceTree = "<group>"; };
    1.45 +		2754DDED106BD3BD00365FAA /* Logging.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Logging.m; sourceTree = "<group>"; };
    1.46 +		2754DDF1106BD3D300365FAA /* ExceptionUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionUtils.h; sourceTree = "<group>"; };
    1.47 +		2754DDF2106BD3D300365FAA /* ExceptionUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExceptionUtils.m; sourceTree = "<group>"; };
    1.48 +		2754DE2B106BD65600365FAA /* CollectionUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionUtils.h; sourceTree = "<group>"; };
    1.49 +		2754DE2C106BD65600365FAA /* CollectionUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CollectionUtils.m; sourceTree = "<group>"; };
    1.50  		27603900105AC81200D931A7 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
    1.51  		276E5BBA1066D135008A2171 /* Base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Base.h; sourceTree = "<group>"; };
    1.52  		276E5BBB1066D135008A2171 /* Chunk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Chunk.h; sourceTree = "<group>"; };
    1.53 @@ -83,6 +110,12 @@
    1.54  		276E5BDB1066D142008A2171 /* TestUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestUtils.h; sourceTree = "<group>"; };
    1.55  		276E5BDC1066D142008A2171 /* VersionDictionary_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VersionDictionary_test.cpp; sourceTree = "<group>"; };
    1.56  		276E5CAE1067315D008A2171 /* libOttoman.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libOttoman.a; sourceTree = BUILT_PRODUCTS_DIR; };
    1.57 +		276E5D091067D24A008A2171 /* MYOttoman.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYOttoman.h; sourceTree = "<group>"; };
    1.58 +		276E5D0A1067D24A008A2171 /* MYOttoman.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MYOttoman.mm; sourceTree = "<group>"; };
    1.59 +		276E5D101067D27E008A2171 /* OttomanCocoa */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = OttomanCocoa; sourceTree = BUILT_PRODUCTS_DIR; };
    1.60 +		276E5D2C1067F86E008A2171 /* MYVersionDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYVersionDictionary.h; sourceTree = "<group>"; };
    1.61 +		276E5D2D1067F86E008A2171 /* MYVersionDictionary.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MYVersionDictionary.mm; sourceTree = "<group>"; };
    1.62 +		276E5D451069246E008A2171 /* MYOttoman_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MYOttoman_internal.h; sourceTree = "<group>"; };
    1.63  		8DD76F6C0486A84900D96B5E /* OttomanTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = OttomanTest; sourceTree = BUILT_PRODUCTS_DIR; };
    1.64  /* End PBXFileReference section */
    1.65  
    1.66 @@ -94,6 +127,14 @@
    1.67  			);
    1.68  			runOnlyForDeploymentPostprocessing = 0;
    1.69  		};
    1.70 +		276E5D0E1067D27E008A2171 /* Frameworks */ = {
    1.71 +			isa = PBXFrameworksBuildPhase;
    1.72 +			buildActionMask = 2147483647;
    1.73 +			files = (
    1.74 +				276E5D151067D2B2008A2171 /* libOttoman.a in Frameworks */,
    1.75 +			);
    1.76 +			runOnlyForDeploymentPostprocessing = 0;
    1.77 +		};
    1.78  		8DD76F660486A84900D96B5E /* Frameworks */ = {
    1.79  			isa = PBXFrameworksBuildPhase;
    1.80  			buildActionMask = 2147483647;
    1.81 @@ -109,6 +150,7 @@
    1.82  		08FB7794FE84155DC02AAC07 /* BPlusTree */ = {
    1.83  			isa = PBXGroup;
    1.84  			children = (
    1.85 +				276E5D081067D20B008A2171 /* Cocoa */,
    1.86  				276E5BB91066D135008A2171 /* include */,
    1.87  				276E5BC31066D13D008A2171 /* src */,
    1.88  				276E5BD61066D142008A2171 /* test */,
    1.89 @@ -124,10 +166,27 @@
    1.90  			children = (
    1.91  				8DD76F6C0486A84900D96B5E /* OttomanTest */,
    1.92  				276E5CAE1067315D008A2171 /* libOttoman.a */,
    1.93 +				276E5D101067D27E008A2171 /* OttomanCocoa */,
    1.94  			);
    1.95  			name = Products;
    1.96  			sourceTree = "<group>";
    1.97  		};
    1.98 +		2754DDEB106BD38600365FAA /* MYUtilities */ = {
    1.99 +			isa = PBXGroup;
   1.100 +			children = (
   1.101 +				2754DE2B106BD65600365FAA /* CollectionUtils.h */,
   1.102 +				2754DE2C106BD65600365FAA /* CollectionUtils.m */,
   1.103 +				2754DDF1106BD3D300365FAA /* ExceptionUtils.h */,
   1.104 +				2754DDF2106BD3D300365FAA /* ExceptionUtils.m */,
   1.105 +				2754DDEC106BD3BD00365FAA /* Logging.h */,
   1.106 +				2754DDED106BD3BD00365FAA /* Logging.m */,
   1.107 +				2754DDC3106BD20A00365FAA /* Test.h */,
   1.108 +				2754DDC4106BD20A00365FAA /* Test.m */,
   1.109 +			);
   1.110 +			name = MYUtilities;
   1.111 +			path = /Volumes/snoog/Code/MYUtilities;
   1.112 +			sourceTree = "<absolute>";
   1.113 +		};
   1.114  		276E5BB91066D135008A2171 /* include */ = {
   1.115  			isa = PBXGroup;
   1.116  			children = (
   1.117 @@ -173,6 +232,21 @@
   1.118  			path = test;
   1.119  			sourceTree = "<group>";
   1.120  		};
   1.121 +		276E5D081067D20B008A2171 /* Cocoa */ = {
   1.122 +			isa = PBXGroup;
   1.123 +			children = (
   1.124 +				276E5D091067D24A008A2171 /* MYOttoman.h */,
   1.125 +				276E5D0A1067D24A008A2171 /* MYOttoman.mm */,
   1.126 +				276E5D2C1067F86E008A2171 /* MYVersionDictionary.h */,
   1.127 +				276E5D2D1067F86E008A2171 /* MYVersionDictionary.mm */,
   1.128 +				276E5D451069246E008A2171 /* MYOttoman_internal.h */,
   1.129 +				2754DD86106BCBCF00365FAA /* MYOttoman_test.m */,
   1.130 +				2754DDEB106BD38600365FAA /* MYUtilities */,
   1.131 +			);
   1.132 +			name = Cocoa;
   1.133 +			path = bindings/Cocoa;
   1.134 +			sourceTree = "<group>";
   1.135 +		};
   1.136  /* End PBXGroup section */
   1.137  
   1.138  /* Begin PBXHeadersBuildPhase section */
   1.139 @@ -212,6 +286,23 @@
   1.140  			productReference = 276E5CAE1067315D008A2171 /* libOttoman.a */;
   1.141  			productType = "com.apple.product-type.library.static";
   1.142  		};
   1.143 +		276E5D0F1067D27E008A2171 /* Cocoa */ = {
   1.144 +			isa = PBXNativeTarget;
   1.145 +			buildConfigurationList = 276E5D161067D2D1008A2171 /* Build configuration list for PBXNativeTarget "Cocoa" */;
   1.146 +			buildPhases = (
   1.147 +				276E5D0D1067D27E008A2171 /* Sources */,
   1.148 +				276E5D0E1067D27E008A2171 /* Frameworks */,
   1.149 +			);
   1.150 +			buildRules = (
   1.151 +			);
   1.152 +			dependencies = (
   1.153 +				276E5D7910692FA7008A2171 /* PBXTargetDependency */,
   1.154 +			);
   1.155 +			name = Cocoa;
   1.156 +			productName = Cocoa;
   1.157 +			productReference = 276E5D101067D27E008A2171 /* OttomanCocoa */;
   1.158 +			productType = "com.apple.product-type.tool";
   1.159 +		};
   1.160  		8DD76F620486A84900D96B5E /* OttomanTest */ = {
   1.161  			isa = PBXNativeTarget;
   1.162  			buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "OttomanTest" */;
   1.163 @@ -244,6 +335,7 @@
   1.164  			targets = (
   1.165  				8DD76F620486A84900D96B5E /* OttomanTest */,
   1.166  				276E5CAD1067315D008A2171 /* Static Library */,
   1.167 +				276E5D0F1067D27E008A2171 /* Cocoa */,
   1.168  			);
   1.169  		};
   1.170  /* End PBXProject section */
   1.171 @@ -265,6 +357,20 @@
   1.172  			);
   1.173  			runOnlyForDeploymentPostprocessing = 0;
   1.174  		};
   1.175 +		276E5D0D1067D27E008A2171 /* Sources */ = {
   1.176 +			isa = PBXSourcesBuildPhase;
   1.177 +			buildActionMask = 2147483647;
   1.178 +			files = (
   1.179 +				276E5D141067D2AD008A2171 /* MYOttoman.mm in Sources */,
   1.180 +				276E5D2E1067F86E008A2171 /* MYVersionDictionary.mm in Sources */,
   1.181 +				2754DD87106BCBCF00365FAA /* MYOttoman_test.m in Sources */,
   1.182 +				2754DDC5106BD20A00365FAA /* Test.m in Sources */,
   1.183 +				2754DDEE106BD3BD00365FAA /* Logging.m in Sources */,
   1.184 +				2754DDF3106BD3D300365FAA /* ExceptionUtils.m in Sources */,
   1.185 +				2754DE2D106BD65600365FAA /* CollectionUtils.m in Sources */,
   1.186 +			);
   1.187 +			runOnlyForDeploymentPostprocessing = 0;
   1.188 +		};
   1.189  		8DD76F640486A84900D96B5E /* Sources */ = {
   1.190  			isa = PBXSourcesBuildPhase;
   1.191  			buildActionMask = 2147483647;
   1.192 @@ -288,6 +394,14 @@
   1.193  		};
   1.194  /* End PBXSourcesBuildPhase section */
   1.195  
   1.196 +/* Begin PBXTargetDependency section */
   1.197 +		276E5D7910692FA7008A2171 /* PBXTargetDependency */ = {
   1.198 +			isa = PBXTargetDependency;
   1.199 +			target = 276E5CAD1067315D008A2171 /* Static Library */;
   1.200 +			targetProxy = 276E5D7810692FA7008A2171 /* PBXContainerItemProxy */;
   1.201 +		};
   1.202 +/* End PBXTargetDependency section */
   1.203 +
   1.204  /* Begin XCBuildConfiguration section */
   1.205  		1DEB923208733DC60010E9CD /* Debug */ = {
   1.206  			isa = XCBuildConfiguration;
   1.207 @@ -320,6 +434,7 @@
   1.208  			buildSettings = {
   1.209  				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
   1.210  				GCC_C_LANGUAGE_STANDARD = c99;
   1.211 +				GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
   1.212  				GCC_OPTIMIZATION_LEVEL = 0;
   1.213  				GCC_PRECOMPILE_PREFIX_HEADER = YES;
   1.214  				GCC_PREPROCESSOR_DEFINITIONS = "";
   1.215 @@ -345,6 +460,7 @@
   1.216  				GCC_C_LANGUAGE_STANDARD = c99;
   1.217  				GCC_DYNAMIC_NO_PIC = YES;
   1.218  				GCC_ENABLE_CPP_RTTI = NO;
   1.219 +				GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
   1.220  				GCC_PRECOMPILE_PREFIX_HEADER = YES;
   1.221  				GCC_PREPROCESSOR_DEFINITIONS = NDEBUG;
   1.222  				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
   1.223 @@ -380,12 +496,43 @@
   1.224  			buildSettings = {
   1.225  				COPY_PHASE_STRIP = YES;
   1.226  				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
   1.227 -				GENERATE_MASTER_OBJECT_FILE = YES;
   1.228  				INSTALL_PATH = /usr/local/lib;
   1.229  				PRODUCT_NAME = Ottoman;
   1.230  			};
   1.231  			name = Release;
   1.232  		};
   1.233 +		276E5D121067D27F008A2171 /* Debug */ = {
   1.234 +			isa = XCBuildConfiguration;
   1.235 +			buildSettings = {
   1.236 +				COPY_PHASE_STRIP = NO;
   1.237 +				GCC_PRECOMPILE_PREFIX_HEADER = NO;
   1.238 +				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Foundation.framework/Headers/Foundation.h";
   1.239 +				GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
   1.240 +				INSTALL_PATH = /usr/local/bin;
   1.241 +				OTHER_LDFLAGS = (
   1.242 +					"-framework",
   1.243 +					Foundation,
   1.244 +				);
   1.245 +				PRODUCT_NAME = OttomanCocoa;
   1.246 +			};
   1.247 +			name = Debug;
   1.248 +		};
   1.249 +		276E5D131067D27F008A2171 /* Release */ = {
   1.250 +			isa = XCBuildConfiguration;
   1.251 +			buildSettings = {
   1.252 +				COPY_PHASE_STRIP = YES;
   1.253 +				GCC_PRECOMPILE_PREFIX_HEADER = NO;
   1.254 +				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Foundation.framework/Headers/Foundation.h";
   1.255 +				GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
   1.256 +				INSTALL_PATH = /usr/local/bin;
   1.257 +				OTHER_LDFLAGS = (
   1.258 +					"-framework",
   1.259 +					Foundation,
   1.260 +				);
   1.261 +				PRODUCT_NAME = OttomanCocoa;
   1.262 +			};
   1.263 +			name = Release;
   1.264 +		};
   1.265  /* End XCBuildConfiguration section */
   1.266  
   1.267  /* Begin XCConfigurationList section */
   1.268 @@ -416,6 +563,15 @@
   1.269  			defaultConfigurationIsVisible = 0;
   1.270  			defaultConfigurationName = Release;
   1.271  		};
   1.272 +		276E5D161067D2D1008A2171 /* Build configuration list for PBXNativeTarget "Cocoa" */ = {
   1.273 +			isa = XCConfigurationList;
   1.274 +			buildConfigurations = (
   1.275 +				276E5D121067D27F008A2171 /* Debug */,
   1.276 +				276E5D131067D27F008A2171 /* Release */,
   1.277 +			);
   1.278 +			defaultConfigurationIsVisible = 0;
   1.279 +			defaultConfigurationName = Release;
   1.280 +		};
   1.281  /* End XCConfigurationList section */
   1.282  	};
   1.283  	rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/bindings/Cocoa/MYOttoman.h	Thu Sep 24 21:47:06 2009 -0700
     2.3 @@ -0,0 +1,81 @@
     2.4 +//
     2.5 +//  MYOttoman.h
     2.6 +//  Ottoman
     2.7 +//
     2.8 +//  Created by Jens Alfke on 9/21/09.
     2.9 +//  Copyright 2009 Jens Alfke. All rights reserved.
    2.10 +//
    2.11 +
    2.12 +#import <Foundation/Foundation.h>
    2.13 +
    2.14 +@class MYVersionDictionary, MYCurrentVersionDictionary;
    2.15 +
    2.16 +
    2.17 +/** A version-controlled persistent dictionary. 
    2.18 +    Each version is stored as a MYVersionDictionary, 
    2.19 +    unsaved changes as an MYCurrentVersionDictionary. */
    2.20 +@interface MYOttoman : NSObject 
    2.21 +{
    2.22 +    void *_ottoman;
    2.23 +    MYVersionDictionary *_lastVersion;
    2.24 +    MYCurrentVersionDictionary *_currentVersion;
    2.25 +}
    2.26 +
    2.27 +/** Creates an "untitled" Ottoman with no file and no lastVersion.
    2.28 +    After adding values to the currentVersion, use saveAs to save it. */
    2.29 +- (id) init;
    2.30 +
    2.31 +/** Opens an existing Ottoman file. */
    2.32 +- (id) initWithURL: (NSURL*)fileURL writeable: (BOOL)writeable error: (NSError**)outError;
    2.33 +
    2.34 +/** Closes an Ottoman. */
    2.35 +- (void) close;
    2.36 +
    2.37 +/** The current file, or nil if the receiver is still in the "untitled" state. */
    2.38 +@property (readonly) NSURL *URL;
    2.39 +
    2.40 +/** The latest saved version of the dictionary. 
    2.41 +    Earlier versions can be accessed through its previousVersion property.
    2.42 +    This will be nil if the receiver is still in the "untitled" state. */
    2.43 +@property (readonly) MYVersionDictionary* lastVersion;
    2.44 +
    2.45 +/** A mutable overlay representing the current state of the dictionary.
    2.46 +    Changes are made in memory until -save is called.
    2.47 +    This will be nil if the receiver was opened read-only (writeable=NO). */
    2.48 +@property (readonly) MYCurrentVersionDictionary* currentVersion;
    2.49 +
    2.50 +/** Has the on-disk file been updated with newer revisions than what I know about? */
    2.51 +@property (readonly) BOOL needsSync;
    2.52 +
    2.53 +/** Reads any newer versions from disk.
    2.54 +    Returns YES if new versions were read, NO if there were none or on error.
    2.55 +    Afterwards, -lastVersion will return the latest version in the file. 
    2.56 +    (The old lastVersion dictionary is still around, so you can save a pointer to it 
    2.57 +    before the call and use it later to see what changed.)
    2.58 +    Changes made to the -currentVersion dictionary are not lost, but are now relative
    2.59 +    to the new lastVersion. You may want to scan them and resolve conflicts. */
    2.60 +- (BOOL) sync: (NSError**)outError;
    2.61 +
    2.62 +/** Saves the current version to the file, by appending.
    2.63 +    Returns NO if there is a version conflict; in that case you need to call -sync,
    2.64 +    possibly resolve conflicts, and then call -save again. */
    2.65 +- (BOOL) save: (NSError**)outError;
    2.66 +
    2.67 +/** Saves the current version to the file, by writing to a new temporary file and
    2.68 +    then atomically replacing the original. 
    2.69 +    Older versions, and older copies of the data, are not preserved, so this
    2.70 +    will typically shrink the file quite a bit.
    2.71 +    Returns NO if there is a version conflict. */
    2.72 +- (BOOL) saveAndCompact: (NSError**)outError;
    2.73 +
    2.74 +/** Saves the current version to a new file, leaving the new file open, 
    2.75 +    so subsequent saves will be written to it. */
    2.76 +- (BOOL) saveAs: (NSURL*)newFileURL
    2.77 +         overwriteAllowed: (BOOL)overwriteAllowed
    2.78 +         error: (NSError**)outError;
    2.79 +
    2.80 +/** Scans the file for damage. Returns YES if the file is OK, NO if problems are found.
    2.81 +    If the 'repair' flag is set, will truncate the file to the last valid version. */
    2.82 +- (BOOL) scavengeAndRepair: (BOOL)repair error: (NSError**)outError;
    2.83 +
    2.84 +@end
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/bindings/Cocoa/MYOttoman.mm	Thu Sep 24 21:47:06 2009 -0700
     3.3 @@ -0,0 +1,205 @@
     3.4 +//
     3.5 +//  MYOttoman.mm
     3.6 +//  Ottoman
     3.7 +//
     3.8 +//  Created by Jens Alfke on 9/21/09.
     3.9 +//  Copyright 2009 Jens Alfke. All rights reserved.
    3.10 +//
    3.11 +
    3.12 +#import "MYOttoman.h"
    3.13 +#import "MYOttoman_internal.h"
    3.14 +extern "C" {
    3.15 +#import "Test.h"
    3.16 +}
    3.17 +
    3.18 +#include "Ottoman.h"
    3.19 +#include "VersionDictionary.h"
    3.20 +#include "File.h"
    3.21 +
    3.22 +
    3.23 +@interface MYOttoman ()
    3.24 +- (void) _versionsChanged;
    3.25 +@end
    3.26 +
    3.27 +
    3.28 +namespace Mooseyard {
    3.29 +
    3.30 +    class ObjCOwnedOttoman :public Ottoman {
    3.31 +    public:
    3.32 +        ObjCOwnedOttoman (MYOttoman *owner)
    3.33 +        :_owner(owner)
    3.34 +        { }
    3.35 +        
    3.36 +        ObjCOwnedOttoman (MYOttoman *owner, NSURL *fileURL, bool writeable)
    3.37 +        :Ottoman(fileURL.path.fileSystemRepresentation, writeable),
    3.38 +        _owner(owner)
    3.39 +        { }
    3.40 +        
    3.41 +    protected:
    3.42 +        virtual void versionsChanged() {
    3.43 +            [_owner _versionsChanged];
    3.44 +        }
    3.45 +    private:
    3.46 +        MYOttoman *_owner;
    3.47 +    };
    3.48 +    
    3.49 +}
    3.50 +
    3.51 +
    3.52 +using namespace Mooseyard;
    3.53 +
    3.54 +
    3.55 +static BOOL ErrorToNSError (const File::Error &x, NSError **outError) {
    3.56 +    if (outError) {
    3.57 +        *outError = [NSError errorWithDomain: NSPOSIXErrorDomain
    3.58 +                                        code: x.code
    3.59 +                                    userInfo: nil];
    3.60 +    }
    3.61 +    return NO;
    3.62 +}
    3.63 +
    3.64 +
    3.65 +@interface MYOttoman ()
    3.66 +@property (readonly) Ottoman* ottoman;
    3.67 +@end
    3.68 +
    3.69 +
    3.70 +@implementation MYOttoman
    3.71 +
    3.72 +
    3.73 +- (id) init {
    3.74 +    return [self initWithURL: nil writeable: YES error: nil];
    3.75 +}
    3.76 +
    3.77 +- (id) initWithURL: (NSURL*)fileURL
    3.78 +         writeable: (BOOL)writeable
    3.79 +             error: (NSError**)outError
    3.80 +{
    3.81 +    self = [super init];
    3.82 +    if (self) {
    3.83 +        try {
    3.84 +            if (fileURL) {
    3.85 +                NSAssert([fileURL isFileURL], @"MYOttoman only supports file: URLs");
    3.86 +                _ottoman = new ObjCOwnedOttoman(self, fileURL, writeable);
    3.87 +            } else {
    3.88 +                _ottoman = new ObjCOwnedOttoman(self);
    3.89 +            }
    3.90 +        } catch (const File::Error &x) {
    3.91 +            ErrorToNSError(x,outError);
    3.92 +            [self release];
    3.93 +            return nil;
    3.94 +        }
    3.95 +        
    3.96 +        if (writeable)
    3.97 +            _currentVersion = [[MYCurrentVersionDictionary alloc]
    3.98 +                                        _initWithOverlayDictionary: self.ottoman->currentVersion()];
    3.99 +    }
   3.100 +    return self;
   3.101 +}
   3.102 +
   3.103 +- (void) dealloc
   3.104 +{
   3.105 +    [_lastVersion release];
   3.106 +    [_currentVersion release];
   3.107 +    delete (Ottoman*)_ottoman;
   3.108 +    [super dealloc];
   3.109 +}
   3.110 +
   3.111 +- (void) finalize {
   3.112 +    delete (Ottoman*)_ottoman;
   3.113 +    [super finalize];
   3.114 +}
   3.115 +
   3.116 +- (void) close {
   3.117 +    delete (Ottoman*)_ottoman;
   3.118 +    _ottoman = nil;
   3.119 +}
   3.120 +
   3.121 +
   3.122 +- (Ottoman*) ottoman {
   3.123 +    Assert(_ottoman, @"MYOttoman has already been closed");
   3.124 +    return (Ottoman*) _ottoman;
   3.125 +}
   3.126 +
   3.127 +- (NSURL*) URL {
   3.128 +    const char *path = self.ottoman->filename();
   3.129 +    return path ?[NSURL fileURLWithPath: [NSString stringWithUTF8String: path]] :nil;
   3.130 +}
   3.131 +
   3.132 +
   3.133 +- (MYVersionDictionary*) lastVersion {
   3.134 +    if (!_lastVersion)