Span.h 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2015 Microsoft Corporation. All rights reserved.
  4. // Copyright (c) 2020 Moonchild Productions. All rights reserved.
  5. //
  6. // This code is licensed under the MIT License (MIT).
  7. //
  8. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  9. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  10. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  11. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  12. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  13. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  14. // THE SOFTWARE.
  15. //
  16. ///////////////////////////////////////////////////////////////////////////////
  17. // Adapted from https://github.com/Microsoft/GSL/blob/3819df6e378ffccf0e29465afe99c3b324c2aa70/include/gsl/span
  18. // and https://github.com/Microsoft/GSL/blob/3819df6e378ffccf0e29465afe99c3b324c2aa70/include/gsl/gsl_util
  19. #ifndef mozilla_Span_h
  20. #define mozilla_Span_h
  21. #include "mozilla/Array.h"
  22. #include "mozilla/Assertions.h"
  23. #include "mozilla/Casting.h"
  24. #include "mozilla/IntegerTypeTraits.h"
  25. #include "mozilla/Move.h"
  26. #include "mozilla/TypeTraits.h"
  27. #include "mozilla/UniquePtr.h"
  28. #include <algorithm>
  29. #include <array>
  30. #include <cstring>
  31. #include <iterator>
  32. #ifdef _MSC_VER
  33. #pragma warning(push)
  34. // turn off some warnings that are noisy about our MOZ_RELEASE_ASSERT statements
  35. #pragma warning(disable : 4127) // conditional expression is constant
  36. // blanket turn off warnings from CppCoreCheck for now
  37. // so people aren't annoyed by them when running the tool.
  38. // more targeted suppressions will be added in a future update to the GSL
  39. #pragma warning(disable : 26481 26482 26483 26485 26490 26491 26492 26493 26495)
  40. #endif // _MSC_VER
  41. namespace mozilla {
  42. // Stuff from gsl_util
  43. // narrow_cast(): a searchable way to do narrowing casts of values
  44. template<class T, class U>
  45. inline T
  46. narrow_cast(U&& u)
  47. {
  48. return static_cast<T>(mozilla::Forward<U>(u));
  49. }
  50. // end gsl_util
  51. // [views.constants], constants
  52. // This was -1 in gsl::span, but using size_t for sizes instead of ptrdiff_t
  53. // and reserving a magic value that realistically doesn't occur in
  54. // compile-time-constant Span sizes makes things a lot less messy in terms of
  55. // comparison between signed and unsigned.
  56. const size_t dynamic_extent = mozilla::MaxValue<size_t>::value;
  57. template<class ElementType, size_t Extent = dynamic_extent>
  58. class Span;
  59. // implementation details
  60. namespace span_details {
  61. // C++14 types that we don't have because we build as C++11.
  62. template<class T>
  63. using remove_cv_t = typename mozilla::RemoveCV<T>::Type;
  64. template<class T>
  65. using remove_const_t = typename mozilla::RemoveConst<T>::Type;
  66. template<bool B, class T, class F>
  67. using conditional_t = typename mozilla::Conditional<B, T, F>::Type;
  68. template<class T>
  69. using add_pointer_t = typename mozilla::AddPointer<T>::Type;
  70. template<bool B, class T = void>
  71. using enable_if_t = typename mozilla::EnableIf<B, T>::Type;
  72. template<class T>
  73. struct is_span_oracle : mozilla::FalseType
  74. {
  75. };
  76. template<class ElementType, size_t Extent>
  77. struct is_span_oracle<mozilla::Span<ElementType, Extent>> : mozilla::TrueType
  78. {
  79. };
  80. template<class T>
  81. struct is_span : public is_span_oracle<remove_cv_t<T>>
  82. {
  83. };
  84. template<class T>
  85. struct is_std_array_oracle : mozilla::FalseType
  86. {
  87. };
  88. template<class ElementType, size_t Extent>
  89. struct is_std_array_oracle<std::array<ElementType, Extent>> : mozilla::TrueType
  90. {
  91. };
  92. template<class T>
  93. struct is_std_array : public is_std_array_oracle<remove_cv_t<T>>
  94. {
  95. };
  96. template<size_t From, size_t To>
  97. struct is_allowed_extent_conversion
  98. : public mozilla::IntegralConstant<bool,
  99. From == To ||
  100. From == mozilla::dynamic_extent ||
  101. To == mozilla::dynamic_extent>
  102. {
  103. };
  104. template<class From, class To>
  105. struct is_allowed_element_type_conversion
  106. : public mozilla::IntegralConstant<bool, mozilla::IsConvertible<From (*)[], To (*)[]>::value>
  107. {
  108. };
  109. template<class Span, bool IsConst>
  110. class span_iterator
  111. {
  112. using element_type_ = typename Span::element_type;
  113. public:
  114. using iterator_category = std::random_access_iterator_tag;
  115. using value_type = remove_const_t<element_type_>;
  116. using difference_type = typename Span::index_type;
  117. using reference = conditional_t<IsConst, const element_type_, element_type_>&;
  118. using pointer = add_pointer_t<reference>;
  119. span_iterator() : span_iterator(nullptr, 0) {}
  120. span_iterator(const Span* span, typename Span::index_type index)
  121. : span_(span)
  122. , index_(index)
  123. {
  124. MOZ_RELEASE_ASSERT(span == nullptr ||
  125. (index_ >= 0 && index <= span_->Length()));
  126. }
  127. friend class span_iterator<Span, true>;
  128. MOZ_IMPLICIT span_iterator(const span_iterator<Span, false>& other)
  129. : span_iterator(other.span_, other.index_)
  130. {
  131. }
  132. span_iterator<Span, IsConst>&
  133. operator=(const span_iterator<Span, IsConst>&) = default;
  134. reference operator*() const
  135. {
  136. MOZ_RELEASE_ASSERT(span_);
  137. return (*span_)[index_];
  138. }
  139. pointer operator->() const
  140. {
  141. MOZ_RELEASE_ASSERT(span_);
  142. return &((*span_)[index_]);
  143. }
  144. span_iterator& operator++()
  145. {
  146. MOZ_RELEASE_ASSERT(span_ && index_ >= 0 && index_ < span_->Length());
  147. ++index_;
  148. return *this;
  149. }
  150. span_iterator operator++(int)
  151. {
  152. auto ret = *this;
  153. ++(*this);
  154. return ret;
  155. }
  156. span_iterator& operator--()
  157. {
  158. MOZ_RELEASE_ASSERT(span_ && index_ > 0 && index_ <= span_->Length());
  159. --index_;
  160. return *this;
  161. }
  162. span_iterator operator--(int)
  163. {
  164. auto ret = *this;
  165. --(*this);
  166. return ret;
  167. }
  168. span_iterator
  169. operator+(difference_type n) const
  170. {
  171. auto ret = *this;
  172. return ret += n;
  173. }
  174. span_iterator& operator+=(difference_type n)
  175. {
  176. MOZ_RELEASE_ASSERT(span_ && (index_ + n) >= 0 &&
  177. (index_ + n) <= span_->Length());
  178. index_ += n;
  179. return *this;
  180. }
  181. span_iterator
  182. operator-(difference_type n) const
  183. {
  184. auto ret = *this;
  185. return ret -= n;
  186. }
  187. span_iterator& operator-=(difference_type n)
  188. {
  189. return *this += -n;
  190. }
  191. difference_type
  192. operator-(const span_iterator& rhs) const
  193. {
  194. MOZ_RELEASE_ASSERT(span_ == rhs.span_);
  195. return index_ - rhs.index_;
  196. }
  197. reference operator[](difference_type n) const
  198. {
  199. return *(*this + n);
  200. }
  201. friend bool operator==(const span_iterator& lhs,
  202. const span_iterator& rhs)
  203. {
  204. return lhs.span_ == rhs.span_ && lhs.index_ == rhs.index_;
  205. }
  206. friend bool operator!=(const span_iterator& lhs,
  207. const span_iterator& rhs)
  208. {
  209. return !(lhs == rhs);
  210. }
  211. friend bool operator<(const span_iterator& lhs, const span_iterator& rhs)
  212. {
  213. MOZ_RELEASE_ASSERT(lhs.span_ == rhs.span_);
  214. return lhs.index_ < rhs.index_;
  215. }
  216. friend bool operator<=(const span_iterator& lhs, const span_iterator& rhs)
  217. {
  218. return !(rhs < lhs);
  219. }
  220. friend bool operator>(const span_iterator& lhs, const span_iterator& rhs)
  221. {
  222. return rhs < lhs;
  223. }
  224. friend bool operator>=(const span_iterator& lhs, const span_iterator& rhs)
  225. {
  226. return !(rhs > lhs);
  227. }
  228. void swap(span_iterator& rhs)
  229. {
  230. std::swap(index_, rhs.index_);
  231. std::swap(span_, rhs.span_);
  232. }
  233. protected:
  234. const Span* span_;
  235. size_t index_;
  236. };
  237. template<class Span, bool IsConst>
  238. inline span_iterator<Span, IsConst>
  239. operator+(typename span_iterator<Span, IsConst>::difference_type n,
  240. const span_iterator<Span, IsConst>& rhs)
  241. {
  242. return rhs + n;
  243. }
  244. template<size_t Ext>
  245. class extent_type
  246. {
  247. public:
  248. using index_type = size_t;
  249. static_assert(Ext >= 0, "A fixed-size Span must be >= 0 in size.");
  250. extent_type() {}
  251. template<index_type Other>
  252. MOZ_IMPLICIT extent_type(extent_type<Other> ext)
  253. {
  254. static_assert(
  255. Other == Ext || Other == dynamic_extent,
  256. "Mismatch between fixed-size extent and size of initializing data.");
  257. MOZ_RELEASE_ASSERT(ext.size() == Ext);
  258. }
  259. MOZ_IMPLICIT extent_type(index_type length)
  260. {
  261. MOZ_RELEASE_ASSERT(length == Ext);
  262. }
  263. index_type size() const { return Ext; }
  264. };
  265. template<>
  266. class extent_type<dynamic_extent>
  267. {
  268. public:
  269. using index_type = size_t;
  270. template<index_type Other>
  271. explicit extent_type(extent_type<Other> ext)
  272. : size_(ext.size())
  273. {
  274. }
  275. explicit extent_type(index_type length)
  276. : size_(length)
  277. {
  278. }
  279. index_type size() const { return size_; }
  280. private:
  281. index_type size_;
  282. };
  283. } // namespace span_details
  284. /**
  285. * Span - slices for C++
  286. *
  287. * Span implements Rust's slice concept for C++. It's called "Span" instead of
  288. * "Slice" to follow the naming used in C++ Core Guidelines.
  289. *
  290. * A Span wraps a pointer and a length that identify a non-owning view to a
  291. * contiguous block of memory of objects of the same type. Various types,
  292. * including (pre-decay) C arrays, XPCOM strings, nsTArray, mozilla::Array,
  293. * mozilla::Range and contiguous standard-library containers, auto-convert
  294. * into Spans when attempting to pass them as arguments to methods that take
  295. * Spans. MakeSpan() functions can be used for explicit conversion in other
  296. * contexts. (Span itself autoconverts into mozilla::Range.)
  297. *
  298. * Like Rust's slices, Span provides safety against out-of-bounds access by
  299. * performing run-time bound checks. However, unlike Rust's slices, Span
  300. * cannot provide safety against use-after-free.
  301. *
  302. * (Note: Span is like Rust's slice only conceptually. Due to the lack of
  303. * ABI guarantees, you should still decompose spans/slices to raw pointer
  304. * and length parts when crossing the FFI.)
  305. *
  306. * In addition to having constructors and MakeSpan() functions that take
  307. * various well-known types, a Span for an arbitrary type can be constructed
  308. * (via constructor or MakeSpan()) from a pointer and a length or a pointer
  309. * and another pointer pointing just past the last element.
  310. *
  311. * A Span<const char> can be obtained for const char* pointing to a
  312. * zero-terminated C string using the MakeCStringSpan() function. A
  313. * corresponding implicit constructor does not exist in order to avoid
  314. * accidental construction in cases where const char* does not point to a
  315. * zero-terminated C string.
  316. *
  317. * Span has methods that follow the Mozilla naming style and methods that
  318. * don't. The methods that follow the Mozilla naming style are meant to be
  319. * used directly from Mozilla code. The methods that don't are meant for
  320. * integration with C++11 range-based loops and with meta-programming that
  321. * expects the same methods that are found on the standard-library
  322. * containers. For example, to decompose a Span into its parts in Mozilla
  323. * code, use Elements() and Length() (as with nsTArray) instead of data()
  324. * and size() (as with std::vector).
  325. *
  326. * The pointer and length wrapped by a Span cannot be changed after a Span has
  327. * been created. When new values are required, simply create a new Span. Span
  328. * has a method called Subspan() that works analogously to the Substring()
  329. * method of XPCOM strings taking a start index and an optional length. As a
  330. * Mozilla extension (relative to Microsoft's gsl::span that mozilla::Span is
  331. * based on), Span has methods From(start), To(end) and FromTo(start, end)
  332. * that correspond to Rust's &slice[start..], &slice[..end] and
  333. * &slice[start..end], respectively. (That is, the end index is the index of
  334. * the first element not to be included in the new subspan.)
  335. *
  336. * When indicating a Span that's only read from, const goes inside the type
  337. * parameter. Don't put const in front of Span. That is:
  338. * size_t ReadsFromOneSpanAndWritesToAnother(Span<const uint8_t> aReadFrom,
  339. * Span<uint8_t> aWrittenTo);
  340. *
  341. * Any Span<const T> can be viewed as Span<const uint8_t> using the function
  342. * AsBytes(). Any Span<T> can be viewed as Span<uint8_t> using the function
  343. * AsWritableBytes().
  344. */
  345. template<class ElementType, size_t Extent>
  346. class Span
  347. {
  348. public:
  349. // constants and types
  350. using element_type = ElementType;
  351. using index_type = size_t;
  352. using pointer = element_type*;
  353. using reference = element_type&;
  354. using iterator =
  355. span_details::span_iterator<Span<ElementType, Extent>, false>;
  356. using const_iterator =
  357. span_details::span_iterator<Span<ElementType, Extent>, true>;
  358. using reverse_iterator = std::reverse_iterator<iterator>;
  359. using const_reverse_iterator = std::reverse_iterator<const_iterator>;
  360. static const index_type extent = Extent;
  361. // [Span.cons], Span constructors, copy, assignment, and destructor
  362. // "Dependent" is needed to make "span_details::enable_if_t<(Dependent || Extent == 0 || Extent == mozilla::MaxValue<size_t>::value)>" SFINAE,
  363. // since "span_details::enable_if_t<(Extent == 0 || Extent == mozilla::MaxValue<size_t>::value)>" is ill-formed when Extent is neither of the extreme values.
  364. /**
  365. * Constructor with no args.
  366. */
  367. template<
  368. bool Dependent = false,
  369. class = span_details::enable_if_t<
  370. (Dependent || Extent == 0 || Extent == mozilla::MaxValue<size_t>::value)>>
  371. Span()
  372. : storage_(nullptr, span_details::extent_type<0>())
  373. {
  374. }
  375. /**
  376. * Constructor for nullptr.
  377. */
  378. MOZ_IMPLICIT Span(std::nullptr_t) : Span() {}
  379. /**
  380. * Constructor for pointer and length.
  381. */
  382. Span(pointer aPtr, index_type aLength)
  383. : storage_(aPtr, aLength)
  384. {
  385. }
  386. /**
  387. * Constructor for start pointer and pointer past end.
  388. */
  389. Span(pointer aStartPtr, pointer aEndPtr)
  390. : storage_(aStartPtr, std::distance(aStartPtr, aEndPtr))
  391. {
  392. }
  393. /**
  394. * Constructor for C array.
  395. */
  396. template<size_t N>
  397. MOZ_IMPLICIT Span(element_type (&aArr)[N])
  398. : storage_(&aArr[0], span_details::extent_type<N>())
  399. {
  400. }
  401. /**
  402. * Constructor for std::array.
  403. */
  404. template<size_t N,
  405. class ArrayElementType = span_details::remove_const_t<element_type>>
  406. MOZ_IMPLICIT Span(std::array<ArrayElementType, N>& aArr)
  407. : storage_(&aArr[0], span_details::extent_type<N>())
  408. {
  409. }
  410. /**
  411. * Constructor for const std::array.
  412. */
  413. template<size_t N>
  414. MOZ_IMPLICIT Span(
  415. const std::array<span_details::remove_const_t<element_type>, N>& aArr)
  416. : storage_(&aArr[0], span_details::extent_type<N>())
  417. {
  418. }
  419. /**
  420. * Constructor for mozilla::Array.
  421. */
  422. template<size_t N,
  423. class ArrayElementType = span_details::remove_const_t<element_type>>
  424. MOZ_IMPLICIT Span(mozilla::Array<ArrayElementType, N>& aArr)
  425. : storage_(&aArr[0], span_details::extent_type<N>())
  426. {
  427. }
  428. /**
  429. * Constructor for const mozilla::Array.
  430. */
  431. template<size_t N>
  432. MOZ_IMPLICIT Span(
  433. const mozilla::Array<span_details::remove_const_t<element_type>, N>& aArr)
  434. : storage_(&aArr[0], span_details::extent_type<N>())
  435. {
  436. }
  437. /**
  438. * Constructor for mozilla::UniquePtr holding an array and length.
  439. */
  440. template<class ArrayElementType = std::add_pointer<element_type>>
  441. Span(const mozilla::UniquePtr<ArrayElementType>& aPtr,
  442. index_type aLength)
  443. : storage_(aPtr.get(), aLength)
  444. {
  445. }
  446. // NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement
  447. // on Container to be a contiguous sequence container.
  448. /**
  449. * Constructor for standard-library containers.
  450. */
  451. template<
  452. class Container,
  453. class = span_details::enable_if_t<
  454. !span_details::is_span<Container>::value &&
  455. !span_details::is_std_array<Container>::value &&
  456. mozilla::IsConvertible<typename Container::pointer, pointer>::value &&
  457. mozilla::IsConvertible<typename Container::pointer,
  458. decltype(mozilla::DeclVal<Container>().data())>::value>>
  459. MOZ_IMPLICIT Span(Container& cont)
  460. : Span(cont.data(), ReleaseAssertedCast<index_type>(cont.size()))
  461. {
  462. }
  463. /**
  464. * Constructor for standard-library containers (const version).
  465. */
  466. template<
  467. class Container,
  468. class = span_details::enable_if_t<
  469. mozilla::IsConst<element_type>::value &&
  470. !span_details::is_span<Container>::value &&
  471. mozilla::IsConvertible<typename Container::pointer, pointer>::value &&
  472. mozilla::IsConvertible<typename Container::pointer,
  473. decltype(mozilla::DeclVal<Container>().data())>::value>>
  474. MOZ_IMPLICIT Span(const Container& cont)
  475. : Span(cont.data(), ReleaseAssertedCast<index_type>(cont.size()))
  476. {
  477. }
  478. /**
  479. * Constructor from other Span.
  480. */
  481. Span(const Span& other) = default;
  482. /**
  483. * Constructor from other Span.
  484. */
  485. Span(Span&& other) = default;
  486. /**
  487. * Constructor from other Span with conversion of element type.
  488. */
  489. template<
  490. class OtherElementType,
  491. size_t OtherExtent,
  492. class = span_details::enable_if_t<
  493. span_details::is_allowed_extent_conversion<OtherExtent, Extent>::value &&
  494. span_details::is_allowed_element_type_conversion<OtherElementType,
  495. element_type>::value>>
  496. MOZ_IMPLICIT Span(const Span<OtherElementType, OtherExtent>& other)
  497. : storage_(other.data(),
  498. span_details::extent_type<OtherExtent>(other.size()))
  499. {
  500. }
  501. /**
  502. * Constructor from other Span with conversion of element type.
  503. */
  504. template<
  505. class OtherElementType,
  506. size_t OtherExtent,
  507. class = span_details::enable_if_t<
  508. span_details::is_allowed_extent_conversion<OtherExtent, Extent>::value &&
  509. span_details::is_allowed_element_type_conversion<OtherElementType,
  510. element_type>::value>>
  511. MOZ_IMPLICIT Span(Span<OtherElementType, OtherExtent>&& other)
  512. : storage_(other.data(),
  513. span_details::extent_type<OtherExtent>(other.size()))
  514. {
  515. }
  516. ~Span() = default;
  517. Span& operator=(const Span& other)
  518. = default;
  519. Span& operator=(Span&& other)
  520. = default;
  521. // [Span.sub], Span subviews
  522. /**
  523. * Subspan with first N elements with compile-time N.
  524. */
  525. template<size_t Count>
  526. Span<element_type, Count> First() const
  527. {
  528. MOZ_RELEASE_ASSERT(Count <= size());
  529. return { data(), Count };
  530. }
  531. /**
  532. * Subspan with last N elements with compile-time N.
  533. */
  534. template<size_t Count>
  535. Span<element_type, Count> Last() const
  536. {
  537. MOZ_RELEASE_ASSERT(Count <= size());
  538. return { data() + (size() - Count), Count };
  539. }
  540. /**
  541. * Subspan with compile-time start index and length.
  542. */
  543. template<size_t Offset, size_t Count = dynamic_extent>
  544. Span<element_type, Count> Subspan() const
  545. {
  546. MOZ_RELEASE_ASSERT(Offset <= size() &&
  547. (Count == dynamic_extent || (Offset + Count <= size())));
  548. return { data() + Offset,
  549. Count == dynamic_extent ? size() - Offset : Count };
  550. }
  551. /**
  552. * Subspan with first N elements with run-time N.
  553. */
  554. Span<element_type, dynamic_extent> First(
  555. index_type aCount) const
  556. {
  557. MOZ_RELEASE_ASSERT(aCount <= size());
  558. return { data(), aCount };
  559. }
  560. /**
  561. * Subspan with last N elements with run-time N.
  562. */
  563. Span<element_type, dynamic_extent> Last(
  564. index_type aCount) const
  565. {
  566. MOZ_RELEASE_ASSERT(aCount <= size());
  567. return { data() + (size() - aCount), aCount };
  568. }
  569. /**
  570. * Subspan with run-time start index and length.
  571. */
  572. Span<element_type, dynamic_extent> Subspan(
  573. index_type aStart,
  574. index_type aLength = dynamic_extent) const
  575. {
  576. MOZ_RELEASE_ASSERT(aStart <= size() &&
  577. (aLength == dynamic_extent ||
  578. (aStart + aLength <= size())));
  579. return { data() + aStart,
  580. aLength == dynamic_extent ? size() - aStart : aLength };
  581. }
  582. /**
  583. * Subspan with run-time start index. (Rust's &foo[start..])
  584. */
  585. Span<element_type, dynamic_extent> From(index_type aStart) const
  586. {
  587. return Subspan(aStart);
  588. }
  589. /**
  590. * Subspan with run-time exclusive end index. (Rust's &foo[..end])
  591. */
  592. Span<element_type, dynamic_extent> To(index_type aEnd) const
  593. {
  594. return Subspan(0, aEnd);
  595. }
  596. /**
  597. * Subspan with run-time start index and exclusive end index.
  598. * (Rust's &foo[start..end])
  599. */
  600. Span<element_type, dynamic_extent> FromTo(index_type aStart, index_type aEnd) const
  601. {
  602. MOZ_RELEASE_ASSERT(aStart <= aEnd);
  603. return Subspan(aStart, aEnd - aStart);
  604. }
  605. // [Span.obs], Span observers
  606. /**
  607. * Number of elements in the span.
  608. */
  609. index_type Length() const { return size(); }
  610. /**
  611. * Number of elements in the span (standard-libray duck typing version).
  612. */
  613. index_type size() const { return storage_.size(); }
  614. /**
  615. * Size of the span in bytes.
  616. */
  617. index_type LengthBytes() const { return size_bytes(); }
  618. /**
  619. * Size of the span in bytes (standard-library naming style version).
  620. */
  621. index_type size_bytes() const
  622. {
  623. return size() * narrow_cast<index_type>(sizeof(element_type));
  624. }
  625. /**
  626. * Checks if the the length of the span is zero.
  627. */
  628. bool IsEmpty() const { return empty(); }
  629. /**
  630. * Checks if the the length of the span is zero (standard-libray duck
  631. * typing version).
  632. */
  633. bool empty() const { return size() == 0; }
  634. // [Span.elem], Span element access
  635. reference operator[](index_type idx) const
  636. {
  637. MOZ_RELEASE_ASSERT(idx < storage_.size());
  638. return data()[idx];
  639. }
  640. /**
  641. * Access element of span by index (standard-library duck typing version).
  642. */
  643. reference at(index_type idx) const { return this->operator[](idx); }
  644. reference operator()(index_type idx) const
  645. {
  646. return this->operator[](idx);
  647. }
  648. /**
  649. * Pointer to the first element of the span.
  650. */
  651. pointer Elements() const { return data(); }
  652. /**
  653. * Pointer to the first element of the span (standard-libray duck typing version).
  654. */
  655. pointer data() const { return storage_.data(); }
  656. // [Span.iter], Span iterator support
  657. iterator begin() const { return { this, 0 }; }
  658. iterator end() const { return { this, Length() }; }
  659. const_iterator cbegin() const { return { this, 0 }; }
  660. const_iterator cend() const { return { this, Length() }; }
  661. reverse_iterator rbegin() const
  662. {
  663. return reverse_iterator{ end() };
  664. }
  665. reverse_iterator rend() const
  666. {
  667. return reverse_iterator{ begin() };
  668. }
  669. const_reverse_iterator crbegin() const
  670. {
  671. return const_reverse_iterator{ cend() };
  672. }
  673. const_reverse_iterator crend() const
  674. {
  675. return const_reverse_iterator{ cbegin() };
  676. }
  677. private:
  678. // this implementation detail class lets us take advantage of the
  679. // empty base class optimization to pay for only storage of a single
  680. // pointer in the case of fixed-size Spans
  681. template<class ExtentType>
  682. class storage_type : public ExtentType
  683. {
  684. public:
  685. template<class OtherExtentType>
  686. storage_type(pointer elements, OtherExtentType ext)
  687. : ExtentType(ext)
  688. , data_(elements)
  689. {
  690. MOZ_RELEASE_ASSERT(
  691. (!elements && ExtentType::size() == 0) ||
  692. (elements && ExtentType::size() != mozilla::MaxValue<size_t>::value));
  693. }
  694. pointer data() const { return data_; }
  695. private:
  696. pointer data_;
  697. };
  698. storage_type<span_details::extent_type<Extent>> storage_;
  699. };
  700. // [Span.comparison], Span comparison operators
  701. template<class ElementType, size_t FirstExtent, size_t SecondExtent>
  702. inline bool
  703. operator==(const Span<ElementType, FirstExtent>& l,
  704. const Span<ElementType, SecondExtent>& r)
  705. {
  706. return (l.size() == r.size()) && std::equal(l.begin(), l.end(), r.begin());
  707. }
  708. template<class ElementType, size_t Extent>
  709. inline bool
  710. operator!=(const Span<ElementType, Extent>& l,
  711. const Span<ElementType, Extent>& r)
  712. {
  713. return !(l == r);
  714. }
  715. template<class ElementType, size_t Extent>
  716. inline bool
  717. operator<(const Span<ElementType, Extent>& l,
  718. const Span<ElementType, Extent>& r)
  719. {
  720. return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
  721. }
  722. template<class ElementType, size_t Extent>
  723. inline bool
  724. operator<=(const Span<ElementType, Extent>& l,
  725. const Span<ElementType, Extent>& r)
  726. {
  727. return !(l > r);
  728. }
  729. template<class ElementType, size_t Extent>
  730. inline bool
  731. operator>(const Span<ElementType, Extent>& l,
  732. const Span<ElementType, Extent>& r)
  733. {
  734. return r < l;
  735. }
  736. template<class ElementType, size_t Extent>
  737. inline bool
  738. operator>=(const Span<ElementType, Extent>& l,
  739. const Span<ElementType, Extent>& r)
  740. {
  741. return !(l < r);
  742. }
  743. namespace span_details {
  744. template<class ElementType, size_t Extent>
  745. struct calculate_byte_size
  746. : mozilla::IntegralConstant<size_t,
  747. static_cast<size_t>(sizeof(ElementType) *
  748. static_cast<size_t>(Extent))>
  749. {
  750. };
  751. template<class ElementType>
  752. struct calculate_byte_size<ElementType, dynamic_extent>
  753. : mozilla::IntegralConstant<size_t, dynamic_extent>
  754. {
  755. };
  756. }
  757. // [Span.objectrep], views of object representation
  758. /**
  759. * View span as Span<const uint8_t>.
  760. */
  761. template<class ElementType, size_t Extent>
  762. Span<const uint8_t,
  763. span_details::calculate_byte_size<ElementType, Extent>::value>
  764. AsBytes(Span<ElementType, Extent> s)
  765. {
  766. return { reinterpret_cast<const uint8_t*>(s.data()), s.size_bytes() };
  767. }
  768. /**
  769. * View span as Span<uint8_t>.
  770. */
  771. template<class ElementType,
  772. size_t Extent,
  773. class = span_details::enable_if_t<!mozilla::IsConst<ElementType>::value>>
  774. Span<uint8_t, span_details::calculate_byte_size<ElementType, Extent>::value>
  775. AsWritableBytes(Span<ElementType, Extent> s)
  776. {
  777. return { reinterpret_cast<uint8_t*>(s.data()), s.size_bytes() };
  778. }
  779. //
  780. // MakeSpan() - Utility functions for creating Spans
  781. //
  782. /**
  783. * Create span from pointer and length.
  784. */
  785. template<class ElementType>
  786. Span<ElementType>
  787. MakeSpan(ElementType* aPtr, typename Span<ElementType>::index_type aLength)
  788. {
  789. return Span<ElementType>(aPtr, aLength);
  790. }
  791. /**
  792. * Create span from start pointer and pointer past end.
  793. */
  794. template<class ElementType>
  795. Span<ElementType>
  796. MakeSpan(ElementType* aStartPtr, ElementType* aEndPtr)
  797. {
  798. return Span<ElementType>(aStartPtr, aEndPtr);
  799. }
  800. /**
  801. * Create span from C array.
  802. */
  803. template<class ElementType, size_t N>
  804. Span<ElementType> MakeSpan(ElementType (&aArr)[N])
  805. {
  806. return Span<ElementType>(aArr);
  807. }
  808. /**
  809. * Create span from mozilla::Array.
  810. */
  811. template<class ElementType, size_t N>
  812. Span<ElementType>
  813. MakeSpan(mozilla::Array<ElementType, N>& aArr)
  814. {
  815. return aArr;
  816. }
  817. /**
  818. * Create span from const mozilla::Array.
  819. */
  820. template<class ElementType, size_t N>
  821. Span<const ElementType>
  822. MakeSpan(const mozilla::Array<ElementType, N>& arr)
  823. {
  824. return arr;
  825. }
  826. /**
  827. * Create span from standard-library container.
  828. */
  829. template<class Container>
  830. Span<typename Container::value_type>
  831. MakeSpan(Container& cont)
  832. {
  833. return Span<typename Container::value_type>(cont);
  834. }
  835. /**
  836. * Create span from standard-library container (const version).
  837. */
  838. template<class Container>
  839. Span<const typename Container::value_type>
  840. MakeSpan(const Container& cont)
  841. {
  842. return Span<const typename Container::value_type>(cont);
  843. }
  844. /**
  845. * Create span from smart pointer and length.
  846. */
  847. template<class Ptr>
  848. Span<typename Ptr::element_type>
  849. MakeSpan(Ptr& aPtr, size_t aLength)
  850. {
  851. return Span<typename Ptr::element_type>(aPtr, aLength);
  852. }
  853. /**
  854. * Create span from C string.
  855. */
  856. inline Span<const char>
  857. MakeCStringSpan(const char* aStr)
  858. {
  859. return Span<const char>(aStr, std::strlen(aStr));
  860. }
  861. } // namespace mozilla
  862. #ifdef _MSC_VER
  863. #pragma warning(pop)
  864. #endif // _MSC_VER
  865. #endif // mozilla_Span_h