clover/util: Null-terminate the result of compat::string::c_str().
[mesa.git] / src / gallium / state_trackers / clover / util / compat.hpp
1 //
2 // Copyright 2012 Francisco Jerez
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22
23 #ifndef CLOVER_UTIL_COMPAT_HPP
24 #define CLOVER_UTIL_COMPAT_HPP
25
26 #include <new>
27 #include <cstring>
28 #include <cstdlib>
29 #include <string>
30 #include <stdint.h>
31
32 namespace clover {
33 namespace compat {
34 // XXX - For cases where we can't rely on STL... I.e. the
35 // interface between code compiled as C++98 and C++11
36 // source. Get rid of this as soon as everything can be
37 // compiled as C++11.
38
39 template<typename T>
40 class vector {
41 protected:
42 static T *
43 alloc(int n, const T *q, int m) {
44 T *p = reinterpret_cast<T *>(std::malloc(n * sizeof(T)));
45
46 for (int i = 0; i < m; ++i)
47 new(&p[i]) T(q[i]);
48
49 return p;
50 }
51
52 static void
53 free(int n, T *p) {
54 for (int i = 0; i < n; ++i)
55 p[i].~T();
56
57 std::free(p);
58 }
59
60 public:
61 typedef T *iterator;
62 typedef const T *const_iterator;
63 typedef T value_type;
64 typedef T &reference;
65 typedef const T &const_reference;
66 typedef std::ptrdiff_t difference_type;
67 typedef std::size_t size_type;
68
69 vector() : p(NULL), _size(0), _capacity(0) {
70 }
71
72 vector(const vector &v) :
73 p(alloc(v._size, v.p, v._size)),
74 _size(v._size), _capacity(v._size) {
75 }
76
77 vector(const_iterator p, size_type n) :
78 p(alloc(n, p, n)), _size(n), _capacity(n) {
79 }
80
81 template<typename C>
82 vector(const C &v) :
83 p(alloc(v.size(), &*v.begin(), v.size())),
84 _size(v.size()) , _capacity(v.size()) {
85 }
86
87 ~vector() {
88 free(_size, p);
89 }
90
91 vector &
92 operator=(const vector &v) {
93 free(_size, p);
94
95 p = alloc(v._size, v.p, v._size);
96 _size = v._size;
97 _capacity = v._size;
98
99 return *this;
100 }
101
102 void
103 reserve(size_type n) {
104 if (_capacity < n) {
105 T *q = alloc(n, p, _size);
106 free(_size, p);
107
108 p = q;
109 _capacity = n;
110 }
111 }
112
113 void
114 resize(size_type n, T x = T()) {
115 if (n <= _size) {
116 for (size_type i = n; i < _size; ++i)
117 p[i].~T();
118
119 } else {
120 reserve(n);
121
122 for (size_type i = _size; i < n; ++i)
123 new(&p[i]) T(x);
124 }
125
126 _size = n;
127 }
128
129 void
130 push_back(const T &x) {
131 reserve(_size + 1);
132 new(&p[_size]) T(x);
133 ++_size;
134 }
135
136 size_type
137 size() const {
138 return _size;
139 }
140
141 size_type
142 capacity() const {
143 return _capacity;
144 }
145
146 iterator
147 begin() {
148 return p;
149 }
150
151 const_iterator
152 begin() const {
153 return p;
154 }
155
156 iterator
157 end() {
158 return p + _size;
159 }
160
161 const_iterator
162 end() const {
163 return p + _size;
164 }
165
166 reference
167 operator[](size_type i) {
168 return p[i];
169 }
170
171 const_reference
172 operator[](size_type i) const {
173 return p[i];
174 }
175
176 private:
177 iterator p;
178 size_type _size;
179 size_type _capacity;
180 };
181
182 template<typename T>
183 class vector_ref {
184 public:
185 typedef T *iterator;
186 typedef const T *const_iterator;
187 typedef T value_type;
188 typedef T &reference;
189 typedef const T &const_reference;
190 typedef std::ptrdiff_t difference_type;
191 typedef std::size_t size_type;
192
193 vector_ref(iterator p, size_type n) : p(p), n(n) {
194 }
195
196 template<typename C>
197 vector_ref(C &v) : p(&*v.begin()), n(v.size()) {
198 }
199
200 size_type
201 size() const {
202 return n;
203 }
204
205 iterator
206 begin() {
207 return p;
208 }
209
210 const_iterator
211 begin() const {
212 return p;
213 }
214
215 iterator
216 end() {
217 return p + n;
218 }
219
220 const_iterator
221 end() const {
222 return p + n;
223 }
224
225 reference
226 operator[](int i) {
227 return p[i];
228 }
229
230 const_reference
231 operator[](int i) const {
232 return p[i];
233 }
234
235 private:
236 iterator p;
237 size_type n;
238 };
239
240 class istream {
241 public:
242 typedef vector_ref<const unsigned char> buffer_t;
243
244 class error {
245 public:
246 virtual ~error() {}
247 };
248
249 istream(const buffer_t &buf) : buf(buf), offset(0) {}
250
251 void
252 read(char *p, size_t n) {
253 if (offset + n > buf.size())
254 throw error();
255
256 std::memcpy(p, buf.begin() + offset, n);
257 offset += n;
258 }
259
260 private:
261 const buffer_t &buf;
262 size_t offset;
263 };
264
265 class ostream {
266 public:
267 typedef vector<unsigned char> buffer_t;
268
269 ostream(buffer_t &buf) : buf(buf), offset(buf.size()) {}
270
271 void
272 write(const char *p, size_t n) {
273 buf.resize(offset + n);
274 std::memcpy(buf.begin() + offset, p, n);
275 offset += n;
276 }
277
278 private:
279 buffer_t &buf;
280 size_t offset;
281 };
282
283 class string {
284 public:
285 typedef char *iterator;
286 typedef const char *const_iterator;
287 typedef char value_type;
288 typedef char &reference;
289 typedef const char &const_reference;
290 typedef std::ptrdiff_t difference_type;
291 typedef std::size_t size_type;
292
293 string() : v() {
294 }
295
296 string(const char *p) : v(p, std::strlen(p)) {
297 }
298
299 template<typename C>
300 string(const C &v) : v(v) {
301 }
302
303 operator std::string() const {
304 return std::string(v.begin(), v.end());
305 }
306
307 void
308 reserve(size_type n) {
309 v.reserve(n);
310 }
311
312 void
313 resize(size_type n, char x = char()) {
314 v.resize(n, x);
315 }
316
317 void
318 push_back(char x) {
319 v.push_back(x);
320 }
321
322 size_type
323 size() const {
324 return v.size();
325 }
326
327 size_type
328 capacity() const {
329 return v.capacity();
330 }
331
332 iterator
333 begin() {
334 return v.begin();
335 }
336
337 const_iterator
338 begin() const {
339 return v.begin();
340 }
341
342 iterator
343 end() {
344 return v.end();
345 }
346
347 const_iterator
348 end() const {
349 return v.end();
350 }
351
352 reference
353 operator[](size_type i) {
354 return v[i];
355 }
356
357 const_reference
358 operator[](size_type i) const {
359 return v[i];
360 }
361
362 const char *
363 c_str() const {
364 v.reserve(size() + 1);
365 *v.end() = 0;
366 return v.begin();
367 }
368
369 const char *
370 find(const string &s) const {
371 for (size_t i = 0; i + s.size() < size(); ++i) {
372 if (!std::memcmp(begin() + i, s.begin(), s.size()))
373 return begin() + i;
374 }
375
376 return end();
377 }
378
379 private:
380 mutable vector<char> v;
381 };
382
383 template<typename T>
384 bool
385 operator==(const vector_ref<T> &a, const vector_ref<T> &b) {
386 if (a.size() != b.size())
387 return false;
388
389 for (size_t i = 0; i < a.size(); ++i)
390 if (a[i] != b[i])
391 return false;
392
393 return true;
394 }
395
396 class exception {
397 public:
398 exception() {}
399 virtual ~exception();
400
401 virtual const char *what() const;
402 };
403
404 class runtime_error : public exception {
405 public:
406 runtime_error(const string &what) : _what(what) {}
407
408 virtual const char *what() const;
409
410 protected:
411 string _what;
412 };
413 }
414 }
415
416 #endif