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