Ver Fonte

Creating an iterator library.
This library contains two smart iterator types, end_aware_iterator, and join_iterator.
end_aware_iterator acts to create an iterator that knows when its at end().
join_iterator is used to provide an iteration behavior for nested containers so that you can seamlessly iterate over all values.

There is also a short (possibly incomplete) test suite for each iterator.

Samuel Jaffe há 8 anos atrás
commit
f577341226
5 ficheiros alterados com 514 adições e 0 exclusões
  1. 57 0
      end_aware_iterator.hpp
  2. 50 0
      end_aware_iterator.t.h
  3. 279 0
      iterator.xcodeproj/project.pbxproj
  4. 88 0
      join_iterator.hpp
  5. 40 0
      join_iterator.t.h

+ 57 - 0
end_aware_iterator.hpp

@@ -0,0 +1,57 @@
+//
+//  end_aware_iterator.hpp
+//  iterator
+//
+//  Created by Sam Jaffe on 2/7/17.
+//
+
+#pragma once
+
+#include <iterator>
+
+template <typename Iterator>
+class end_aware_iterator {
+public:
+  using iter_type = Iterator;
+  using value_type = typename std::iterator_traits<iter_type>::value_type;
+  using reference = typename std::iterator_traits<iter_type>::reference;
+  using pointer = typename std::iterator_traits<iter_type>::pointer;
+  using difference_type = typename std::iterator_traits<iter_type>::difference_type;
+  using iterator_category = std::forward_iterator_tag;
+public:
+  end_aware_iterator(iter_type it, iter_type end) : curr_(it), end_(end) {}
+  
+  template <typename I>
+  end_aware_iterator( end_aware_iterator<I> const & other )
+  : curr_(other.current()), end_(other.end()) {
+    
+  }
+  
+  end_aware_iterator & operator++() {
+    if ( !done() ) { ++curr_; }
+    return *this;
+  }
+  
+  end_aware_iterator operator++(int) {
+    end_aware_iterator tmp{*this};
+    operator++();
+    return tmp;
+  }
+
+  reference operator*() { return *curr_; }
+  pointer operator->() { return std::addressof(*curr_); }
+  
+  bool done() const { return curr_ == end_; }
+  bool operator==(end_aware_iterator const & other) const {
+    return curr_ == other.curr_ && end_ == other.end_;
+  }
+  
+  bool operator!=(end_aware_iterator const & other) {
+    return !(operator==(other));
+  }
+  
+  iter_type current() const { return curr_; }
+  iter_type end() const { return end_; }
+private:
+  iter_type curr_, end_;
+};

+ 50 - 0
end_aware_iterator.t.h

@@ -0,0 +1,50 @@
+//
+//  end_aware_iterator.t.h
+//  iterator
+//
+//  Created by Sam Jaffe on 2/7/17.
+//
+
+#pragma once
+
+#include <cxxtest/TestSuite.h>
+
+#include <vector>
+
+#include "end_aware_iterator.hpp"
+
+class end_aware_TestSuite : public CxxTest::TestSuite {
+public:
+  using vec_t = std::vector<int>;
+  using ea_iter = end_aware_iterator<vec_t::iterator>;
+public:
+  void test_iterator_points_to_same() {
+    vec_t v{1, 2, 3, 4, 5};
+    TS_ASSERT_EQUALS(*v.begin(), *ea_iter(v.begin(), v.end()));
+  }
+
+  void test_iterator_edits_same() {
+    vec_t v{1, 2, 3, 4, 5};
+    *ea_iter(v.begin(), v.end()) = -1;
+    TS_ASSERT_EQUALS(v[0], -1);
+  }
+  
+  void test_not_done_until_end() {
+    vec_t v{1, 2, 3, 4, 5};
+    ea_iter it{v.end()-1, v.end()};
+    TS_ASSERT(!it.done());
+    ++it;
+    TS_ASSERT_EQUALS(it, ea_iter(v.end(),v.end()));
+    TS_ASSERT(it.done());
+  }
+
+  void test_cannot_go_past_end() {
+    vec_t v{1, 2, 3, 4, 5};
+    ea_iter it{v.end(), v.end()};
+    ea_iter const cp = it;
+    ++it;
+    TS_ASSERT_EQUALS(it, cp);
+    TS_ASSERT(it.done());
+  }
+  
+};

+ 279 - 0
iterator.xcodeproj/project.pbxproj

@@ -0,0 +1,279 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		CD21AE2B1E4A3EB000536178 /* iterator_tc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD21AE291E4A3EB000536178 /* iterator_tc.cpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		CD21AE1B1E4A3E7900536178 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		CD21AE1D1E4A3E7900536178 /* iterator_tc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = iterator_tc; sourceTree = BUILT_PRODUCTS_DIR; };
+		CD21AE291E4A3EB000536178 /* iterator_tc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = iterator_tc.cpp; sourceTree = "<group>"; };
+		CD21AE2A1E4A3EB000536178 /* join_iterator.t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = join_iterator.t.h; sourceTree = "<group>"; };
+		CD21AE2C1E4A3EC100536178 /* join_iterator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = join_iterator.hpp; sourceTree = "<group>"; };
+		CD21AE2E1E4A3F8E00536178 /* end_aware_iterator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = end_aware_iterator.hpp; sourceTree = "<group>"; };
+		CD21AE2F1E4A428D00536178 /* end_aware_iterator.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = end_aware_iterator.t.h; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		CD21AE1A1E4A3E7900536178 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		CD21AE141E4A3E7900536178 = {
+			isa = PBXGroup;
+			children = (
+				CD21AE281E4A3E8C00536178 /* src */,
+				CD21AE271E4A3E8600536178 /* test */,
+				CD21AE1E1E4A3E7900536178 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		CD21AE1E1E4A3E7900536178 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CD21AE1D1E4A3E7900536178 /* iterator_tc */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		CD21AE271E4A3E8600536178 /* test */ = {
+			isa = PBXGroup;
+			children = (
+				CD21AE2F1E4A428D00536178 /* end_aware_iterator.t.h */,
+				CD21AE2A1E4A3EB000536178 /* join_iterator.t.h */,
+				CD21AE291E4A3EB000536178 /* iterator_tc.cpp */,
+			);
+			name = test;
+			sourceTree = "<group>";
+		};
+		CD21AE281E4A3E8C00536178 /* src */ = {
+			isa = PBXGroup;
+			children = (
+				CD21AE2E1E4A3F8E00536178 /* end_aware_iterator.hpp */,
+				CD21AE2C1E4A3EC100536178 /* join_iterator.hpp */,
+			);
+			name = src;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		CD21AE1C1E4A3E7900536178 /* iterator_tc */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CD21AE241E4A3E7900536178 /* Build configuration list for PBXNativeTarget "iterator_tc" */;
+			buildPhases = (
+				CD21AE2D1E4A3EF600536178 /* ShellScript */,
+				CD21AE191E4A3E7900536178 /* Sources */,
+				CD21AE1A1E4A3E7900536178 /* Frameworks */,
+				CD21AE1B1E4A3E7900536178 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = iterator_tc;
+			productName = iterator;
+			productReference = CD21AE1D1E4A3E7900536178 /* iterator_tc */;
+			productType = "com.apple.product-type.tool";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		CD21AE151E4A3E7900536178 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0720;
+				ORGANIZATIONNAME = "Sam Jaffe";
+				TargetAttributes = {
+					CD21AE1C1E4A3E7900536178 = {
+						CreatedOnToolsVersion = 7.2.1;
+					};
+				};
+			};
+			buildConfigurationList = CD21AE181E4A3E7900536178 /* Build configuration list for PBXProject "iterator" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = CD21AE141E4A3E7900536178;
+			productRefGroup = CD21AE1E1E4A3E7900536178 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				CD21AE1C1E4A3E7900536178 /* iterator_tc */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		CD21AE2D1E4A3EF600536178 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "cxxtestgen --error-printer -o iterator_tc.cpp join_iterator.t.h end_aware_iterator.t.h";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		CD21AE191E4A3E7900536178 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CD21AE2B1E4A3EB000536178 /* iterator_tc.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		CD21AE221E4A3E7900536178 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				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.10;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		CD21AE231E4A3E7900536178 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				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.10;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		CD21AE251E4A3E7900536178 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				HEADER_SEARCH_PATHS = /usr/local/include/;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		CD21AE261E4A3E7900536178 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				HEADER_SEARCH_PATHS = /usr/local/include/;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		CD21AE181E4A3E7900536178 /* Build configuration list for PBXProject "iterator" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CD21AE221E4A3E7900536178 /* Debug */,
+				CD21AE231E4A3E7900536178 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CD21AE241E4A3E7900536178 /* Build configuration list for PBXNativeTarget "iterator_tc" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CD21AE251E4A3E7900536178 /* Debug */,
+				CD21AE261E4A3E7900536178 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = CD21AE151E4A3E7900536178 /* Project object */;
+}

+ 88 - 0
join_iterator.hpp

@@ -0,0 +1,88 @@
+//
+//  join_iterator.hpp
+//  iterator
+//
+//  Created by Sam Jaffe on 2/7/17.
+//
+
+#pragma once
+
+#include <iterator>
+
+#include "end_aware_iterator.hpp"
+
+template <typename MetaIterator>
+class joining_iterator {
+public:
+  using join_iter = MetaIterator;
+  using joinable_type = typename join_iter::value_type;
+  using iter_type = decltype(std::begin(*std::declval<MetaIterator>()));
+ 
+  using value_type = typename std::iterator_traits<iter_type>::value_type;
+  using reference = typename std::iterator_traits<iter_type>::reference;
+  using pointer = typename std::iterator_traits<iter_type>::pointer;
+  using difference_type = typename std::iterator_traits<iter_type>::difference_type;
+  using iterator_category = std::forward_iterator_tag;
+public:
+  explicit joining_iterator( )
+  : joiner_({}, {}), iterator_({}, {}) {
+    
+  }
+  
+  template <typename I>
+  joining_iterator( joining_iterator<I> const & other )
+  : joiner_(other.join_iterator()), iterator_(other.element_iterator()) {
+    
+  }
+  
+  joining_iterator( join_iter start, join_iter end )
+  : joiner_(start, end), iterator_({}, {}) {
+    update_iterator();
+  }
+
+  joining_iterator( join_iter start, join_iter end, iter_type lstart, iter_type lend, bool update = false )
+  : joiner_(start, end), iterator_(lstart, lend) {
+    if ( update ) { update_iterator(); }
+  }
+
+  joining_iterator & operator++() {
+    if ( (++iterator_).done() ) {
+      ++joiner_;
+      update_iterator();
+    }
+    return *this;
+  }
+  
+  joining_iterator operator++(int) {
+    joining_iterator tmp{*this};
+    operator++();
+    return tmp;
+  }
+  
+  reference operator*() { return iterator_.operator*(); }
+  pointer operator->() { return iterator_.operator->(); }
+  
+  bool operator==(joining_iterator const & other) const {
+    return joiner_ == other.joiner_ && ((joiner_.done() && other.joiner_.done()) ||
+                                        iterator_ == other.iterator_);
+  }
+  
+  bool operator!=(joining_iterator const & other) {
+    return !(operator==(other));
+  }
+  
+  end_aware_iterator<join_iter> join_iterator() const { return joiner_; }
+  end_aware_iterator<iter_type> element_iterator() const { return iterator_; }
+private:
+  void update_iterator() {
+    while ( !joiner_.done() && std::begin(*joiner_) == std::end(*joiner_) ) {
+      ++joiner_;
+    }
+    if ( !joiner_.done() ) {
+      iterator_ = { std::begin(*joiner_), std::end(*joiner_) };
+    }
+  }
+  
+  end_aware_iterator<join_iter> joiner_;
+  end_aware_iterator<iter_type> iterator_;
+};

+ 40 - 0
join_iterator.t.h

@@ -0,0 +1,40 @@
+//
+//  iterator.t.h
+//  iterator
+//
+//  Created by Sam Jaffe on 2/7/17.
+//
+#pragma once
+
+#include <cxxtest/TestSuite.h>
+
+#include "join_iterator.hpp"
+
+class join_iterator_TestSuite : public CxxTest::TestSuite {
+public:
+  using vec_t = std::vector<int>;
+  using meta_vec_t = std::vector<vec_t>;
+  using jn_iter = joining_iterator<meta_vec_t::iterator>;
+  
+//  vec_t v{1,2,3,4,5,6};
+//  meta_vec_t mv{{1,2,3},{4,5,6}};
+public:
+  void test_points_to_beginning() {
+    meta_vec_t mv{{1,2,3},{4,5,6}};
+    TS_ASSERT_EQUALS(*jn_iter(mv.begin(), mv.end()), mv[0][0]);
+  }
+  
+  void test_steps_to_next_list() {
+    meta_vec_t mv{{1,2,3},{4,5,6}};
+    jn_iter it(mv.begin(), mv.end(), mv.front().end(), mv.front().end());
+    TS_ASSERT_EQUALS(*++it, mv[1][0]);
+  }
+  
+  void test_cannot_go_past_end() {
+    meta_vec_t mv{{1,2,3},{4,5,6}};
+    jn_iter it(mv.end(), mv.end(), mv.back().end(), mv.back().end());
+    jn_iter const cp = it;
+    ++it;
+    TS_ASSERT_EQUALS(it, cp);
+  }
+};