// Copyright 2020 The Abseil Authors
//
// 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
//
//     https://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 ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_
#define ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iosfwd>
#include <limits>
#include <memory>

#include "absl/container/internal/layout.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_flat.h"

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {

// All operations modifying a ring buffer are implemented as static methods
// requiring a CordRepRing instance with a reference adopted by the method.
//
// The methods return the modified ring buffer, which may be equal to the input
// if the input was not shared, and having large enough capacity to accommodate
// any newly added node(s). Otherwise, a copy of the input rep with the new
// node(s) added is returned.
//
// Any modification on non shared ring buffers with enough capacity will then
// require minimum atomic operations. Caller should where possible provide
// reasonable `extra` hints for both anticipated extra `flat` byte space, as
// well as anticipated extra nodes required for complex operations.
//
// Example of code creating a ring buffer, adding some data to it,
// and discarding the buffer when done:
//
//   void FunWithRings() {
//     // Create ring with 3 flats
//     CordRep* flat = CreateFlat("Hello");
//     CordRepRing* ring = CordRepRing::Create(flat, 2);
//     ring = CordRepRing::Append(ring, CreateFlat(" "));
//     ring = CordRepRing::Append(ring, CreateFlat("world"));
//     DoSomethingWithRing(ring);
//     CordRep::Unref(ring);
//   }
//
// Example of code Copying an existing ring buffer and modifying it:
//
//   void MoreFunWithRings(CordRepRing* src) {
//     CordRepRing* ring = CordRep::Ref(src)->ring();
//     ring = CordRepRing::Append(ring, CreateFlat("Hello"));
//     ring = CordRepRing::Append(ring, CreateFlat(" "));
//     ring = CordRepRing::Append(ring, CreateFlat("world"));
//     DoSomethingWithRing(ring);
//     CordRep::Unref(ring);
//   }
//
class CordRepRing : public CordRep {
 public:
  // `pos_type` represents a 'logical position'. A CordRepRing instance has a
  // `begin_pos` (default 0), and each node inside the buffer will have an
  // `end_pos` which is the `end_pos` of the previous node (or `begin_pos`) plus
  // this node's length. The purpose is to allow for a binary search on this
  // position, while allowing O(1) prepend and append operations.
  using pos_type = size_t;

  // `index_type` is the type for the `head`, `tail` and `capacity` indexes.
  // Ring buffers are limited to having no more than four billion entries.
  using index_type = uint32_t;

  // `offset_type` is the type for the data offset inside a child rep's data.
  using offset_type = uint32_t;

  // Position holds the node index and relative offset into the node for
  // some physical offset in the contained data as returned by the Find()
  // and FindTail() methods.
  struct Position {
    index_type index;
    size_t offset;
  };

  // The maximum # of child nodes that can be hosted inside a CordRepRing.
  static constexpr size_t kMaxCapacity = (std::numeric_limits<uint32_t>::max)();

  // CordRepring can not be default constructed, moved, copied or assigned.
  CordRepRing() = delete;
  CordRepRing(const CordRepRing&) = delete;
  CordRepRing& operator=(const CordRepRing&) = delete;

  // Returns true if this instance is valid, false if some or all of the
  // invariants are broken. Intended for debug purposes only.
  // `output` receives an explanation of the broken invariants.
  bool IsValid(std::ostream& output) const;

  // Returns the size in bytes for a CordRepRing with `capacity' entries.
  static constexpr size_t AllocSize(size_t capacity);

  // Returns the distance in bytes from `pos` to `end_pos`.
  static constexpr size_t Distance(pos_type pos, pos_type end_pos);

  // Creates a new ring buffer from the provided `rep`. Adopts a reference
  // on `rep`. The returned ring buffer has a capacity of at least `extra + 1`
  static CordRepRing* Create(CordRep* child, size_t extra = 0);

  // `head`, `tail` and `capacity` indexes defining the ring buffer boundaries.
  index_type head() const { return head_; }
  index_type tail() const { return tail_; }
  index_type capacity() const { return capacity_; }

  // Returns the number of entries in this instance.
  index_type entries() const { return entries(head_, tail_); }

  // Returns the logical begin position of this instance.
  pos_type begin_pos() const { return begin_pos_; }

  // Returns the number of entries for a given head-tail range.
  // Requires `head` and `tail` values to be less than `capacity()`.
  index_type entries(index_type head, index_type tail) const {
    assert(head < capacity_ && tail < capacity_);
    return tail - head + ((tail > head) ? 0 : capacity_);
  }

  // Returns the logical end position of entry `index`.
  pos_type const& entry_end_pos(index_type index) const {
    assert(IsValidIndex(index));
    return Layout::Partial().Pointer<0>(data_)[index];
  }

  // Returns the child pointer of entry `index`.
  CordRep* const& entry_child(index_type index) const {
    assert(IsValidIndex(index));
    return Layout::Partial(capacity()).Pointer<1>(data_)[index];
  }

  // Returns the data offset of entry `index`
  offset_type const& entry_data_offset(index_type index) const {
    assert(IsValidIndex(index));
    return Layout::Partial(capacity(), capacity()).Pointer<2>(data_)[index];
  }

  // Appends the provided child node to the `rep` instance.
  // Adopts a reference from `rep` and `child` which may not be null.
  // If the provided child is a FLAT or EXTERNAL node, or a SUBSTRING node
  // containing a FLAT or EXTERNAL node, then flat or external the node is added
  // 'as is', with an offset added for the SUBSTRING case.
  // If the provided child is a RING or CONCAT tree, or a SUBSTRING of a RING or
  // CONCAT tree, then all child nodes not excluded by any start offset or
  // length values are added recursively.
  static CordRepRing* Append(CordRepRing* rep, CordRep* child);

  // Appends the provided string data to the `rep` instance.
  // This function will attempt to utilize any remaining capacity in the last
  // node of the input if that node is not shared (directly or indirectly), and
  // of type FLAT. Remaining data will be added as one or more FLAT nodes.
  // Any last node added to the ring buffer will be allocated with up to
  // `extra` bytes of capacity for (anticipated) subsequent append actions.
  static CordRepRing* Append(CordRepRing* rep, string_view data,
                             size_t extra = 0);

  // Prepends the provided child node to the `rep` instance.
  // Adopts a reference from `rep` and `child` which may not be null.
  // If the provided child is a FLAT or EXTERNAL node, or a SUBSTRING node
  // containing a FLAT or EXTERNAL node, then flat or external the node is
  // prepended 'as is', with an optional offset added for the SUBSTRING case.
  // If the provided child is a RING or CONCAT tree, or a SUBSTRING of a RING
  // or CONCAT tree, then all child nodes not excluded by any start offset or
  // length values are added recursively.
  static CordRepRing* Prepend(CordRepRing* rep, CordRep* child);

  // Prepends the provided string data to the `rep` instance.
  // This function will attempt to utilize any remaining capacity in the first
  // node of the input if that node is not shared (directly or indirectly), and
  // of type FLAT. Remaining data will be added as one or more FLAT nodes.
  // Any first node prepnded to the ring buffer will be allocated with up to
  // `extra` bytes of capacity for (anticipated) subsequent prepend actions.
  static CordRepRing* Prepend(CordRepRing* rep, string_view data,
                              size_t extra = 0);

  // Returns a span referencing potentially unused capacity in the last node.
  // The returned span may be empty if no such capacity is available, or if the
  // current instance is shared. Else, a span of size `n <= size` is returned.
  // If non empty, the ring buffer is adjusted to the new length, with the newly
  // added capacity left uninitialized. Callers should assign a value to the
  // entire span before any other operations on this instance.
  Span<char> GetAppendBuffer(size_t size);

  // Returns a span referencing potentially unused capacity in the first node.
  // This function is identical to GetAppendBuffer except that it returns a span
  // referencing up to `size` capacity directly before the existing data.
  Span<char> GetPrependBuffer(size_t size);

  // Returns a cord ring buffer containing `len` bytes of data starting at
  // `offset`. If the input is not shared, this function will remove all head
  // and tail child nodes outside of the requested range, and adjust the new
  // head and tail nodes as required. If the input is shared, this function
  // returns a new instance sharing some or all of the nodes from the input.
  static CordRepRing* SubRing(CordRepRing* r, size_t offset, size_t len,
                              size_t extra = 0);

  // Returns a cord ring buffer with the first `len` bytes removed.
  // If the input is not shared, this function will remove all head child nodes
  // fully inside the first `length` bytes, and adjust the new head as required.
  // If the input is shared, this function returns a new instance sharing some
  // or all of the nodes from the input.
  static CordRepRing* RemoveSuffix(CordRepRing* r, size_t len,
                                   size_t extra = 0);

  // Returns a cord ring buffer with the last `len` bytes removed.
  // If the input is not shared, this function will remove all head child nodes
  // fully inside the first `length` bytes, and adjust the new head as required.
  // If the input is shared, this function returns a new instance sharing some
  // or all of the nodes from the input.
  static CordRepRing* RemovePrefix(CordRepRing* r, size_t len,
                                   size_t extra = 0);

  // Returns the character at `offset`. Requires that `offset < length`.
  char GetCharacter(size_t offset) const;

  // Returns true if this instance manages a single contiguous buffer, in which
  // case the (optional) output parameter `fragment` is set. Otherwise, the
  // function returns false, and `fragment` is left unchanged.
  bool IsFlat(absl::string_view* fragment) const;

  // Returns true if the data starting at `offset` with length `len` is
  // managed by this instance inside a single contiguous buffer, in which case
  // the (optional) output parameter `fragment` is set to the contiguous memory
  // starting at offset `offset` with length `length`. Otherwise, the function
  // returns false, and `fragment` is left unchanged.
  bool IsFlat(size_t offset, size_t len, absl::string_view* fragment) const;

  // Testing only: set capacity to requested capacity.
  void SetCapacityForTesting(size_t capacity);

  // Returns the CordRep data pointer for the provided CordRep.
  // Requires that the provided `rep` is either a FLAT or EXTERNAL CordRep.
  static const char* GetLeafData(const CordRep* rep);

  // Returns the CordRep data pointer for the provided CordRep.
  // Requires that `rep` is either a FLAT, EXTERNAL, or SUBSTRING CordRep.
  static const char* GetRepData(const CordRep* rep);

  // Advances the provided position, wrapping around capacity as needed.
  // Requires `index` < capacity()
  inline index_type advance(index_type index) const;

  // Advances the provided position by 'n`, wrapping around capacity as needed.
  // Requires `index` < capacity() and `n` <= capacity.
  inline index_type advance(index_type index, index_type n) const;

  // Retreats the provided position, wrapping around 0 as needed.
  // Requires `index` < capacity()
  inline index_type retreat(index_type index) const;

  // Retreats the provided position by 'n', wrapping around 0 as needed.
  // Requires `index` < capacity()
  inline index_type retreat(index_type index, index_type n) const;

  // Returns the logical begin position of entry `index`
  pos_type const& entry_begin_pos(index_type index) const {
    return (index == head_) ? begin_pos_ : entry_end_pos(retreat(index));
  }

  // Returns the physical start offset of entry `index`
  size_t entry_start_offset(index_type index) const {
    return Distance(begin_pos_, entry_begin_pos(index));
  }

  // Returns the physical end offset of entry `index`
  size_t entry_end_offset(index_type index) const {
    return Distance(begin_pos_, entry_end_pos(index));
  }

  // Returns the data length for entry `index`
  size_t entry_length(index_type index) const {
    return Distance(entry_begin_pos(index), entry_end_pos(index));
  }

  // Returns the data for entry `index`
  absl::string_view entry_data(index_type index) const;

  // Returns the position for `offset` as {index, prefix}. `index` holds the
  // index of the entry at the specified offset and `prefix` holds the relative
  // offset inside that entry.
  // Requires `offset` < length.
  //
  // For example we can implement GetCharacter(offset) as:
  //   char GetCharacter(size_t offset) {
  //     Position pos = this->Find(offset);
  //     return this->entry_data(pos.pos)[pos.offset];
  //   }
  inline Position Find(size_t offset) const;

  // Find starting at `head`
  inline Position Find(index_type head, size_t offset) const;

  // Returns the tail position for `offset` as {tail index, suffix}.
  // `tail index` holds holds the index of the entry holding the offset directly
  // before 'offset` advanced by one. 'suffix` holds the relative offset from
  // that relative offset in the entry to the end of the entry.
  // For example, FindTail(length) will return {tail(), 0}, FindTail(length - 5)
  // will return {retreat(tail), 5)} provided the preceding entry contains at
  // least 5 bytes of data.
  // Requires offset >= 1 && offset <= length.
  //
  // This function is very useful in functions that need to clip the end of some
  // ring buffer such as 'RemovePrefix'.
  // For example, we could implement RemovePrefix for non shared instances as:
  //   void RemoveSuffix(size_t n) {
  //     Position pos = FindTail(length - n);
  //     UnrefEntries(pos.pos, this->tail_);
  //     this->tail_ = pos.pos;
  //     entry(retreat(pos.pos)).end_pos -= pos.offset;
  //   }
  inline Position FindTail(size_t offset) const;

  // Find tail starting at `head`
  inline Position FindTail(index_type head, size_t offset) const;

  // Invokes f(index_type index) for each entry inside the range [head, tail>
  template <typename F>
  void ForEach(index_type head, index_type tail, F&& f) const {
    index_type n1 = (tail > head) ? tail : capacity_;
    for (index_type i = head; i < n1; ++i) f(i);
    if (tail <= head) {
      for (index_type i = 0; i < tail; ++i) f(i);
    }
  }

  // Invokes f(index_type index) for each entry inside this instance.
  template <typename F>
  void ForEach(F&& f) const {
    ForEach(head_, tail_, std::forward<F>(f));
  }

  // Dump this instance's data tp stream `s` in human readable format, excluding
  // the actual data content itself. Intended for debug purposes only.
  friend std::ostream& operator<<(std::ostream& s, const CordRepRing& rep);

 private:
  enum class AddMode { kAppend, kPrepend };

  using Layout = container_internal::Layout<pos_type, CordRep*, offset_type>;

  class Filler;
  class Transaction;
  class CreateTransaction;

  static constexpr size_t kLayoutAlignment = Layout::Partial().Alignment();

  // Creates a new CordRepRing.
  explicit CordRepRing(index_type capacity) : capacity_(capacity) {}

  // Returns true if `index` is a valid index into this instance.
  bool IsValidIndex(index_type index) const;

  // Debug use only: validates the provided CordRepRing invariants.
  // Verification of all CordRepRing methods can be enabled by defining
  // EXTRA_CORD_RING_VALIDATION, i.e.: `--copts=-DEXTRA_CORD_RING_VALIDATION`
  // Verification is VERY expensive, so only do it for debugging purposes.
  static CordRepRing* Validate(CordRepRing* rep, const char* file = nullptr,
                               int line = 0);

  // Allocates a CordRepRing large enough to hold `capacity + extra' entries.
  // The returned capacity may be larger if the allocated memory allows for it.
  // The maximum capacity of a CordRepRing is capped at kMaxCapacity.
  // Throws `std::length_error` if `capacity + extra' exceeds kMaxCapacity.
  static CordRepRing* New(size_t capacity, size_t extra);

  // Deallocates (but does not destroy) the provided ring buffer.
  static void Delete(CordRepRing* rep);

  // Destroys the provided ring buffer, decrementing the reference count of all
  // contained child CordReps. The provided 1\`rep` should have a ref count of
  // one (pre decrement destroy call observing `refcount.IsOne()`) or zero
  // (post decrement destroy call observing `!refcount.Decrement()`).
  static void Destroy(CordRepRing* rep);

  // Returns a mutable reference to the logical end position array.
  pos_type* entry_end_pos() {
    return Layout::Partial().Pointer<0>(data_);
  }

  // Returns a mutable reference to the child pointer array.
  CordRep** entry_child() {
    return Layout::Partial(capacity()).Pointer<1>(data_);
  }

  // Returns a mutable reference to the data offset array.
  offset_type* entry_data_offset() {
    return Layout::Partial(capacity(), capacity()).Pointer<2>(data_);
  }

  // Find implementations for the non fast path 0 / length cases.
  Position FindSlow(index_type head, size_t offset) const;
  Position FindTailSlow(index_type head, size_t offset) const;

  // Finds the index of the first node that is inside a reasonable distance
  // of the node at `offset` from which we can continue with a linear search.
  template <bool wrap>
  index_type FindBinary(index_type head, index_type tail, size_t offset) const;

  // Fills the current (initialized) instance from the provided source, copying
  // entries [head, tail). Adds a reference to copied entries if `ref` is true.
  template <bool ref>
  void Fill(const CordRepRing* src, index_type head, index_type tail);

  // Create a copy of 'rep', copying all entries [head, tail), allocating room
  // for `extra` entries. Adds a reference on all copied entries.
  static CordRepRing* Copy(CordRepRing* rep, index_type head, index_type tail,
                           size_t extra = 0);

  // Returns a Mutable CordRepRing reference from `rep` with room for at least
  // `extra` additional nodes. Adopts a reference count from `rep`.
  // This function will return `rep` if, and only if:
  // - rep.entries + extra <= rep.capacity
  // - rep.refcount == 1
  // Otherwise, this function will create a new copy of `rep` with additional
  // capacity to satisfy `extra` extra nodes, and unref the old `rep` instance.
  //
  // If a new CordRepRing can not be allocated, or the new capacity would exceed
  // the maxmimum capacity, then the input is consumed only, and an exception is
  // thrown.
  static CordRepRing* Mutable(CordRepRing* rep, size_t extra);

  // Slow path for Append(CordRepRing* rep, CordRep* child). This function is
  // exercised if the provided `child` in Append() is not a leaf node, i.e., a
  // ring buffer or old (concat) cord tree.
  static CordRepRing* AppendSlow(CordRepRing* rep, CordRep* child);

  // Appends the provided leaf node. Requires `child` to be FLAT or EXTERNAL.
  static CordRepRing* AppendLeaf(CordRepRing* rep, CordRep* child,
                                 size_t offset, size_t length);

  // Prepends the provided leaf node. Requires `child` to be FLAT or EXTERNAL.
  static CordRepRing* PrependLeaf(CordRepRing* rep, CordRep* child,
                                  size_t offset, size_t length);

  // Slow path for Prepend(CordRepRing* rep, CordRep* child). This function is
  // exercised if the provided `child` in Prepend() is not a leaf node, i.e., a
  // ring buffer or old (concat) cord tree.
  static CordRepRing* PrependSlow(CordRepRing* rep, CordRep* child);

  // Slow path for Create(CordRep* child, size_t extra). This function is
  // exercised if the provided `child` in Prepend() is not a leaf node, i.e., a
  // ring buffer or old (concat) cord tree.
  static CordRepRing* CreateSlow(CordRep* child, size_t extra);

  // Creates a new ring buffer from the provided `child` leaf node. Requires
  // `child` to be FLAT or EXTERNAL. on `rep`.
  // The returned ring buffer has a capacity of at least `1 + extra`
  static CordRepRing* CreateFromLeaf(CordRep* child, size_t offset,
                                     size_t length, size_t extra);

  // Appends or prepends (depending on AddMode) the ring buffer in `ring' to
  // `rep` starting at `offset` with length `len`.
  template <AddMode mode>
  static CordRepRing* AddRing(CordRepRing* rep, CordRepRing* ring,
                              size_t offset, size_t len);

  // Increases the data offset for entry `index` by `n`.
  void AddDataOffset(index_type index, size_t n);

  // Descreases the length for entry `index` by `n`.
  void SubLength(index_type index, size_t n);

  index_type head_;
  index_type tail_;
  index_type capacity_;
  pos_type begin_pos_;

  alignas(kLayoutAlignment) char data_[kLayoutAlignment];

  friend struct CordRep;
};

constexpr size_t CordRepRing::AllocSize(size_t capacity) {
  return sizeof(CordRepRing) - sizeof(data_) +
         Layout(capacity, capacity, capacity).AllocSize();
}

inline constexpr size_t CordRepRing::Distance(pos_type pos, pos_type end_pos) {
  return (end_pos - pos);
}

inline const char* CordRepRing::GetLeafData(const CordRep* rep) {
  return rep->tag != EXTERNAL ? rep->flat()->Data() : rep->external()->base;
}

inline const char* CordRepRing::GetRepData(const CordRep* rep) {
  if (rep->tag >= FLAT) return rep->flat()->Data();
  if (rep->tag == EXTERNAL) return rep->external()->base;
  return GetLeafData(rep->substring()->child) + rep->substring()->start;
}

inline CordRepRing::index_type CordRepRing::advance(index_type index) const {
  assert(index < capacity_);
  return ++index == capacity_ ? 0 : index;
}

inline CordRepRing::index_type CordRepRing::advance(index_type index,
                                                    index_type n) const {
  assert(index < capacity_ && n <= capacity_);
  return (index += n) >= capacity_ ? index - capacity_ : index;
}

inline CordRepRing::index_type CordRepRing::retreat(index_type index) const {
  assert(index < capacity_);
  return (index > 0 ? index : capacity_) - 1;
}

inline CordRepRing::index_type CordRepRing::retreat(index_type index,
                                                    index_type n) const {
  assert(index < capacity_ && n <= capacity_);
  return index >= n ? index - n : capacity_ - n + index;
}

inline absl::string_view CordRepRing::entry_data(index_type index) const {
  size_t data_offset = entry_data_offset(index);
  return {GetRepData(entry_child(index)) + data_offset, entry_length(index)};
}

inline bool CordRepRing::IsValidIndex(index_type index) const {
  if (index >= capacity_) return false;
  return (tail_ > head_) ? (index >= head_ && index < tail_)
                         : (index >= head_ || index < tail_);
}

#ifndef EXTRA_CORD_RING_VALIDATION
inline CordRepRing* CordRepRing::Validate(CordRepRing* rep,
                                          const char* /*file*/, int /*line*/) {
  return rep;
}
#endif

inline CordRepRing::Position CordRepRing::Find(size_t offset) const {
  assert(offset < length);
  return (offset == 0) ? Position{head_, 0} : FindSlow(head_, offset);
}

inline CordRepRing::Position CordRepRing::Find(index_type head,
                                               size_t offset) const {
  assert(offset < length);
  assert(IsValidIndex(head) && offset >= entry_start_offset(head));
  return (offset == 0) ? Position{head_, 0} : FindSlow(head, offset);
}

inline CordRepRing::Position CordRepRing::FindTail(size_t offset) const {
  assert(offset > 0 && offset <= length);
  return (offset == length) ? Position{tail_, 0} : FindTailSlow(head_, offset);
}

inline CordRepRing::Position CordRepRing::FindTail(index_type head,
                                                   size_t offset) const {
  assert(offset > 0 && offset <= length);
  assert(IsValidIndex(head) && offset >= entry_start_offset(head) + 1);
  return (offset == length) ? Position{tail_, 0} : FindTailSlow(head, offset);
}

// Now that CordRepRing is defined, we can define CordRep's helper casts:
inline CordRepRing* CordRep::ring() {
  assert(IsRing());
  return static_cast<CordRepRing*>(this);
}

inline const CordRepRing* CordRep::ring() const {
  assert(IsRing());
  return static_cast<const CordRepRing*>(this);
}

inline bool CordRepRing::IsFlat(absl::string_view* fragment) const {
  if (entries() == 1) {
    if (fragment) *fragment = entry_data(head());
    return true;
  }
  return false;
}

inline bool CordRepRing::IsFlat(size_t offset, size_t len,
                                absl::string_view* fragment) const {
  const Position pos = Find(offset);
  const absl::string_view data = entry_data(pos.index);
  if (data.length() >= len && data.length() - len >= pos.offset) {
    if (fragment) *fragment = data.substr(pos.offset, len);
    return true;
  }
  return false;
}

std::ostream& operator<<(std::ostream& s, const CordRepRing& rep);

}  // namespace cord_internal
ABSL_NAMESPACE_END
}  // namespace absl

#endif  // ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_
