Range.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * Copyright (c) 2016-present, Facebook, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under both the BSD-style license (found in the
  6. * LICENSE file in the root directory of this source tree) and the GPLv2 (found
  7. * in the COPYING file in the root directory of this source tree).
  8. */
  9. /**
  10. * A subset of `folly/Range.h`.
  11. * All code copied verbatim modulo formatting
  12. */
  13. #pragma once
  14. #include "utils/Likely.h"
  15. #include <cstddef>
  16. #include <cstring>
  17. #include <stdexcept>
  18. #include <string>
  19. #include <type_traits>
  20. namespace pzstd {
  21. namespace detail {
  22. /*
  23. *Use IsCharPointer<T>::type to enable const char* or char*.
  24. *Use IsCharPointer<T>::const_type to enable only const char*.
  25. */
  26. template <class T>
  27. struct IsCharPointer {};
  28. template <>
  29. struct IsCharPointer<char*> {
  30. typedef int type;
  31. };
  32. template <>
  33. struct IsCharPointer<const char*> {
  34. typedef int const_type;
  35. typedef int type;
  36. };
  37. } // namespace detail
  38. template <typename Iter>
  39. class Range {
  40. Iter b_;
  41. Iter e_;
  42. public:
  43. using size_type = std::size_t;
  44. using iterator = Iter;
  45. using const_iterator = Iter;
  46. using value_type = typename std::remove_reference<
  47. typename std::iterator_traits<Iter>::reference>::type;
  48. using reference = typename std::iterator_traits<Iter>::reference;
  49. constexpr Range() : b_(), e_() {}
  50. constexpr Range(Iter begin, Iter end) : b_(begin), e_(end) {}
  51. constexpr Range(Iter begin, size_type size) : b_(begin), e_(begin + size) {}
  52. template <class T = Iter, typename detail::IsCharPointer<T>::type = 0>
  53. /* implicit */ Range(Iter str) : b_(str), e_(str + std::strlen(str)) {}
  54. template <class T = Iter, typename detail::IsCharPointer<T>::const_type = 0>
  55. /* implicit */ Range(const std::string& str)
  56. : b_(str.data()), e_(b_ + str.size()) {}
  57. // Allow implicit conversion from Range<From> to Range<To> if From is
  58. // implicitly convertible to To.
  59. template <
  60. class OtherIter,
  61. typename std::enable_if<
  62. (!std::is_same<Iter, OtherIter>::value &&
  63. std::is_convertible<OtherIter, Iter>::value),
  64. int>::type = 0>
  65. constexpr /* implicit */ Range(const Range<OtherIter>& other)
  66. : b_(other.begin()), e_(other.end()) {}
  67. Range(const Range&) = default;
  68. Range(Range&&) = default;
  69. Range& operator=(const Range&) = default;
  70. Range& operator=(Range&&) = default;
  71. constexpr size_type size() const {
  72. return e_ - b_;
  73. }
  74. bool empty() const {
  75. return b_ == e_;
  76. }
  77. Iter data() const {
  78. return b_;
  79. }
  80. Iter begin() const {
  81. return b_;
  82. }
  83. Iter end() const {
  84. return e_;
  85. }
  86. void advance(size_type n) {
  87. if (UNLIKELY(n > size())) {
  88. throw std::out_of_range("index out of range");
  89. }
  90. b_ += n;
  91. }
  92. void subtract(size_type n) {
  93. if (UNLIKELY(n > size())) {
  94. throw std::out_of_range("index out of range");
  95. }
  96. e_ -= n;
  97. }
  98. Range subpiece(size_type first, size_type length = std::string::npos) const {
  99. if (UNLIKELY(first > size())) {
  100. throw std::out_of_range("index out of range");
  101. }
  102. return Range(b_ + first, std::min(length, size() - first));
  103. }
  104. };
  105. using ByteRange = Range<const unsigned char*>;
  106. using MutableByteRange = Range<unsigned char*>;
  107. using StringPiece = Range<const char*>;
  108. }