From 1c0a6f8133200bcee81ddf3d74600b7a0149d858 Mon Sep 17 00:00:00 2001 From: Roenke Date: Sun, 3 Apr 2016 20:40:19 +0300 Subject: [PATCH 1/5] Add classroom work. --- practice/strings/CMakeLists.txt | 9 +++ practice/strings/imstring.h | 109 ++++++++++++++++++++++++++++++++ practice/strings/main.cpp | 50 +++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 practice/strings/CMakeLists.txt create mode 100644 practice/strings/imstring.h create mode 100644 practice/strings/main.cpp diff --git a/practice/strings/CMakeLists.txt b/practice/strings/CMakeLists.txt new file mode 100644 index 0000000..672a107 --- /dev/null +++ b/practice/strings/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 2.8) # Проверка версии CMake. + # Если версия установленой программы + # старее указаной, произайдёт аварийный выход. + +add_executable(main imstring.h main.cpp) # Создает исполняемый файл с именем main + # из исходника main.cpp + + +set (CMAKE_CXX_FLAGS "-std=c++11") diff --git a/practice/strings/imstring.h b/practice/strings/imstring.h new file mode 100644 index 0000000..de49a67 --- /dev/null +++ b/practice/strings/imstring.h @@ -0,0 +1,109 @@ +#pragma once +#include +#include +#include + +struct imstring; + +struct imstring { +public: + imstring(); + imstring(const char*); + imstring(imstring const& other); + imstring(imstring && other); + imstring(imstring const& left, imstring const& right); + imstring& operator=(imstring const& other) = delete; + + size_t size() const; + const char* c_str() const; + + imstring& operator+=(imstring const& other); + std::ostream& operator<<(std::ostream & stream) const; + const char operator[](int ix) const; + + std::string::iterator begin(); + std::string::iterator end(); + + +private: + std::shared_ptr shared_string_; + + bool is_concat; + imstring left_; + imstring right_; +}; + +imstring::imstring() + : imstring("") +{} + +imstring::imstring(const char * c_str) + : shared_string_(std::make_shared(c_str)) + , is_concat(false) +{} + +imstring::imstring(const imstring &other) + : shared_string_(other.shared_string_) + , is_concat(other.is_concat) + , left_(other.left_) + , right_(other.right_) +{} + +imstring::imstring(imstring &&other) +{ + shared_string_ = std::move(other.shared_string_); + is_concat = other.is_concat; + if (other.is_concat) { + left_(std::move(other.left_)); + right_(std::move(other.right_)); + } + + other.is_concat = false; +} + +imstring::imstring(const imstring &left, const imstring &right) + : left_(left) + , right_(right) + , is_concat(true) + , shared_string_(nullptr) +{} + +size_t imstring::size() const +{ + return shared_string_->size(); +} + +const char *imstring::c_str() const +{ + return shared_string_->c_str(); +} + +imstring& imstring::operator+=(const imstring &other) +{ + return *this; +} + +std::ostream &imstring::operator<<(std::ostream &stream) const +{ + stream << *shared_string_; + return stream; +} + +const char imstring::operator[](int ix) const +{ + return shared_string_->operator [](ix); +} + +std::string::iterator imstring::begin() +{ + return shared_string_->begin(); +} + +std::string::iterator imstring::end() +{ + return shared_string_->end(); +} + +imstring& operator+(imstring left, imstring const& right) { + return left += right; +} diff --git a/practice/strings/main.cpp b/practice/strings/main.cpp new file mode 100644 index 0000000..c04799b --- /dev/null +++ b/practice/strings/main.cpp @@ -0,0 +1,50 @@ +#include "imstring.h" +#include +#include +#include +#include +#include +#include + +template +void test_strings_equal(STR1& str1, STR2 &str2) +{ + assert(str1.size() == str2.size()); + assert(std::equal(str1.begin(), str1.end(), str2.begin())); + assert(std::distance(str1.begin(), str1.end()) == + std::distance(str2.begin(), str2.end())); + // call operator << before we force strings to be not lazy + std::cout << str1 << std::endl << str2 << std::endl; + assert(strcmp(str1.c_str(), str2.c_str()) == 0); +} + +int main() +{ + std::string str1("foo bar buzz"); + + // Test creation from implicit c string + imstring imstr1 = str1.c_str(); + test_strings_equal(str1, imstr1); + test_strings_equal(imstr1, str1); + + // Test copying of shared immutable string buffer + imstring imstr1_cp(imstr1); + test_strings_equal(str1, imstr1); + test_strings_equal(imstr1, imstr1_cp); + assert(imstr1.begin() == imstr1.begin()); + assert(imstr1.end() == imstr1.end()); + // check laziness + assert(&(*imstr1.begin()) == &(*imstr1_cp.begin())); + + // Test lazy concatenation + imstring imstr_concat1 = imstr1 + imstr1_cp; + imstring imstr_concat2 = imstr_concat1 + imstr_concat1 + + imstr1 + imstr1_cp + imstr_concat1; + std::string str_concat1 = str1 + str1; + std::string str_concat2 = str_concat1 + str_concat1 + + str1 + str1 + str_concat1; + test_strings_equal(str_concat2, imstr_concat2); + test_strings_equal(imstr_concat2, str_concat2); + + return 0; +} From a2c120443dca8e390266be11cb2dcc618998bca3 Mon Sep 17 00:00:00 2001 From: Roenke Date: Sun, 3 Apr 2016 22:35:22 +0300 Subject: [PATCH 2/5] Add naive implementation for immutable string. --- practice/strings/imstring.cpp | 145 ++++++++++++++++++++++++++++++++++ practice/strings/imstring.h | 114 +++++++------------------- 2 files changed, 174 insertions(+), 85 deletions(-) create mode 100644 practice/strings/imstring.cpp diff --git a/practice/strings/imstring.cpp b/practice/strings/imstring.cpp new file mode 100644 index 0000000..a8fc5e2 --- /dev/null +++ b/practice/strings/imstring.cpp @@ -0,0 +1,145 @@ +#include "imstring.h" +#include + +imstring::buffer::buffer(std::string const& value) + : is_concat(false) + , value_(value) + , left_(nullptr) + , right_(nullptr) +{} + +imstring::buffer::buffer(std::shared_ptr left, std::shared_ptr right) + : is_concat(true) + , value_("") + , left_(left) + , right_(right) +{} + +size_t imstring::buffer::size() const { + if(is_concat) { + return (left_ ? left_->size() : 0) + + (right_ ? right_->size() : 0); + } + + return value_.size(); +} + +const char* imstring::buffer::c_str() { + if(is_concat) { + collapse(); + } + + assert(!is_concat); + return value_.c_str(); +} + +char imstring::buffer::get_at(size_t ix) { + if(is_concat) { + auto left_size = left_->size(); + if(left_->size() < ix) { + return left_->get_at(ix); + } + + return right_->get_at(ix - left_size); + } + + return value_[ix]; +} + +std::string::iterator imstring::buffer::begin() { + collapse(); + return value_.begin(); +} + +std::string::iterator imstring::buffer::end() { + collapse(); + return value_.end(); +} + +void imstring::buffer::collapse() { + if (!is_concat) return; + std::vector> primitive_buffers; + auto total_size = add_primitive_buffers(primitive_buffers); + + value_.reserve(total_size); + value_ = ""; + for (auto buffer_ptr : primitive_buffers) { + value_ += buffer_ptr->value_; + } + + right_ = left_ = nullptr; + is_concat = false; +} + +size_t imstring::buffer::add_primitive_buffers(std::vector>& buffers) const { + size_t total_size = 0; + + if (left_->is_concat) { + total_size += left_->add_primitive_buffers(buffers); + } + else { + total_size += left_->size(); + buffers.push_back(left_); + } + + if(right_->is_concat) { + total_size += right_->add_primitive_buffers(buffers); + } + else { + total_size += right_->size(); + buffers.push_back(right_); + } + + return total_size; +} + +imstring::imstring() + : shared_buffer_(std::make_shared("")) +{} + +imstring::imstring(const char* c_str) + : shared_buffer_(std::make_shared(c_str)) +{} + +imstring::imstring(imstring const& other) + : shared_buffer_(other.shared_buffer_) +{} + +imstring::imstring(imstring&& other) + : shared_buffer_(std::move(other.shared_buffer_)) +{} + +size_t imstring::size() const { + return shared_buffer_->size(); +} + +const char* imstring::c_str() const { + return shared_buffer_->c_str(); +} + +imstring& imstring::operator+=(imstring const& other) { + shared_buffer_ = std::make_shared(shared_buffer_, other.shared_buffer_); + return *this; +} + +char imstring::operator[](int ix) const { + return shared_buffer_->get_at(ix); +} + +std::string::iterator imstring::begin() const { + return shared_buffer_->begin(); +} + +std::string::iterator imstring::end() const { + return shared_buffer_->end(); +} + +imstring operator+(imstring left, imstring const& right) { + return left += right; +} + +std::ostream& operator<<(std::ostream& stream, imstring const& imstring) { + // TODO: make more lazy + stream << imstring.c_str(); + return stream; +} diff --git a/practice/strings/imstring.h b/practice/strings/imstring.h index de49a67..a871328 100644 --- a/practice/strings/imstring.h +++ b/practice/strings/imstring.h @@ -1,109 +1,53 @@ #pragma once #include #include -#include +#include struct imstring; struct imstring { +private: + struct buffer { + buffer(std::string const& value); + + buffer(std::shared_ptr left, std::shared_ptr right); + + size_t size() const; + const char* c_str(); + char get_at(size_t ix); + + std::string::iterator begin(); + std::string::iterator end(); + + private: + void collapse(); + size_t add_primitive_buffers(std::vector>& buffers) const; + + bool is_concat; + std::string value_; + std::shared_ptr left_; + std::shared_ptr right_; + }; // buffer public: imstring(); imstring(const char*); imstring(imstring const& other); imstring(imstring && other); - imstring(imstring const& left, imstring const& right); imstring& operator=(imstring const& other) = delete; size_t size() const; const char* c_str() const; imstring& operator+=(imstring const& other); - std::ostream& operator<<(std::ostream & stream) const; - const char operator[](int ix) const; + char operator[](int ix) const; - std::string::iterator begin(); - std::string::iterator end(); + std::string::iterator begin() const; + std::string::iterator end() const; private: - std::shared_ptr shared_string_; - - bool is_concat; - imstring left_; - imstring right_; + std::shared_ptr shared_buffer_; }; -imstring::imstring() - : imstring("") -{} - -imstring::imstring(const char * c_str) - : shared_string_(std::make_shared(c_str)) - , is_concat(false) -{} - -imstring::imstring(const imstring &other) - : shared_string_(other.shared_string_) - , is_concat(other.is_concat) - , left_(other.left_) - , right_(other.right_) -{} - -imstring::imstring(imstring &&other) -{ - shared_string_ = std::move(other.shared_string_); - is_concat = other.is_concat; - if (other.is_concat) { - left_(std::move(other.left_)); - right_(std::move(other.right_)); - } - - other.is_concat = false; -} - -imstring::imstring(const imstring &left, const imstring &right) - : left_(left) - , right_(right) - , is_concat(true) - , shared_string_(nullptr) -{} - -size_t imstring::size() const -{ - return shared_string_->size(); -} - -const char *imstring::c_str() const -{ - return shared_string_->c_str(); -} - -imstring& imstring::operator+=(const imstring &other) -{ - return *this; -} - -std::ostream &imstring::operator<<(std::ostream &stream) const -{ - stream << *shared_string_; - return stream; -} - -const char imstring::operator[](int ix) const -{ - return shared_string_->operator [](ix); -} - -std::string::iterator imstring::begin() -{ - return shared_string_->begin(); -} - -std::string::iterator imstring::end() -{ - return shared_string_->end(); -} - -imstring& operator+(imstring left, imstring const& right) { - return left += right; -} +imstring operator+(imstring left, imstring const& right); +std::ostream& operator<<(std::ostream& ostream, imstring const& imstring); From ba7bb105dd583949eace03a0b83b4ddd39391a90 Mon Sep 17 00:00:00 2001 From: Roenke Date: Mon, 4 Apr 2016 09:02:38 +0300 Subject: [PATCH 3/5] Add basic interface for iterator. --- practice/strings/imstring.cpp | 4 ++-- practice/strings/imstring.h | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/practice/strings/imstring.cpp b/practice/strings/imstring.cpp index a8fc5e2..5d9b1b2 100644 --- a/practice/strings/imstring.cpp +++ b/practice/strings/imstring.cpp @@ -139,7 +139,7 @@ imstring operator+(imstring left, imstring const& right) { } std::ostream& operator<<(std::ostream& stream, imstring const& imstring) { - // TODO: make more lazy - stream << imstring.c_str(); + // TODO: make more lazy + stream << imstring; return stream; } diff --git a/practice/strings/imstring.h b/practice/strings/imstring.h index a871328..269d7bb 100644 --- a/practice/strings/imstring.h +++ b/practice/strings/imstring.h @@ -6,6 +6,31 @@ struct imstring; struct imstring { +public: + struct iterator : std::iterator{ + // all categories + iterator(iterator const& other); + iterator& operator=(iterator const& other); + + iterator& operator++(); + iterator operator++(int); + + // input iterator + // TODO: move out-scope + bool operator==(iterator const& other); + bool operator!=(iterator const& other); + + char operator*(); + char* operator->(); + + // forward iterator + iterator(); + + // bidirectional iterator + iterator& operator--(); + iterator operator--(int); + }; + private: struct buffer { buffer(std::string const& value); From 7fee96c739a55d052073e959d5cfc29caab981bc Mon Sep 17 00:00:00 2001 From: Roenke Date: Mon, 4 Apr 2016 09:40:56 +0300 Subject: [PATCH 4/5] Add basic implementation for few methods of imstring::iterator. --- practice/strings/imstring.cpp | 63 +++++++++++++++++++++++++++------ practice/strings/imstring.h | 65 ++++++++++++++++++++++------------- practice/strings/main.cpp | 12 +++++++ 3 files changed, 106 insertions(+), 34 deletions(-) diff --git a/practice/strings/imstring.cpp b/practice/strings/imstring.cpp index 5d9b1b2..d2bfa73 100644 --- a/practice/strings/imstring.cpp +++ b/practice/strings/imstring.cpp @@ -1,22 +1,33 @@ #include "imstring.h" #include +imstring::iterator::iterator(std::shared_ptr buffer) + : root_ (buffer) + , current_node_(buffer) { + to_next_value(); + eval_end(); +} + +imstring::iterator& imstring::iterator::operator++() { + +} + imstring::buffer::buffer(std::string const& value) - : is_concat(false) + : is_concat_(false) , value_(value) , left_(nullptr) , right_(nullptr) {} imstring::buffer::buffer(std::shared_ptr left, std::shared_ptr right) - : is_concat(true) + : is_concat_(true) , value_("") , left_(left) , right_(right) {} size_t imstring::buffer::size() const { - if(is_concat) { + if(is_concat_) { return (left_ ? left_->size() : 0) + (right_ ? right_->size() : 0); } @@ -25,16 +36,16 @@ size_t imstring::buffer::size() const { } const char* imstring::buffer::c_str() { - if(is_concat) { + if(is_concat_) { collapse(); } - assert(!is_concat); + assert(!is_concat_); return value_.c_str(); } char imstring::buffer::get_at(size_t ix) { - if(is_concat) { + if(is_concat_) { auto left_size = left_->size(); if(left_->size() < ix) { return left_->get_at(ix); @@ -57,7 +68,7 @@ std::string::iterator imstring::buffer::end() { } void imstring::buffer::collapse() { - if (!is_concat) return; + if (!is_concat_) return; std::vector> primitive_buffers; auto total_size = add_primitive_buffers(primitive_buffers); @@ -68,13 +79,13 @@ void imstring::buffer::collapse() { } right_ = left_ = nullptr; - is_concat = false; + is_concat_ = false; } size_t imstring::buffer::add_primitive_buffers(std::vector>& buffers) const { size_t total_size = 0; - if (left_->is_concat) { + if (left_->is_concat_) { total_size += left_->add_primitive_buffers(buffers); } else { @@ -82,7 +93,7 @@ size_t imstring::buffer::add_primitive_buffers(std::vectoris_concat) { + if(right_->is_concat_) { total_size += right_->add_primitive_buffers(buffers); } else { @@ -93,6 +104,32 @@ size_t imstring::buffer::add_primitive_buffers(std::vectoris_concat_) { + while (current_node_->is_concat_) { + stack_.push(current_node_); + current_node_ = current_node_->left_; + } + + current_pos_ = current_node_->value_.begin(); + } + + // TODO: Complete method. +} + +void imstring::iterator::eval_end() { + auto node = root_; + while(!node->is_concat_) { + node = node->right_; + } + + end_pos_ = node->value_.end(); +} + imstring::imstring() : shared_buffer_(std::make_shared("")) {} @@ -134,12 +171,16 @@ std::string::iterator imstring::end() const { return shared_buffer_->end(); } +imstring::iterator imstring::_begin() const { + return iterator(shared_buffer_); +} + imstring operator+(imstring left, imstring const& right) { return left += right; } std::ostream& operator<<(std::ostream& stream, imstring const& imstring) { // TODO: make more lazy - stream << imstring; + stream << imstring.c_str(); return stream; } diff --git a/practice/strings/imstring.h b/practice/strings/imstring.h index 269d7bb..60db371 100644 --- a/practice/strings/imstring.h +++ b/practice/strings/imstring.h @@ -2,15 +2,43 @@ #include #include #include +#include struct imstring; struct imstring { +private: + struct iterator; + struct buffer { + buffer(std::string const& value); + + buffer(std::shared_ptr left, std::shared_ptr right); + + size_t size() const; + const char* c_str(); + char get_at(size_t ix); + + std::string::iterator begin(); + std::string::iterator end(); + + friend struct iterator; + private: + void collapse(); + size_t add_primitive_buffers(std::vector>& buffers) const; + + bool is_concat_; + std::string value_; + std::shared_ptr left_; + std::shared_ptr right_; + }; // buffer + public: - struct iterator : std::iterator{ + struct iterator : std::iterator { + explicit iterator(std::shared_ptr buffer); + // all categories - iterator(iterator const& other); - iterator& operator=(iterator const& other); + iterator(iterator const& other) = default; + iterator& operator=(iterator const& other) = default; iterator& operator++(); iterator operator++(int); @@ -29,30 +57,19 @@ struct imstring { // bidirectional iterator iterator& operator--(); iterator operator--(int); - }; -private: - struct buffer { - buffer(std::string const& value); + private: + bool to_next_value(); + void eval_end(); + std::shared_ptr root_; - buffer(std::shared_ptr left, std::shared_ptr right); + std::shared_ptr current_node_; + std::string::iterator current_pos_; + std::string::iterator end_pos_; - size_t size() const; - const char* c_str(); - char get_at(size_t ix); + std::stack> stack_; + }; // iterator - std::string::iterator begin(); - std::string::iterator end(); - - private: - void collapse(); - size_t add_primitive_buffers(std::vector>& buffers) const; - - bool is_concat; - std::string value_; - std::shared_ptr left_; - std::shared_ptr right_; - }; // buffer public: imstring(); imstring(const char*); @@ -69,6 +86,8 @@ struct imstring { std::string::iterator begin() const; std::string::iterator end() const; + iterator _begin() const; + iterator _end() const; private: std::shared_ptr shared_buffer_; diff --git a/practice/strings/main.cpp b/practice/strings/main.cpp index c04799b..369008e 100644 --- a/practice/strings/main.cpp +++ b/practice/strings/main.cpp @@ -18,6 +18,16 @@ void test_strings_equal(STR1& str1, STR2 &str2) assert(strcmp(str1.c_str(), str2.c_str()) == 0); } +void my_tests() { + std::string str("abc"); + + auto it = str.begin(); + ++it; + assert(*it == 'b'); + --it; + assert(*it == 'a'); +} + int main() { std::string str1("foo bar buzz"); @@ -46,5 +56,7 @@ int main() test_strings_equal(str_concat2, imstr_concat2); test_strings_equal(imstr_concat2, str_concat2); + my_tests(); + return 0; } From 66ec3cfccc6b37dc00807e81c27ca12e1b9cce8d Mon Sep 17 00:00:00 2001 From: Roenke Date: Mon, 25 Apr 2016 14:04:59 +0300 Subject: [PATCH 5/5] Add some changes to string practice. TODO: Complete it. --- practice/strings/imstring.cpp | 26 ++++++++++++++++++++++++-- practice/strings/imstring.h | 2 ++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/practice/strings/imstring.cpp b/practice/strings/imstring.cpp index d2bfa73..9ef1466 100644 --- a/practice/strings/imstring.cpp +++ b/practice/strings/imstring.cpp @@ -9,7 +9,13 @@ imstring::iterator::iterator(std::shared_ptr buffer) } imstring::iterator& imstring::iterator::operator++() { - + // TODO: implement +} + +imstring::iterator imstring::iterator::operator++(int) { + auto copy(*this); + this->operator++(); + return copy; } imstring::buffer::buffer(std::string const& value) @@ -24,7 +30,7 @@ imstring::buffer::buffer(std::shared_ptr left, std::shared_ptr r , value_("") , left_(left) , right_(right) -{} +{} size_t imstring::buffer::size() const { if(is_concat_) { @@ -104,6 +110,14 @@ size_t imstring::buffer::add_primitive_buffers(std::vectorvalue_.begin(); + current_end_ = current_node_->value_.end(); + return true; } + + // TODO: Complete method. } @@ -175,6 +193,10 @@ imstring::iterator imstring::_begin() const { return iterator(shared_buffer_); } +imstring::iterator imstring::_end() const { + return iterator(); +} + imstring operator+(imstring left, imstring const& right) { return left += right; } diff --git a/practice/strings/imstring.h b/practice/strings/imstring.h index 60db371..4fb1770 100644 --- a/practice/strings/imstring.h +++ b/practice/strings/imstring.h @@ -60,11 +60,13 @@ struct imstring { private: bool to_next_value(); + bool to_prev_value(); void eval_end(); std::shared_ptr root_; std::shared_ptr current_node_; std::string::iterator current_pos_; + std::string::iterator current_end_; std::string::iterator end_pos_; std::stack> stack_;