text: /*
   * Copyright (C) 2015 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  #ifndef ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
  #define ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
  
  #include <museum/8.1.0/external/libcxx/stddef.h>  // for offsetof()
  #include <museum/8.1.0/external/libcxx/string.h>  // for memset()
  
  #include <museum/8.1.0/art/runtime/stride_iterator.h>
  #include <museum/8.1.0/art/runtime/base/bit_utils.h>
  #include <museum/8.1.0/art/runtime/base/casts.h>
  #include <museum/8.1.0/art/runtime/base/iteration_range.h>
  
  namespace facebook { namespace museum { namespace MUSEUM_VERSION { namespace art {
  
  template<typename T>
  class LengthPrefixedArray {
   public:
    explicit LengthPrefixedArray(size_t length)
        : size_(dchecked_integral_cast<uint32_t>(length)) {}
  
    T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
      DCHECK_LT(index, size_);
      return AtUnchecked(index, element_size, alignment);
    }
  
    const T& At(size_t index, size_t element_size = sizeof(T), size_t alignment = alignof(T)) const {
      DCHECK_LT(index, size_);
      return AtUnchecked(index, element_size, alignment);
    }
  
    StrideIterator<T> begin(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
      return StrideIterator<T>(&AtUnchecked(0, element_size, alignment), element_size);
    }
  
    StrideIterator<const T> begin(size_t element_size = sizeof(T),
                                  size_t alignment = alignof(T)) const {
      return StrideIterator<const T>(&AtUnchecked(0, element_size, alignment), element_size);
    }
  
    StrideIterator<T> end(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
      return StrideIterator<T>(&AtUnchecked(size_, element_size, alignment), element_size);
    }
  
    StrideIterator<const T> end(size_t element_size = sizeof(T),
                                size_t alignment = alignof(T)) const {
      return StrideIterator<const T>(&AtUnchecked(size_, element_size, alignment), element_size);
    }
  
    static size_t OffsetOfElement(size_t index,
                                  size_t element_size = sizeof(T),
                                  size_t alignment = alignof(T)) {
      DCHECK_ALIGNED_PARAM(element_size, alignment);
      return RoundUp(offsetof(LengthPrefixedArray<T>, data_), alignment) + index * element_size;
    }
  
    static size_t ComputeSize(size_t num_elements,
                              size_t element_size = sizeof(T),
                              size_t alignment = alignof(T)) {
      size_t result = OffsetOfElement(num_elements, element_size, alignment);
      DCHECK_ALIGNED_PARAM(result, alignment);
      return result;
    }
  
    size_t size() const {
      return size_;
    }
  
    // Update the length but does not reallocate storage.
    void SetSize(size_t length) {
      size_ = dchecked_integral_cast<uint32_t>(length);
    }
  
    // Clear the potentially uninitialized padding between the size_ and actual data.
    void ClearPadding(size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
      size_t gap_offset = offsetof(LengthPrefixedArray<T>, data_);
      size_t gap_size = OffsetOfElement(0, element_size, alignment) - gap_offset;
      memset(reinterpret_cast<uint8_t*>(this) + gap_offset, 0, gap_size);
    }
  
   private:
    T& AtUnchecked(size_t index, size_t element_size, size_t alignment) {
      return *reinterpret_cast<T*>(
          reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment));
    }
  
    const T& AtUnchecked(size_t index, size_t element_size, size_t alignment) const {
      return *reinterpret_cast<T*>(
          reinterpret_cast<uintptr_t>(this) + OffsetOfElement(index, element_size, alignment));
    }
  
    uint32_t size_;
    uint8_t data_[0];
  };
  
  // Returns empty iteration range if the array is null.
  template<typename T>
  IterationRange<StrideIterator<T>> MakeIterationRangeFromLengthPrefixedArray(
      LengthPrefixedArray<T>* arr, size_t element_size = sizeof(T), size_t alignment = alignof(T)) {
    return arr != nullptr ?
        MakeIterationRange(arr->begin(element_size, alignment), arr->end(element_size, alignment)) :
        MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0));
  }
  
  } } } } // namespace facebook::museum::MUSEUM_VERSION::art
  
  #endif  // ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
  