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 
31 namespace 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 
45 enum : uint {
46  kSpanMaxSize = 0xFFFFFFFF,
47  kSpanKeepOffset = 0xFFFFFFFF
48 };
49 
50 #pragma mark -
51 #pragma mark SpanValidationMode
52 
53 enum SpanValidationMode {
54  kValidateRead,
55  kValidateWrite,
56  kValidateSeek
57 };
58 
59 namespace SpanInternal {
60 #pragma mark -
61 #pragma mark SpanIterator
62 
65  template <typename Span, bool IsConst>
66  class SpanIterator {
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 
253 template <typename ValueType, template <typename> class Derived>
254 class 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 
266 public:
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)
281 protected:
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)
295 protected:
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 
313 public:
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 
439 public:
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)
476 protected:
477 #endif
478  inline bool operator_bool() const { return impl().data() != nullptr; }
479 
480 #pragma mark -
481 #pragma mark SpanBase - Copying
482 
483 public:
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)
507 protected:
508 #endif
509 
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 
533 template <typename ValueType, template <typename> class Derived>
534 class 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 
544 public:
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 
604 public:
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)
628 protected:
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 
646 private:
647  typedef typename remove_const<value_type>::type mutable_value_type;
648  typedef Derived<mutable_value_type> mutable_value_derived_type;
649 
650 public:
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 
690 template <typename ValueType>
691 class 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 
697 public:
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 
713 template <typename ValueType, template <typename> class Derived>
714 class 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 
724 public:
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 
755 private:
756  String _name;
757  size_type _sourceByteOffset = 0;
758 
759 #pragma mark -
760 #pragma mark NamedSpanImpl - Subspan
761 
762 public:
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)
786 protected:
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 
808 public:
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 
823 private:
824  typedef typename remove_const<value_type>::type mutable_value_type;
825  typedef Derived<mutable_value_type> mutable_value_derived_type;
826 
827 public:
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 
864 template <typename ValueType>
865 class NamedSpan : public NamedSpanImpl<ValueType, NamedSpan> {
867 
868  template <typename T> friend class NamedSpan;
869 
870 public:
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 
892 template <typename OwnedSpan>
893 class 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 
903 public:
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)
977 protected:
978 #endif
979  inline bool operator_bool() const { return _span; }
980 
981 private:
982  OwnedSpan _span;
983 
984 #pragma mark -
985 #pragma mark SpanOwner - Data access
986 
987 public:
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
bool checkInvalidBounds(const index_type index, const difference_type deltaInBytes) const
Definition: span.h:512
virtual int64 size() const =0
Definition: str.h:59
virtual int64 pos() const =0
void unsafeCopyDataTo(void *target) const
Definition: span.h:488
void clear()
Definition: span.h:971
static String format(MSVC_PRINTF const char *fmt,...) GCC_PRINTF(1
Definition: span.h:714
Definition: span.h:534
Definition: span.h:254
Definition: span.h:865
void copyDataTo(Other &target) const
Definition: span.h:497
pointer release()
Definition: span.h:962
Definition: stream.h:745
Definition: span.h:893
Out copy(In first, In last, Out dst)
Definition: algorithm.h:52
const char * getName() const
Definition: file.h:126
Definition: file.h:47
Definition: type_traits.h:44
Definition: algorithm.h:29
Definition: type_traits.h:66
SpanOwner & moveFrom(SpanOwner &other)
Definition: span.h:948
Definition: memstream.h:43
void NORETURN_PRE error(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
SpanOwner(const SpanOwner &other)
Definition: span.h:911
Definition: safe-bool.h:56
size_t strnlen(const char *src, size_t maxSize)
const_pointer getUnsafeDataAt(const index_type index, size_type numEntries=kSpanMaxSize) const
Definition: span.h:409
virtual uint32 read(void *dataPtr, uint32 dataSize)=0
Definition: span.h:691