
#include <iostream>
using namespace std;

class Str
{

	char* s;

      public:
	Str() { s = nullptr; }
	~Str()
	{ // Destructor
		clear();
	}

	Str(const Str& str)
	{ // Copy constructor
		s = 0;
		assign(str.s);
	}

	Str(const char* other)
	{
		s = 0;
		assign(other);
	}

	Str(Str&& other) noexcept
	  : s(other.s)
	{
		other.s = nullptr;
	}

	Str& operator=(const char* str)
	{
		assign(str);
		return *this;
	}

	Str& operator=(const Str& str)
	{
		assign(str.s);
		return *this;
	}

	Str& operator=(Str&& str)
	{
		std::swap(s, str.s);
		return *this;
	}

	Str operator+(const Str& b)
	{
		Str res;
		if (!s || !b.s)
			return res;

		size_t buf = length() + b.length() + 1;
		res.s = new char[buf];

		char* o = res.s;
		if (s)
			for (char* i = s; *i; i++, o++) {
				*o = *i;
			}
		if (b.s)
			for (char* i = b.s; *i; i++, o++) {
				*o = *i;
			}

		*o = 0;

		return (res);
	}

	char& operator[](size_t index) { return s[index]; }

	const char& operator[](size_t index) const { return s[index]; }

	size_t length() const
	{
		size_t length = 0;
		if (!s)
			return 0;

		for (; s[length]; ++length)
			;

		return length;
	}

	void clear()
	{
		if (s)
			delete s;
		s = nullptr;
	}

	void assign(const char* text)
	{

		clear();
		if (!text) {
			return;
		}

		size_t length;

		for (length = 0; text[length]; ++length)
			;

		s = new char[length + 1]{ 0 };

		for (size_t i = 0; i < length; ++i)
			s[i] = text[i];
	}

	const char* buffer() const { return s; }

	class iterator
	{
		char* p;

	      public:
		iterator(const iterator& other)
		  : p(other.p)
		{}
		// iterator& operator=(const iterator& other) { p = other.p; }

		iterator(char* c)
		  : p(c)
		{}

		char& operator*() { return *p; }

		bool operator==(const iterator& other) { return p == other.p; }

		bool operator!=(const iterator& other) { return p != other.p; }
		iterator& operator++()
		{
			++p;
			if (!*p)
				p = nullptr;

			return *this;
		}
	};
	class const_iterator
	{
		char* p;

	      public:
		const_iterator(const const_iterator& other)
		  : p(other.p)
		{}
		// iterator& operator=(const const_iterator& other) { p =
		// other.p; }

		const_iterator(char* c)
		  : p(c)
		{}

		char operator*() { return *p; }

		bool operator==(const const_iterator& other)
		{
			return p == other.p;
		}

		bool operator!=(const const_iterator& other)
		{
			return p != other.p;
		}
		const_iterator& operator++()
		{
			++p;
			if (!*p)
				p = nullptr;

			return *this;
		}
	};

	const_iterator begin() const { return const_iterator(s); }

	const_iterator end() const { return const_iterator(nullptr); }

	iterator begin() { return iterator(s); }

	iterator end() { return iterator(nullptr); }
};

ostream&
operator<<(ostream& o, const Str& str)
{
	for (char i : str) {
		o << i;
	}
	return o;
}

int
main()
{
	Str a, b;
	a = "first";
	b = "second";
	cout << a << endl;
	cout << a + Str("asd") + Str("zxc") + b << endl;

	for (char& i : b) {
		++i;
	}
	for (char i : b) {
		cout << i << endl;
	}
}
