From 17b87fb59e80230e511277907e2add6c7a8e2cd3 Mon Sep 17 00:00:00 2001 From: "darin%meer.net" Date: Thu, 1 Apr 2004 20:47:48 +0000 Subject: [PATCH] fixes bug 239303 "provide basic string conversion routines for the Gecko SDK" r=bsmedberg sr=dbaron a=chofmann git-svn-id: svn://10.0.0.236/trunk@154433 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/xpcom/build/nsStringAPI.cpp | 49 ++++ mozilla/xpcom/build/nsXPCOMPrivate.h | 33 ++- mozilla/xpcom/build/nsXPComInit.cpp | 2 + mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp | 16 ++ mozilla/xpcom/string/public/nsStringAPI.h | 55 ++++ mozilla/xpcom/string/src/nsStringAPI.cpp | 49 ++++ mozilla/xpcom/stub/nsStringAPI.cpp | 49 ++++ mozilla/xpcom/tests/TestMinStringAPI.cpp | 257 +++++++++++------- 8 files changed, 391 insertions(+), 119 deletions(-) diff --git a/mozilla/xpcom/build/nsStringAPI.cpp b/mozilla/xpcom/build/nsStringAPI.cpp index 58b3985ad5d..cbd82e6d60f 100644 --- a/mozilla/xpcom/build/nsStringAPI.cpp +++ b/mozilla/xpcom/build/nsStringAPI.cpp @@ -42,6 +42,7 @@ #define nsACString_external nsACString_external_ #include "nsStringAPI.h" +#include "nsNativeCharsetUtils.h" /* ------------------------------------------------------------------------- */ @@ -192,3 +193,51 @@ NS_CStringCopy(nsACString &aDest, const nsACString &aSrc) { aDest.Assign(aSrc); } + +/* ------------------------------------------------------------------------- */ + +NS_STRINGAPI(nsresult) +NS_CStringToUTF16(const nsACString &aSrc, PRUint32 aSrcEncoding, nsAString &aDest) +{ + // XXX handle errors + + switch (aSrcEncoding) + { + case NS_ENCODING_ASCII: + CopyASCIItoUTF16(aSrc, aDest); + break; + case NS_ENCODING_UTF8: + CopyUTF8toUTF16(aSrc, aDest); + break; + case NS_ENCODING_NATIVE_FILESYSTEM: + NS_CopyNativeToUnicode(aSrc, aDest); + break; + default: + return NS_ERROR_NOT_IMPLEMENTED; + } + + return NS_OK; +} + +NS_STRINGAPI(nsresult) +NS_UTF16ToCString(const nsAString &aSrc, PRUint32 aDestEncoding, nsACString &aDest) +{ + // XXX handle errors + + switch (aDestEncoding) + { + case NS_ENCODING_ASCII: + LossyCopyUTF16toASCII(aSrc, aDest); + break; + case NS_ENCODING_UTF8: + CopyUTF16toUTF8(aSrc, aDest); + break; + case NS_ENCODING_NATIVE_FILESYSTEM: + NS_CopyUnicodeToNative(aSrc, aDest); + break; + default: + return NS_ERROR_NOT_IMPLEMENTED; + } + + return NS_OK; +} diff --git a/mozilla/xpcom/build/nsXPCOMPrivate.h b/mozilla/xpcom/build/nsXPCOMPrivate.h index 8b38ab361be..ea6bb653cd9 100644 --- a/mozilla/xpcom/build/nsXPCOMPrivate.h +++ b/mozilla/xpcom/build/nsXPCOMPrivate.h @@ -88,19 +88,22 @@ typedef nsresult (* NewNativeLocalFileFunc)(const nsACString &path, PRBool follo typedef nsresult (* GetDebugFunc)(nsIDebug* *result); typedef nsresult (* GetTraceRefcntFunc)(nsITraceRefcnt* *result); -typedef PRBool (* StringContainerInitFunc)(nsStringContainer&); -typedef void (* StringContainerFinishFunc)(nsStringContainer&); -typedef PRUint32 (* StringGetDataFunc)(const nsAString&, const PRUnichar**, PRBool*); -typedef void (* StringSetDataFunc)(nsAString&, const PRUnichar*, PRUint32); -typedef void (* StringSetDataRangeFunc)(nsAString&, PRUint32, PRUint32, const PRUnichar*, PRUint32); -typedef void (* StringCopyFunc)(nsAString &, const nsAString &); +typedef PRBool (* StringContainerInitFunc)(nsStringContainer&); +typedef void (* StringContainerFinishFunc)(nsStringContainer&); +typedef PRUint32 (* StringGetDataFunc)(const nsAString&, const PRUnichar**, PRBool*); +typedef void (* StringSetDataFunc)(nsAString&, const PRUnichar*, PRUint32); +typedef void (* StringSetDataRangeFunc)(nsAString&, PRUint32, PRUint32, const PRUnichar*, PRUint32); +typedef void (* StringCopyFunc)(nsAString &, const nsAString &); -typedef PRBool (* CStringContainerInitFunc)(nsCStringContainer&); -typedef void (* CStringContainerFinishFunc)(nsCStringContainer&); -typedef PRUint32 (* CStringGetDataFunc)(const nsACString&, const char**, PRBool*); -typedef void (* CStringSetDataFunc)(nsACString&, const char*, PRUint32); -typedef void (* CStringSetDataRangeFunc)(nsACString&, PRUint32, PRUint32, const char*, PRUint32); -typedef void (* CStringCopyFunc)(nsACString &, const nsACString &); +typedef PRBool (* CStringContainerInitFunc)(nsCStringContainer&); +typedef void (* CStringContainerFinishFunc)(nsCStringContainer&); +typedef PRUint32 (* CStringGetDataFunc)(const nsACString&, const char**, PRBool*); +typedef void (* CStringSetDataFunc)(nsACString&, const char*, PRUint32); +typedef void (* CStringSetDataRangeFunc)(nsACString&, PRUint32, PRUint32, const char*, PRUint32); +typedef void (* CStringCopyFunc)(nsACString &, const nsACString &); + +typedef nsresult (* CStringToUTF16)(const nsACString &, PRUint32, const nsAString &); +typedef nsresult (* UTF16ToCString)(const nsAString &, PRUint32, const nsACString &); // PRIVATE typedef nsresult (* RegisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine, PRUint32 priority); @@ -122,11 +125,11 @@ typedef struct XPCOMFunctions{ RegisterXPCOMExitRoutineFunc registerExitRoutine; UnregisterXPCOMExitRoutineFunc unregisterExitRoutine; - // Added Post 1.4 + // Added for Mozilla 1.5 GetDebugFunc getDebug; GetTraceRefcntFunc getTraceRefcnt; - // Added Post 1.6 + // Added for Mozilla 1.7 StringContainerInitFunc stringContainerInit; StringContainerFinishFunc stringContainerFinish; StringGetDataFunc stringGetData; @@ -139,6 +142,8 @@ typedef struct XPCOMFunctions{ CStringSetDataFunc cstringSetData; CStringSetDataRangeFunc cstringSetDataRange; CStringCopyFunc cstringCopy; + CStringToUTF16 cstringToUTF16; + UTF16ToCString utf16ToCString; } XPCOMFunctions; diff --git a/mozilla/xpcom/build/nsXPComInit.cpp b/mozilla/xpcom/build/nsXPComInit.cpp index f7082e06c56..49b5ef1a761 100644 --- a/mozilla/xpcom/build/nsXPComInit.cpp +++ b/mozilla/xpcom/build/nsXPComInit.cpp @@ -873,6 +873,8 @@ NS_GetFrozenFunctions(XPCOMFunctions *functions, const char* libraryPath) GET_FUNC(cstringSetData, CStringSetDataFunc, "NS_CStringSetData"); GET_FUNC(cstringSetDataRange, CStringSetDataRangeFunc, "NS_CStringSetDataRange"); GET_FUNC(cstringCopy, CStringCopyFunc, "NS_CStringCopy"); + GET_FUNC(cstringToUTF16, CStringToUTF16, "NS_CStringToUTF16"); + GET_FUNC(utf16ToCString, UTF16ToCString, "NS_UTF16ToCString"); } rv = NS_OK; diff --git a/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp b/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp index 289133d89bb..7aae76a5465 100644 --- a/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp +++ b/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp @@ -357,6 +357,22 @@ NS_CStringCopy(nsACString &aDest, const nsACString &aSrc) xpcomFunctions.cstringCopy(aDest, aSrc); } +extern "C" NS_COM nsresult +NS_CStringToUTF16(const nsACString &aSrc, PRUint32 aSrcEncoding, nsAString &aDest) +{ + if (!xpcomGlueInit) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.cstringToUTF16(aSrc, aSrcEncoding, aDest); +} + +extern "C" NS_COM nsresult +NS_UTF16ToCString(const nsAString &aSrc, PRUint32 aDestEncoding, nsACString &aDest) +{ + if (!xpcomGlueInit) + return NS_ERROR_NOT_INITIALIZED; + return xpcomFunctions.utf16ToCString(aSrc, aDestEncoding, aDest); +} + #endif // #ifndef XPCOM_GLUE_NO_DYNAMIC_LOADING diff --git a/mozilla/xpcom/string/public/nsStringAPI.h b/mozilla/xpcom/string/public/nsStringAPI.h index 1cb4de048f3..aa929933474 100644 --- a/mozilla/xpcom/string/public/nsStringAPI.h +++ b/mozilla/xpcom/string/public/nsStringAPI.h @@ -520,4 +520,59 @@ NS_CStringCutData(nsACString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength) NS_CStringSetDataRange(aStr, aCutOffset, aCutLength, nsnull, 0); } +/* ------------------------------------------------------------------------- */ + +/** + * Encodings that can be used with the following conversion routines. + */ +enum { + /* Conversion between ASCII and UTF-16 assumes that all bytes in the source + * string are 7-bit ASCII and can be inflated to UTF-16 by inserting null + * bytes. Reverse conversion is done by truncating every other byte. The + * conversion may result in loss and/or corruption of information if the + * strings do not strictly contain ASCII data. */ + NS_ENCODING_ASCII = 0, + + /* Conversion between UTF-8 and UTF-16 is non-lossy. */ + NS_ENCODING_UTF8 = 1, + + /* Conversion from UTF-16 to the native filesystem charset may result in a + * loss of information. No attempt is made to protect against data loss in + * this case. The native filesystem charset applies to strings passed to + * the "Native" method variants on nsIFile and nsILocalFile. */ + NS_ENCODING_NATIVE_FILESYSTEM = 2 +}; + +/** + * NS_CStringToUTF16 + * + * This function converts the characters in a nsACString to an array of UTF-16 + * characters, in the platform endianness. The result is stored in a nsAString + * object. + * + * @param aSource abstract string reference containing source string + * @param aSrcEncoding character encoding of the source string + * @param aDest abstract string reference to hold the result + */ +NS_STRINGAPI(nsresult) +NS_CStringToUTF16(const nsACString &aSource, PRUint32 aSrcEncoding, + nsAString &aDest); + +/** + * NS_UTF16ToCString + * + * This function converts the UTF-16 characters in a nsAString to a single-byte + * encoding. The result is stored in a nsACString object. In some cases this + * conversion may be lossy. In such cases, the conversion may succeed with a + * return code indicating loss of information. The exact behavior is not + * specified at this time. + * + * @param aSource abstract string reference containing source string + * @param aDestEncoding character encoding of the resulting string + * @param aDest abstract string reference to hold the result + */ +NS_STRINGAPI(nsresult) +NS_UTF16ToCString(const nsAString &aSource, PRUint32 aDestEncoding, + nsACString &aDest); + #endif // nsStringAPI_h__ diff --git a/mozilla/xpcom/string/src/nsStringAPI.cpp b/mozilla/xpcom/string/src/nsStringAPI.cpp index 58b3985ad5d..cbd82e6d60f 100644 --- a/mozilla/xpcom/string/src/nsStringAPI.cpp +++ b/mozilla/xpcom/string/src/nsStringAPI.cpp @@ -42,6 +42,7 @@ #define nsACString_external nsACString_external_ #include "nsStringAPI.h" +#include "nsNativeCharsetUtils.h" /* ------------------------------------------------------------------------- */ @@ -192,3 +193,51 @@ NS_CStringCopy(nsACString &aDest, const nsACString &aSrc) { aDest.Assign(aSrc); } + +/* ------------------------------------------------------------------------- */ + +NS_STRINGAPI(nsresult) +NS_CStringToUTF16(const nsACString &aSrc, PRUint32 aSrcEncoding, nsAString &aDest) +{ + // XXX handle errors + + switch (aSrcEncoding) + { + case NS_ENCODING_ASCII: + CopyASCIItoUTF16(aSrc, aDest); + break; + case NS_ENCODING_UTF8: + CopyUTF8toUTF16(aSrc, aDest); + break; + case NS_ENCODING_NATIVE_FILESYSTEM: + NS_CopyNativeToUnicode(aSrc, aDest); + break; + default: + return NS_ERROR_NOT_IMPLEMENTED; + } + + return NS_OK; +} + +NS_STRINGAPI(nsresult) +NS_UTF16ToCString(const nsAString &aSrc, PRUint32 aDestEncoding, nsACString &aDest) +{ + // XXX handle errors + + switch (aDestEncoding) + { + case NS_ENCODING_ASCII: + LossyCopyUTF16toASCII(aSrc, aDest); + break; + case NS_ENCODING_UTF8: + CopyUTF16toUTF8(aSrc, aDest); + break; + case NS_ENCODING_NATIVE_FILESYSTEM: + NS_CopyUnicodeToNative(aSrc, aDest); + break; + default: + return NS_ERROR_NOT_IMPLEMENTED; + } + + return NS_OK; +} diff --git a/mozilla/xpcom/stub/nsStringAPI.cpp b/mozilla/xpcom/stub/nsStringAPI.cpp index 58b3985ad5d..cbd82e6d60f 100644 --- a/mozilla/xpcom/stub/nsStringAPI.cpp +++ b/mozilla/xpcom/stub/nsStringAPI.cpp @@ -42,6 +42,7 @@ #define nsACString_external nsACString_external_ #include "nsStringAPI.h" +#include "nsNativeCharsetUtils.h" /* ------------------------------------------------------------------------- */ @@ -192,3 +193,51 @@ NS_CStringCopy(nsACString &aDest, const nsACString &aSrc) { aDest.Assign(aSrc); } + +/* ------------------------------------------------------------------------- */ + +NS_STRINGAPI(nsresult) +NS_CStringToUTF16(const nsACString &aSrc, PRUint32 aSrcEncoding, nsAString &aDest) +{ + // XXX handle errors + + switch (aSrcEncoding) + { + case NS_ENCODING_ASCII: + CopyASCIItoUTF16(aSrc, aDest); + break; + case NS_ENCODING_UTF8: + CopyUTF8toUTF16(aSrc, aDest); + break; + case NS_ENCODING_NATIVE_FILESYSTEM: + NS_CopyNativeToUnicode(aSrc, aDest); + break; + default: + return NS_ERROR_NOT_IMPLEMENTED; + } + + return NS_OK; +} + +NS_STRINGAPI(nsresult) +NS_UTF16ToCString(const nsAString &aSrc, PRUint32 aDestEncoding, nsACString &aDest) +{ + // XXX handle errors + + switch (aDestEncoding) + { + case NS_ENCODING_ASCII: + LossyCopyUTF16toASCII(aSrc, aDest); + break; + case NS_ENCODING_UTF8: + CopyUTF16toUTF8(aSrc, aDest); + break; + case NS_ENCODING_NATIVE_FILESYSTEM: + NS_CopyUnicodeToNative(aSrc, aDest); + break; + default: + return NS_ERROR_NOT_IMPLEMENTED; + } + + return NS_OK; +} diff --git a/mozilla/xpcom/tests/TestMinStringAPI.cpp b/mozilla/xpcom/tests/TestMinStringAPI.cpp index a7641beb451..d61979944ec 100644 --- a/mozilla/xpcom/tests/TestMinStringAPI.cpp +++ b/mozilla/xpcom/tests/TestMinStringAPI.cpp @@ -44,119 +44,166 @@ static const char kAsciiData[] = "hello world"; static const PRUnichar kUnicodeData[] = {'h','e','l','l','o',' ','w','o','r','l','d','\0'}; -static PRBool -TestACString(nsACString &s) -{ - const char *ptr; - PRUint32 len; - - NS_CStringGetData(s, &ptr); - if (ptr == nsnull || *ptr != '\0') - { - NS_BREAK(); - return PR_FALSE; - } - - NS_CStringSetData(s, kAsciiData, PR_UINT32_MAX); - len = NS_CStringGetData(s, &ptr); - if (ptr == nsnull || strcmp(ptr, kAsciiData) != 0) - { - NS_BREAK(); - return PR_FALSE; - } - if (len != sizeof(kAsciiData)-1) - { - NS_BREAK(); - return PR_FALSE; - } - - nsCStringContainer temp; - NS_CStringContainerInit(temp); - NS_CStringCopy(temp, s); - - len = NS_CStringGetData(temp, &ptr); - if (ptr == nsnull || strcmp(ptr, kAsciiData) != 0) - { - NS_BREAK(); - return PR_FALSE; - } - if (len != sizeof(kAsciiData)-1) - { - NS_BREAK(); - return PR_FALSE; - } - - NS_CStringContainerFinish(temp); - - return PR_TRUE; -} - -static PRBool -TestAString(nsAString &s) -{ - const PRUnichar *ptr; - PRUint32 len; - - NS_StringGetData(s, &ptr); - if (ptr == nsnull || *ptr != '\0') - { - NS_BREAK(); - return PR_FALSE; - } - - NS_StringSetData(s, kUnicodeData, PR_UINT32_MAX); - len = NS_StringGetData(s, &ptr); - if (ptr == nsnull || nsCRT::strcmp(ptr, kUnicodeData) != 0) - { - NS_BREAK(); - return PR_FALSE; - } - if (len != sizeof(kUnicodeData)/2 - 1) - { - NS_BREAK(); - return PR_FALSE; - } - - nsStringContainer temp; - NS_StringContainerInit(temp); - NS_StringCopy(temp, s); - - len = NS_StringGetData(temp, &ptr); - if (ptr == nsnull || nsCRT::strcmp(ptr, kUnicodeData) != 0) - { - NS_BREAK(); - return PR_FALSE; - } - if (len != sizeof(kUnicodeData)/2 - 1) - { - NS_BREAK(); - return PR_FALSE; - } - - NS_StringContainerFinish(temp); - - return PR_TRUE; -} - -int main() -{ - PRBool rv; - - // TestCStringContainer +static PRBool test_basic_1() { nsCStringContainer s; NS_CStringContainerInit(s); - rv = TestACString(s); + + const char *ptr; + PRUint32 len; + + NS_CStringGetData(s, &ptr); + if (ptr == nsnull || *ptr != '\0') + { + NS_ERROR("unexpected result"); + return PR_FALSE; + } + + NS_CStringSetData(s, kAsciiData, PR_UINT32_MAX); + len = NS_CStringGetData(s, &ptr); + if (ptr == nsnull || strcmp(ptr, kAsciiData) != 0) + { + NS_ERROR("unexpected result"); + return PR_FALSE; + } + if (len != sizeof(kAsciiData)-1) + { + NS_ERROR("unexpected result"); + return PR_FALSE; + } + + nsCStringContainer temp; + NS_CStringContainerInit(temp); + NS_CStringCopy(temp, s); + + len = NS_CStringGetData(temp, &ptr); + if (ptr == nsnull || strcmp(ptr, kAsciiData) != 0) + { + NS_ERROR("unexpected result"); + return PR_FALSE; + } + if (len != sizeof(kAsciiData)-1) + { + NS_ERROR("unexpected result"); + return PR_FALSE; + } + + NS_CStringContainerFinish(temp); + NS_CStringContainerFinish(s); - printf("TestACString\t%s\n", rv ? "PASSED" : "FAILED"); + return PR_TRUE; } - // TestStringContainer +static PRBool test_basic_2() { nsStringContainer s; NS_StringContainerInit(s); - rv = TestAString(s); + + const PRUnichar *ptr; + PRUint32 len; + + NS_StringGetData(s, &ptr); + if (ptr == nsnull || *ptr != '\0') + { + NS_ERROR("unexpected result"); + return PR_FALSE; + } + + NS_StringSetData(s, kUnicodeData, PR_UINT32_MAX); + len = NS_StringGetData(s, &ptr); + if (ptr == nsnull || nsCRT::strcmp(ptr, kUnicodeData) != 0) + { + NS_ERROR("unexpected result"); + return PR_FALSE; + } + if (len != sizeof(kUnicodeData)/2 - 1) + { + NS_ERROR("unexpected result"); + return PR_FALSE; + } + + nsStringContainer temp; + NS_StringContainerInit(temp); + NS_StringCopy(temp, s); + + len = NS_StringGetData(temp, &ptr); + if (ptr == nsnull || nsCRT::strcmp(ptr, kUnicodeData) != 0) + { + NS_ERROR("unexpected result"); + return PR_FALSE; + } + if (len != sizeof(kUnicodeData)/2 - 1) + { + NS_ERROR("unexpected result"); + return PR_FALSE; + } + + NS_StringContainerFinish(temp); + NS_StringContainerFinish(s); - printf("TestAString\t%s\n", rv ? "PASSED" : "FAILED"); + + return PR_TRUE; + } + +static PRBool test_convert() + { + nsStringContainer s; + NS_StringContainerInit(s); + NS_StringSetData(s, kUnicodeData, sizeof(kUnicodeData)/2 - 1); + + nsCStringContainer temp; + NS_CStringContainerInit(temp); + + const char *data; + + NS_UTF16ToCString(s, NS_ENCODING_ASCII, temp); + NS_CStringGetData(temp, &data); + if (strcmp(data, kAsciiData) != 0) + return PR_FALSE; + + NS_UTF16ToCString(s, NS_ENCODING_UTF8, temp); + NS_CStringGetData(temp, &data); + if (strcmp(data, kAsciiData) != 0) + return PR_FALSE; + + NS_CStringContainerFinish(temp); + + NS_StringContainerFinish(s); + return PR_TRUE; + } + +//---- + +typedef PRBool (*TestFunc)(); + +static const struct Test + { + const char* name; + TestFunc func; + } +tests[] = + { + { "test_basic_1", test_basic_1 }, + { "test_basic_2", test_basic_2 }, + { "test_convert", test_convert }, + { nsnull, nsnull } + }; + +//---- + +int main(int argc, char **argv) + { + int count = 1; + if (argc > 1) + count = atoi(argv[1]); + + while (count--) + { + for (const Test* t = tests; t->name != nsnull; ++t) + { + printf("%25s : %s\n", t->name, t->func() ? "SUCCESS" : "FAILURE"); + } + } + + return 0; } -}