/*
 * 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_LIBARTBASE_BASE_LENGTH_PREFIXED_ARRAY_H_
#define ART_LIBARTBASE_BASE_LENGTH_PREFIXED_ARRAY_H_

#include <stddef.h>  // for offsetof()
#include <string.h>  // for memset()

#include "bit_utils.h"
#include "casts.h"
#include "iteration_range.h"
#include "stride_iterator.h"

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 art

#endif  // ART_LIBARTBASE_BASE_LENGTH_PREFIXED_ARRAY_H_
