// Copyright 2016 PDFium Authors. All rights reserved.
// 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_CFX_STRING_C_TEMPLATE_H_
#define CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_

#include <algorithm>
#include <iterator>
#include <type_traits>
#include <utility>
#include <vector>

#include "core/fxcrt/cfx_unowned_ptr.h"
#include "core/fxcrt/fx_system.h"
#include "third_party/base/optional.h"
#include "third_party/base/stl_util.h"

// An immutable string with caller-provided storage which must outlive the
// string itself. These are not necessarily nul-terminated, so that substring
// extraction (via the Mid(), Left(), and Right() methods) is copy-free.
template <typename T>
class CFX_StringCTemplate {
 public:
  using CharType = T;
  using UnsignedType = typename std::make_unsigned<CharType>::type;
  using const_iterator = const CharType*;
  using const_reverse_iterator = std::reverse_iterator<const_iterator>;

  CFX_StringCTemplate() : m_Ptr(nullptr), m_Length(0) {}

  // Deliberately implicit to avoid calling on every string literal.
  // NOLINTNEXTLINE(runtime/explicit)
  CFX_StringCTemplate(const CharType* ptr)
      : m_Ptr(reinterpret_cast<const UnsignedType*>(ptr)),
        m_Length(ptr ? FXSYS_len(ptr) : 0) {}

  CFX_StringCTemplate(const CharType* ptr, FX_STRSIZE len)
      : m_Ptr(reinterpret_cast<const UnsignedType*>(ptr)), m_Length(len) {}

  template <typename U = UnsignedType>
  CFX_StringCTemplate(
      const UnsignedType* ptr,
      FX_STRSIZE size,
      typename std::enable_if<!std::is_same<U, CharType>::value>::type* = 0)
      : m_Ptr(ptr), m_Length(size) {}

  // Deliberately implicit to avoid calling on every string literal.
  // |ch| must be an lvalue that outlives the the CFX_StringCTemplate.
  // NOLINTNEXTLINE(runtime/explicit)
  CFX_StringCTemplate(CharType& ch) {
    m_Ptr = reinterpret_cast<const UnsignedType*>(&ch);
    m_Length = 1;
  }

  CFX_StringCTemplate(const CFX_StringCTemplate& src) {
    m_Ptr = src.m_Ptr;
    m_Length = src.m_Length;
  }

  // Any changes to |vec| invalidate the string.
  explicit CFX_StringCTemplate(const std::vector<UnsignedType>& vec) {
    m_Length = pdfium::CollectionSize<FX_STRSIZE>(vec);
    m_Ptr = m_Length ? vec.data() : nullptr;
  }

  CFX_StringCTemplate& operator=(const CharType* src) {
    m_Ptr = reinterpret_cast<const UnsignedType*>(src);
    m_Length = src ? FXSYS_len(src) : 0;
    return *this;
  }

  CFX_StringCTemplate& operator=(const CFX_StringCTemplate& src) {
    m_Ptr = src.m_Ptr;
    m_Length = src.m_Length;
    return *this;
  }

  const_iterator begin() const {
    return reinterpret_cast<const CharType*>(m_Ptr.Get());
  }
  const_iterator end() const {
    return m_Ptr ? reinterpret_cast<const CharType*>(m_Ptr.Get()) + m_Length
                 : nullptr;
  }

  const_reverse_iterator rbegin() const {
    return const_reverse_iterator(end());
  }
  const_reverse_iterator rend() const {
    return const_reverse_iterator(begin());
  }

  bool operator==(const CharType* ptr) const {
    return FXSYS_len(ptr) == m_Length &&
           FXSYS_cmp(ptr, reinterpret_cast<const CharType*>(m_Ptr.Get()),
                     m_Length) == 0;
  }
  bool operator==(const CFX_StringCTemplate& other) const {
    return other.m_Length == m_Length &&
           FXSYS_cmp(reinterpret_cast<const CharType*>(other.m_Ptr.Get()),
                     reinterpret_cast<const CharType*>(m_Ptr.Get()),
                     m_Length) == 0;
  }
  bool operator!=(const CharType* ptr) const { return !(*this == ptr); }
  bool operator!=(const CFX_StringCTemplate& other) const {
    return !(*this == other);
  }

  uint32_t GetID() const {
    if (m_Length == 0)
      return 0;

    uint32_t strid = 0;
    FX_STRSIZE size = std::min(static_cast<FX_STRSIZE>(4), m_Length);
    for (FX_STRSIZE i = 0; i < size; i++)
      strid = strid * 256 + m_Ptr.Get()[i];

    return strid << ((4 - size) * 8);
  }

  const UnsignedType* raw_str() const { return m_Ptr.Get(); }
  const CharType* unterminated_c_str() const {
    return reinterpret_cast<const CharType*>(m_Ptr.Get());
  }

  FX_STRSIZE GetLength() const { return m_Length; }
  bool IsEmpty() const { return m_Length == 0; }
  bool IsValidIndex(FX_STRSIZE index) const { return index < GetLength(); }
  bool IsValidLength(FX_STRSIZE length) const { return length <= GetLength(); }

  const UnsignedType& operator[](const FX_STRSIZE index) const {
    ASSERT(IsValidIndex(index));
    return m_Ptr.Get()[index];
  }

  UnsignedType First() const { return GetLength() ? (*this)[0] : 0; }

  UnsignedType Last() const {
    return GetLength() ? (*this)[GetLength() - 1] : 0;
  }

  const CharType CharAt(const FX_STRSIZE index) const {
    ASSERT(IsValidIndex(index));
    return static_cast<CharType>(m_Ptr.Get()[index]);
  }

  pdfium::Optional<FX_STRSIZE> Find(CharType ch) const {
    const UnsignedType* found = reinterpret_cast<const UnsignedType*>(FXSYS_chr(
        reinterpret_cast<const CharType*>(m_Ptr.Get()), ch, m_Length));

    return found ? pdfium::Optional<FX_STRSIZE>(found - m_Ptr.Get())
                 : pdfium::Optional<FX_STRSIZE>();
  }

  bool Contains(CharType ch) const { return Find(ch).has_value(); }

  CFX_StringCTemplate Mid(FX_STRSIZE first, FX_STRSIZE count) const {
    if (!m_Ptr.Get())
      return CFX_StringCTemplate();

    if (!IsValidIndex(first))
      return CFX_StringCTemplate();

    if (count == 0 || !IsValidLength(count))
      return CFX_StringCTemplate();

    if (!IsValidIndex(first + count - 1))
      return CFX_StringCTemplate();

    return CFX_StringCTemplate(m_Ptr.Get() + first, count);
  }

  CFX_StringCTemplate Left(FX_STRSIZE count) const {
    if (count == 0 || !IsValidLength(count))
      return CFX_StringCTemplate();
    return Mid(0, count);
  }

  CFX_StringCTemplate Right(FX_STRSIZE count) const {
    if (count == 0 || !IsValidLength(count))
      return CFX_StringCTemplate();
    return Mid(GetLength() - count, count);
  }

  CFX_StringCTemplate TrimmedRight(CharType ch) const {
    if (IsEmpty())
      return CFX_StringCTemplate();

    FX_STRSIZE pos = GetLength();
    while (pos && CharAt(pos - 1) == ch)
      pos--;

    if (pos == 0)
      return CFX_StringCTemplate();

    return CFX_StringCTemplate(m_Ptr.Get(), pos);
  }

  bool operator<(const CFX_StringCTemplate& that) const {
    int result = FXSYS_cmp(reinterpret_cast<const CharType*>(m_Ptr.Get()),
                           reinterpret_cast<const CharType*>(that.m_Ptr.Get()),
                           std::min(m_Length, that.m_Length));
    return result < 0 || (result == 0 && m_Length < that.m_Length);
  }

  bool operator>(const CFX_StringCTemplate& that) const {
    int result = FXSYS_cmp(reinterpret_cast<const CharType*>(m_Ptr.Get()),
                           reinterpret_cast<const CharType*>(that.m_Ptr.Get()),
                           std::min(m_Length, that.m_Length));
    return result > 0 || (result == 0 && m_Length > that.m_Length);
  }

 protected:
  CFX_UnownedPtr<const UnsignedType> m_Ptr;
  FX_STRSIZE m_Length;

 private:
  void* operator new(size_t) throw() { return nullptr; }
};

template <typename T>
inline bool operator==(const T* lhs, const CFX_StringCTemplate<T>& rhs) {
  return rhs == lhs;
}

template <typename T>
inline bool operator!=(const T* lhs, const CFX_StringCTemplate<T>& rhs) {
  return rhs != lhs;
}

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

using CFX_ByteStringC = CFX_StringCTemplate<char>;
using CFX_WideStringC = CFX_StringCTemplate<wchar_t>;

#endif  // CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_
