ScummVM API documentation
span.h
1/* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#ifndef COMMON_SPAN_H
23#define COMMON_SPAN_H
24
25#include "common/file.h"
26#include "common/memstream.h"
27#include "common/safe-bool.h"
28#include "common/scummsys.h"
29#include "common/type_traits.h"
30
31namespace Common {
32
33#define COMMON_SPAN_TYPEDEFS \
34 typedef typename super_type::value_type value_type; \
35 typedef typename super_type::difference_type difference_type; \
36 typedef typename super_type::index_type index_type; \
37 typedef typename super_type::size_type size_type; \
38 typedef typename super_type::const_iterator const_iterator; \
39 typedef typename super_type::iterator iterator; \
40 typedef typename super_type::pointer pointer; \
41 typedef typename super_type::const_pointer const_pointer; \
42 typedef typename super_type::reference reference; \
43 typedef typename super_type::const_reference const_reference
44
45enum : uint {
46 kSpanMaxSize = 0xFFFFFFFF,
47 kSpanKeepOffset = 0xFFFFFFFF
48};
49
50#pragma mark -
51#pragma mark SpanValidationMode
52
53enum SpanValidationMode {
54 kValidateRead,
55 kValidateWrite,
56 kValidateSeek
57};
58
59namespace SpanInternal {
60#pragma mark -
61#pragma mark SpanIterator
65 template <typename Span, bool IsConst>
67 typedef typename Span::value_type span_value_type;
69
70 public:
71 typedef typename Span::difference_type difference_type;
72 typedef typename remove_const<span_value_type>::type value_type;
75
76 inline SpanIterator() : _span(nullptr), _index(0) {}
77
78 inline SpanIterator(span_type *const span, const difference_type index) :
79 _span(span),
80 _index(index) {
81 if (span != nullptr) {
82 span->validate(index, 0, kValidateSeek);
83 }
84 }
85
86 inline SpanIterator(const SpanIterator &other) :
87 _span(other._span),
88 _index(other._index) {}
89
90 inline SpanIterator &operator=(const SpanIterator &other) {
91 _span = other._span;
92 _index = other._index;
93 return *this;
94 }
95
96#pragma mark -
97#pragma mark SpanIterator - Dereferencing operations
98
99 public:
100 inline reference operator*() const {
101 // validation is in Span::operator[]
102 return (*_span)[_index];
103 }
104
105 inline pointer operator->() const {
106 return &operator*();
107 }
108
109 inline reference operator[](const difference_type index) const {
110 // validation is in SpanIterator::operator+=
111 return *(*this + index);
112 }
113
114#pragma mark -
115#pragma mark SpanIterator - Arithmetic operations
116
117 public:
118 inline SpanIterator &operator+=(const difference_type delta) {
119 assert(_span != nullptr);
120 _span->validate(_index, delta, kValidateSeek);
121 _index += delta;
122 return *this;
123 }
124
125 inline SpanIterator &operator-=(const difference_type delta) {
126 return operator+=(-delta);
127 }
128
129 inline SpanIterator &operator++() {
130 return operator+=(1);
131 }
132
133 inline SpanIterator operator++(int) {
134 SpanIterator old(*this);
135 operator+=(1);
136 return old;
137 }
138
139 inline SpanIterator &operator--() {
140 return operator+=(-1);
141 }
142
143 inline SpanIterator operator--(int) {
144 SpanIterator old(*this);
145 operator+=(-1);
146 return old;
147 }
148
149 inline SpanIterator operator+(const difference_type delta) const {
150 SpanIterator it(*this);
151 return it += delta;
152 }
153
154 inline SpanIterator operator-(const difference_type delta) const {
155 return operator+(-delta);
156 }
157
158 inline difference_type operator-(const SpanIterator &other) const {
159 assert(_span == other._span);
160 return _index - other._index;
161 }
162
163#pragma mark -
164#pragma mark SpanIterator - Comparison operations
165
166 public:
167 inline bool operator==(const SpanIterator& other) const {
168 return _span == other._span && _index == other._index;
169 }
170
171 inline bool operator!=(const SpanIterator& other) const {
172 return !operator==(other);
173 }
174
175 inline bool operator<(const SpanIterator& other) const {
176 assert(_span == other._span);
177 return _index < other._index;
178 }
179
180 inline bool operator<=(const SpanIterator& other) const {
181 return !other.operator<(*this);
182 }
183
184 inline bool operator>(const SpanIterator& other) const {
185 return other.operator<(*this);
186 }
187
188 inline bool operator>=(const SpanIterator& other) const {
189 return !operator<(other);
190 }
191
192#pragma mark -
193#pragma mark SpanIterator - Data access convenience functions
194
195 public:
196 inline int8 getInt8() const {
197 return _span->getInt8At(_index);
198 }
199
200 inline uint8 getUint8() const {
201 return _span->getUint8At(_index);
202 }
203
204 inline int16 getInt16BE() const {
205 return _span->getInt16BEAt(_index);
206 }
207
208 inline int16 getInt16LE() const {
209 return _span->getInt16LEAt(_index);
210 }
211
212 inline uint16 getUint16BE() const {
213 return _span->getUint16BEAt(_index);
214 }
215
216 inline uint16 getUint16LE() const {
217 return _span->getUint16LEAt(_index);
218 }
219
220 inline uint32 getUint24LE() const {
221 return _span->getUint24LEAt(_index);
222 }
223
224 inline uint32 getUint32() const {
225 return _span->getUint32At(_index);
226 }
227
228 inline int32 getInt32BE() const {
229 return _span->getInt32BEAt(_index);
230 }
231
232 inline int32 getInt32LE() const {
233 return _span->getInt32LEAt(_index);
234 }
235
236 inline uint32 getUint32BE() const {
237 return _span->getUint32BEAt(_index);
238 }
239
240 inline uint32 getUint32LE() const {
241 return _span->getUint32LEAt(_index);
242 }
243
244 protected:
245 span_type *_span;
246 difference_type _index;
247 };
248} // End of namespace SpanInternal
249
250#pragma mark -
251#pragma mark SpanBase
252
253template <typename ValueType, template <typename> class Derived>
254class SpanBase : public SafeBool<Derived<ValueType> > {
255 typedef Derived<ValueType> derived_type;
256 typedef typename add_const<derived_type>::type const_derived_type;
257 typedef typename remove_const<derived_type>::type mutable_derived_type;
258
259 template <typename T, bool U> friend class SpanInternal::SpanIterator;
260 template <typename T, template <typename> class U> friend class SpanBase;
261 template <typename T, typename U> friend struct SafeBool;
262#ifdef CXXTEST_RUNNING
263 friend class ::SpanTestSuite;
264#endif
265
266public:
267 typedef ValueType value_type;
268 typedef int32 difference_type;
269 typedef uint32 index_type;
270 typedef uint32 size_type;
273 typedef value_type *pointer;
274 typedef const value_type *const_pointer;
275 typedef value_type &reference;
276 typedef const value_type &const_reference;
277
278 inline size_type byteSize() const { return impl().size() * sizeof(value_type); }
279
280#if !defined(_MSC_VER)
281protected:
282#endif
283 inline SpanBase() {}
284 inline SpanBase(const SpanBase &) {}
285 inline SpanBase &operator=(const SpanBase &) { return this->impl(); }
286 inline ~SpanBase() {}
287
288 inline const_derived_type &impl() const { return static_cast<const_derived_type &>(*this); }
289 inline mutable_derived_type &impl() { return static_cast<mutable_derived_type &>(*this); }
290
291#pragma mark -
292#pragma mark SpanBase - Interface
293
294#if !defined(_MSC_VER)
295protected:
296#endif
297 inline void clear();
298
299 inline size_type size() const;
300
301 inline const_iterator cbegin() const;
302 inline const_iterator cend() const;
303 inline const_iterator begin() const;
304 inline const_iterator end() const;
305 inline iterator begin();
306 inline iterator end();
307
308 inline pointer data() const;
309
310#pragma mark -
311#pragma mark SpanBase - Data access functions
312
313public:
314 inline const_reference operator[](const index_type index) const {
315 impl().validate(index, sizeof(value_type));
316 return impl().data()[index];
317 }
318
319 inline reference operator[](const index_type index) {
320 impl().validate(index, sizeof(value_type));
321 return impl().data()[index];
322 }
323
324 inline int8 getInt8At(const index_type index) const {
325 static_assert(sizeof(value_type) == sizeof(uint8), "int8 can only be read from byte or char spans");
326 return (int8)getUint8At(index);
327 }
328
329 inline uint8 getUint8At(const index_type index) const {
330 static_assert(sizeof(value_type) == sizeof(uint8), "uint8 can only be read from byte or char spans");
331 impl().validate(index, sizeof(uint8));
332 return (uint8)impl().data()[index];
333 }
334
335 inline int16 getInt16BEAt(const index_type index) const {
336 static_assert(sizeof(value_type) <= sizeof(uint16), "int16 can only be read from int16 or smaller spans");
337 return (int16)impl().getUint16BEAt(index);
338 }
339
340 inline int16 getInt16LEAt(const index_type index) const {
341 static_assert(sizeof(value_type) <= sizeof(uint16), "int16 can only be read from int16 or smaller spans");
342 return (int16)impl().getUint16LEAt(index);
343 }
344
345 inline uint16 getUint16BEAt(const index_type index) const {
346 static_assert(sizeof(value_type) <= sizeof(uint16), "uint16 can only be read from int16 or smaller spans");
347 impl().validate(index, sizeof(uint16));
348 return READ_BE_UINT16(impl().data() + index);
349 }
350
351 inline uint16 getUint16LEAt(const index_type index) const {
352 static_assert(sizeof(value_type) <= sizeof(uint16), "uint16 can only be read from int16 or smaller spans");
353 impl().validate(index, sizeof(uint16));
354 return READ_LE_UINT16(impl().data() + index);
355 }
356
357 inline uint32 getUint24LEAt(const index_type index) const {
358 static_assert(sizeof(value_type) <= 3, "uint24 can only be read from int24 or smaller spans");
359 impl().validate(index, 3);
360 return READ_LE_UINT24(impl().data() + index);
361 }
362
363 inline uint32 getUint32At(const index_type index) const {
364 static_assert(sizeof(value_type) <= sizeof(uint32), "uint32 can only be read from int32 or smaller spans");
365 impl().validate(index, sizeof(uint32));
366 return READ_UINT32(impl().data() + index);
367 }
368
369 inline int32 getInt32BEAt(const index_type index) const {
370 static_assert(sizeof(value_type) <= sizeof(uint32), "int32 can only be read from int32 or smaller spans");
371 return (int32)impl().getUint32BEAt(index);
372 }
373
374 inline int32 getInt32LEAt(const index_type index) const {
375 static_assert(sizeof(value_type) <= sizeof(uint32), "int32 can only be read from int32 or smaller spans");
376 return (int32)impl().getUint32LEAt(index);
377 }
378
379 inline uint32 getUint32BEAt(const index_type index) const {
380 static_assert(sizeof(value_type) <= sizeof(uint32), "uint32 can only be read from int32 or smaller spans");
381 impl().validate(index, sizeof(uint32));
382 return READ_BE_UINT32(impl().data() + index);
383 }
384
385 inline uint32 getUint32LEAt(const index_type index) const {
386 static_assert(sizeof(value_type) <= sizeof(uint32), "uint32 can only be read from int32 or smaller spans");
387 impl().validate(index, sizeof(uint32));
388 return READ_LE_UINT32(impl().data() + index);
389 }
390
391 inline String getStringAt(const index_type index, size_type numEntries = kSpanMaxSize) const {
392 static_assert(sizeof(value_type) == sizeof(char), "strings can only be read from byte or char spans");
393 const char *string = (const char *)impl().data() + index;
394
395 if (numEntries == kSpanMaxSize) {
396 numEntries = strnlen(string, impl().size() - index);
397 }
398
399 impl().validate(index, numEntries);
400 return String(string, numEntries);
401 }
402
409 inline const_pointer getUnsafeDataAt(const index_type index, size_type numEntries = kSpanMaxSize) const {
410 if (numEntries == kSpanMaxSize) {
411 numEntries = impl().size() - index;
412 }
413
414 impl().validate(index, numEntries * sizeof(value_type));
415 return impl().data() + index;
416 }
417
418 inline pointer getUnsafeDataAt(const index_type index, size_type numEntries = kSpanMaxSize) {
419 if (numEntries == kSpanMaxSize) {
420 numEntries = impl().size() - index;
421 }
422
423 impl().validate(index, numEntries * sizeof(value_type));
424 return impl().data() + index;
425 }
426
427 inline MemoryReadStream toStream(const index_type index = 0, size_type numEntries = kSpanMaxSize) const {
428 if (numEntries == kSpanMaxSize) {
429 numEntries = impl().size() - index;
430 }
431
432 impl().validate(index, numEntries * sizeof(value_type));
433 return MemoryReadStream(impl().data() + index, numEntries * sizeof(value_type), DisposeAfterUse::NO);
434 }
435
436#pragma mark -
437#pragma mark SpanBase - Operators
438
439public:
440 template <typename Other>
441 inline bool operator==(const Other &other) const {
442 return impl().data() == other.impl().data() && impl().size() == other.impl().size();
443 }
444
445 template <typename Other>
446 inline bool operator!=(const Other &other) const {
447 return !operator==(other);
448 }
449
450 template <typename Other>
451 inline difference_type operator-(const Other &other) const {
452 return impl().data() - other.impl().data();
453 }
454
455 template <typename Other>
456 inline bool operator<(const Other &other) const {
457 return impl().data() < other.impl().data();
458 }
459
460 template <typename Other>
461 inline bool operator<=(const Other &other) const {
462 return !other.operator<(*this);
463 }
464
465 template <typename Other>
466 inline bool operator>(const Other &other) const {
467 return other.operator<(*this);
468 }
469
470 template <typename Other>
471 inline bool operator>=(const Other &other) const {
472 return !operator<(other);
473 }
474
475#if !defined(_MSC_VER)
476protected:
477#endif
478 inline bool operator_bool() const { return impl().data() != nullptr; }
479
480#pragma mark -
481#pragma mark SpanBase - Copying
482
483public:
488 inline void unsafeCopyDataTo(void *target) const {
489 memcpy(target, impl().data(), impl().byteSize());
490 }
491
496 template <typename Other>
497 inline void copyDataTo(Other &target) const {
498 assert((impl().byteSize() % sizeof(typename Other::value_type)) == 0);
499 target.impl().validate(0, impl().byteSize(), kValidateWrite);
500 memcpy(target.impl().data(), impl().data(), impl().byteSize());
501 }
502
503#pragma mark -
504#pragma mark SpanBase - Validation
505
506#if !defined(_MSC_VER)
507protected:
508#endif
512 inline bool checkInvalidBounds(const index_type index, const difference_type deltaInBytes) const {
513 // There is a potential that large bogus values may cause arithmetic
514 // overflow, so the individual operands are checked separately first.
515 // Values that are not allowed to be negative are treated as unsigned to
516 // reduce the number of necessary comparisons
517 const size_t maxByteOffset = index * (signed)sizeof(value_type) + deltaInBytes;
518 return index > impl().size() || deltaInBytes > (difference_type)impl().byteSize() || maxByteOffset > impl().byteSize();
519 }
520
521 inline void validate(const index_type index, const difference_type deltaInBytes, const SpanValidationMode mode = kValidateRead) const {
522 /* LCOV_EXCL_START */
523 if (impl().checkInvalidBounds(index, deltaInBytes)) {
524 error("%s", impl().getValidationMessage(index, deltaInBytes, mode).c_str());
525 }
526 /* LCOV_EXCL_STOP */
527 }
528};
529
530#pragma mark -
531#pragma mark SpanImpl
532
533template <typename ValueType, template <typename> class Derived>
534class SpanImpl : public SpanBase<ValueType, Derived> {
536 typedef typename add_const<Derived<ValueType> >::type const_derived_type;
537 typedef typename remove_const<Derived<ValueType> >::type mutable_derived_type;
538
539 template <typename T, template <typename> class U> friend class SpanImpl;
540#ifdef CXXTEST_RUNNING
541 friend class ::SpanTestSuite;
542#endif
543
544public:
545 COMMON_SPAN_TYPEDEFS;
546
547 inline SpanImpl() : super_type(), _data(nullptr), _size(0) {}
548
549 inline SpanImpl(const pointer data_, const size_type size_) :
550 super_type(),
551 _data(data_),
552 _size(size_) {}
553
554 template <typename Other>
555 inline SpanImpl(const Other &other) :
556 super_type(),
557 _data(other.data()),
558 _size(other.size()) {}
559
560 inline void clear() {
561 _data = nullptr;
562 _size = 0;
563 }
564
565 inline size_type size() const { return _size; }
566 inline pointer data() const { return _data; }
567
568 inline const_iterator cbegin() const { return const_iterator(&this->impl(), 0); }
569 inline const_iterator cend() const { return const_iterator(&this->impl(), size()); }
570 inline const_iterator begin() const { return const_iterator(&this->impl(), 0); }
571 inline const_iterator end() const { return const_iterator(&this->impl(), size()); }
572 inline iterator begin() { return iterator(&this->impl(), 0); }
573 inline iterator end() { return iterator(&this->impl(), size()); }
574
575 const String name() const { return String::format("%p", static_cast<const void *>(data())); }
576
577 String getValidationMessage(const index_type index, const difference_type deltaInBytes, const SpanValidationMode mode) const {
578 const char *modeName = "unknown";
579 switch (mode) {
580 case kValidateRead:
581 modeName = "reading";
582 break;
583 case kValidateWrite:
584 modeName = "writing";
585 break;
586 case kValidateSeek:
587 modeName = "seeking";
588 break;
589 default:
590 break;
591 }
592
593 return String::format("Access violation %s %s: %u + %d > %u",
594 modeName,
595 this->impl().name().c_str(),
596 index,
597 deltaInBytes / (int)sizeof(value_type),
598 size());
599 }
600
601#pragma mark -
602#pragma mark SpanImpl - Subspan
603
604public:
605 template <typename NewValueType>
606 inline const Derived<NewValueType> subspan(const index_type index, size_type numEntries = kSpanMaxSize) const {
607 Derived<NewValueType> span;
608 populateSubspan(span, index, numEntries);
609 return span;
610 }
611
612 template <typename NewValueType>
613 inline Derived<NewValueType> subspan(const index_type index, size_type numEntries = kSpanMaxSize) {
614 Derived<NewValueType> span;
615 populateSubspan(span, index, numEntries);
616 return span;
617 }
618
619 inline const_derived_type subspan(const index_type index, const size_type numEntries = kSpanMaxSize) const {
620 return subspan<value_type>(index, numEntries);
621 }
622
623 inline mutable_derived_type subspan(const index_type index, const size_type numEntries = kSpanMaxSize) {
624 return subspan<value_type>(index, numEntries);
625 }
626
627#if !defined(_MSC_VER)
628protected:
629#endif
630 template <typename NewValueType>
631 void populateSubspan(Derived<NewValueType> &span, const index_type index, size_type numEntries) const {
632 if (numEntries == kSpanMaxSize) {
633 numEntries = CLIP<size_type>(size() - index, 0, size());
634 }
635
636 assert(numEntries * sizeof(value_type) % sizeof(NewValueType) == 0);
637 this->validate(index, numEntries * sizeof(value_type), kValidateSeek);
638
639 span._data = (NewValueType *)const_cast<mutable_value_type *>(_data + index);
640 span._size = numEntries * sizeof(value_type) / sizeof(NewValueType);
641 }
642
643#pragma mark -
644#pragma mark SpanImpl - Allocation
645
646private:
647 typedef typename remove_const<value_type>::type mutable_value_type;
648 typedef Derived<mutable_value_type> mutable_value_derived_type;
649
650public:
651 mutable_value_derived_type &allocate(const size_type numEntries) {
652 assert(_data == nullptr);
653 assert(numEntries != kSpanMaxSize);
654 _data = new mutable_value_type[numEntries];
655 _size = numEntries;
656 return reinterpret_cast<mutable_value_derived_type &>(const_cast<Derived<value_type> &>(this->impl()));
657 }
658
659 template <typename Other>
660 mutable_value_derived_type &allocateFromSpan(const Other &other) {
661 assert(_data == nullptr);
662 assert(sizeof(value_type) == sizeof(typename Other::value_type));
663 _data = new mutable_value_type[other.size()];
664 _size = other.size();
665 copy(other.begin(), other.end(), const_cast<mutable_value_type *>(_data));
666 return reinterpret_cast<mutable_value_derived_type &>(const_cast<Derived<value_type> &>(this->impl()));
667 }
668
669 mutable_value_derived_type &allocateFromStream(SeekableReadStream &stream, size_type numEntries = kSpanMaxSize) {
670 if (numEntries == kSpanMaxSize) {
671 numEntries = (stream.size() - stream.pos()) / sizeof(value_type);
672 }
673
674 const uint32 bytesRequested = numEntries * sizeof(value_type);
675 assert(stream.pos() + bytesRequested <= (uint)stream.size());
676 allocate(numEntries);
677 const uint32 bytesRead = stream.read((void *)const_cast<mutable_value_type *>(_data), bytesRequested);
678 assert(bytesRead == bytesRequested);
679 (void)bytesRead;
680 return reinterpret_cast<mutable_value_derived_type &>(const_cast<Derived<value_type> &>(this->impl()));
681 }
682
683 value_type *_data;
684 size_type _size;
685};
686
687#pragma mark -
688#pragma mark Span
689
690template <typename ValueType>
691class Span : public SpanImpl<ValueType, Span> {
693 typedef typename add_const<Span<ValueType> >::type const_derived_type;
694 typedef typename remove_const<Span<ValueType> >::type mutable_derived_type;
695 template <typename T> friend class Span;
696
697public:
698 COMMON_SPAN_TYPEDEFS;
699
700 inline Span() : super_type() {}
701
702 inline Span(const pointer data_, const size_type size_) : super_type(data_, size_) {}
703
704 // Allows unrelated sibling classes like NamedSpan to assign to superclass
705 // siblings like Span
706 template <typename Other>
707 inline Span(const Other &other) : super_type(other) {}
708};
709
710#pragma mark -
711#pragma mark NamedSpanImpl
712
713template <typename ValueType, template <typename> class Derived>
714class NamedSpanImpl : public SpanImpl<ValueType, Derived> {
716 typedef typename add_const<Derived<ValueType> >::type const_derived_type;
717 typedef typename remove_const<Derived<ValueType> >::type mutable_derived_type;
718
719 template <typename T, template <typename> class U> friend class NamedSpanImpl;
720#ifdef CXXTEST_RUNNING
721 friend class ::SpanTestSuite;
722#endif
723
724public:
725 COMMON_SPAN_TYPEDEFS;
726
727 inline NamedSpanImpl() = default;
728
729 inline NamedSpanImpl(const pointer data_,
730 const size_type size_,
731 const String &name_ = String(),
732 const size_type sourceByteOffset_ = 0) :
733 super_type(data_, size_),
734 _name(name_),
735 _sourceByteOffset(sourceByteOffset_) {}
736
737 template <typename Other>
738 inline NamedSpanImpl(const Other &other) :
739 super_type(other),
740 _name(other.name()),
741 _sourceByteOffset(other.sourceByteOffset()) {}
742
743 inline void clear() {
744 super_type::clear();
745 _name.clear();
746 _sourceByteOffset = 0;
747 }
748
749 const String &name() const { return _name; }
750 String &name() { return _name; }
751
752 const size_type &sourceByteOffset() const { return _sourceByteOffset; }
753 size_type &sourceByteOffset() { return _sourceByteOffset; }
754
755private:
756 String _name;
757 size_type _sourceByteOffset = 0;
758
759#pragma mark -
760#pragma mark NamedSpanImpl - Subspan
761
762public:
763 template <typename NewValueType>
764 inline const Derived<NewValueType> subspan(const index_type index, const size_type numEntries = kSpanMaxSize, const String &name_ = String(), const size_type sourceByteOffset_ = kSpanKeepOffset) const {
765 Derived<NewValueType> span;
766 populateSubspan(span, index, numEntries, name_, sourceByteOffset_);
767 return span;
768 }
769
770 template <typename NewValueType>
771 inline Derived<NewValueType> subspan(const index_type index, const size_type numEntries = kSpanMaxSize, const String &name_ = String(), const size_type sourceByteOffset_ = kSpanKeepOffset) {
772 Derived<NewValueType> span;
773 populateSubspan(span, index, numEntries, name_, sourceByteOffset_);
774 return span;
775 }
776
777 inline const_derived_type subspan(const index_type index, const size_type numEntries = kSpanMaxSize, const String &name_ = String(), const size_type sourceByteOffset_ = kSpanKeepOffset) const {
778 return subspan<value_type>(index, numEntries, name_, sourceByteOffset_);
779 }
780
781 inline mutable_derived_type subspan(const index_type index, const size_type numEntries = kSpanMaxSize, const String &name_ = String(), const size_type sourceByteOffset_ = kSpanKeepOffset) {
782 return subspan<value_type>(index, numEntries, name_, sourceByteOffset_);
783 }
784
785#if !defined(_MSC_VER)
786protected:
787#endif
788 template <typename NewValueType>
789 void populateSubspan(Derived<NewValueType> &span, const index_type index, size_type numEntries, const String &name_, const size_type sourceByteOffset_ = kSpanKeepOffset) const {
790 super_type::template populateSubspan<NewValueType>(span, index, numEntries);
791
792 if (name_.empty()) {
793 span._name = _name;
794 } else {
795 span._name = name_;
796 }
797
798 if (sourceByteOffset_ == kSpanKeepOffset) {
799 span._sourceByteOffset = _sourceByteOffset + index * sizeof(value_type);
800 } else {
801 span._sourceByteOffset = sourceByteOffset_;
802 }
803 }
804
805#pragma mark -
806#pragma mark NamedSpanImpl - Validation
807
808public:
809 String getValidationMessage(const index_type index, const difference_type deltaInBytes, const SpanValidationMode mode) const {
810 const index_type indexInBytes = index * sizeof(value_type);
811 const size_type maxSizeInBytes = this->impl().byteSize();
812
813 return super_type::getValidationMessage(index, deltaInBytes, mode) +
814 String::format(" (abs: %u + %d > %u)",
815 this->impl().sourceByteOffset() + indexInBytes,
816 deltaInBytes,
817 this->impl().sourceByteOffset() + maxSizeInBytes);
818 }
819
820#pragma mark -
821#pragma mark NamedSpanImpl - Allocation
822
823private:
824 typedef typename remove_const<value_type>::type mutable_value_type;
825 typedef Derived<mutable_value_type> mutable_value_derived_type;
826
827public:
828 mutable_value_derived_type &allocate(const size_type numEntries, const String &name_ = String()) {
829 super_type::allocate(numEntries);
830 _name = name_;
831 _sourceByteOffset = 0;
832 return reinterpret_cast<mutable_value_derived_type &>(const_cast<Derived<value_type> &>(this->impl()));
833 }
834
835 template <typename OtherValueType>
836 mutable_value_derived_type &allocateFromSpan(const NamedSpanImpl<OtherValueType, Derived> &other) {
837 super_type::allocateFromSpan(other);
838 _name = other.name();
839 _sourceByteOffset = other.sourceByteOffset();
840 return reinterpret_cast<mutable_value_derived_type &>(const_cast<Derived<value_type> &>(this->impl()));
841 }
842
843 template <typename OtherValueType, template <typename> class OtherDerived>
844 mutable_value_derived_type &allocateFromSpan(const SpanImpl<OtherValueType, OtherDerived> &other) {
845 super_type::allocateFromSpan(other);
846 return reinterpret_cast<mutable_value_derived_type &>(const_cast<Derived<value_type> &>(this->impl()));
847 }
848
849 mutable_value_derived_type &allocateFromStream(SeekableReadStream &stream, size_type numEntries = kSpanMaxSize, const String &name_ = String()) {
850 super_type::allocateFromStream(stream, numEntries);
851 _name = name_;
852 _sourceByteOffset = 0;
853 return reinterpret_cast<mutable_value_derived_type &>(const_cast<Derived<value_type> &>(this->impl()));
854 }
855
856 mutable_value_derived_type &allocateFromStream(File &file, const size_type numEntries = kSpanMaxSize) {
857 return allocateFromStream(file, numEntries, file.getName());
858 }
859};
860
861#pragma mark -
862#pragma mark NamedSpan
863
864template <typename ValueType>
865class NamedSpan : public NamedSpanImpl<ValueType, NamedSpan> {
867
868 template <typename T> friend class NamedSpan;
869
870public:
871 COMMON_SPAN_TYPEDEFS;
872
873 inline NamedSpan() = default;
874
875 inline NamedSpan(const pointer data_,
876 const size_type size_,
877 const String &name_ = String(),
878 const size_type sourceByteOffset_ = 0) :
879 super_type(data_, size_, name_, sourceByteOffset_) {}
880
881 template <typename Other>
882 inline NamedSpan(const Other &other) : super_type(other) {}
883};
884
885#pragma mark -
886#pragma mark SpanOwner
887
892template <typename OwnedSpan>
893class SpanOwner : public SafeBool<SpanOwner<OwnedSpan> > {
894 typedef typename OwnedSpan::value_type value_type;
895 typedef typename OwnedSpan::size_type size_type;
896 typedef typename OwnedSpan::index_type index_type;
897 typedef typename OwnedSpan::pointer pointer;
898 typedef typename OwnedSpan::reference reference;
899 typedef typename OwnedSpan::const_reference const_reference;
900
901 template <typename T, typename U> friend struct SafeBool;
902
903public:
904 inline SpanOwner() : _span() {}
905
906 inline SpanOwner(const OwnedSpan &span) : _span(span) {}
907
911 inline SpanOwner(const SpanOwner &other) {
912 // Allocating memory when copy-constructing from an unallocated owner
913 // will break the new owner by making it appear allocated even though
914 // it doesn't (and shouldn't) contain data
915 if (!other) {
916 SpanOwner();
917 return;
918 }
919
920 _span.allocateFromSpan(other._span);
921 }
922
923 inline SpanOwner &operator=(const SpanOwner &other) {
924 if (this == &other) {
925 return *this;
926 }
927
928 delete[] const_cast<typename remove_const<value_type>::type *>(_span.data());
929 _span.clear();
930
931 // Allocating memory when copy-assigning from an unallocated owner
932 // will break the new owner by making it appear allocated even though
933 // it doesn't (and shouldn't) contain data
934 if (other) {
935 _span.allocateFromSpan(other._span);
936 }
937
938 return *this;
939 }
940
941 inline ~SpanOwner() {
942 delete[] const_cast<typename remove_const<value_type>::type *>(_span.data());
943 }
944
948 inline SpanOwner &moveFrom(SpanOwner &other) {
949 if (this == &other) {
950 return *this;
951 }
952
953 delete[] const_cast<typename remove_const<value_type>::type *>(_span.data());
954 _span = other._span;
955 other.release();
956 return *this;
957 }
958
962 inline pointer release() {
963 pointer data = _span.data();
964 _span.clear();
965 return data;
966 }
967
971 inline void clear() {
972 delete[] const_cast<typename remove_const<value_type>::type *>(_span.data());
973 _span.clear();
974 }
975
976#if !defined(_MSC_VER)
977protected:
978#endif
979 inline bool operator_bool() const { return _span; }
980
981private:
982 OwnedSpan _span;
983
984#pragma mark -
985#pragma mark SpanOwner - Data access
986
987public:
988 inline const OwnedSpan &operator*() const { return _span; }
989 inline OwnedSpan &operator*() { return _span; }
990
991 inline const OwnedSpan *operator->() const { return &_span; }
992 inline OwnedSpan *operator->() { return &_span; }
993
994 inline const_reference operator[](const index_type index) const { return _span[index]; }
995 inline reference operator[](const index_type index) { return _span[index]; }
996};
997
998} // End of namespace Common
999
1000#endif
Definition: file.h:47
const char * getName() const
Definition: file.h:126
Definition: span.h:865
Definition: span.h:714
virtual uint32 read(void *dataPtr, uint32 dataSize)=0
Definition: stream.h:745
virtual int64 pos() const =0
virtual int64 size() const =0
Definition: span.h:254
bool checkInvalidBounds(const index_type index, const difference_type deltaInBytes) const
Definition: span.h:512
void unsafeCopyDataTo(void *target) const
Definition: span.h:488
void copyDataTo(Other &target) const
Definition: span.h:497
const_pointer getUnsafeDataAt(const index_type index, size_type numEntries=kSpanMaxSize) const
Definition: span.h:409
Definition: span.h:691
Definition: span.h:534
Definition: span.h:893
void clear()
Definition: span.h:971
pointer release()
Definition: span.h:962
SpanOwner(const SpanOwner &other)
Definition: span.h:911
SpanOwner & moveFrom(SpanOwner &other)
Definition: span.h:948
Definition: str.h:59
static String format(MSVC_PRINTF const char *fmt,...) GCC_PRINTF(1
Out copy(In first, In last, Out dst)
Definition: algorithm.h:52
size_t strnlen(const char *src, size_t maxSize)
void NORETURN_PRE error(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
Definition: algorithm.h:29
int32 numEntries(const char *filename)
Definition: safe-bool.h:56
Definition: type_traits.h:66
Definition: type_traits.h:44