Skip to content

Instantly share code, notes, and snippets.

@VTroyanGolovyan
Created March 16, 2022 09:25
Show Gist options
  • Save VTroyanGolovyan/84a1deb7229858d5d96bf9d4cbde0ec1 to your computer and use it in GitHub Desktop.
Save VTroyanGolovyan/84a1deb7229858d5d96bf9d4cbde0ec1 to your computer and use it in GitHub Desktop.
COW
cmake_minimum_required(VERSION 3.21)
project(COWS)
set(CMAKE_CXX_STANDARD 20)
add_executable(COWS main.cpp COWString.cpp StringImpl.cpp)
//
// Created by Владислав on 09.03.2022.
//
#include "COWString.h"
CowString::CowString(const std::string_view& s)
: control_block_(new StringImpl(s)){
}
CowString::CowString(const CowString& other) {
control_block_ = other.control_block_;
control_block_->IncRefs();
}
CowString::CowString(CowString&& other) noexcept {
control_block_ = other.control_block_;
other.control_block_ = new StringImpl("");
}
CowString& CowString::operator=(const CowString& other) {
if (this != std::addressof(other)) {
if (control_block_ != nullptr && control_block_->Refs() == 1) {
delete control_block_;
} else if (control_block_ != nullptr) {
control_block_->DecRefs();
}
control_block_ = other.control_block_;
control_block_->IncRefs();
}
return *this;
}
CowString& CowString::operator=(CowString&& other) noexcept {
if (this != std::addressof(other)) {
control_block_ = other.control_block_;
other.control_block_ = new StringImpl("");;
}
return *this;
}
char CowString::At(size_t i) const {
return control_block_->At(i);
}
char const* CowString::GetData() const {
return control_block_->GetData();
}
CowString::CharReference CowString::operator[](size_t index) {
return {this, index};
}
char CowString::operator[](size_t index) const {
return control_block_->At(index);
}
CowString& CowString::operator+=(const CowString& other) {
CopyOnWrite();
*control_block_ += std::string_view(other);
return *this;
}
CowString& CowString::operator+=(const std::string_view& other) {
CopyOnWrite();
*control_block_ += std::string_view(other);
return *this;
}
CowString CowString::operator+(const CowString& other) const {
auto temp = *this;
temp += other;
return temp;
}
CowString CowString::operator+(const std::string_view& other) const {
auto temp = *this;
temp += other;
return temp;
}
bool CowString::operator==(const CowString& other) const {
return *control_block_ == *other.control_block_;
}
bool CowString::operator==(const std::string_view& other) const {
return *control_block_ == other;
}
bool CowString::operator!=(const CowString& other) const {
return *control_block_ != *other.control_block_;
}
bool CowString::operator!=(const std::string_view& other) const {
return *control_block_ != other;
}
CowString::operator std::string_view() const {
return std::string_view(*control_block_);
}
CowString::~CowString() {
if (control_block_ != nullptr && control_block_->Refs() == 1) {
delete control_block_;
} else if (control_block_ != nullptr){
control_block_->DecRefs();
}
}
void CowString::CopyOnWrite() {
if (control_block_->Refs() > 1) {
control_block_->DecRefs();
control_block_ = new StringImpl(*control_block_);
}
}
CowString::CharReference::CharReference(
CowString* owner,
size_t index
) : owner_(owner), index_(index) {}
CowString::CharReference& CowString::CharReference::operator=(const char& other) {
if ((*owner_->control_block_)[index_] == other) {
return *this;
}
owner_->CopyOnWrite();
(*owner_->control_block_)[index_] = other;
return *this;
}
CowString::CharReference::operator char() {
return (*owner_->control_block_)[index_];
}
#pragma once
#include <string_view>
#include "StringImpl.h"
class CowString {
public:
class CharReference {
public:
CharReference(
CowString* owner,
size_t index
);
CharReference& operator=(const char& other);
operator char();
private:
CowString* owner_;
size_t index_;
};
template<bool IsConst>
class Iterator {
public:
using reference_type = std::conditional_t<IsConst, char, CharReference>;
using owner_ptr_type = std::conditional_t<IsConst, const CowString*, CowString*>;
Iterator(owner_ptr_type owner, size_t index) : str_(owner), index_(index) {}
Iterator<IsConst>& operator++() {
++index_;
return *this;
}
Iterator<IsConst> operator++(int) {
auto cpy = *this;
++index_;
return cpy;
}
Iterator<IsConst>& operator--() {
--index_;
return *this;
}
Iterator<IsConst> operator--(int) {
auto cpy = *this;
--index_;
return cpy;
}
reference_type operator[](size_t i) {
return CharReference(const_cast<CowString*>(str_), index_ + i);
}
reference_type operator*() {
return CharReference(const_cast<CowString*>(str_), index_);
}
reference_type operator[](size_t i) const {
return str_->At(index_ + i);
}
reference_type operator*() const {
return str_->At(index_);
}
bool operator==(const Iterator<IsConst>& other) const {
return index_ == other.index_;
}
bool operator!=(const Iterator<IsConst>& other) const {
return index_ != other.index_;
}
private:
size_t index_;
owner_ptr_type str_;
};
typedef Iterator<false> iterator;
typedef Iterator<true> const_iterator;
iterator begin() {
return {this, 0};
}
iterator end() {
return {this, control_block_->Size()};
}
const_iterator begin() const {
return {this, 0};
}
const_iterator end() const {
return {this, control_block_->Size()};
}
friend class CharReference;
CowString(const std::string_view& s);
CowString(const CowString& other);
CowString(CowString&& other) noexcept;
CowString& operator=(const CowString& other);
CowString& operator=(CowString&& other) noexcept;
char const* GetData() const;
char At(size_t i) const;
CharReference operator[](size_t index);
char operator[](size_t index) const;
CowString& operator+=(const CowString& other);
CowString& operator+=(const std::string_view& other);
CowString operator+(const CowString& other) const;
CowString operator+(const std::string_view& other) const;
bool operator==(const CowString& other) const;
bool operator==(const std::string_view& other) const;
bool operator!=(const CowString& other) const;
bool operator!=(const std::string_view& other) const;
explicit operator std::string_view() const;
~CowString();
private:
void CopyOnWrite();
StringImpl* control_block_;
};
#include <iostream>
#include "COWString.h"
int main() {
const CowString str1("hello");
CowString str2 = str1;
assert(str1.GetData() == str2.GetData());
str2[0] = 'h';
assert(str1.GetData() == str2.GetData());
str2 += " world";
assert(str1.GetData() != str2.GetData());
for (const auto ch : str1) {
assert(std::isalpha(ch));
}
const auto* const str2_data = str2.GetData();
str2[5] = '_';
assert("hello_world" == str2);
assert(str2 == "hello_world");
assert(str2_data == str2.GetData());
str2 = str1;
assert("hello" == str2);
assert(str1.GetData() == str2.GetData());
const CowString& const_str2 = str2;
assert('e' == const_str2.At(1));
auto it1 = str1.begin();
auto it2 = str2.begin();
auto const_it2 = const_str2.begin();
*it2 = 'H';
assert("Hello" == str2);
assert("Hello" != str1);
assert('h' == *it1);
assert('H' == *it2);
assert('H' == *const_it2);
return 0;
}
//
// Created by Владислав on 09.03.2022.
//
#include "StringImpl.h"
//
// Created by Владислав on 09.03.2022.
//
#ifndef COWS_STRINGIMPL_H
#define COWS_STRINGIMPL_H
#include <string>
#include <string_view>
class StringImpl {
public:
StringImpl(const std::string_view& data) : data_(data), ref_count_(1) {
}
StringImpl(const StringImpl& other) : data_(other.data_), ref_count_(1) {
}
StringImpl(StringImpl&& other) {
}
StringImpl& operator=(const StringImpl& other) {
data_ = other.data_;
ref_count_ = 1;
return *this;
}
void IncRefs() {
++ref_count_;
}
size_t Size() {
return data_.size();
}
void DecRefs() {
--ref_count_;
}
size_t Refs() {
return ref_count_;
}
char const* GetData() {
return data_.data();
}
bool operator==(const std::string_view& other) const {
return data_ == other;
}
bool operator!=(const std::string_view& other) const {
return data_ != other;
}
StringImpl& operator += (const std::string_view& other) {
data_ += other;
return *this;
}
char& operator[](size_t index) {
return data_[index];
}
operator std::string_view() {
return data_;
}
char At(size_t i) {
return data_[i];
}
private:
std::string data_;
size_t ref_count_;
};
#endif //COWS_STRINGIMPL_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment