// Copyright 2021 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.

#include <cstddef>
#include <cstdint>

#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/container/inlined_vector.h"
#include "absl/strings/cord_analysis.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_btree.h"
#include "absl/strings/internal/cord_rep_crc.h"
#include "absl/strings/internal/cord_rep_flat.h"
#include "absl/strings/internal/cord_rep_ring.h"
//
#include "absl/base/macros.h"
#include "absl/base/port.h"
#include "absl/functional/function_ref.h"

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
namespace {

// Accounting mode for analyzing memory usage.
enum class Mode { kTotal, kFairShare };

// CordRepRef holds a `const CordRep*` reference in rep, and depending on mode,
// holds a 'fraction' representing a cumulative inverse refcount weight.
template <Mode mode>
struct CordRepRef {
  // Instantiates a CordRepRef instance.
  explicit CordRepRef(const CordRep* r) : rep(r) {}

  // Creates a child reference holding the provided child.
  // Overloaded to add cumulative reference count for kFairShare.
  CordRepRef Child(const CordRep* child) const { return CordRepRef(child); }

  const CordRep* rep;
};

// RawUsage holds the computed total number of bytes.
template <Mode mode>
struct RawUsage {
  size_t total = 0;

  // Add 'size' to total, ignoring the CordRepRef argument.
  void Add(size_t size, CordRepRef<mode>) { total += size; }
};

// Returns n / refcount avoiding a div for the common refcount == 1.
template <typename refcount_t>
double MaybeDiv(double d, refcount_t refcount) {
  return refcount == 1 ? d : d / refcount;
}

// Overloaded 'kFairShare' specialization for CordRepRef. This class holds a
// `fraction` value which represents a cumulative inverse refcount weight.
// For example, a top node with a reference count of 2 will have a fraction
// value of 1/2 = 0.5, representing the 'fair share' of memory it references.
// A node below such a node with a reference count of 5 then has a fraction of
// 0.5 / 5 = 0.1 representing the fair share of memory below that node, etc.
template <>
struct CordRepRef<Mode::kFairShare> {
  // Creates a CordRepRef with the provided rep and top (parent) fraction.
  explicit CordRepRef(const CordRep* r, double frac = 1.0)
      : rep(r), fraction(MaybeDiv(frac, r->refcount.Get())) {}

  // Returns a CordRepRef with a fraction of `this->fraction / child.refcount`
  CordRepRef Child(const CordRep* child) const {
    return CordRepRef(child, fraction);
  }

  const CordRep* rep;
  double fraction;
};

// Overloaded 'kFairShare' specialization for RawUsage
template <>
struct RawUsage<Mode::kFairShare> {
  double total = 0;

  // Adds `size` multiplied by `rep.fraction` to the total size.
  void Add(size_t size, CordRepRef<Mode::kFairShare> rep) {
    total += static_cast<double>(size) * rep.fraction;
  }
};

// Returns true if the provided rep is a valid data edge.
bool IsDataEdge(const CordRep* rep) {
  // The fast path is that `rep` is an EXTERNAL or FLAT node, making the below
  // if a single, well predicted branch. We then repeat the FLAT or EXTERNAL
  // check in the slow path the SUBSTRING check to optimize for the hot path.
  if (rep->tag == EXTERNAL || rep->tag >= FLAT) return true;
  if (rep->tag == SUBSTRING) rep = rep->substring()->child;
  return rep->tag == EXTERNAL || rep->tag >= FLAT;
}

// Computes the estimated memory size of the provided data edge.
// External reps are assumed 'heap allocated at their exact size'.
template <Mode mode>
void AnalyzeDataEdge(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) {
  assert(IsDataEdge(rep.rep));

  // Consume all substrings
  if (rep.rep->tag == SUBSTRING) {
    raw_usage.Add(sizeof(CordRepSubstring), rep);
    rep = rep.Child(rep.rep->substring()->child);
  }

  // Consume FLAT / EXTERNAL
  const size_t size =
      rep.rep->tag >= FLAT
          ? rep.rep->flat()->AllocatedSize()
          : rep.rep->length + sizeof(CordRepExternalImpl<intptr_t>);
  raw_usage.Add(size, rep);
}

// Computes the memory size of the provided Ring tree.
template <Mode mode>
void AnalyzeRing(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) {
  const CordRepRing* ring = rep.rep->ring();
  raw_usage.Add(CordRepRing::AllocSize(ring->capacity()), rep);
  ring->ForEach([&](CordRepRing::index_type pos) {
    AnalyzeDataEdge(rep.Child(ring->entry_child(pos)), raw_usage);
  });
}

// Computes the memory size of the provided Btree tree.
template <Mode mode>
void AnalyzeBtree(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) {
  raw_usage.Add(sizeof(CordRepBtree), rep);
  const CordRepBtree* tree = rep.rep->btree();
  if (tree->height() > 0) {
    for (CordRep* edge : tree->Edges()) {
      AnalyzeBtree(rep.Child(edge), raw_usage);
    }
  } else {
    for (CordRep* edge : tree->Edges()) {
      AnalyzeDataEdge(rep.Child(edge), raw_usage);
    }
  }
}

template <Mode mode>
size_t GetEstimatedUsage(const CordRep* rep) {
  // Zero initialized memory usage totals.
  RawUsage<mode> raw_usage;

  // Capture top level node and refcount into a CordRepRef.
  CordRepRef<mode> repref(rep);

  // Consume the top level CRC node if present.
  if (repref.rep->tag == CRC) {
    raw_usage.Add(sizeof(CordRepCrc), repref);
    repref = repref.Child(repref.rep->crc()->child);
  }

  if (IsDataEdge(repref.rep)) {
    AnalyzeDataEdge(repref, raw_usage);
  } else if (repref.rep->tag == BTREE) {
    AnalyzeBtree(repref, raw_usage);
  } else if (repref.rep->tag == RING) {
    AnalyzeRing(repref, raw_usage);
  } else {
    assert(false);
  }

  return static_cast<size_t>(raw_usage.total);
}

}  // namespace

size_t GetEstimatedMemoryUsage(const CordRep* rep) {
  return GetEstimatedUsage<Mode::kTotal>(rep);
}

size_t GetEstimatedFairShareMemoryUsage(const CordRep* rep) {
  return GetEstimatedUsage<Mode::kFairShare>(rep);
}

}  // namespace cord_internal
ABSL_NAMESPACE_END
}  // namespace absl
