-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathStrBlob.h
169 lines (168 loc) · 4.49 KB
/
StrBlob.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
#ifndef STRBLOB_H
#define STRBLOB_H
#include <string>
#include <vector>
#include <initializer_list>
#include <memory>
#include <stdexcept>
class StrBlobPtr;
class ConstStrBlobPtr;
class StrBlob {
friend class StrBlobPtr;
friend class ConstStrBlobPtr;
public:
typedef std::vector<std::string>::size_type size_type;
StrBlob();
StrBlob(std::initializer_list<std::string> il);
size_type size() const { return data->size(); }
// add and remove elements
void push_back(const std::string &t) { data->push_back(t); }
void pop_back();
// elements access
std::string& front();
std::string& back();
// const versions of front and back required by exercise 12.2
const std::string& front() const;
const std::string& back() const;
// return reference count
size_type use_count() const { return data.use_count(); }
StrBlobPtr begin();
StrBlobPtr end();
ConstStrBlobPtr begin() const;
ConstStrBlobPtr end() const;
// access elements
std::string& at(size_type) const;
private:
std::shared_ptr<std::vector<std::string>> data;
// throws msg if data[i] isn't valid
void check(size_type i, const std::string &msg) const;
};
// constructor
StrBlob::StrBlob() : data(std::make_shared<std::vector<std::string>>()) {}
StrBlob::StrBlob(std::initializer_list<std::string> il) :
data(std::make_shared<std::vector<std::string>>(il)) {};
void StrBlob::check(size_type i, const std::string &msg) const
{
if(i >= data->size())
throw std::out_of_range(msg);
}
// add and remove elements
void StrBlob::pop_back()
{
check(0, "pop_back on empty StrBlob");
data->pop_back();
}
// elements access
std::string& StrBlob::front()
{
check(0, "front on empty StrBlob");
data->front();
}
std::string& StrBlob::back()
{
check(0, "back on empty StrBlob");
data->back();
}
const std::string& StrBlob::front() const
{
check(0, "front on empty StrBlob");
data->front();
}
const std::string& StrBlob::back() const
{
check(0, "back on empty StrBlob");
data->back();
}
std::string& StrBlob::at(size_type n) const
{
check(n, "index out of range");
return data->at(n);
}
// ******************************
// nonconst version of StrBlobPtr
// ******************************
class StrBlobPtr{
public:
StrBlobPtr() : curr(0) {}
StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) {}
std::string& deref() const;
StrBlobPtr& incr();
private:
std::shared_ptr<std::vector<std::string>> check(size_t, const std::string&) const;
std::weak_ptr<std::vector<std::string>> wptr; // const pointer
size_t curr;
};
std::shared_ptr<std::vector<std::string>> StrBlobPtr::check(size_t i, const std::string& msg) const
{
auto ret = wptr.lock();
if(!ret)
throw std::runtime_error("unbound StrBlobPtr");
if(i >= ret->size())
throw std::out_of_range(msg);
return ret;
}
std::string& StrBlobPtr::deref() const
{
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
StrBlobPtr& StrBlobPtr::incr()
{
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
// ***************************
// const version of StrBlobPtr
// ***************************
class ConstStrBlobPtr{
public:
ConstStrBlobPtr() : curr(0) {}
ConstStrBlobPtr(const StrBlob &a, size_t sz = 0) : wptr(a.data),curr(sz) {}
std::string& deref() const;
ConstStrBlobPtr& incr();
private:
std::shared_ptr<std::vector<std::string>> check(size_t, const std::string&) const;
std::weak_ptr<std::vector<std::string>> wptr;
size_t curr;
};
std::shared_ptr<std::vector<std::string>> ConstStrBlobPtr::check(size_t i, const std::string& msg) const
{
auto ret = wptr.lock();
if(!ret)
throw std::runtime_error("unbound StrBlobPtr");
if(i >= ret->size())
throw std::out_of_range(msg);
return ret;
}
std::string& ConstStrBlobPtr::deref() const
{
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
ConstStrBlobPtr& ConstStrBlobPtr::incr()
{
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
// we have to define these member functions here, after the definition of StrBlobPtr
StrBlobPtr StrBlob::begin()
{
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end()
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
ConstStrBlobPtr StrBlob::begin() const
{
return ConstStrBlobPtr(*this);
}
ConstStrBlobPtr StrBlob::end() const
{
auto ret = ConstStrBlobPtr(*this, data->size());
return ret;
}
#endif