-
Notifications
You must be signed in to change notification settings - Fork 246
/
String.cpp
114 lines (98 loc) · 3.05 KB
/
String.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <iostream>
#include "String.h"
std::allocator<char> String::alloc;
String::String(const_iterator ci) : String() {
std::cout << "String::String(const_iterator ci)" << std::endl;
while (ci && *ci != '\0')
push_back(*ci++);
}
String::String(std::initializer_list<char> il) : String() {
for (const auto &c : il)
push_back(c);
}
void String::push_back(const_reference c) {
if (size() == capacity())
reallocate(empty() ? 1 : 2 * capacity());
alloc.construct(first_free++, c);
}
void String::pop_back() {
if (!empty())
alloc.destroy(--first_free);
}
void String::reserve(size_type n) {
if (n > capacity()) {
reallocate(n);
}
}
void String::resize(size_type n, const_reference c) {
if (n > size()) {
for (int i = n - size(); i > 0; --i)
push_back(c);
} else if (n < size()) {
for (int i = size() - n; i > 0; --i)
pop_back();
}
}
void String::reallocate(size_type n) {
auto new_first_elem = alloc.allocate(n);
auto new_first_free = new_first_elem;
for (auto it = begin(); it != end(); ++it)
alloc.construct(new_first_free++, std::move(*it));
// the above three lines of code can be replaced by the following code:
//auto new_first_free = std::uninitialized_copy(
// std::make_move_iterator(begin()),
// std::make_move_iterator(end()), new_first_elem);
free();
first_elem = new_first_elem;
first_free = new_first_free;
cap = first_elem + n;
}
void String::free() {
while (!empty())
alloc.destroy(--first_free);
alloc.deallocate(first_elem, capacity());
first_elem = first_free = cap = nullptr;
}
String::~String() {
free();
}
String::String(const String &rhs) {
std::cout << "String::String(const String &rhs)" << std::endl;
first_elem = alloc.allocate(rhs.size());
first_free = cap = std::uninitialized_copy(rhs.begin(), rhs.end(),
first_elem);
}
String &String::operator=(const String &rhs) {
std::cout << "String &String::operator=(const String &rhs)" << std::endl;
auto new_first_elem = alloc.allocate(rhs.size());
auto new_first_free = std::uninitialized_copy(rhs.begin(), rhs.end(),
new_first_elem);
free();
first_elem = new_first_elem;
first_free = cap = new_first_free;
return *this;
}
String::String(String &&rhs) noexcept
: first_elem(rhs.first_elem), first_free(rhs.first_free), cap(rhs.cap) {
std::cout << "String::String(String &&rhs)" << std::endl;
rhs.first_elem = rhs.first_free = rhs.cap = nullptr;
}
String &String::operator=(String &&rhs) noexcept {
std::cout << "String &String::operator=(String &&rhs)" << std::endl;
if (this != &rhs) {
free();
first_elem = rhs.first_elem;
first_free = rhs.first_free;
cap = rhs.cap;
rhs.first_elem = rhs.first_free = rhs.cap = nullptr;
}
return *this;
}
String &String::operator=(const_iterator ci) {
std::cout << "String &String::operator=(const_iterator ci)" << std::endl;
*this = String(ci);
return *this;
}
std::string String::str() const {
return std::string(cbegin(), cend());
}