This repository was archived by the owner on Apr 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathex14_27_StrBlob_StrBlobPtr.h
193 lines (151 loc) · 4.7 KB
/
ex14_27_StrBlob_StrBlobPtr.h
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#ifndef STRBLOB_STRBLOBPTR
#define STRBLOB_STRBLOBPTR
#include "headers.h"
class StrBlobPtr;
class StrBlob {
friend class StrBlobPtr;
friend bool operator==(const StrBlob &lhs, const StrBlob &rhs);
friend bool operator!=(const StrBlob &lhs, const StrBlob &rhs);
public:
using size_type = vector<string>::size_type;
StrBlob();
StrBlob(initializer_list<string> il);
StrBlob(const StrBlob &from) : data(make_shared<vector<string>>(*(from.data))) {}
StrBlob &operator=(const StrBlob &rhs) {
data = make_shared<vector<string>>(*(rhs.data));
return *this;
}
size_type size() { return data->size(); }
bool empty() { return data->empty(); }
void push_back(const string &s) { data->push_back(s); }
string &front();
const string &front() const;
string &back();
const string &back() const;
StrBlobPtr begin();
StrBlobPtr end();
string &operator[](const size_t idx);
const string &operator[](const size_t idx) const;
private:
shared_ptr<vector<string>> data;
void check(size_type i, const string &msg) const;
};
StrBlob::StrBlob() : data(make_shared<vector<string>>()) {}
StrBlob::StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {}
void StrBlob::check(StrBlob::size_type i, const string &msg) const {
if (i >= data->size()) {
throw out_of_range(msg);
}
}
string &StrBlob::front() {
check(0, "front at empty StrBlob");
return data->front();
}
const string &StrBlob::front() const {
check(0, "front at empty StrBlob");
return data->front();
}
string &StrBlob::back() {
check(0, "back at empty StrBlob");
return data->back();
}
const string &StrBlob::back() const {
check(0, "back at empty StrBlob");
return data->back();
}
string &StrBlob::operator[](const size_t idx) {
return data->at[idx];
}
const string &StrBlob::operator[](const size_t idx) const {
return data->at[idx];
}
bool operator==(const StrBlob &lhs, const StrBlob &rhs) {
return *lhs.data == *rhs.data;
}
bool operator!=(const StrBlob &lhs, const StrBlob &rhs) {
return !(lhs == rhs);
}
class StrBlobPtr {
friend bool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs);
friend bool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs);
public:
StrBlobPtr() : curr(0) {}
StrBlobPtr(StrBlob &sb, size_t init_idx = 0) : wptr(sb.data), curr(init_idx) {}
string &deref();
StrBlobPtr &incre();
string &operator[](size_t n);
const string &operator[](size_t n) const;
StrBlobPtr &operator++();
StrBlobPtr &operator--();
StrBlobPtr operator++(int dummy);
StrBlobPtr operator--(int dummy);
private:
shared_ptr<vector<string>> check(size_t i, const string &msg) const;
weak_ptr<vector<string>> wptr;
size_t curr;
};
string &StrBlobPtr::deref() {
auto p = check(curr, "dereference past the end");
return (*p)[curr];
}
StrBlobPtr &StrBlobPtr::incre() {
check(curr, "increment past end of StrBlob");
++curr;
return *this;
}
StrBlobPtr StrBlob::begin() {
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end() {
return StrBlobPtr(*this, data->size());
}
string &StrBlobPtr::operator[](size_t n) { // same as deref()
auto p = check(n, "dereference out of range.");
return (*p)[n];
}
const string &StrBlobPtr::operator[](size_t n) const { // same as deref()
auto p = check(n, "dereference out of range.");
return (*p)[n];
}
StrBlobPtr &StrBlobPtr::operator++(){
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
StrBlobPtr &StrBlobPtr::operator--(){
curr--;
check(curr, "decrement past begin of StrBlobPtr");
return *this;
}
StrBlobPtr StrBlobPtr::operator++(int dummy){
auto ret = *this;
// auto ret = *this; works here because synthesized copy constructor is used and
// a distinct new copy is made from *this.
++*this;
return ret;
}
StrBlobPtr StrBlobPtr::operator--(int dummy){
auto ret = *this;
--*this;
return ret;
}
shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg) const {
auto sp = wptr.lock();
if (!sp) {
throw runtime_error("Memory already freed!");
}
if (i >= sp->size()) {
throw out_of_range(msg);
}
return sp;
}
bool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs) {
// Referr to the same element in the same vector
return *(lhs.wptr.lock()) == *(rhs.wptr.lock()) && lhs.curr == rhs.curr;
}
bool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs) {
return !(lhs == rhs);
}
// Exercise 14.19: Should not define operator< for StrBlobPtr.
// If indeed have to, should only for StrBlobPtr pointing to the same StrBlob object
#endif