|
| 1 | +/* |
| 2 | + * Copyright (C) 2018 Yusuke Suzuki <utatane.tea@gmail.com> |
| 3 | + * Copyright (C) 2024 Apple Inc. All Rights Reserved. |
| 4 | + * Copyright (C) 2025 Comcast Inc. |
| 5 | + * Copyright (C) 2025 Igalia S.L. |
| 6 | + * |
| 7 | + * Redistribution and use in source and binary forms, with or without |
| 8 | + * modification, are permitted provided that the following conditions |
| 9 | + * are met: |
| 10 | + * 1. Redistributions of source code must retain the above copyright |
| 11 | + * notice, this list of conditions and the following disclaimer. |
| 12 | + * 2. Redistributions in binary form must reproduce the above copyright |
| 13 | + * notice, this list of conditions and the following disclaimer in the |
| 14 | + * documentation and/or other materials provided with the distribution. |
| 15 | + * |
| 16 | + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| 17 | + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 18 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 19 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| 20 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 21 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 22 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 23 | + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 24 | + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | + */ |
| 28 | + |
| 29 | +#pragma once |
| 30 | + |
| 31 | +#include <wtf/Compiler.h> |
| 32 | +#include <wtf/HashFunctions.h> |
| 33 | +#include <wtf/glib/GSpanExtras.h> |
| 34 | +#include <wtf/text/ASCIILiteral.h> |
| 35 | +#include <wtf/text/CStringView.h> |
| 36 | +#include <wtf/text/StringCommon.h> |
| 37 | +#include <wtf/text/SuperFastHash.h> |
| 38 | + |
| 39 | +namespace WTF { |
| 40 | + |
| 41 | +class PrintStream; |
| 42 | + |
| 43 | +class GMallocString final { |
| 44 | + WTF_FORBID_HEAP_ALLOCATION; |
| 45 | + WTF_MAKE_NONCOPYABLE(GMallocString); |
| 46 | +public: |
| 47 | + |
| 48 | + static GMallocString unsafeAdoptFromUTF8(char* string) |
| 49 | + { |
| 50 | + if (!string) |
| 51 | + return GMallocString(); |
| 52 | + return GMallocString { adoptGMallocSpan<char8_t>(unsafeMakeSpan(byteCast<char8_t>(string), string ? std::char_traits<char>::length(string) + 1 : 0)) }; |
| 53 | + } |
| 54 | + |
| 55 | + static GMallocString unsafeAdoptFromUTF8(GUniquePtr<char>&& pointer) |
| 56 | + { |
| 57 | + return unsafeAdoptFromUTF8(pointer.release()); |
| 58 | + } |
| 59 | + |
| 60 | + static GMallocString unsafeAdoptFromUTF8(GUniqueOutPtr<char>&& pointer) |
| 61 | + { |
| 62 | + return unsafeAdoptFromUTF8(pointer.release()); |
| 63 | + } |
| 64 | + |
| 65 | + static GMallocString adoptFromUTF8(std::span<char> string) |
| 66 | + { |
| 67 | + if (string.size() < 1) |
| 68 | + return GMallocString(); |
| 69 | + RELEASE_ASSERT(string[string.size() - 1] == '\0'); |
| 70 | + return GMallocString { adoptGMallocSpan<char8_t>(byteCast<char8_t>(string)) }; |
| 71 | + } |
| 72 | + |
| 73 | + explicit GMallocString(const CStringView& view) |
| 74 | + { |
| 75 | + m_spanWithNullTerminator = dupGMallocSpan(view.spanIncludingNullTerminator()); |
| 76 | + } |
| 77 | + |
| 78 | + WTF_EXPORT_PRIVATE void dump(PrintStream& out) const; |
| 79 | + |
| 80 | + GMallocString() = default; |
| 81 | + constexpr GMallocString(std::nullptr_t) |
| 82 | + : GMallocString() |
| 83 | + { } |
| 84 | + |
| 85 | + GMallocString(GMallocString&& other) |
| 86 | + : m_spanWithNullTerminator(WTFMove(other.m_spanWithNullTerminator)) |
| 87 | + { |
| 88 | + } |
| 89 | + GMallocString& operator=(GMallocString&& other) |
| 90 | + { |
| 91 | + GMallocSpan<char8_t> otherSpan = WTFMove(other.m_spanWithNullTerminator); |
| 92 | + std::swap(m_spanWithNullTerminator, otherSpan); |
| 93 | + return *this; |
| 94 | + } |
| 95 | + |
| 96 | + bool isNull() const { return m_spanWithNullTerminator.span().empty(); } |
| 97 | + const char* utf8() const LIFETIME_BOUND { return byteCast<char>(m_spanWithNullTerminator.span().data()); } |
| 98 | + char* leakUTF8() WARN_UNUSED_RETURN { return byteCast<char>(m_spanWithNullTerminator.leakSpan().data()); } |
| 99 | + size_t lengthInBytes() const { return !m_spanWithNullTerminator.span().empty() ? m_spanWithNullTerminator.span().size() - 1 : 0; } |
| 100 | + std::span<const char8_t> span() const LIFETIME_BOUND { return m_spanWithNullTerminator.span().first(lengthInBytes()); } |
| 101 | + std::span<const char8_t> spanIncludingNullTerminator() const LIFETIME_BOUND { return m_spanWithNullTerminator.span(); } |
| 102 | + size_t isEmpty() const { return m_spanWithNullTerminator.span().size() <= 1; } |
| 103 | + |
| 104 | + explicit operator bool() const { return !isEmpty(); } |
| 105 | + bool operator!() const { return isEmpty(); } |
| 106 | + |
| 107 | +private: |
| 108 | + explicit GMallocString(GMallocSpan<char8_t>&& string) |
| 109 | + : m_spanWithNullTerminator(WTFMove(string)) |
| 110 | + { |
| 111 | + } |
| 112 | + |
| 113 | + GMallocSpan<char8_t> m_spanWithNullTerminator; |
| 114 | +}; |
| 115 | + |
| 116 | +inline bool operator==(const GMallocString& a, const GMallocString& b) |
| 117 | +{ |
| 118 | + return equal(a.span(), b.span()); |
| 119 | +} |
| 120 | + |
| 121 | +inline bool operator==(const GMallocString& a, ASCIILiteral b) |
| 122 | +{ |
| 123 | + return equal(a.span(), byteCast<char8_t>(b.span())); |
| 124 | +} |
| 125 | + |
| 126 | +inline bool operator==(const GMallocString& a, CStringView b) |
| 127 | +{ |
| 128 | + return equal(a.span(), b.span()); |
| 129 | +} |
| 130 | + |
| 131 | +// GMallocString is null terminated |
| 132 | +inline const char* safePrintfType(const GMallocString& string) { return string.utf8(); } |
| 133 | + |
| 134 | +inline CStringView toCStringView(const GMallocString& string LIFETIME_BOUND) { return CStringView::fromUTF8(string.spanIncludingNullTerminator()); } |
| 135 | + |
| 136 | +} // namespace WTF |
| 137 | + |
| 138 | +using WTF::GMallocString; |
| 139 | +using WTF::toCStringView; |
0 commit comments