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 RemoveConst<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 AddConst<derived_type>::type const_derived_type;
257  typedef typename RemoveConst<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 AddConst<Derived<ValueType> >::type const_derived_type;
537  typedef typename RemoveConst<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 RemoveConst<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 (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 (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  return (mutable_value_derived_type &)const_cast<Derived<value_type> &>(this->impl());
680  }
681 
682  value_type *_data;
683  size_type _size;
684 };
685 
686 #pragma mark -
687 #pragma mark Span
688 
689 template <typename ValueType>
690 class Span : public SpanImpl<ValueType, Span> {
692  typedef typename AddConst<Span<ValueType> >::type const_derived_type;
693  typedef typename RemoveConst<Span<ValueType> >::type mutable_derived_type;
694  template <typename T> friend class Span;
695 
696 public:
697  COMMON_SPAN_TYPEDEFS
698 
699  inline Span() : super_type() {}
700 
701  inline Span(const pointer data_, const size_type size_) : super_type(data_, size_) {}
702 
703  // Allows unrelated sibling classes like NamedSpan to assign to superclass
704  // siblings like Span
705  template <typename Other>
706  inline Span(const Other &other) : super_type(other) {}
707 };
708 
709 #pragma mark -
710 #pragma mark NamedSpanImpl
711 
712 template <typename ValueType, template <typename> class Derived>
713 class NamedSpanImpl : public SpanImpl<ValueType, Derived> {
715  typedef typename AddConst<Derived<ValueType> >::type const_derived_type;
716  typedef typename RemoveConst<Derived<ValueType> >::type mutable_derived_type;
717 
718  template <typename T, template <typename> class U> friend class NamedSpanImpl;
719 #ifdef CXXTEST_RUNNING
720  friend class ::SpanTestSuite;
721 #endif
722 
723 public:
724  COMMON_SPAN_TYPEDEFS
725 
726  inline NamedSpanImpl() : super_type(), _name(), _sourceByteOffset(0) {}
727 
728  inline NamedSpanImpl(const pointer data_,
729  const size_type size_,
730  const String &name_ = String(),
731  const size_type sourceByteOffset_ = 0) :
732  super_type(data_, size_),
733  _name(name_),
734  _sourceByteOffset(sourceByteOffset_) {}
735 
736  template <typename Other>
737  inline NamedSpanImpl(const Other &other) :
738  super_type(other),
739  _name(other.name()),
740  _sourceByteOffset(other.sourceByteOffset()) {}
741 
742  inline void clear() {
743  super_type::clear();
744  _name.clear();
745  _sourceByteOffset = 0;
746  }
747 
748  const String &name() const { return _name; }
749  String &name() { return _name; }
750 
751  const size_type &sourceByteOffset() const { return _sourceByteOffset; }
752  size_type &sourceByteOffset() { return _sourceByteOffset; }
753 
754 private:
755  String _name;
756  size_type _sourceByteOffset;
757 
758 #pragma mark -
759 #pragma mark NamedSpanImpl - Subspan
760 
761 public:
762  template <typename NewValueType>
763  inline const Derived<NewValueType> subspan(const index_type index, const size_type numEntries = kSpanMaxSize, const String &name_ = String(), const size_type sourceByteOffset_ = kSpanKeepOffset) const {
764  Derived<NewValueType> span;
765  populateSubspan(span, index, numEntries, name_, sourceByteOffset_);
766  return span;
767  }
768 
769  template <typename NewValueType>
770  inline Derived<NewValueType> subspan(const index_type index, const size_type numEntries = kSpanMaxSize, const String &name_ = String(), const size_type sourceByteOffset_ = kSpanKeepOffset) {
771  Derived<NewValueType> span;
772  populateSubspan(span, index, numEntries, name_, sourceByteOffset_);
773  return span;
774  }
775 
776  inline const_derived_type subspan(const index_type index, const size_type numEntries = kSpanMaxSize, const String &name_ = String(), const size_type sourceByteOffset_ = kSpanKeepOffset) const {
777  return subspan<value_type>(index, numEntries, name_, sourceByteOffset_);
778  }
779 
780  inline mutable_derived_type subspan(const index_type index, const size_type numEntries = kSpanMaxSize, const String &name_ = String(), const size_type sourceByteOffset_ = kSpanKeepOffset) {
781  return subspan<value_type>(index, numEntries, name_, sourceByteOffset_);
782  }
783 
784 #if !defined(_MSC_VER)
785 protected:
786 #endif
787  template <typename NewValueType>
788  void populateSubspan(Derived<NewValueType> &span, const index_type index, size_type numEntries, const String &name_, const size_type sourceByteOffset_ = kSpanKeepOffset) const {
789  super_type::template populateSubspan<NewValueType>(span, index, numEntries);
790 
791  if (name_.empty()) {
792  span._name = _name;
793  } else {
794  span._name = name_;
795  }
796 
797  if (sourceByteOffset_ == kSpanKeepOffset) {
798  span._sourceByteOffset = _sourceByteOffset + index * sizeof(value_type);
799  } else {
800  span._sourceByteOffset = sourceByteOffset_;
801  }
802  }
803 
804 #pragma mark -
805 #pragma mark NamedSpanImpl - Validation
806 
807 public:
808  String getValidationMessage(const index_type index, const difference_type deltaInBytes, const SpanValidationMode mode) const {
809  const index_type indexInBytes = index * sizeof(value_type);
810  const size_type maxSizeInBytes = this->impl().byteSize();
811 
812  return super_type::getValidationMessage(index, deltaInBytes, mode) +
813  String::format(" (abs: %u + %d > %u)",
814  this->impl().sourceByteOffset() + indexInBytes,
815  deltaInBytes,
816  this->impl().sourceByteOffset() + maxSizeInBytes);
817  }
818 
819 #pragma mark -
820 #pragma mark NamedSpanImpl - Allocation
821 
822 private:
823  typedef typename RemoveConst<value_type>::type mutable_value_type;
824  typedef Derived<mutable_value_type> mutable_value_derived_type;
825 
826 public:
827  mutable_value_derived_type &allocate(const size_type numEntries, const String &name_ = String()) {
828  super_type::allocate(numEntries);
829  _name = name_;
830  _sourceByteOffset = 0;
831  return (mutable_value_derived_type &)const_cast<Derived<value_type> &>(this->impl());
832  }
833 
834  template <typename OtherValueType>
835  mutable_value_derived_type &allocateFromSpan(const NamedSpanImpl<OtherValueType, Derived> &other) {
836  super_type::allocateFromSpan(other);
837  _name = other.name();
838  _sourceByteOffset = other.sourceByteOffset();
839  return (mutable_value_derived_type &)const_cast<Derived<value_type> &>(this->impl());
840  }
841 
842  template <typename OtherValueType, template <typename> class OtherDerived>
843  mutable_value_derived_type &allocateFromSpan(const SpanImpl<OtherValueType, OtherDerived> &other) {
844  super_type::allocateFromSpan(other);
845  return (mutable_value_derived_type &)const_cast<Derived<value_type> &>(this->impl());
846  }
847 
848  mutable_value_derived_type &allocateFromStream(SeekableReadStream &stream, size_type numEntries = kSpanMaxSize, const String &name_ = String()) {
849  super_type::allocateFromStream(stream, numEntries);
850  _name = name_;
851  _sourceByteOffset = 0;
852  return (mutable_value_derived_type &)const_cast<Derived<value_type> &>(this->impl());
853  }
854 
855  mutable_value_derived_type &allocateFromStream(File &file, const size_type numEntries = kSpanMaxSize) {
856  return allocateFromStream(file, numEntries, file.getName());
857  }
858 };
859 
860 #pragma mark -
861 #pragma mark NamedSpan
862 
863 template <typename ValueType>
864 class NamedSpan : public NamedSpanImpl<ValueType, NamedSpan> {
866 
867  template <typename T> friend class NamedSpan;
868 
869 public:
870  COMMON_SPAN_TYPEDEFS
871 
872  inline NamedSpan() : super_type() {}
873 
874  inline NamedSpan(const pointer data_,
875  const size_type size_,
876  const String &name_ = String(),
877  const size_type sourceByteOffset_ = 0) :
878  super_type(data_, size_, name_, sourceByteOffset_) {}
879 
880  template <typename Other>
881  inline NamedSpan(const Other &other) : super_type(other) {}
882 };
883 
884 #pragma mark -
885 #pragma mark SpanOwner
886 
891 template <typename OwnedSpan>
892 class SpanOwner : public SafeBool<SpanOwner<OwnedSpan> > {
893  typedef typename OwnedSpan::value_type value_type;
894  typedef typename OwnedSpan::size_type size_type;
895  typedef typename OwnedSpan::index_type index_type;
896  typedef typename OwnedSpan::pointer pointer;
897  typedef typename OwnedSpan::reference reference;
898  typedef typename OwnedSpan::const_reference const_reference;
899 
900  template <typename T, typename U> friend struct SafeBool;
901 
902 public:
903  inline SpanOwner() : _span() {}
904 
905  inline SpanOwner(const OwnedSpan &span) : _span(span) {}
906 
910  inline SpanOwner(const SpanOwner &other) {
911  // Allocating memory when copy-constructing from an unallocated owner
912  // will break the new owner by making it appear allocated even though
913  // it doesn't (and shouldn't) contain data
914  if (!other) {
915  SpanOwner();
916  return;
917  }
918 
919  _span.allocateFromSpan(other._span);
920  }
921 
922  inline SpanOwner &operator=(const SpanOwner &other) {
923  if (this == &other) {
924  return *this;
925  }
926 
927  delete[] const_cast<typename RemoveConst<value_type>::type *>(_span.data());
928  _span.clear();
929 
930  // Allocating memory when copy-assigning from an unallocated owner
931  // will break the new owner by making it appear allocated even though
932  // it doesn't (and shouldn't) contain data
933  if (other) {
934  _span.allocateFromSpan(other._span);
935  }
936 
937  return *this;
938  }
939 
940  inline ~SpanOwner() {
941  delete[] const_cast<typename RemoveConst<value_type>::type *>(_span.data());
942  }
943 
947  inline SpanOwner &moveFrom(SpanOwner &other) {
948  if (this == &other) {
949  return *this;
950  }
951 
952  delete[] const_cast<typename RemoveConst<value_type>::type *>(_span.data());
953  _span = other._span;
954  other.release();
955  return *this;
956  }
957 
961  inline pointer release() {
962  pointer data = _span.data();
963  _span.clear();
964  return data;
965  }
966 
970  inline void clear() {
971  delete[] const_cast<typename RemoveConst<value_type>::type *>(_span.data());
972  _span.clear();
973  }
974 
975 #if !defined(_MSC_VER)
976 protected:
977 #endif
978  inline bool operator_bool() const { return _span; }
979 
980 private:
981  OwnedSpan _span;
982 
983 #pragma mark -
984 #pragma mark SpanOwner - Data access
985 
986 public:
987  inline const OwnedSpan &operator*() const { return _span; }
988  inline OwnedSpan &operator*() { return _span; }
989 
990  inline const OwnedSpan *operator->() const { return &_span; }
991  inline OwnedSpan *operator->() { return &_span; }
992 
993  inline const_reference operator[](const index_type index) const { return _span[index]; }
994  inline reference operator[](const index_type index) { return _span[index]; }
995 };
996 
997 } // End of namespace Common
998 
999 #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:970
static String format(MSVC_PRINTF const char *fmt,...) GCC_PRINTF(1
Definition: span.h:713
Definition: span.h:534
Definition: span.h:254
Definition: span.h:864
void copyDataTo(Other &target) const
Definition: span.h:497
pointer release()
Definition: span.h:961
Definition: stream.h:745
Definition: span.h:892
Definition: type-traits.h:28
Out copy(In first, In last, Out dst)
Definition: algorithm.h:52
Definition: type-traits.h:30
const char * getName() const
Definition: file.h:126
Definition: file.h:47
Definition: algorithm.h:29
SpanOwner & moveFrom(SpanOwner &other)
Definition: span.h:947
Definition: memstream.h:43
void NORETURN_PRE error(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
SpanOwner(const SpanOwner &other)
Definition: span.h:910
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:690