summaryrefslogtreecommitdiff
path: root/core/fxcrt/string_view_template.h
diff options
context:
space:
mode:
Diffstat (limited to 'core/fxcrt/string_view_template.h')
-rw-r--r--core/fxcrt/string_view_template.h247
1 files changed, 247 insertions, 0 deletions
diff --git a/core/fxcrt/string_view_template.h b/core/fxcrt/string_view_template.h
new file mode 100644
index 0000000000..21426acaeb
--- /dev/null
+++ b/core/fxcrt/string_view_template.h
@@ -0,0 +1,247 @@
+// 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_STRING_VIEW_TEMPLATE_H_
+#define CORE_FXCRT_STRING_VIEW_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"
+
+namespace fxcrt {
+
+// 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 StringViewTemplate {
+ 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>;
+
+ StringViewTemplate() : m_Ptr(nullptr), m_Length(0) {}
+
+ // Deliberately implicit to avoid calling on every string literal.
+ // NOLINTNEXTLINE(runtime/explicit)
+ StringViewTemplate(const CharType* ptr)
+ : m_Ptr(reinterpret_cast<const UnsignedType*>(ptr)),
+ m_Length(ptr ? FXSYS_len(ptr) : 0) {}
+
+ StringViewTemplate(const CharType* ptr, FX_STRSIZE len)
+ : m_Ptr(reinterpret_cast<const UnsignedType*>(ptr)), m_Length(len) {}
+
+ template <typename U = UnsignedType>
+ StringViewTemplate(
+ 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 StringViewTemplate.
+ // NOLINTNEXTLINE(runtime/explicit)
+ StringViewTemplate(CharType& ch) {
+ m_Ptr = reinterpret_cast<const UnsignedType*>(&ch);
+ m_Length = 1;
+ }
+
+ StringViewTemplate(const StringViewTemplate& src) {
+ m_Ptr = src.m_Ptr;
+ m_Length = src.m_Length;
+ }
+
+ // Any changes to |vec| invalidate the string.
+ explicit StringViewTemplate(const std::vector<UnsignedType>& vec) {
+ m_Length = pdfium::CollectionSize<FX_STRSIZE>(vec);
+ m_Ptr = m_Length ? vec.data() : nullptr;
+ }
+
+ StringViewTemplate& operator=(const CharType* src) {
+ m_Ptr = reinterpret_cast<const UnsignedType*>(src);
+ m_Length = src ? FXSYS_len(src) : 0;
+ return *this;
+ }
+
+ StringViewTemplate& operator=(const StringViewTemplate& 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 StringViewTemplate& 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 StringViewTemplate& 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(); }
+
+ StringViewTemplate Mid(FX_STRSIZE first, FX_STRSIZE count) const {
+ if (!m_Ptr.Get())
+ return StringViewTemplate();
+
+ if (!IsValidIndex(first))
+ return StringViewTemplate();
+
+ if (count == 0 || !IsValidLength(count))
+ return StringViewTemplate();
+
+ if (!IsValidIndex(first + count - 1))
+ return StringViewTemplate();
+
+ return StringViewTemplate(m_Ptr.Get() + first, count);
+ }
+
+ StringViewTemplate Left(FX_STRSIZE count) const {
+ if (count == 0 || !IsValidLength(count))
+ return StringViewTemplate();
+ return Mid(0, count);
+ }
+
+ StringViewTemplate Right(FX_STRSIZE count) const {
+ if (count == 0 || !IsValidLength(count))
+ return StringViewTemplate();
+ return Mid(GetLength() - count, count);
+ }
+
+ StringViewTemplate TrimmedRight(CharType ch) const {
+ if (IsEmpty())
+ return StringViewTemplate();
+
+ FX_STRSIZE pos = GetLength();
+ while (pos && CharAt(pos - 1) == ch)
+ pos--;
+
+ if (pos == 0)
+ return StringViewTemplate();
+
+ return StringViewTemplate(m_Ptr.Get(), pos);
+ }
+
+ bool operator<(const StringViewTemplate& 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 StringViewTemplate& 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 StringViewTemplate<T>& rhs) {
+ return rhs == lhs;
+}
+
+template <typename T>
+inline bool operator!=(const T* lhs, const StringViewTemplate<T>& rhs) {
+ return rhs != lhs;
+}
+
+extern template class StringViewTemplate<char>;
+extern template class StringViewTemplate<wchar_t>;
+
+using ByteStringView = StringViewTemplate<char>;
+using WideStringView = StringViewTemplate<wchar_t>;
+
+} // namespace fxcrt
+
+using ByteStringView = fxcrt::ByteStringView;
+using WideStringView = fxcrt::WideStringView;
+
+#endif // CORE_FXCRT_STRING_VIEW_TEMPLATE_H_