// 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 "absl/strings/cord_analysis.h"

#include <cstddef>
#include <cstdint>

#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/container/inlined_vector.h"
#include "absl/strings/internal/cord_data_edge.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;
  }
};

// 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
