chromium/third_party/abseil-cpp/absl/strings/internal/cord_internal.h

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

#ifndef ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
#define ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_

#include <atomic>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <type_traits>

#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
#include "absl/base/internal/invoke.h"
#include "absl/base/optimization.h"
#include "absl/container/internal/compressed_tuple.h"
#include "absl/container/internal/container_memory.h"
#include "absl/meta/type_traits.h"
#include "absl/strings/string_view.h"

// We can only add poisoning if we can detect consteval executions.
#if defined(ABSL_HAVE_CONSTANT_EVALUATED) && \
    (defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
     defined(ABSL_HAVE_MEMORY_SANITIZER))
#define ABSL_INTERNAL_CORD_HAVE_SANITIZER
#endif

#define ABSL_CORD_INTERNAL_NO_SANITIZE

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {

// The overhead of a vtable is too much for Cord, so we roll our own subclasses
// using only a single byte to differentiate classes from each other - the "tag"
// byte.  Define the subclasses first so we can provide downcasting helper
// functions in the base class.
struct CordRep;
struct CordRepConcat;
struct CordRepExternal;
struct CordRepFlat;
struct CordRepSubstring;
struct CordRepCrc;
class CordRepBtree;

class CordzInfo;

// Default feature enable states for cord ring buffers
enum CordFeatureDefaults {};

extern std::atomic<bool> shallow_subcords_enabled;

inline void enable_shallow_subcords(bool enable) {}

enum Constants {};

// Emits a fatal error "Unexpected node type: xyz" and aborts the program.
[[noreturn]] void LogFatalNodeType(CordRep* rep);

// Fast implementation of memmove for up to 15 bytes. This implementation is
// safe for overlapping regions. If nullify_tail is true, the destination is
// padded with '\0' up to 15 bytes.
template <bool nullify_tail = false>
inline void SmallMemmove(char* dst, const char* src, size_t n) {}

// Compact class for tracking the reference count and state flags for CordRep
// instances.  Data is stored in an atomic int32_t for compactness and speed.
class RefcountAndFlags {};

// Various representations that we allow
enum CordRepKind {};

// There are various locations where we want to check if some rep is a 'plain'
// data edge, i.e. an external or flat rep. By having FLAT == EXTERNAL + 1, we
// can perform this check in a single branch as 'tag >= EXTERNAL'
// Note that we can leave this optimization to the compiler. The compiler will
// DTRT when it sees a condition like `tag == EXTERNAL || tag >= FLAT`.
static_assert;

struct CordRep {};

struct CordRepSubstring : public CordRep {};

// Type for function pointer that will invoke the releaser function and also
// delete the `CordRepExternalImpl` corresponding to the passed in
// `CordRepExternal`.
ExternalReleaserInvoker;

// External CordReps are allocated together with a type erased releaser. The
// releaser is stored in the memory directly following the CordRepExternal.
struct CordRepExternal : public CordRep {};

// Use go/ranked-overloads for dispatching.
struct Rank0 {};
struct Rank1 : Rank0 {};

template <typename Releaser, typename = ::absl::base_internal::invoke_result_t<
                                 Releaser, absl::string_view>>
void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view data) {}

template <typename Releaser,
          typename = ::absl::base_internal::invoke_result_t<Releaser>>
void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view) {}

// We use CompressedTuple so that we can benefit from EBCO.
template <typename Releaser>
struct CordRepExternalImpl
    : public CordRepExternal,
      public ::absl::container_internal::CompressedTuple<Releaser> {};

inline CordRepSubstring* CordRepSubstring::Create(CordRep* child, size_t pos,
                                                  size_t n) {}

inline CordRep* CordRepSubstring::Substring(CordRep* rep, size_t pos,
                                            size_t n) {}

inline void CordRepExternal::Delete(CordRep* rep) {}

template <typename Str>
struct ConstInitExternalStorage {};

template <typename Str>
ABSL_CONST_INIT CordRepExternal
    ConstInitExternalStorage<Str>::value(Str::value);

enum {};

constexpr char GetOrNull(absl::string_view data, size_t pos) {}

// We store cordz_info as 64 bit pointer value in little endian format. This
// guarantees that the least significant byte of cordz_info matches the first
// byte of the inline data representation in `data`, which holds the inlined
// size or the 'is_tree' bit.
cordz_info_t;

// Assert that the `cordz_info` pointer value perfectly overlaps the last half
// of `data` and can hold a pointer value.
static_assert;
static_assert;

// LittleEndianByte() creates a little endian representation of 'value', i.e.:
// a little endian value where the first byte in the host's representation
// holds 'value`, with all other bytes being 0.
static constexpr cordz_info_t LittleEndianByte(unsigned char value) {}

class InlineData {};

static_assert;

#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER

constexpr InlineData::InlineData(const InlineData& rhs) noexcept
    : rep_(rhs.rep_.SanitizerSafeCopy()) {
  poison();
}

inline InlineData& InlineData::operator=(const InlineData& rhs) noexcept {
  unpoison();
  rep_ = rhs.rep_.SanitizerSafeCopy();
  poison();
  return *this;
}

constexpr void InlineData::poison_this() {
  if (!absl::is_constant_evaluated()) {
    container_internal::SanitizerPoisonObject(this);
  }
}

constexpr void InlineData::unpoison() {
  if (!absl::is_constant_evaluated()) {
    container_internal::SanitizerUnpoisonObject(this);
  }
}

constexpr void InlineData::poison() {
  if (!absl::is_constant_evaluated()) {
    if (is_tree()) {
      container_internal::SanitizerUnpoisonObject(this);
    } else if (const size_t size = inline_size()) {
      if (size < kMaxInline) {
        const char* end = rep_.as_chars() + size;
        container_internal::SanitizerPoisonMemoryRegion(end, kMaxInline - size);
      }
    } else {
      container_internal::SanitizerPoisonObject(this);
    }
  }
}

#else  // ABSL_INTERNAL_CORD_HAVE_SANITIZER

constexpr InlineData::InlineData(const InlineData&) noexcept = default;
inline InlineData& InlineData::operator=(const InlineData&) noexcept = default;

constexpr void InlineData::poison_this() {}
constexpr void InlineData::unpoison() {}
constexpr void InlineData::poison() {}

#endif  // ABSL_INTERNAL_CORD_HAVE_SANITIZER

inline CordRepSubstring* CordRep::substring() {}

inline const CordRepSubstring* CordRep::substring() const {}

inline CordRepExternal* CordRep::external() {}

inline const CordRepExternal* CordRep::external() const {}

inline CordRep* CordRep::Ref(CordRep* rep) {}

inline void CordRep::Unref(CordRep* rep) {}

inline void swap(InlineData& lhs, InlineData& rhs) noexcept {}

}  // namespace cord_internal

ABSL_NAMESPACE_END
}  // namespace absl
#endif  // ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_