/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsString.h" #include "nsCharTraits.h" #include "nsXPCOMStrings.h" #include "nsNativeCharsetUtils.h" /* ------------------------------------------------------------------------- */ XPCOM_API(nsresult) NS_StringContainerInit(nsStringContainer& aContainer) { NS_ASSERTION(sizeof(nsStringContainer_base) >= sizeof(nsString), "nsStringContainer is not large enough"); // use placement new to avoid heap allocating nsString object new (&aContainer) nsString(); return NS_OK; } XPCOM_API(nsresult) NS_StringContainerInit2(nsStringContainer& aContainer, const char16_t* aData, uint32_t aDataLength, uint32_t aFlags) { NS_ASSERTION(sizeof(nsStringContainer_base) >= sizeof(nsString), "nsStringContainer is not large enough"); if (!aData) { new (&aContainer) nsString(); } else { if (aDataLength == UINT32_MAX) { if (NS_WARN_IF(aFlags & NS_STRING_CONTAINER_INIT_SUBSTRING)) { return NS_ERROR_INVALID_ARG; } aDataLength = nsCharTraits<char16_t>::length(aData); } if (aFlags & (NS_STRING_CONTAINER_INIT_DEPEND | NS_STRING_CONTAINER_INIT_ADOPT)) { uint32_t flags; if (aFlags & NS_STRING_CONTAINER_INIT_SUBSTRING) { flags = nsSubstring::F_NONE; } else { flags = nsSubstring::F_TERMINATED; } if (aFlags & NS_STRING_CONTAINER_INIT_ADOPT) { flags |= nsSubstring::F_OWNED; } new (&aContainer) nsSubstring(const_cast<char16_t*>(aData), aDataLength, flags); } else { new (&aContainer) nsString(aData, aDataLength); } } return NS_OK; } XPCOM_API(void) NS_StringContainerFinish(nsStringContainer& aContainer) { // call the nsString dtor reinterpret_cast<nsString*>(&aContainer)->~nsString(); } /* ------------------------------------------------------------------------- */ XPCOM_API(uint32_t) NS_StringGetData(const nsAString& aStr, const char16_t** aData, bool* aTerminated) { if (aTerminated) { *aTerminated = aStr.IsTerminated(); } *aData = aStr.BeginReading(); return aStr.Length(); } XPCOM_API(uint32_t) NS_StringGetMutableData(nsAString& aStr, uint32_t aDataLength, char16_t** aData) { if (aDataLength != UINT32_MAX) { aStr.SetLength(aDataLength); if (aStr.Length() != aDataLength) { *aData = nullptr; return 0; } } *aData = aStr.BeginWriting(); return aStr.Length(); } XPCOM_API(char16_t*) NS_StringCloneData(const nsAString& aStr) { return ToNewUnicode(aStr); } XPCOM_API(nsresult) NS_StringSetData(nsAString& aStr, const char16_t* aData, uint32_t aDataLength) { aStr.Assign(aData, aDataLength); return NS_OK; // XXX report errors } XPCOM_API(nsresult) NS_StringSetDataRange(nsAString& aStr, uint32_t aCutOffset, uint32_t aCutLength, const char16_t* aData, uint32_t aDataLength) { if (aCutOffset == UINT32_MAX) { // append case if (aData) { aStr.Append(aData, aDataLength); } return NS_OK; // XXX report errors } if (aCutLength == UINT32_MAX) { aCutLength = aStr.Length() - aCutOffset; } if (aData) { if (aDataLength == UINT32_MAX) { aStr.Replace(aCutOffset, aCutLength, nsDependentString(aData)); } else { aStr.Replace(aCutOffset, aCutLength, Substring(aData, aDataLength)); } } else { aStr.Cut(aCutOffset, aCutLength); } return NS_OK; // XXX report errors } XPCOM_API(nsresult) NS_StringCopy(nsAString& aDest, const nsAString& aSrc) { aDest.Assign(aSrc); return NS_OK; // XXX report errors } XPCOM_API(void) NS_StringSetIsVoid(nsAString& aStr, const bool aIsVoid) { aStr.SetIsVoid(aIsVoid); } XPCOM_API(bool) NS_StringGetIsVoid(const nsAString& aStr) { return aStr.IsVoid(); } /* ------------------------------------------------------------------------- */ XPCOM_API(nsresult) NS_CStringContainerInit(nsCStringContainer& aContainer) { NS_ASSERTION(sizeof(nsStringContainer_base) >= sizeof(nsCString), "nsCStringContainer is not large enough"); // use placement new to avoid heap allocating nsCString object new (&aContainer) nsCString(); return NS_OK; } XPCOM_API(nsresult) NS_CStringContainerInit2(nsCStringContainer& aContainer, const char* aData, uint32_t aDataLength, uint32_t aFlags) { NS_ASSERTION(sizeof(nsStringContainer_base) >= sizeof(nsCString), "nsStringContainer is not large enough"); if (!aData) { new (&aContainer) nsCString(); } else { if (aDataLength == UINT32_MAX) { if (NS_WARN_IF(aFlags & NS_CSTRING_CONTAINER_INIT_SUBSTRING)) { return NS_ERROR_INVALID_ARG; } aDataLength = nsCharTraits<char>::length(aData); } if (aFlags & (NS_CSTRING_CONTAINER_INIT_DEPEND | NS_CSTRING_CONTAINER_INIT_ADOPT)) { uint32_t flags; if (aFlags & NS_CSTRING_CONTAINER_INIT_SUBSTRING) { flags = nsCSubstring::F_NONE; } else { flags = nsCSubstring::F_TERMINATED; } if (aFlags & NS_CSTRING_CONTAINER_INIT_ADOPT) { flags |= nsCSubstring::F_OWNED; } new (&aContainer) nsCSubstring(const_cast<char*>(aData), aDataLength, flags); } else { new (&aContainer) nsCString(aData, aDataLength); } } return NS_OK; } XPCOM_API(void) NS_CStringContainerFinish(nsCStringContainer& aContainer) { // call the nsCString dtor reinterpret_cast<nsCString*>(&aContainer)->~nsCString(); } /* ------------------------------------------------------------------------- */ XPCOM_API(uint32_t) NS_CStringGetData(const nsACString& aStr, const char** aData, bool* aTerminated) { if (aTerminated) { *aTerminated = aStr.IsTerminated(); } *aData = aStr.BeginReading(); return aStr.Length(); } XPCOM_API(uint32_t) NS_CStringGetMutableData(nsACString& aStr, uint32_t aDataLength, char** aData) { if (aDataLength != UINT32_MAX) { aStr.SetLength(aDataLength); if (aStr.Length() != aDataLength) { *aData = nullptr; return 0; } } *aData = aStr.BeginWriting(); return aStr.Length(); } XPCOM_API(char*) NS_CStringCloneData(const nsACString& aStr) { return ToNewCString(aStr); } XPCOM_API(nsresult) NS_CStringSetData(nsACString& aStr, const char* aData, uint32_t aDataLength) { aStr.Assign(aData, aDataLength); return NS_OK; // XXX report errors } XPCOM_API(nsresult) NS_CStringSetDataRange(nsACString& aStr, uint32_t aCutOffset, uint32_t aCutLength, const char* aData, uint32_t aDataLength) { if (aCutOffset == UINT32_MAX) { // append case if (aData) { aStr.Append(aData, aDataLength); } return NS_OK; // XXX report errors } if (aCutLength == UINT32_MAX) { aCutLength = aStr.Length() - aCutOffset; } if (aData) { if (aDataLength == UINT32_MAX) { aStr.Replace(aCutOffset, aCutLength, nsDependentCString(aData)); } else { aStr.Replace(aCutOffset, aCutLength, Substring(aData, aDataLength)); } } else { aStr.Cut(aCutOffset, aCutLength); } return NS_OK; // XXX report errors } XPCOM_API(nsresult) NS_CStringCopy(nsACString& aDest, const nsACString& aSrc) { aDest.Assign(aSrc); return NS_OK; // XXX report errors } XPCOM_API(void) NS_CStringSetIsVoid(nsACString& aStr, const bool aIsVoid) { aStr.SetIsVoid(aIsVoid); } XPCOM_API(bool) NS_CStringGetIsVoid(const nsACString& aStr) { return aStr.IsVoid(); } /* ------------------------------------------------------------------------- */ XPCOM_API(nsresult) NS_CStringToUTF16(const nsACString& aSrc, nsCStringEncoding aSrcEncoding, nsAString& aDest) { switch (aSrcEncoding) { case NS_CSTRING_ENCODING_ASCII: CopyASCIItoUTF16(aSrc, aDest); break; case NS_CSTRING_ENCODING_UTF8: CopyUTF8toUTF16(aSrc, aDest); break; case NS_CSTRING_ENCODING_NATIVE_FILESYSTEM: NS_CopyNativeToUnicode(aSrc, aDest); break; default: return NS_ERROR_NOT_IMPLEMENTED; } return NS_OK; // XXX report errors } XPCOM_API(nsresult) NS_UTF16ToCString(const nsAString& aSrc, nsCStringEncoding aDestEncoding, nsACString& aDest) { switch (aDestEncoding) { case NS_CSTRING_ENCODING_ASCII: LossyCopyUTF16toASCII(aSrc, aDest); break; case NS_CSTRING_ENCODING_UTF8: CopyUTF16toUTF8(aSrc, aDest); break; case NS_CSTRING_ENCODING_NATIVE_FILESYSTEM: NS_CopyUnicodeToNative(aSrc, aDest); break; default: return NS_ERROR_NOT_IMPLEMENTED; } return NS_OK; // XXX report errors }