// Copyright 2024 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#ifndef CORE_FXCRT_STRING_TEMPLATE_H_
#define CORE_FXCRT_STRING_TEMPLATE_H_

#include <stddef.h>

#include <type_traits>

#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/span.h"
#include "core/fxcrt/string_data_template.h"
#include "core/fxcrt/string_view_template.h"

namespace fxcrt {

inline constexpr const char* EmptyString(char*) {
  return "";
}
inline constexpr const wchar_t* EmptyString(wchar_t*) {
  return L"";
}

// Base class for a  mutable string with shared buffers using copy-on-write
// semantics that avoids std::string's iterator stability guarantees.
template <typename T>
class StringTemplate {
 public:
  using CharType = T;
  using UnsignedType = typename std::make_unsigned<CharType>::type;
  using StringView = StringViewTemplate<T>;
  using const_iterator = T*;
  using const_reverse_iterator = std::reverse_iterator<const_iterator>;

  bool IsEmpty() const { return !GetLength(); }
  size_t GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; }

  // Return length as determined by the position of the first NUL.
  size_t GetStringLength() const {
    return m_pData ? m_pData->GetStringLength() : 0;
  }

  // Explicit conversion to UnsignedType*. May return nullptr.
  // Note: Any subsequent modification of |this| will invalidate the result.
  const UnsignedType* unsigned_str() const {
    return m_pData ? reinterpret_cast<const UnsignedType*>(m_pData->m_String)
                   : nullptr;
  }

  // Explicit conversion to StringView.
  // Note: Any subsequent modification of |this| will invalidate the result.
  StringView AsStringView() const {
    return StringView(unsigned_str(), GetLength());
  }

  // Explicit conversion to C-style string. The result is never nullptr,
  // and is always NUL terminated.
  // Note: Any subsequent modification of |this| will invalidate the result.
  const CharType* c_str() const {
    return m_pData ? m_pData->m_String
                   : EmptyString(static_cast<CharType*>(nullptr));
  }

  // Explicit conversion to span.
  // Note: Any subsequent modification of |this| will invalidate the result.
  pdfium::span<const CharType> span() const {
    return m_pData ? m_pData->span() : pdfium::span<const CharType>();
  }

  // Explicit conversion to spans of unsigned types.
  // Note: Any subsequent modification of |this| will invalidate the result.
  pdfium::span<const UnsignedType> unsigned_span() const {
    return reinterpret_span<const UnsignedType>(span());
  }

  // Explicit conversion to spans including the NUL terminator. The result is
  // never an empty span. Only a const-form is provided to preclude modifying
  // the terminator. Usage should be rare and carefully considered.
  // Note: Any subsequent modification of |this| will invalidate the result.
  pdfium::span<const CharType> span_with_terminator() const {
    // SAFETY: EmptyString() returns one NUL byte.
    return m_pData ? m_pData->span_with_terminator()
                   : UNSAFE_BUFFERS(pdfium::make_span(
                         EmptyString(static_cast<CharType*>(nullptr)), 1u));
  }

  // Explicit conversion to spans of unsigned types including the NUL
  // terminator. The result is never an empty span. Only a const-form is
  // provided to preclude modifying the terminator. Usage should be rare
  // and carefully considered.
  // Note: Any subsequent modification of |this| will invalidate the result.
  pdfium::span<const UnsignedType> unsigned_span_with_terminator() const {
    return reinterpret_span<const UnsignedType>(span_with_terminator());
  }

  // Note: Any subsequent modification of |this| will invalidate iterators.
  const_iterator begin() const {
    return m_pData ? m_pData->span().begin() : nullptr;
  }
  const_iterator end() const {
    return m_pData ? m_pData->span().end() : nullptr;
  }

  // Note: Any subsequent modification of |this| will invalidate iterators.
  const_reverse_iterator rbegin() const {
    return const_reverse_iterator(end());
  }
  const_reverse_iterator rend() const {
    return const_reverse_iterator(begin());
  }

  bool IsValidIndex(size_t index) const { return index < GetLength(); }
  bool IsValidLength(size_t length) const { return length <= GetLength(); }

  // CHECK() if index is out of range (via span's operator[]).
  CharType operator[](const size_t index) const {
    CHECK(m_pData);
    return m_pData->span()[index];
  }

  // Unlike std::wstring::front(), this is always safe and returns a
  // NUL char when the string is empty.
  CharType Front() const { return m_pData ? m_pData->Front() : 0; }

  // Unlike std::wstring::back(), this is always safe and returns a
  // NUL char when the string is empty.
  CharType Back() const { return m_pData ? m_pData->Back() : 0; }

  // Holds on to buffer if possible for later re-use. Use assignment
  // to force immediate release if desired.
  void clear();

  // Increase the backing store of the string so that it is capable of storing
  // at least `nMinBufLength` chars. Returns a span to the entire buffer,
  // which may be larger than `nMinBufLength` due to rounding by allocators.
  // Note: any modification of the string (including ReleaseBuffer()) may
  // invalidate the span, which must not outlive its buffer.
  pdfium::span<T> GetBuffer(size_t nMinBufLength);

  // Sets the size of the string to `nNewLength` chars. Call this after a call
  // to GetBuffer(), to indicate how much of the buffer was actually used.
  void ReleaseBuffer(size_t nNewLength);

  // Returns size of string following insertion.
  size_t Insert(size_t index, T ch);
  size_t InsertAtFront(T ch) { return Insert(0, ch); }
  size_t InsertAtBack(T ch) { return Insert(GetLength(), ch); }

  // Returns number of instances of `ch` removed.
  size_t Remove(T ch);

  // Returns size of the string following deletion.
  size_t Delete(size_t index, size_t count = 1);

  // Returns the index within the string when found.
  std::optional<size_t> Find(StringView str, size_t start = 0) const;
  std::optional<size_t> Find(T ch, size_t start = 0) const;
  std::optional<size_t> ReverseFind(T ch) const;

  bool Contains(StringView str, size_t start = 0) const {
    return Find(str, start).has_value();
  }
  bool Contains(T ch, size_t start = 0) const {
    return Find(ch, start).has_value();
  }

  // Replace all occurences of `oldstr' with `newstr'.
  size_t Replace(StringView oldstr, StringView newstr);

  // Overwrite character at `index`.
  void SetAt(size_t index, T ch);

  void Reserve(size_t len) { GetBuffer(len); }

  // Remove character `ch` from  both/front/back of string.
  void Trim(T ch);
  void TrimFront(T ch);
  void TrimBack(T ch);

  // Remove all characters in `targets` from both/front/back of string.
  void Trim(StringView targets);
  void TrimFront(StringView targets);
  void TrimBack(StringView targets);

 protected:
  using StringData = StringDataTemplate<T>;

  StringTemplate() = default;
  StringTemplate(const StringTemplate& other) = default;

  // Move-construct a StringTemplate. After construction, |other| is empty.
  StringTemplate(StringTemplate&& other) noexcept = default;

  ~StringTemplate() = default;

  void ReallocBeforeWrite(size_t nNewLen);
  void AllocBeforeWrite(size_t nNewLen);
  void AssignCopy(const T* pSrcData, size_t nSrcLen);
  void Concat(const T* pSrcData, size_t nSrcLen);

  RetainPtr<StringData> m_pData;
};

extern template class StringTemplate<char>;
extern template class StringTemplate<wchar_t>;

}  // namespace fxcrt

#endif  // CORE_FXCRT_STRING_TEMPLATE_H_
