Milestone: compiles and runs successfully using ArrayDynamic
authorTJ <hacker@iam.tj>
Tue, 14 Apr 2015 16:31:37 +0000 (17:31 +0100)
committerTJ <hacker@iam.tj>
Tue, 14 Apr 2015 16:31:37 +0000 (17:31 +0100)
DataStructures.hpp
GenericStorageContainerTemplateImpl.hpp
GenericStorageContainerTest.cpp

index 83cc2ed..d88ec1c 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef _DATASTRUCTURE_HPP_
 #define _DATASTRUCTURE_HPP_
 
-// #include <iterator>
 #include <memory>
 #include <new>      // for std::nothrow
 
@@ -47,24 +46,25 @@ namespace tj
     protected:
     typedef AbstractDataStructure<D> self_type;
 
-    D* data_;
+    std::shared_ptr<D> data_;
     size_t capacity_;
     size_t size_;
     size_t current_;
 
     public:
     
-    AbstractDataStructure(size_t capacity = 0) : data_(nullptr), capacity_(capacity), size_(0), current_(0)
+    AbstractDataStructure(size_t capacity = 0) :
+      // use a lambda as the shared_ptr array deleter since the default deleter does not handle array deletion
+      data_(new D[capacity_], []( D* p) {delete[] p; } ),
+      capacity_(capacity),
+      size_(0),
+      current_(0)
     {
       if (capacity_)
-        data_ = new(std::nothrow) D[capacity_];
+        data_.reset(new(std::nothrow) D[capacity_]);
     };
 
-    virtual ~AbstractDataStructure() 
-    {
-      if (data_ != nullptr)
-        delete[] data_;
-    };
+    virtual ~AbstractDataStructure() {};
 
     /* API available to application
      *
@@ -88,7 +88,7 @@ namespace tj
      */
     virtual D* get_data()
     {
-      return (data_ && size_ > 0) ? &data_[current_] : nullptr;
+      return (data_.get() && size_ > 0) ? &data_.get()[current_] : nullptr;
     };
 
     virtual self_type* get_begin() = 0;
@@ -142,12 +142,32 @@ namespace tj
      */
     virtual D* find(D& needle, D* last_found = nullptr) = 0;
 
-    virtual bool operator==(const D& right_hand_side)
+    // comparison methods
+    virtual bool operator==(const self_type& right_hand_side)
     {
       bool result = false;
-      // TODO: implement
+      if (this->data_.get() && right_hand_side.data_.get())
+        result = this->current_ == right_hand_side.current_;
+
+      return result;
+    };
+    virtual bool operator!=(const self_type& right_hand_side)
+    {
+      return !this->operator==(right_hand_side);
+    };
+    virtual bool operator< (const self_type& right_hand_side)
+    {
+      bool result = false;
+      if (this->data_.get() && right_hand_side.data_.get())
+        result = this->current_ < right_hand_side.current_;
+
       return result;
     };
+    virtual bool operator<=(const self_type& right_hand_side)
+    {
+      return this->operator==(right_hand_side) | this->operator<(right_hand_side);
+    };
+
   };
 
 
@@ -163,13 +183,33 @@ namespace tj
     public:
     DataStructure_ArrayDynamic<AD>(size_t capacity = 512) : AbstractDataStructure<AD>(capacity), growth_(512) {};
 
+    /* Copy constructor that can do deep and shallow copies.
+     * Shallow copies are efficient for use by iterators where the only unique variable is
+     * the 'current_' index - the object can share a pointer to the data.
+     */
+    DataStructure_ArrayDynamic<AD>(const self_type& copy, bool shallow = false)
+    {
+      this->data_ = copy.data_;
+      this->capacity_ = copy.capacity_;
+      this->size_ = copy.size_;
+      this->current_ = copy.current_;
+      this->growth_ = copy.growth_;
+      if (!shallow)
+      {
+        this->data_.reset(new AD [this->capacity_]);
+        for (size_t i = 0; i < this->capacity_; ++i)
+            this->data_.get()[i] = copy.data_.get()[i];
+      }
+    }
+
     virtual self_type* get_begin()
     {
       self_type* result = nullptr;
 
       if (this->size_ > 0) {
-        this->current_ = 0;
-        result = this;
+        // TODO: make a shallow copy (share the array to avoid an expensive copy)
+        result = new self_type(*this, true);
+        result->current_ = 0;
       }
       return result;
     };
@@ -180,8 +220,9 @@ namespace tj
 
       if (this->size_ > 0)
       {
-        this->current_ = this->size_ - 1;
-        result = this;
+        result = new self_type(*this, true);
+        // 1 beyond last element; used by iterator loops to detect when to break
+        result->current_ = result->size_;
       }
       return result;
     };
@@ -192,11 +233,11 @@ namespace tj
 
       if (this->size_ > 0)
       {
-        if (this->current_ + 1 < this->size_)
-        {
-          ++this->current_;
-          result = this;
-        }
+        /* if (this->current_ + 1 < this->size_)
+        { */
+          result = new self_type(*this, true);
+          ++result->current_;
+        // }
       }
 
       return result;
@@ -210,8 +251,8 @@ namespace tj
       {
         if (this->current_ - 1 >= 0)
         {
-          --this->current_;
-          result = this;
+          result = new self_type(*this, true);
+          --result->current_;
         }
       }
 
@@ -234,7 +275,7 @@ namespace tj
 
         if (this->capacity_ > index)
         {
-          this->data_[index] = data;
+          this->data_.get()[index] = data;
 
           if (index >= this->size_)
             this->size_ = index + 1;
@@ -295,10 +336,24 @@ namespace tj
       return result;
     };
 
+    // comparisons require both sides to have the same array pointer
     virtual bool operator==(const self_type& right_hand_side)
     {
       bool result = false;
-      // TODO: implement
+
+      if (this->data_.get() == right_hand_side.data_.get())
+        result = this->current_ == right_hand_side.current_;
+
+      return result;
+    };
+
+    virtual bool operator<(const self_type& right_hand_side)
+    {
+      bool result = false;
+
+      if (this->data_.get() == right_hand_side.data_.get())
+        result = this->current_ < right_hand_side.current_;
+
       return result;
     };
 
@@ -309,10 +364,9 @@ namespace tj
       if (temp != nullptr)
       {
         for (size_t index = 0; index < this->size_; ++index)
-          temp[index] = this->data_[index];
+          temp[index] = this->data_.get()[index];
 
-        delete[] this->data_;
-        this->data_ = temp;
+        this->data_.reset(temp);
 
         this->capacity_ += this->growth_;
         result = true;
index e84b99a..104edb1 100644 (file)
@@ -92,10 +92,11 @@ namespace tj
       // prefix increment operator
       self_type operator++(int unused)
       {
+        DATA_STRUCTURE<T>* result = nullptr;
+
         if (element_) {
-          DATA_STRUCTURE<T>* temp = element_->get_next();
-          if (temp)
-            element_ = temp;
+          result = element_->get_next();
+          element_ = result;
         }
         return *this;
       };
@@ -119,13 +120,13 @@ namespace tj
         return *this;
       };
 
-      // Comparison methods
+      // comparison methods
       bool operator==(const self_type& right_hand_side)
       {
         bool result = false;
 
         if (element_ && right_hand_side.element_)
-          result = *element_ == *right_hand_side.element_; 
+          result = *this->element_ == *right_hand_side.element_; 
 
         return result;
       };
@@ -135,6 +136,22 @@ namespace tj
         return !this->operator==(right_hand_side);
       };
 
+      bool operator<(const self_type& right_hand_side)
+      {
+        bool result = false;
+
+        if (element_ && right_hand_side.element_)
+          result = *this->element_ < *right_hand_side.element_;
+
+        return result;
+      };
+
+      bool operator<=(const self_type& right_hand_side)
+      {
+        return this->operator==(right_hand_side) | this->operator<(right_hand_side);
+      };
+
+      // data access
       T operator* ()
       {
 
@@ -195,7 +212,6 @@ namespace tj
 
     ~GenericStorageContainerTemplateImpl<T, DATA_STRUCTURE>()
     {
-      delete &data_structure_;
     };
 
     // capacity
index 65f220c..0ffc321 100644 (file)
@@ -44,10 +44,25 @@ main (int argc, char **argv, char **env)
         break;
       case 3: // List using forward Iterator
         cout << "size = " << my_collection_of_ints.get_size() << endl;
+
+        /* the traditional style of iterator loop
+        for (GSCTI<int, DataStructure_ArrayDynamic>::_iterator end = my_collection_of_ints.end(),
+             i = my_collection_of_ints.begin();
+             i != end;
+             ++i)
+        {
+          cout << "Data = " << *i << endl;
+        }
+        */
+
+        /* the modern range-based for loop
+         * see http://en.cppreference.com/w/cpp/language/range-for
+         */
         for (auto i : my_collection_of_ints) // XXX: C++11 'range for' automagically uses the iterator
         {
-          cout << "Node = " << i << endl;
+          cout << "Data = " << i << endl;
         }
+       
         break;
       case 4: // List using reverse Iterator
         break;