Browse Source

Initialize program args from scratch code.

Sam Jaffe 4 years ago
commit
65a9106db3

+ 85 - 0
include/program_args/arguments.h

@@ -0,0 +1,85 @@
+#pragma once
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace program {
+
+template <typename Impl>
+class Arguments {
+protected:
+  struct Option;
+  struct Positional;
+  template <typename, typename> struct WithDefault;
+
+public:
+  Arguments() = default;
+  Arguments(int argc, char const * const * const argv);
+
+  auto option(std::string const &name, std::string const &description = "");
+  auto argument(size_t index, std::string const &name, std::string const &description = "");
+
+private:
+  void usage() const;
+
+private:
+  // Metadata variables
+  bool primed_{false};
+  std::map<std::string, std::string> option_descriptions;
+  std::map<std::string, std::string> positional_descriptions;
+  std::map<std::string, std::string> option_name_mapping;
+  std::map<size_t, std::string> argument_names;
+
+  // Data variables
+  std::string program;
+  size_t optional_from{std::numeric_limits<size_t>::max()};
+  std::map<std::string, std::string> options;
+  std::vector<std::string> arguments;
+};
+
+template <typename Impl>
+template <typename B, typename V>
+struct Arguments<Impl>::WithDefault {
+  B impl;
+  V default_value;
+  template <typename T> operator T() const { return impl ?: T(default_value); }
+};
+
+template <typename Impl>
+struct Arguments<Impl>::Option {
+  Arguments<Impl> *self;
+  std::string name;
+  char abbrev;
+  std::string description;
+
+  template <typename T> auto operator=(T &&value);
+  template <typename T> operator T() const;
+  bool primed() const;
+  explicit operator bool() const;
+};
+
+template <typename Impl>
+struct Arguments<Impl>::Positional {
+  Arguments<Impl> *self;
+  size_t index;
+  bool is_optional;
+  std::string name;
+  std::string description;
+
+  template <typename T> auto operator=(T &&value);
+  template <typename T> operator T() const;
+  bool primed() const;
+  explicit operator bool() const;
+};
+
+}
+
+#include "arguments_impl.hpp"
+
+#define TYPED_MAIN(tname)                               \
+  int typed_main(tname const &args);                    \
+  int main(int argc, char const * const * const argv) { \
+    return typed_main(tname(argc, argv));               \
+  }                                                     \
+  int typed_main(tname const &args)

+ 149 - 0
include/program_args/arguments_impl.hpp

@@ -0,0 +1,149 @@
+#pragma once
+
+#include "options.hpp"
+
+#include <utility>
+
+namespace program {
+
+template <typename Impl>
+template <typename T>
+Arguments<Impl>::Option::operator T() const {
+  return (*this) ? self->options.at(name) : T();
+}
+
+template <typename Impl>
+Arguments<Impl>::Option::operator bool() const {
+  return primed() && self->options.count(name);
+}
+
+template <typename Impl>
+template <typename T>
+auto Arguments<Impl>::Option::operator=(T &&value) {
+  return WithDefault<Option, T>{*this, std::forward<T>(value)};
+}
+
+inline std::string join(std::string const &tok,
+                        std::vector<std::string> const &data) {
+  std::string accum = data.empty() ? "" : data.front();
+  for (size_t i = 1; i < data.size(); ++i) {
+    accum += tok;
+    accum += data[i];
+  }
+  return accum;
+}
+
+template <typename Impl>
+bool Arguments<Impl>::Option::primed() const {
+  if (self->primed_) { return true; }
+  std::vector<std::string> aliases{"--" + name};
+  if (abbrev) {
+    aliases.emplace_back(std::string{'-', abbrev});
+  }
+  for (auto &alias : aliases) {
+    self->option_name_mapping.emplace(alias, name);
+  }
+  self->option_descriptions.emplace(join("/", aliases), description);
+  return false;
+}
+
+}
+
+namespace program {
+
+template <typename Impl>
+template <typename T>
+Arguments<Impl>::Positional::operator T() const {
+  return (*this) ? self->arguments.at(index) : T();
+}
+
+template <typename Impl>
+Arguments<Impl>::Positional::operator bool() const {
+  return primed(); // TODO(samjaffe): Existance check?
+}
+
+template <typename Impl>
+template <typename T>
+auto Arguments<Impl>::Positional::operator=(T &&value) {
+  is_optional = true;
+  return WithDefault<Positional, T>{*this, std::forward<T>(value)};
+}
+
+template <typename Impl>
+bool Arguments<Impl>::Positional::primed() const {
+  if (self->primed_) { return true; }
+  if (is_optional) {
+    self->optional_from = std::min(self->optional_from, index);
+  } else if (self->optional_from < index) {
+    throw std::logic_error{
+      "Cannot have required positional named '" + name +
+        "' after optional positionals"};
+  }
+  self->argument_names.emplace(index, name);
+  self->positional_descriptions.emplace(name, description);
+  return false;
+}
+
+}
+
+#define arg_equals(str) !strncmp(argv[i], str, sizeof(str))
+namespace program {
+
+template <typename Impl>
+Arguments<Impl>::Arguments(int argc, char const * const * const argv) {
+  Impl generator;
+  *this = static_cast<Arguments const&>(generator);
+  if (argument_names.rbegin()->first != argument_names.size() - 1) {
+    throw std::logic_error{"Jagged arguments are not supported"};
+  }
+
+  primed_ = true;
+  program = argv[0];
+  for (size_t i = 1; i < argc; ++i) {
+    if (arg_equals("--help")) {
+      usage();
+      std::exit(0);
+    } else if (arg_equals("--")) {
+      arguments.insert(arguments.end(), &argv[i+1], &argv[argc]);
+      i = argc;
+    } else if (argv[i][0] == '-') {
+      // TODO(samjaffe): Arity
+      options.emplace(option_name_mapping.at(argv[i]), argv[i+1]);
+      ++i;
+    } else {
+      arguments.emplace_back(argv[i]);
+    }
+  }
+}
+
+template <typename Impl>
+void Arguments<Impl>::usage() const {
+  std::cout << program << " [options...]";
+  for (auto &[index, name] : argument_names) {
+    std::cout << " " << (index == optional_from ? "[" : "")  << name;
+  }
+  if (optional_from != std::numeric_limits<size_t>::max()) {
+    std::cout << "]";
+  }
+  std::cout << "\nPositional Arguments:\n";
+  for (auto &[name, desc] : positional_descriptions) {
+    std::cout << "  " << name << ": " << desc << "\n";
+  }
+  std::cout << "Options:\n";
+  for (auto &[opt, desc] : option_descriptions) {
+    std::cout << "  " << opt << ": " << desc << "\n";
+  }
+}
+
+template <typename Impl>
+auto Arguments<Impl>::option(std::string const &name, std::string const &description) {
+  return Option{this, name, 0, description};
+}
+
+template <typename Impl>
+auto Arguments<Impl>::argument(size_t index, std::string const &name,
+                               std::string const &description) {
+  return Positional{this, index, false, name, description};
+}
+
+}

+ 357 - 0
program_args.xcodeproj/project.pbxproj

@@ -0,0 +1,357 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 50;
+	objects = {
+
+/* Begin PBXContainerItemProxy section */
+		CDE4F79A25CF316A009E4EC1 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CDE4F79325CF316A009E4EC1 /* GoogleMock.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 05818F861A685AEA0072A469;
+			remoteInfo = GoogleMock;
+		};
+		CDE4F79C25CF316A009E4EC1 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CDE4F79325CF316A009E4EC1 /* GoogleMock.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 05E96ABD1A68600C00204102;
+			remoteInfo = gmock;
+		};
+		CDE4F79E25CF316A009E4EC1 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CDE4F79325CF316A009E4EC1 /* GoogleMock.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 05E96B1F1A68634900204102;
+			remoteInfo = gtest;
+		};
+		CDE4F7A025CF316A009E4EC1 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CDE4F79325CF316A009E4EC1 /* GoogleMock.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 05818F901A685AEA0072A469;
+			remoteInfo = GoogleMockTests;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		CDE4F78A25CF309E009E4EC1 /* libprogram_args.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libprogram_args.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		CDE4F79325CF316A009E4EC1 /* GoogleMock.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GoogleMock.xcodeproj; path = "../../../gmock-xcode-master/GoogleMock.xcodeproj"; sourceTree = "<group>"; };
+		CDE4F7A225CF317C009E4EC1 /* program_args */ = {isa = PBXFileReference; lastKnownFileType = folder; name = program_args; path = include/program_args; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		CDE4F78825CF309E009E4EC1 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		CDE4F78125CF309E009E4EC1 = {
+			isa = PBXGroup;
+			children = (
+				CDE4F79325CF316A009E4EC1 /* GoogleMock.xcodeproj */,
+				CDE4F7A225CF317C009E4EC1 /* program_args */,
+				CDE4F79125CF30BA009E4EC1 /* test */,
+				CDE4F78B25CF309E009E4EC1 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		CDE4F78B25CF309E009E4EC1 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CDE4F78A25CF309E009E4EC1 /* libprogram_args.a */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		CDE4F79125CF30BA009E4EC1 /* test */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			path = test;
+			sourceTree = "<group>";
+		};
+		CDE4F79425CF316A009E4EC1 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CDE4F79B25CF316A009E4EC1 /* GoogleMock.framework */,
+				CDE4F79D25CF316A009E4EC1 /* gmock.framework */,
+				CDE4F79F25CF316A009E4EC1 /* gtest.framework */,
+				CDE4F7A125CF316A009E4EC1 /* GoogleMockTests.xctest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		CDE4F78625CF309E009E4EC1 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		CDE4F78925CF309E009E4EC1 /* program_args */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CDE4F78E25CF309E009E4EC1 /* Build configuration list for PBXNativeTarget "program_args" */;
+			buildPhases = (
+				CDE4F78625CF309E009E4EC1 /* Headers */,
+				CDE4F78725CF309E009E4EC1 /* Sources */,
+				CDE4F78825CF309E009E4EC1 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = program_args;
+			productName = program_args;
+			productReference = CDE4F78A25CF309E009E4EC1 /* libprogram_args.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		CDE4F78225CF309E009E4EC1 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 1240;
+				TargetAttributes = {
+					CDE4F78925CF309E009E4EC1 = {
+						CreatedOnToolsVersion = 12.4;
+					};
+				};
+			};
+			buildConfigurationList = CDE4F78525CF309E009E4EC1 /* Build configuration list for PBXProject "program_args" */;
+			compatibilityVersion = "Xcode 9.3";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = CDE4F78125CF309E009E4EC1;
+			productRefGroup = CDE4F78B25CF309E009E4EC1 /* Products */;
+			projectDirPath = "";
+			projectReferences = (
+				{
+					ProductGroup = CDE4F79425CF316A009E4EC1 /* Products */;
+					ProjectRef = CDE4F79325CF316A009E4EC1 /* GoogleMock.xcodeproj */;
+				},
+			);
+			projectRoot = "";
+			targets = (
+				CDE4F78925CF309E009E4EC1 /* program_args */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+		CDE4F79B25CF316A009E4EC1 /* GoogleMock.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = GoogleMock.framework;
+			remoteRef = CDE4F79A25CF316A009E4EC1 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CDE4F79D25CF316A009E4EC1 /* gmock.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = gmock.framework;
+			remoteRef = CDE4F79C25CF316A009E4EC1 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CDE4F79F25CF316A009E4EC1 /* gtest.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = gtest.framework;
+			remoteRef = CDE4F79E25CF316A009E4EC1 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CDE4F7A125CF316A009E4EC1 /* GoogleMockTests.xctest */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.cfbundle;
+			path = GoogleMockTests.xctest;
+			remoteRef = CDE4F7A025CF316A009E4EC1 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXReferenceProxy section */
+
+/* Begin PBXSourcesBuildPhase section */
+		CDE4F78725CF309E009E4EC1 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		CDE4F78C25CF309E009E4EC1 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.15;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		CDE4F78D25CF309E009E4EC1 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.15;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				MTL_FAST_MATH = YES;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		CDE4F78F25CF309E009E4EC1 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_STYLE = Automatic;
+				EXECUTABLE_PREFIX = lib;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		CDE4F79025CF309E009E4EC1 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_STYLE = Automatic;
+				EXECUTABLE_PREFIX = lib;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		CDE4F78525CF309E009E4EC1 /* Build configuration list for PBXProject "program_args" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CDE4F78C25CF309E009E4EC1 /* Debug */,
+				CDE4F78D25CF309E009E4EC1 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CDE4F78E25CF309E009E4EC1 /* Build configuration list for PBXNativeTarget "program_args" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CDE4F78F25CF309E009E4EC1 /* Debug */,
+				CDE4F79025CF309E009E4EC1 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = CDE4F78225CF309E009E4EC1 /* Project object */;
+}