--- a/dom/base/Link.cpp
+++ b/dom/base/Link.cpp
@@ -732,17 +732,18 @@ Link::GetSearch(nsAString &_search)
// Do not throw! Not having a valid URI or URL should result in an empty
// string.
return;
}
nsAutoCString search;
nsresult rv = url->GetQuery(search);
if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
- CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, _search);
+ _search.Assign((char16_t)'?');
+ AppendUTF8toUTF16(search, _search);
}
}
void
Link::GetPort(nsAString &_port)
{
_port.Truncate();
--- a/dom/url/URLMainThread.cpp
+++ b/dom/url/URLMainThread.cpp
@@ -422,17 +422,18 @@ URLMainThread::GetSearch(nsAString& aSea
// Do not throw! Not having a valid URI or URL should result in an empty
// string.
nsAutoCString search;
nsresult rv;
rv = mURI->GetQuery(search);
if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
- CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, aSearch);
+ aSearch.Assign((char16_t)'?');
+ AppendUTF8toUTF16(search, aSearch);
}
}
void
URLMainThread::GetHash(nsAString& aHash, ErrorResult& aRv) const
{
aHash.Truncate();
--- a/dom/url/URLWorker.cpp
+++ b/dom/url/URLWorker.cpp
@@ -1110,17 +1110,18 @@ URLWorker::GetSearch(nsAString& aSearch,
aSearch.Truncate();
if (mStdURL) {
nsAutoCString search;
nsresult rv;
rv = mStdURL->GetQuery(search);
if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
- CopyUTF8toUTF16(NS_LITERAL_CSTRING("?") + search, aSearch);
+ aSearch.Assign((char16_t)'?');
+ AppendUTF8toUTF16(search, aSearch);
}
return;
}
MOZ_ASSERT(mURLProxy);
RefPtr<GetterRunnable> runnable =
new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterSearch, aSearch,
mURLProxy);
--- a/servo/support/gecko/nsstring/src/conversions.rs
+++ b/servo/support/gecko/nsstring/src/conversions.rs
@@ -499,8 +499,43 @@ impl nsACString {
/// Convert a Latin1 (i.e. byte value equals scalar value; not windows-1252!)
/// into UTF-8 and fallibly append the conversion result to this string.
pub fn fallible_append_latin1_to_utf8<T: Latin1StringLike + ?Sized>(&mut self, other: &T) -> Result<(), ()> {
let len = self.len();
self.fallible_append_latin1_to_utf8_check(other, len)
}
}
+
+#[no_mangle]
+pub unsafe extern "C" fn nsstring_fallible_append_utf8_impl(this: *mut nsAString, other: *const u8, other_len: usize, old_len: usize) -> bool {
+ let other_slice = ::std::slice::from_raw_parts(other, other_len);
+ (*this).fallible_append_utf8_impl(other_slice, old_len).is_ok()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn nsstring_fallible_append_latin1_impl(this: *mut nsAString, other: *const u8, other_len: usize, old_len: usize) -> bool {
+ let other_slice = ::std::slice::from_raw_parts(other, other_len);
+ (*this).fallible_append_latin1_impl(other_slice, old_len).is_ok()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn nscstring_fallible_append_utf16_to_utf8_impl(this: *mut nsACString, other: *const u16, other_len: usize, old_len: usize) -> bool {
+ let other_slice = ::std::slice::from_raw_parts(other, other_len);
+ (*this).fallible_append_utf16_to_utf8_impl(other_slice, old_len).is_ok()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn nscstring_fallible_append_utf16_to_latin1_lossy_impl(this: *mut nsACString, other: *const u16, other_len: usize, old_len: usize) -> bool {
+ let other_slice = ::std::slice::from_raw_parts(other, other_len);
+ (*this).fallible_append_utf16_to_latin1_lossy_impl(other_slice, old_len).is_ok()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn nscstring_fallible_append_utf8_to_latin1_lossy_check(this: *mut nsACString, other: *const nsACString, old_len: usize) -> bool {
+ (*this).fallible_append_utf8_to_latin1_lossy_check(&*other, old_len).is_ok()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn nscstring_fallible_append_latin1_to_utf8_check(this: *mut nsACString, other: *const nsACString, old_len: usize) -> bool {
+ (*this).fallible_append_latin1_to_utf8_check(&*other, old_len).is_ok()
+}
+
--- a/servo/support/gecko/nsstring/src/lib.rs
+++ b/servo/support/gecko/nsstring/src/lib.rs
@@ -125,16 +125,23 @@ use std::mem;
use std::ops::{Deref, DerefMut};
use std::os::raw::c_void;
use std::slice;
use std::str;
use std::u32;
mod conversions;
+pub use self::conversions::nsstring_fallible_append_utf8_impl;
+pub use self::conversions::nsstring_fallible_append_latin1_impl;
+pub use self::conversions::nscstring_fallible_append_utf16_to_utf8_impl;
+pub use self::conversions::nscstring_fallible_append_utf16_to_latin1_lossy_impl;
+pub use self::conversions::nscstring_fallible_append_utf8_to_latin1_lossy_check;
+pub use self::conversions::nscstring_fallible_append_latin1_to_utf8_check;
+
///////////////////////////////////
// Internal Implementation Flags //
///////////////////////////////////
mod data_flags {
bitflags! {
// While this has the same layout as u16, it cannot be passed
// over FFI safely as a u16.
--- a/xpcom/string/nsReadableUtils.cpp
+++ b/xpcom/string/nsReadableUtils.cpp
@@ -73,340 +73,16 @@ FirstNonASCII(const char16_t* aBegin, co
if (mozilla::supports_sse2()) {
return mozilla::SSE2::FirstNonASCII(aBegin, aEnd);
}
#endif
return FirstNonASCIIUnvectorized(aBegin, aEnd);
}
-void
-LossyCopyUTF16toASCII(const nsAString& aSource, nsACString& aDest)
-{
- aDest.Truncate();
- LossyAppendUTF16toASCII(aSource, aDest);
-}
-
-void
-CopyASCIItoUTF16(const nsACString& aSource, nsAString& aDest)
-{
- if (!CopyASCIItoUTF16(aSource, aDest, mozilla::fallible)) {
- // Note that this may wildly underestimate the allocation that failed, as
- // we report the length of aSource as UTF-16 instead of UTF-8.
- aDest.AllocFailed(aDest.Length() + aSource.Length());
- }
-}
-
-bool
-CopyASCIItoUTF16(const nsACString& aSource, nsAString& aDest,
- const mozilla::fallible_t& aFallible)
-{
- aDest.Truncate();
- return AppendASCIItoUTF16(aSource, aDest, aFallible);
-}
-
-void
-LossyCopyUTF16toASCII(const char16ptr_t aSource, nsACString& aDest)
-{
- aDest.Truncate();
- if (aSource) {
- LossyAppendUTF16toASCII(nsDependentString(aSource), aDest);
- }
-}
-
-void
-CopyASCIItoUTF16(const char* aSource, nsAString& aDest)
-{
- aDest.Truncate();
- if (aSource) {
- AppendASCIItoUTF16(nsDependentCString(aSource), aDest);
- }
-}
-
-void
-CopyUTF16toUTF8(const nsAString& aSource, nsACString& aDest)
-{
- if (!CopyUTF16toUTF8(aSource, aDest, mozilla::fallible)) {
- // Note that this may wildly underestimate the allocation that failed, as
- // we report the length of aSource as UTF-16 instead of UTF-8.
- aDest.AllocFailed(aDest.Length() + aSource.Length());
- }
-}
-
-bool
-CopyUTF16toUTF8(const nsAString& aSource, nsACString& aDest,
- const mozilla::fallible_t& aFallible)
-{
- aDest.Truncate();
- if (!AppendUTF16toUTF8(aSource, aDest, aFallible)) {
- return false;
- }
- return true;
-}
-
-void
-CopyUTF8toUTF16(const nsACString& aSource, nsAString& aDest)
-{
- aDest.Truncate();
- AppendUTF8toUTF16(aSource, aDest);
-}
-
-void
-CopyUTF16toUTF8(const char16ptr_t aSource, nsACString& aDest)
-{
- aDest.Truncate();
- AppendUTF16toUTF8(aSource, aDest);
-}
-
-void
-CopyUTF8toUTF16(const char* aSource, nsAString& aDest)
-{
- aDest.Truncate();
- AppendUTF8toUTF16(aSource, aDest);
-}
-
-void
-LossyAppendUTF16toASCII(const nsAString& aSource, nsACString& aDest)
-{
- uint32_t old_dest_length = aDest.Length();
- aDest.SetLength(old_dest_length + aSource.Length());
-
- nsAString::const_iterator fromBegin, fromEnd;
-
- nsACString::iterator dest;
- aDest.BeginWriting(dest);
-
- dest.advance(old_dest_length);
-
- // right now, this won't work on multi-fragment destinations
- LossyConvertEncoding16to8 converter(dest.get());
-
- copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd),
- converter);
-}
-
-void
-AppendASCIItoUTF16(const nsACString& aSource, nsAString& aDest)
-{
- if (!AppendASCIItoUTF16(aSource, aDest, mozilla::fallible)) {
- aDest.AllocFailed(aDest.Length() + aSource.Length());
- }
-}
-
-bool
-AppendASCIItoUTF16(const nsACString& aSource, nsAString& aDest,
- const mozilla::fallible_t& aFallible)
-{
- uint32_t old_dest_length = aDest.Length();
- if (!aDest.SetLength(old_dest_length + aSource.Length(),
- aFallible)) {
- return false;
- }
-
- nsACString::const_iterator fromBegin, fromEnd;
-
- nsAString::iterator dest;
- aDest.BeginWriting(dest);
-
- dest.advance(old_dest_length);
-
- // right now, this won't work on multi-fragment destinations
- LossyConvertEncoding8to16 converter(dest.get());
-
- copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd),
- converter);
- return true;
-}
-
-void
-LossyAppendUTF16toASCII(const char16ptr_t aSource, nsACString& aDest)
-{
- if (aSource) {
- LossyAppendUTF16toASCII(nsDependentString(aSource), aDest);
- }
-}
-
-bool
-AppendASCIItoUTF16(const char* aSource, nsAString& aDest, const mozilla::fallible_t& aFallible)
-{
- if (aSource) {
- return AppendASCIItoUTF16(nsDependentCString(aSource), aDest, aFallible);
- }
-
- return true;
-}
-
-void
-AppendASCIItoUTF16(const char* aSource, nsAString& aDest)
-{
- if (aSource) {
- AppendASCIItoUTF16(nsDependentCString(aSource), aDest);
- }
-}
-
-void
-AppendUTF16toUTF8(const nsAString& aSource, nsACString& aDest)
-{
- if (!AppendUTF16toUTF8(aSource, aDest, mozilla::fallible)) {
- // Note that this may wildly underestimate the allocation that failed, as
- // we report the length of aSource as UTF-16 instead of UTF-8.
- aDest.AllocFailed(aDest.Length() + aSource.Length());
- }
-}
-
-bool
-AppendUTF16toUTF8(const nsAString& aSource, nsACString& aDest,
- const mozilla::fallible_t& aFallible)
-{
- // At 16 characters analysis showed better performance of both the all ASCII
- // and non-ASCII cases, so we limit calling |FirstNonASCII| to strings of
- // that length.
- const nsAString::size_type kFastPathMinLength = 16;
-
- int32_t firstNonASCII = 0;
- if (aSource.Length() >= kFastPathMinLength) {
- firstNonASCII = FirstNonASCII(aSource.BeginReading(), aSource.EndReading());
- }
-
- if (firstNonASCII == -1) {
- // This is all ASCII, we can use the more efficient lossy append.
- mozilla::CheckedInt<nsACString::size_type> new_length(aSource.Length());
- new_length += aDest.Length();
-
- if (!new_length.isValid() ||
- !aDest.SetCapacity(new_length.value(), aFallible)) {
- return false;
- }
-
- LossyAppendUTF16toASCII(aSource, aDest);
- return true;
- }
-
- nsAString::const_iterator source_start, source_end;
- CalculateUTF8Size calculator;
- aSource.BeginReading(source_start);
- aSource.EndReading(source_end);
-
- // Skip the characters that we know are single byte.
- source_start.advance(firstNonASCII);
-
- copy_string(source_start,
- source_end, calculator);
-
- // Include the ASCII characters that were skipped in the count.
- size_t count = calculator.Size() + firstNonASCII;
-
- if (count) {
- auto old_dest_length = aDest.Length();
- // Grow the buffer if we need to.
- mozilla::CheckedInt<nsACString::size_type> new_length(count);
- new_length += old_dest_length;
-
- if (!new_length.isValid() ||
- !aDest.SetLength(new_length.value(), aFallible)) {
- return false;
- }
-
- // All ready? Time to convert
-
- nsAString::const_iterator ascii_end;
- aSource.BeginReading(ascii_end);
-
- if (firstNonASCII >= static_cast<int32_t>(kFastPathMinLength)) {
- // Use the more efficient lossy converter for the ASCII portion.
- LossyConvertEncoding16to8 lossy_converter(
- aDest.BeginWriting() + old_dest_length);
- nsAString::const_iterator ascii_start;
- aSource.BeginReading(ascii_start);
- ascii_end.advance(firstNonASCII);
-
- copy_string(ascii_start, ascii_end, lossy_converter);
- } else {
- // Not using the lossy shortcut, we need to include the leading ASCII
- // chars.
- firstNonASCII = 0;
- }
-
- ConvertUTF16toUTF8 converter(
- aDest.BeginWriting() + old_dest_length + firstNonASCII);
- copy_string(ascii_end,
- aSource.EndReading(source_end), converter);
-
- NS_ASSERTION(converter.Size() == count - firstNonASCII,
- "Unexpected disparity between CalculateUTF8Size and "
- "ConvertUTF16toUTF8");
- }
-
- return true;
-}
-
-void
-AppendUTF8toUTF16(const nsACString& aSource, nsAString& aDest)
-{
- if (!AppendUTF8toUTF16(aSource, aDest, mozilla::fallible)) {
- aDest.AllocFailed(aDest.Length() + aSource.Length());
- }
-}
-
-bool
-AppendUTF8toUTF16(const nsACString& aSource, nsAString& aDest,
- const mozilla::fallible_t& aFallible)
-{
- nsACString::const_iterator source_start, source_end;
- CalculateUTF8Length calculator;
- copy_string(aSource.BeginReading(source_start),
- aSource.EndReading(source_end), calculator);
-
- uint32_t count = calculator.Length();
-
- // Avoid making the string mutable if we're appending an empty string
- if (count) {
- uint32_t old_dest_length = aDest.Length();
-
- // Grow the buffer if we need to.
- if (!aDest.SetLength(old_dest_length + count, aFallible)) {
- return false;
- }
-
- // All ready? Time to convert
-
- ConvertUTF8toUTF16 converter(aDest.BeginWriting() + old_dest_length);
- copy_string(aSource.BeginReading(source_start),
- aSource.EndReading(source_end), converter);
-
- NS_ASSERTION(converter.ErrorEncountered() ||
- converter.Length() == count,
- "CalculateUTF8Length produced the wrong length");
-
- if (converter.ErrorEncountered()) {
- NS_ERROR("Input wasn't UTF8 or incorrect length was calculated");
- aDest.SetLength(old_dest_length);
- }
- }
-
- return true;
-}
-
-void
-AppendUTF16toUTF8(const char16ptr_t aSource, nsACString& aDest)
-{
- if (aSource) {
- AppendUTF16toUTF8(nsDependentString(aSource), aDest);
- }
-}
-
-void
-AppendUTF8toUTF16(const char* aSource, nsAString& aDest)
-{
- if (aSource) {
- AppendUTF8toUTF16(nsDependentCString(aSource), aDest);
- }
-}
-
-
/**
* A helper function that allocates a buffer of the desired character type big enough to hold a copy of the supplied string (plus a zero terminator).
*
* @param aSource an string you will eventually be making a copy of
* @return a new buffer (of the type specified by the second parameter) which you must free with |free|.
*
*/
template <class FromStringT, class ToCharT>
--- a/xpcom/string/nsReadableUtils.h
+++ b/xpcom/string/nsReadableUtils.h
@@ -20,70 +20,322 @@
// Can't include mozilla/Encoding.h here
extern "C" {
size_t encoding_utf8_valid_up_to(uint8_t const* buffer, size_t buffer_len);
bool encoding_mem_is_ascii(uint8_t const* buffer, size_t buffer_len);
bool encoding_mem_is_basic_latin(char16_t const* buffer, size_t buffer_len);
}
+// From the nsstring crate
+extern "C" {
+ bool nsstring_fallible_append_utf8_impl(nsAString* aThis, const uint8_t* aOther, size_t aOtherLen, size_t aOldLen);
+ bool nsstring_fallible_append_latin1_impl(nsAString* aThis, const uint8_t* aOther, size_t aOtherLen, size_t aOldLen);
+ bool nscstring_fallible_append_utf16_to_utf8_impl(nsACString* aThis, const char16_t*, size_t aOtherLen, size_t aOldLen);
+ bool nscstring_fallible_append_utf16_to_latin1_lossy_impl(nsACString* aThis, const char16_t*, size_t aOtherLen, size_t aOldLen);
+ bool nscstring_fallible_append_utf8_to_latin1_lossy_check(nsACString* aThis, const nsACString* aOther, size_t aOldLen);
+ bool nscstring_fallible_append_latin1_to_utf8_check(nsACString* aThis, const nsACString* aOther, size_t aOldLen);
+}
+
inline size_t
Distance(const nsReadingIterator<char16_t>& aStart,
const nsReadingIterator<char16_t>& aEnd)
{
MOZ_ASSERT(aStart.get() <= aEnd.get());
return static_cast<size_t>(aEnd.get() - aStart.get());
}
inline size_t
Distance(const nsReadingIterator<char>& aStart,
const nsReadingIterator<char>& aEnd)
{
MOZ_ASSERT(aStart.get() <= aEnd.get());
return static_cast<size_t>(aEnd.get() - aStart.get());
}
-void LossyCopyUTF16toASCII(const nsAString& aSource, nsACString& aDest);
-void CopyASCIItoUTF16(const nsACString& aSource, nsAString& aDest);
-MOZ_MUST_USE bool CopyASCIItoUTF16(const nsACString& aSource, nsAString& aDest,
- const mozilla::fallible_t&);
+// UTF-8 to UTF-16
+// Invalid UTF-8 byte sequences are replaced with the REPLACEMENT CHARACTER.
+
+inline MOZ_MUST_USE bool CopyUTF8toUTF16(mozilla::Span<const uint8_t> aSource,
+ nsAString& aDest,
+ const mozilla::fallible_t&)
+{
+ return nsstring_fallible_append_utf8_impl(&aDest, aSource.Elements(), aSource.Length(), 0);
+}
+
+inline void CopyUTF8toUTF16(mozilla::Span<const uint8_t> aSource,
+ nsAString& aDest)
+{
+ if (MOZ_UNLIKELY(!CopyUTF8toUTF16(aSource, aDest, mozilla::fallible))) {
+ aDest.AllocFailed(aSource.Length());
+ }
+}
+
+inline MOZ_MUST_USE bool AppendUTF8toUTF16(mozilla::Span<const uint8_t> aSource,
+ nsAString& aDest,
+ const mozilla::fallible_t&)
+{
+ return nsstring_fallible_append_utf8_impl(&aDest, aSource.Elements(), aSource.Length(), aDest.Length());
+}
+
+inline void AppendUTF8toUTF16(mozilla::Span<const uint8_t> aSource,
+ nsAString& aDest)
+{
+ if (MOZ_UNLIKELY(!AppendUTF8toUTF16(aSource, aDest, mozilla::fallible))) {
+ aDest.AllocFailed(aDest.Length() + aSource.Length());
+ }
+}
-void LossyCopyUTF16toASCII(const char16ptr_t aSource, nsACString& aDest);
-void CopyASCIItoUTF16(const char* aSource, nsAString& aDest);
+inline MOZ_MUST_USE bool CopyUTF8toUTF16(const char* aSource,
+ nsAString& aDest,
+ const mozilla::fallible_t&)
+{
+ if (aSource) {
+ return CopyUTF8toUTF16(mozilla::AsBytes(mozilla::MakeStringSpan(aSource)), aDest, mozilla::fallible);
+ }
+ return true;
+}
+
+inline void CopyUTF8toUTF16(const char* aSource,
+ nsAString& aDest)
+{
+ if (aSource) {
+ CopyUTF8toUTF16(mozilla::AsBytes(mozilla::MakeStringSpan(aSource)), aDest);
+ }
+}
+
+inline MOZ_MUST_USE bool AppendUTF8toUTF16(const char* aSource,
+ nsAString& aDest,
+ const mozilla::fallible_t&)
+{
+ if (aSource) {
+ return AppendUTF8toUTF16(mozilla::AsBytes(mozilla::MakeStringSpan(aSource)), aDest, mozilla::fallible);
+ }
+ return true;
+}
+
+inline void AppendUTF8toUTF16(const char* aSource,
+ nsAString& aDest)
+{
+ if (aSource) {
+ AppendUTF8toUTF16(mozilla::AsBytes(mozilla::MakeStringSpan(aSource)), aDest);
+ }
+}
-void CopyUTF16toUTF8(const nsAString& aSource, nsACString& aDest);
-MOZ_MUST_USE bool CopyUTF16toUTF8(const nsAString& aSource, nsACString& aDest,
- const mozilla::fallible_t&);
-void CopyUTF8toUTF16(const nsACString& aSource, nsAString& aDest);
+// Latin1 to UTF-16
+// Interpret each incoming unsigned byte value as a Unicode scalar value (not windows-1252!).
+// The function names say "ASCII" instead of "Latin1" for legacy reasons.
+
+inline MOZ_MUST_USE bool CopyASCIItoUTF16(mozilla::Span<const uint8_t> aSource,
+ nsAString& aDest,
+ const mozilla::fallible_t&)
+{
+ return nsstring_fallible_append_latin1_impl(&aDest, aSource.Elements(), aSource.Length(), 0);
+}
+
+inline void CopyASCIItoUTF16(mozilla::Span<const uint8_t> aSource,
+ nsAString& aDest)
+{
+ if (MOZ_UNLIKELY(!CopyASCIItoUTF16(aSource, aDest, mozilla::fallible))) {
+ aDest.AllocFailed(aSource.Length());
+ }
+}
+
+inline MOZ_MUST_USE bool AppendASCIItoUTF16(mozilla::Span<const uint8_t> aSource,
+ nsAString& aDest,
+ const mozilla::fallible_t&)
+{
+ return nsstring_fallible_append_latin1_impl(&aDest, aSource.Elements(), aSource.Length(), aDest.Length());
+}
+
+inline void AppendASCIItoUTF16(mozilla::Span<const uint8_t> aSource,
+ nsAString& aDest)
+{
+ if (MOZ_UNLIKELY(!AppendASCIItoUTF16(aSource, aDest, mozilla::fallible))) {
+ aDest.AllocFailed(aDest.Length() + aSource.Length());
+ }
+}
-void CopyUTF16toUTF8(const char16ptr_t aSource, nsACString& aDest);
-void CopyUTF8toUTF16(const char* aSource, nsAString& aDest);
+inline MOZ_MUST_USE bool CopyASCIItoUTF16(const char* aSource,
+ nsAString& aDest,
+ const mozilla::fallible_t&)
+{
+ if (aSource) {
+ return CopyASCIItoUTF16(mozilla::AsBytes(mozilla::MakeStringSpan(aSource)), aDest, mozilla::fallible);
+ }
+ return true;
+}
+
+inline void CopyASCIItoUTF16(const char* aSource,
+ nsAString& aDest)
+{
+ if (aSource) {
+ CopyASCIItoUTF16(mozilla::AsBytes(mozilla::MakeStringSpan(aSource)), aDest);
+ }
+}
+
+inline MOZ_MUST_USE bool AppendASCIItoUTF16(const char* aSource,
+ nsAString& aDest,
+ const mozilla::fallible_t&)
+{
+ if (aSource) {
+ return AppendASCIItoUTF16(mozilla::AsBytes(mozilla::MakeStringSpan(aSource)), aDest, mozilla::fallible);
+ }
+ return true;
+}
+
+inline void AppendASCIItoUTF16(const char* aSource,
+ nsAString& aDest)
+{
+ if (aSource) {
+ AppendASCIItoUTF16(mozilla::AsBytes(mozilla::MakeStringSpan(aSource)), aDest);
+ }
+}
-void LossyAppendUTF16toASCII(const nsAString& aSource, nsACString& aDest);
-void AppendASCIItoUTF16(const nsACString& aSource, nsAString& aDest);
-MOZ_MUST_USE bool AppendASCIItoUTF16(const nsACString& aSource,
- nsAString& aDest,
- const mozilla::fallible_t&);
+// UTF-16 to UTF-8
+// Unpaired surrogates are replaced with the REPLACEMENT CHARACTER.
+
+inline MOZ_MUST_USE bool CopyUTF16toUTF8(mozilla::Span<const char16_t> aSource,
+ nsACString& aDest,
+ const mozilla::fallible_t&)
+{
+ return nscstring_fallible_append_utf16_to_utf8_impl(&aDest, aSource.Elements(), aSource.Length(), 0);
+}
+
+inline void CopyUTF16toUTF8(mozilla::Span<const char16_t> aSource,
+ nsACString& aDest)
+{
+ if (MOZ_UNLIKELY(!CopyUTF16toUTF8(aSource, aDest, mozilla::fallible))) {
+ aDest.AllocFailed(aSource.Length());
+ }
+}
+
+inline MOZ_MUST_USE bool AppendUTF16toUTF8(mozilla::Span<const char16_t> aSource,
+ nsACString& aDest,
+ const mozilla::fallible_t&)
+{
+ return nscstring_fallible_append_utf16_to_utf8_impl(&aDest, aSource.Elements(), aSource.Length(), aDest.Length());
+}
+
+inline void AppendUTF16toUTF8(mozilla::Span<const char16_t> aSource,
+ nsACString& aDest)
+{
+ if (MOZ_UNLIKELY(!AppendUTF16toUTF8(aSource, aDest, mozilla::fallible))) {
+ aDest.AllocFailed(aDest.Length() + aSource.Length());
+ }
+}
-void LossyAppendUTF16toASCII(const char16ptr_t aSource, nsACString& aDest);
-MOZ_MUST_USE bool AppendASCIItoUTF16(const char* aSource,
- nsAString& aDest,
- const mozilla::fallible_t&);
-void AppendASCIItoUTF16(const char* aSource, nsAString& aDest);
+inline MOZ_MUST_USE bool CopyUTF16toUTF8(const char16_t* aSource,
+ nsACString& aDest,
+ const mozilla::fallible_t&)
+{
+ if (aSource) {
+ return CopyUTF16toUTF8(mozilla::MakeStringSpan(aSource), aDest, mozilla::fallible);
+ }
+ return true;
+}
+
+inline void CopyUTF16toUTF8(const char16_t* aSource,
+ nsACString& aDest)
+{
+ if (aSource) {
+ CopyUTF16toUTF8(mozilla::MakeStringSpan(aSource), aDest);
+ }
+}
+
+inline MOZ_MUST_USE bool AppendUTF16toUTF8(const char16_t* aSource,
+ nsACString& aDest,
+ const mozilla::fallible_t&)
+{
+ if (aSource) {
+ return AppendUTF16toUTF8(mozilla::MakeStringSpan(aSource), aDest, mozilla::fallible);
+ }
+ return true;
+}
+
+inline void AppendUTF16toUTF8(const char16_t* aSource,
+ nsACString& aDest)
+{
+ if (aSource) {
+ AppendUTF16toUTF8(mozilla::MakeStringSpan(aSource), aDest);
+ }
+}
-void AppendUTF16toUTF8(const nsAString& aSource, nsACString& aDest);
-MOZ_MUST_USE bool AppendUTF16toUTF8(const nsAString& aSource,
- nsACString& aDest,
- const mozilla::fallible_t&);
-void AppendUTF8toUTF16(const nsACString& aSource, nsAString& aDest);
-MOZ_MUST_USE bool AppendUTF8toUTF16(const nsACString& aSource,
- nsAString& aDest,
- const mozilla::fallible_t&);
+// UTF-16 to Latin1
+// If all code points in the input are below U+0100, represents each scalar value
+// as an unsigned byte. (This is not windows-1252!)
+// If there are code points above U+00FF, asserts in debug builds and memory-safely
+// produces garbage in release builds. The nature of the garbage may differ based on
+// CPU architecture and must not be relied upon.
+// The names say "ASCII" instead of "Latin1" for legacy reasons.
+
+inline MOZ_MUST_USE bool LossyCopyUTF16toASCII(mozilla::Span<const char16_t> aSource,
+ nsACString& aDest,
+ const mozilla::fallible_t&)
+{
+ return nscstring_fallible_append_utf16_to_latin1_lossy_impl(&aDest, aSource.Elements(), aSource.Length(), 0);
+}
+
+inline void LossyCopyUTF16toASCII(mozilla::Span<const char16_t> aSource,
+ nsACString& aDest)
+{
+ if (MOZ_UNLIKELY(!LossyCopyUTF16toASCII(aSource, aDest, mozilla::fallible))) {
+ aDest.AllocFailed(aSource.Length());
+ }
+}
+
+inline MOZ_MUST_USE bool LossyAppendUTF16toASCII(mozilla::Span<const char16_t> aSource,
+ nsACString& aDest,
+ const mozilla::fallible_t&)
+{
+ return nscstring_fallible_append_utf16_to_latin1_lossy_impl(&aDest, aSource.Elements(), aSource.Length(), aDest.Length());
+}
-void AppendUTF16toUTF8(const char16ptr_t aSource, nsACString& aDest);
-void AppendUTF8toUTF16(const char* aSource, nsAString& aDest);
+inline void LossyAppendUTF16toASCII(mozilla::Span<const char16_t> aSource,
+ nsACString& aDest)
+{
+ if (MOZ_UNLIKELY(!LossyAppendUTF16toASCII(aSource, aDest, mozilla::fallible))) {
+ aDest.AllocFailed(aDest.Length() + aSource.Length());
+ }
+}
+
+inline MOZ_MUST_USE bool LossyCopyUTF16toASCII(const char16_t* aSource,
+ nsACString& aDest,
+ const mozilla::fallible_t&)
+{
+ if (aSource) {
+ return LossyCopyUTF16toASCII(mozilla::MakeStringSpan(aSource), aDest, mozilla::fallible);
+ }
+ return true;
+}
+
+inline void LossyCopyUTF16toASCII(const char16_t* aSource,
+ nsACString& aDest)
+{
+ if (aSource) {
+ LossyCopyUTF16toASCII(mozilla::MakeStringSpan(aSource), aDest);
+ }
+}
+
+inline MOZ_MUST_USE bool LossyAppendUTF16toASCII(const char16_t* aSource,
+ nsACString& aDest,
+ const mozilla::fallible_t&)
+{
+ if (aSource) {
+ return LossyAppendUTF16toASCII(mozilla::MakeStringSpan(aSource), aDest, mozilla::fallible);
+ }
+ return true;
+}
+
+inline void LossyAppendUTF16toASCII(const char16_t* aSource,
+ nsACString& aDest)
+{
+ if (aSource) {
+ LossyAppendUTF16toASCII(mozilla::MakeStringSpan(aSource), aDest);
+ }
+}
/**
* Returns a new |char| buffer containing a zero-terminated copy of |aSource|.
*
* Allocates and returns a new |char| buffer which you must free with |free|.
* Performs a lossy encoding conversion by chopping 16-bit wide characters down to 8-bits wide while copying |aSource| to your new buffer.
* This conversion is not well defined; but it reproduces legacy string behavior.
* The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls.