-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBlobPtr.h
More file actions
171 lines (157 loc) · 4.32 KB
/
BlobPtr.h
File metadata and controls
171 lines (157 loc) · 4.32 KB
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
#ifndef BLOBPTR_H
#define BLOBPTR_H
#include <vector>
#include <string>
#include <memory>
#include <cstddef>
#include <stdexcept>
#include <iostream>
template <typename T> class Blob;
template <typename T> class BlobPtr;
template <typename T> bool operator==(const BlobPtr<T> &, const BlobPtr<T> &);
template <typename T> bool operator<(const BlobPtr<T> &, const BlobPtr<T> &);
template <typename T> std::ptrdiff_t operator-(const BlobPtr<T> &, const BlobPtr<T> &);
template <typename T>
class BlobPtr {
friend bool operator==<T>(const BlobPtr<T> &, const BlobPtr<T> &);
friend bool operator< <T>(const BlobPtr<T> &, const BlobPtr<T> &);
friend std::ptrdiff_t operator-<T>(const BlobPtr<T> &, const BlobPtr<T> &);
public:
BlobPtr() noexcept;
BlobPtr(Blob<T> &, std::size_t = 0) noexcept;
T &operator*() const;
BlobPtr &operator+=(std::size_t);
BlobPtr &operator-=(std::size_t);
BlobPtr &operator++(); // prefix
BlobPtr &operator--();
BlobPtr operator++(int); // postfix
BlobPtr operator--(int);
private:
std::shared_ptr<std::vector<T>> check(std::size_t, const std::string &) const;
std::weak_ptr<std::vector<T>> wptr;
std::size_t curr;
};
template <typename T>
BlobPtr<T>::BlobPtr() noexcept
try : curr(0) {}
catch (const std::exception &err) {
std::cerr << err.what() << std::endl;
}
template <typename T>
BlobPtr<T>::BlobPtr(Blob<T> &a, std::size_t sz) noexcept
try : wptr(a.data), curr(sz) {}
catch (const std::exception &err) {
std::cerr << err.what() << std::endl;
}
// Dereference
template <typename T>
T &BlobPtr<T>::operator*() const {
std::shared_ptr<std::vector<T>> p = check(curr, "dereference past end");
return (*p)[curr];
}
// Compound addition assignment
template <typename T>
BlobPtr<T> &BlobPtr<T>::operator+=(std::size_t n) {
curr += n;
check(curr - 1, "increment past end of BlobPtr");
return *this;
}
// Compound subtraction assignment
template <typename T>
BlobPtr<T> &BlobPtr<T>::operator-=(std::size_t n) {
curr -= n;
check(curr, "decrement past beginning of BlobPtr");
return *this;
}
// Prefix increment
template <typename T>
BlobPtr<T> &BlobPtr<T>::operator++() {
check(curr, "increment past end of BlobPtr");
++curr;
return *this;
}
// Prefix decrement
template <typename T>
BlobPtr<T> &BlobPtr<T>::operator--() {
check(--curr, "decrement past beginning of BlobPtr");
return *this;
}
// Postfix increment
template <typename T>
BlobPtr<T> BlobPtr<T>::operator++(int) {
BlobPtr old = *this;
++*this;
return old;
}
// Postfix decrement
template <typename T>
BlobPtr<T> BlobPtr<T>::operator--(int) {
BlobPtr old = *this;
--*this;
return old;
}
template <typename T>
std::shared_ptr<std::vector<T>>
BlobPtr<T>::check(std::size_t i, const std::string &msg) const {
std::shared_ptr<std::vector<T>> ret = wptr.lock();
if (!ret)
throw std::runtime_error("unbound BlobPtr");
if (i >= ret->size())
throw std::out_of_range(msg);
return ret;
}
// Equality
template <typename T>
bool operator==(const BlobPtr<T> &lhs, const BlobPtr<T> &rhs) {
return (lhs.wptr.lock() == rhs.wptr.lock())
&& (lhs.curr == rhs.curr);
}
// Inequality
template <typename T>
bool operator!=(const BlobPtr<T> &lhs, const BlobPtr<T> &rhs) {
return !(lhs == rhs);
}
// Less-than
template <typename T>
bool operator<(const BlobPtr<T> &lhs, const BlobPtr<T> &rhs) {
if (lhs.wptr.lock() != rhs.wptr.lock())
throw std::runtime_error("comparing two BlobPtrs that don't point to the same object");
return lhs.curr < rhs.curr;
}
// Greater-than
template <typename T>
bool operator>(const BlobPtr<T> &lhs, const BlobPtr<T> &rhs) {
return rhs < lhs;
}
// Less-than or equal
template <typename T>
bool operator<=(const BlobPtr<T> &lhs, const BlobPtr<T> &rhs) {
return !(lhs > rhs);
}
// Greater-than or equal
template <typename T>
bool operator>=(const BlobPtr<T> &lhs, const BlobPtr<T> &rhs) {
return !(lhs < rhs);
}
// Addition
template <typename T>
BlobPtr<T> operator+(const BlobPtr<T> &p, std::size_t n) {
BlobPtr<T> ret = p;
ret += n;
return ret;
}
// Subtraction
template <typename T>
BlobPtr<T> operator-(const BlobPtr<T> &p, std::size_t n) {
BlobPtr<T> ret = p;
ret -= n;
return ret;
}
// Subtraction
template <typename T>
std::ptrdiff_t operator-(const BlobPtr<T> &lhs, const BlobPtr<T> &rhs) {
if (lhs.wptr.lock() != rhs.wptr.lock())
throw std::runtime_error("the two BlobPtrs don't point to the same object");
return lhs.curr - rhs.curr;
}
#endif