diff --git a/mozilla/xpcom/build/dlldeps.cpp b/mozilla/xpcom/build/dlldeps.cpp index ea4cb1b0d58..a8600701deb 100644 --- a/mozilla/xpcom/build/dlldeps.cpp +++ b/mozilla/xpcom/build/dlldeps.cpp @@ -207,6 +207,7 @@ void XXXNeverCalled() NS_CStringContainerInit2(sc1, nsnull, 0, 0); NS_CStringContainerFinish(sc1); NS_CStringGetData(str2, nsnull, nsnull); + NS_CStringGetMutableData(str2, 0, nsnull); NS_CStringSetData(str2, nsnull, 0); NS_CStringSetDataRange(str2, 0, 0, nsnull, 0); NS_CStringCopy(str2, str2); @@ -216,6 +217,7 @@ void XXXNeverCalled() NS_StringContainerInit2(sc2, nsnull, 0, 0); NS_StringContainerFinish(sc2); NS_StringGetData(str1, nsnull, nsnull); + NS_StringGetMutableData(str1, 0, nsnull); NS_StringSetData(str1, nsnull, 0); NS_StringSetDataRange(str1, 0, 0, nsnull, 0); NS_StringCopy(str1, str1); diff --git a/mozilla/xpcom/build/nsStringAPI.cpp b/mozilla/xpcom/build/nsStringAPI.cpp index 903774871cf..c89d9cc0ae4 100644 --- a/mozilla/xpcom/build/nsStringAPI.cpp +++ b/mozilla/xpcom/build/nsStringAPI.cpp @@ -122,6 +122,24 @@ NS_StringGetData(const nsAString &aStr, const PRUnichar **aData, return begin.size_forward(); } +NS_STRINGAPI(PRUint32) +NS_StringGetMutableData(nsAString &aStr, PRUint32 aDataLength, + PRUnichar **aData) +{ + if (aDataLength != PR_UINT32_MAX) { + aStr.SetLength(aDataLength); + if (aStr.Length() != aDataLength) { + *aData = nsnull; + return 0; + } + } + + nsAString::iterator begin; + aStr.BeginWriting(begin); + *aData = begin.get(); + return begin.size_forward(); +} + NS_STRINGAPI(PRUnichar *) NS_StringCloneData(const nsAString &aStr) { @@ -252,6 +270,23 @@ NS_CStringGetData(const nsACString &aStr, const char **aData, return begin.size_forward(); } +NS_STRINGAPI(PRUint32) +NS_CStringGetMutableData(nsACString &aStr, PRUint32 aDataLength, char **aData) +{ + if (aDataLength != PR_UINT32_MAX) { + aStr.SetLength(aDataLength); + if (aStr.Length() != aDataLength) { + *aData = nsnull; + return 0; + } + } + + nsACString::iterator begin; + aStr.BeginWriting(begin); + *aData = begin.get(); + return begin.size_forward(); +} + NS_STRINGAPI(char *) NS_CStringCloneData(const nsACString &aStr) { diff --git a/mozilla/xpcom/build/nsXPCOMPrivate.h b/mozilla/xpcom/build/nsXPCOMPrivate.h index 57799019f9a..b46f8287456 100644 --- a/mozilla/xpcom/build/nsXPCOMPrivate.h +++ b/mozilla/xpcom/build/nsXPCOMPrivate.h @@ -99,6 +99,7 @@ typedef nsresult (* StringContainerInitFunc)(nsStringContainer&); typedef nsresult (* StringContainerInit2Func)(nsStringContainer&, const PRUnichar *, PRUint32, PRUint32); typedef void (* StringContainerFinishFunc)(nsStringContainer&); typedef PRUint32 (* StringGetDataFunc)(const nsAString&, const PRUnichar**, PRBool*); +typedef PRUint32 (* StringGetMutableDataFunc)(nsAString&, PRUint32, PRUnichar**); typedef PRUnichar* (* StringCloneDataFunc)(const nsAString&); typedef nsresult (* StringSetDataFunc)(nsAString&, const PRUnichar*, PRUint32); typedef nsresult (* StringSetDataRangeFunc)(nsAString&, PRUint32, PRUint32, const PRUnichar*, PRUint32); @@ -108,6 +109,7 @@ typedef nsresult (* CStringContainerInitFunc)(nsCStringContainer&); typedef nsresult (* CStringContainerInit2Func)(nsCStringContainer&, const char *, PRUint32, PRUint32); typedef void (* CStringContainerFinishFunc)(nsCStringContainer&); typedef PRUint32 (* CStringGetDataFunc)(const nsACString&, const char**, PRBool*); +typedef PRUint32 (* CStringGetMutableDataFunc)(nsACString&, PRUint32, char**); typedef char* (* CStringCloneDataFunc)(const nsACString&); typedef nsresult (* CStringSetDataFunc)(nsACString&, const char*, PRUint32); typedef nsresult (* CStringSetDataRangeFunc)(nsACString&, PRUint32, PRUint32, const char*, PRUint32); @@ -168,6 +170,8 @@ typedef struct XPCOMFunctions{ FreeFunc freeFunc; StringContainerInit2Func stringContainerInit2; CStringContainerInit2Func cstringContainerInit2; + StringGetMutableDataFunc stringGetMutableData; + CStringGetMutableDataFunc cstringGetMutableData; } XPCOMFunctions; diff --git a/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp b/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp index c3b4e3028fc..27a4ecbbe5d 100644 --- a/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp +++ b/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp @@ -317,6 +317,16 @@ NS_StringGetData(const nsAString &aStr, const PRUnichar **aBuf, PRBool *aTerm) return xpcomFunctions.stringGetData(aStr, aBuf, aTerm); } +extern "C" NS_COM PRUint32 +NS_StringGetMutableData(nsAString &aStr, PRUint32 aLen, PRUnichar **aBuf) +{ + if (!xpcomFunctions.stringGetMutableData) { + *aBuf = nsnull; + return 0; + } + return xpcomFunctions.stringGetMutableData(aStr, aLen, aBuf); +} + extern "C" NS_COM PRUnichar * NS_StringCloneData(const nsAString &aStr) { @@ -388,6 +398,16 @@ NS_CStringGetData(const nsACString &aStr, const char **aBuf, PRBool *aTerm) return xpcomFunctions.cstringGetData(aStr, aBuf, aTerm); } +extern "C" NS_COM PRUint32 +NS_CStringGetMutableData(nsACString &aStr, PRUint32 aLen, char **aBuf) +{ + if (!xpcomFunctions.cstringGetMutableData) { + *aBuf = nsnull; + return 0; + } + return xpcomFunctions.cstringGetMutableData(aStr, aLen, aBuf); +} + extern "C" NS_COM char * NS_CStringCloneData(const nsACString &aStr) { diff --git a/mozilla/xpcom/string/public/nsStringAPI.h b/mozilla/xpcom/string/public/nsStringAPI.h index 6d3568efbe1..0fe6bcb9aef 100644 --- a/mozilla/xpcom/string/public/nsStringAPI.h +++ b/mozilla/xpcom/string/public/nsStringAPI.h @@ -52,6 +52,7 @@ # define NS_StringContainerInit2 NS_StringContainerInit2_P # define NS_StringContainerFinish NS_StringContainerFinish_P # define NS_StringGetData NS_StringGetData_P +# define NS_StringGetMutableData NS_StringGetMutableData_P # define NS_StringCloneData NS_StringCloneData_P # define NS_StringSetData NS_StringSetData_P # define NS_StringSetDataRange NS_StringSetDataRange_P @@ -60,6 +61,7 @@ # define NS_CStringContainerInit2 NS_CStringContainerInit2_P # define NS_CStringContainerFinish NS_CStringContainerFinish_P # define NS_CStringGetData NS_CStringGetData_P +# define NS_CStringGetMutableData NS_CStringGetMutableData_P # define NS_CStringCloneData NS_CStringCloneData_P # define NS_CStringSetData NS_CStringSetData_P # define NS_CStringSetDataRange NS_CStringSetDataRange_P @@ -247,6 +249,39 @@ NS_StringGetData (const nsAString &aStr, const PRUnichar **aData, PRBool *aTerminated = nsnull); +/** + * NS_StringGetMutableData + * + * This function provides mutable access to a string's internal buffer. It + * returns a pointer to an array of characters that may be modified. The + * returned pointer remains valid until the string object is passed to some + * other string function. + * + * Optionally, this function may be used to resize the string's internal + * buffer. The aDataLength parameter specifies the requested length of the + * string's internal buffer. By passing some value other than PR_UINT32_MAX, + * the caller can request that the buffer be resized to the specified number of + * characters before returning. The caller is not responsible for writing a + * null-terminator. + * + * @param aStr abstract string reference + * @param aDataLength number of characters to resize the string's internal + * buffer to or PR_UINT32_MAX if no resizing is needed + * @param aData out param that upon return holds the address of aStr's + * internal buffer or null if the function failed + * @return number of characters or zero if the function failed + * + * This function does not necessarily null-terminate aStr after resizing its + * internal buffer. The behavior depends on the implementation of the abstract + * string, aStr. If aStr is a reference to a nsStringContainer, then its data + * will be null-terminated by this function. + * + * @status FROZEN + */ +NS_STRINGAPI(PRUint32) +NS_StringGetMutableData + (nsAString &aStr, PRUint32 aDataLength, PRUnichar **aData); + /** * NS_StringCloneData * @@ -519,6 +554,39 @@ NS_CStringGetData (const nsACString &aStr, const char **aData, PRBool *aTerminated = nsnull); +/** + * NS_CStringGetMutableData + * + * This function provides mutable access to a string's internal buffer. It + * returns a pointer to an array of characters that may be modified. The + * returned pointer remains valid until the string object is passed to some + * other string function. + * + * Optionally, this function may be used to resize the string's internal + * buffer. The aDataLength parameter specifies the requested length of the + * string's internal buffer. By passing some value other than PR_UINT32_MAX, + * the caller can request that the buffer be resized to the specified number of + * characters before returning. The caller is not responsible for writing a + * null-terminator. + * + * @param aStr abstract string reference + * @param aDataLength number of characters to resize the string's internal + * buffer to or PR_UINT32_MAX if no resizing is needed + * @param aData out param that upon return holds the address of aStr's + * internal buffer or null if the function failed + * @return number of characters or zero if the function failed + * + * This function does not necessarily null-terminate aStr after resizing its + * internal buffer. The behavior depends on the implementation of the abstract + * string, aStr. If aStr is a reference to a nsStringContainer, then its data + * will be null-terminated by this function. + * + * @status FROZEN + */ +NS_STRINGAPI(PRUint32) +NS_CStringGetMutableData + (nsACString &aStr, PRUint32 aDataLength, char **aData); + /** * NS_CStringCloneData * @@ -782,6 +850,20 @@ public: return data + len; } + NS_HIDDEN_(char_type*) BeginWriting() + { + char_type *data; + NS_StringGetMutableData(*this, PR_UINT32_MAX, &data); + return data; + } + + NS_HIDDEN_(PRBool) SetLength(PRUint32 aLen) + { + char_type *data; + NS_StringGetMutableData(*this, aLen, &data); + return data != nsnull; + } + NS_HIDDEN_(size_type) Length() const { const char_type* data; @@ -869,6 +951,20 @@ public: return data + len; } + NS_HIDDEN_(char_type*) BeginWriting() + { + char_type *data; + NS_CStringGetMutableData(*this, PR_UINT32_MAX, &data); + return data; + } + + NS_HIDDEN_(PRBool) SetLength(PRUint32 aLen) + { + char_type *data; + NS_CStringGetMutableData(*this, aLen, &data); + return data != nsnull; + } + NS_HIDDEN_(size_type) Length() const { const char_type* data; diff --git a/mozilla/xpcom/stub/nsXPComStub.cpp b/mozilla/xpcom/stub/nsXPComStub.cpp index 0d47b8f4df8..f9110f424a4 100644 --- a/mozilla/xpcom/stub/nsXPComStub.cpp +++ b/mozilla/xpcom/stub/nsXPComStub.cpp @@ -82,7 +82,9 @@ static const XPCOMFunctions kFrozenFunctions = { &NS_Realloc_P, &NS_Free_P, &NS_StringContainerInit2_P, - &NS_CStringContainerInit2_P + &NS_CStringContainerInit2_P, + &NS_StringGetMutableData_P, + &NS_CStringGetMutableData_P }; extern "C" NS_EXPORT nsresult @@ -259,6 +261,13 @@ NS_StringGetData(const nsAString &aStr, const PRUnichar **aBuf, PRBool *aTerm) return NS_StringGetData_P(aStr, aBuf, aTerm); } +#undef NS_StringGetMutableData +extern "C" NS_EXPORT PRUint32 +NS_StringGetMutableData(nsAString &aStr, PRUint32 aLen, PRUnichar **aBuf) +{ + return NS_StringGetMutableData_P(aStr, aLen, aBuf); +} + #undef NS_StringCloneData extern "C" NS_EXPORT PRUnichar * NS_StringCloneData(const nsAString &aStr) @@ -319,6 +328,13 @@ NS_CStringGetData(const nsACString &aStr, const char **aBuf, PRBool *aTerm) return NS_CStringGetData_P(aStr, aBuf, aTerm); } +#undef NS_CStringGetMutableData +extern "C" NS_EXPORT PRUint32 +NS_CStringGetMutableData(nsACString &aStr, PRUint32 aLen, char **aBuf) +{ + return NS_CStringGetMutableData_P(aStr, aLen, aBuf); +} + #undef NS_CStringCloneData extern "C" NS_EXPORT char * NS_CStringCloneData(const nsACString &aStr) diff --git a/mozilla/xpcom/tests/TestMinStringAPI.cpp b/mozilla/xpcom/tests/TestMinStringAPI.cpp index d0b6145542c..708ed3cdc7d 100644 --- a/mozilla/xpcom/tests/TestMinStringAPI.cpp +++ b/mozilla/xpcom/tests/TestMinStringAPI.cpp @@ -431,6 +431,39 @@ static PRBool test_adopt_sub() return rv; } +static PRBool test_mutation() + { + nsCStringContainer s; + NS_CStringContainerInit(s); + + const char kText[] = "Every good boy does fine."; + + char *buf; + PRUint32 len = NS_CStringGetMutableData(s, sizeof(kText) - 1, &buf); + if (!buf || len != sizeof(kText) - 1) + return PR_FALSE; + memcpy(buf, kText, sizeof(kText)); + + const char *data; + NS_CStringGetData(s, &data); + if (strcmp(data, kText) != 0) + return PR_FALSE; + + PRUint32 newLen = len + 1; + len = NS_CStringGetMutableData(s, newLen, &buf); + if (!buf || len != newLen) + return PR_FALSE; + + buf[len - 1] = '.'; + + NS_CStringGetData(s, &data); + if (strncmp(data, kText, len - 1) != 0 || data[len - 1] != '.') + return PR_FALSE; + + NS_CStringContainerFinish(s); + return PR_TRUE; + } + //---- typedef PRBool (*TestFunc)(); @@ -452,6 +485,7 @@ tests[] = { "test_depend_sub", test_depend_sub }, { "test_adopt", test_adopt }, { "test_adopt_sub", test_adopt_sub }, + { "test_mutation", test_mutation }, { nsnull, nsnull } };