зеркало из https://github.com/mozilla/gecko-dev.git
fixes bug 264274 "support dependent strings in frozen string API" r=biesi sr=bsmedberg
This commit is contained in:
Родитель
83f994441b
Коммит
90246214db
|
@ -96,6 +96,7 @@ typedef nsresult (* GetDebugFunc)(nsIDebug* *result);
|
|||
typedef nsresult (* GetTraceRefcntFunc)(nsITraceRefcnt* *result);
|
||||
|
||||
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 PRUnichar* (* StringCloneDataFunc)(const nsAString&);
|
||||
|
@ -104,6 +105,7 @@ typedef nsresult (* StringSetDataRangeFunc)(nsAString&, PRUint32, PRUint32, co
|
|||
typedef nsresult (* StringCopyFunc)(nsAString &, const nsAString &);
|
||||
|
||||
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 char* (* CStringCloneDataFunc)(const nsACString&);
|
||||
|
@ -159,9 +161,13 @@ typedef struct XPCOMFunctions{
|
|||
UTF16ToCString utf16ToCString;
|
||||
StringCloneDataFunc stringCloneData;
|
||||
CStringCloneDataFunc cstringCloneData;
|
||||
|
||||
// Added for Mozilla 1.8
|
||||
AllocFunc allocFunc;
|
||||
ReallocFunc reallocFunc;
|
||||
FreeFunc freeFunc;
|
||||
StringContainerInit2Func stringContainerInit2;
|
||||
CStringContainerInit2Func cstringContainerInit2;
|
||||
|
||||
} XPCOMFunctions;
|
||||
|
||||
|
|
|
@ -288,6 +288,17 @@ NS_StringContainerInit(nsStringContainer &aStr)
|
|||
return xpcomFunctions.stringContainerInit(aStr);
|
||||
}
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_StringContainerInit2(nsStringContainer &aStr,
|
||||
const PRUnichar *aData,
|
||||
PRUint32 aDataLength,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
if (!xpcomFunctions.stringContainerInit2)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
return xpcomFunctions.stringContainerInit2(aStr, aData, aDataLength, aFlags);
|
||||
}
|
||||
|
||||
extern "C" NS_COM void
|
||||
NS_StringContainerFinish(nsStringContainer &aStr)
|
||||
{
|
||||
|
@ -348,6 +359,17 @@ NS_CStringContainerInit(nsCStringContainer &aStr)
|
|||
return xpcomFunctions.cstringContainerInit(aStr);
|
||||
}
|
||||
|
||||
extern "C" NS_COM nsresult
|
||||
NS_CStringContainerInit2(nsCStringContainer &aStr,
|
||||
const char *aData,
|
||||
PRUint32 aDataLength,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
if (!xpcomFunctions.cstringContainerInit2)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
return xpcomFunctions.cstringContainerInit2(aStr, aData, aDataLength, aFlags);
|
||||
}
|
||||
|
||||
extern "C" NS_COM void
|
||||
NS_CStringContainerFinish(nsCStringContainer &aStr)
|
||||
{
|
||||
|
|
|
@ -70,7 +70,7 @@ class nsACString;
|
|||
* implementation detail.
|
||||
*
|
||||
* The string data stored in a string container is always single fragment
|
||||
* and null-terminated.
|
||||
* and may be null-terminated depending on how it is initialized.
|
||||
*
|
||||
* Typically, string containers are allocated on the stack for temporary
|
||||
* use. However, they can also be malloc'd if necessary. In either case,
|
||||
|
@ -128,6 +128,27 @@ class nsACString;
|
|||
*/
|
||||
class nsStringContainer;
|
||||
|
||||
/**
|
||||
* Flags that may be OR'd together to pass to NS_StringContainerInit2:
|
||||
*/
|
||||
enum {
|
||||
/* Data passed into NS_StringContainerInit2 is not copied; instead, the
|
||||
* string references the passed in data pointer directly. The caller must
|
||||
* ensure that the data is valid for the lifetime of the string container.
|
||||
* This flag should not be combined with NS_STRING_CONTAINER_INIT_ADOPT. */
|
||||
NS_STRING_CONTAINER_INIT_DEPEND = (1 << 1),
|
||||
|
||||
/* Data passed into NS_StringContainerInit2 is not copied; instead, the
|
||||
* string takes ownership over the data pointer. The caller must have
|
||||
* allocated the data array using the XPCOM memory allocator (nsMemory).
|
||||
* This flag should not be combined with NS_STRING_CONTAINER_INIT_DEPEND. */
|
||||
NS_STRING_CONTAINER_INIT_ADOPT = (1 << 2),
|
||||
|
||||
/* Data passed into NS_StringContainerInit2 is a substring that is not
|
||||
* null-terminated. */
|
||||
NS_STRING_CONTAINER_INIT_SUBSTRING = (1 << 3)
|
||||
};
|
||||
|
||||
/**
|
||||
* NS_StringContainerInit
|
||||
*
|
||||
|
@ -142,6 +163,32 @@ class nsStringContainer;
|
|||
NS_STRINGAPI(nsresult)
|
||||
NS_StringContainerInit(nsStringContainer &aContainer);
|
||||
|
||||
/**
|
||||
* NS_StringContainerInit2
|
||||
*
|
||||
* @param aContainer string container reference
|
||||
* @param aData character buffer (may be null)
|
||||
* @param aDataLength number of characters stored at aData (may pass
|
||||
* PR_UINT32_MAX if aData is null-terminated)
|
||||
* @param aFlags flags affecting how the string container is
|
||||
* initialized. this parameter is ignored when aData
|
||||
* is null. otherwise, if this parameter is 0, then
|
||||
* aData is copied into the string.
|
||||
*
|
||||
* This function resembles NS_StringContainerInit but provides further
|
||||
* options that permit more efficient memory usage. When aContainer is
|
||||
* no longer needed, NS_StringContainerFinish should be called.
|
||||
*
|
||||
* NOTE: NS_StringContainerInit2(container, nsnull, 0, 0) is equivalent to
|
||||
* NS_StringContainerInit(container).
|
||||
*
|
||||
* @status FROZEN
|
||||
*/
|
||||
NS_STRINGAPI(nsresult)
|
||||
NS_StringContainerInit2
|
||||
(nsStringContainer &aContainer, const PRUnichar *aData = nsnull,
|
||||
PRUint32 aDataLength = PR_UINT32_MAX, PRUint32 aFlags = 0);
|
||||
|
||||
/**
|
||||
* NS_StringContainerFinish
|
||||
*
|
||||
|
@ -347,12 +394,33 @@ NS_StringCutData(nsAString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength)
|
|||
* implementation detail.
|
||||
*
|
||||
* The string data stored in a string container is always single fragment
|
||||
* and null-terminated.
|
||||
* and may be null-terminated depending on how it is initialized.
|
||||
*
|
||||
* @see nsStringContainer for use cases and further documentation.
|
||||
*/
|
||||
class nsCStringContainer;
|
||||
|
||||
/**
|
||||
* Flags that may be OR'd together to pass to NS_StringContainerInit2:
|
||||
*/
|
||||
enum {
|
||||
/* Data passed into NS_CStringContainerInit2 is not copied; instead, the
|
||||
* string references the passed in data pointer directly. The caller must
|
||||
* ensure that the data is valid for the lifetime of the string container.
|
||||
* This flag should not be combined with NS_CSTRING_CONTAINER_INIT_ADOPT. */
|
||||
NS_CSTRING_CONTAINER_INIT_DEPEND = (1 << 1),
|
||||
|
||||
/* Data passed into NS_CStringContainerInit2 is not copied; instead, the
|
||||
* string takes ownership over the data pointer. The caller must have
|
||||
* allocated the data array using the XPCOM memory allocator (nsMemory).
|
||||
* This flag should not be combined with NS_CSTRING_CONTAINER_INIT_DEPEND. */
|
||||
NS_CSTRING_CONTAINER_INIT_ADOPT = (1 << 2),
|
||||
|
||||
/* Data passed into NS_CStringContainerInit2 is a substring that is not
|
||||
* null-terminated. */
|
||||
NS_CSTRING_CONTAINER_INIT_SUBSTRING = (1 << 3)
|
||||
};
|
||||
|
||||
/**
|
||||
* NS_CStringContainerInit
|
||||
*
|
||||
|
@ -367,6 +435,32 @@ class nsCStringContainer;
|
|||
NS_STRINGAPI(nsresult)
|
||||
NS_CStringContainerInit(nsCStringContainer &aContainer);
|
||||
|
||||
/**
|
||||
* NS_CStringContainerInit2
|
||||
*
|
||||
* @param aContainer string container reference
|
||||
* @param aData character buffer (may be null)
|
||||
* @param aDataLength number of characters stored at aData (may pass
|
||||
* PR_UINT32_MAX if aData is null-terminated)
|
||||
* @param aFlags flags affecting how the string container is
|
||||
* initialized. this parameter is ignored when aData
|
||||
* is null. otherwise, if this parameter is 0, then
|
||||
* aData is copied into the string.
|
||||
*
|
||||
* This function resembles NS_CStringContainerInit but provides further
|
||||
* options that permit more efficient memory usage. When aContainer is
|
||||
* no longer needed, NS_CStringContainerFinish should be called.
|
||||
*
|
||||
* NOTE: NS_CStringContainerInit2(container, nsnull, 0, 0) is equivalent to
|
||||
* NS_CStringContainerInit(container).
|
||||
*
|
||||
* @status FROZEN
|
||||
*/
|
||||
NS_STRINGAPI(nsresult)
|
||||
NS_CStringContainerInit2
|
||||
(nsCStringContainer &aContainer, const char *aData = nsnull,
|
||||
PRUint32 aDataLength = PR_UINT32_MAX, PRUint32 aFlags = 0);
|
||||
|
||||
/**
|
||||
* NS_CStringContainerFinish
|
||||
*
|
||||
|
|
|
@ -405,6 +405,16 @@ class nsTSubstring_CharT : public nsTAString_CharT
|
|||
Assign(tuple);
|
||||
}
|
||||
|
||||
/**
|
||||
* allows for direct initialization of a nsTSubstring object.
|
||||
*
|
||||
* NOTE: this constructor is declared public _only_ for convenience
|
||||
* inside the string implementation.
|
||||
*/
|
||||
nsTSubstring_CharT( char_type *data, size_type length, PRUint32 flags )
|
||||
: abstract_string_type(data, length, flags) {}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
friend class nsTObsoleteAStringThunk_CharT;
|
||||
|
@ -419,10 +429,6 @@ class nsTSubstring_CharT : public nsTAString_CharT
|
|||
: abstract_string_type(
|
||||
NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer), 0, F_TERMINATED) {}
|
||||
|
||||
// allow subclasses to initialize fields directly
|
||||
nsTSubstring_CharT( char_type *data, size_type length, PRUint32 flags )
|
||||
: abstract_string_type(data, length, flags) {}
|
||||
|
||||
// version of constructor that leaves mData and mLength uninitialized
|
||||
explicit
|
||||
nsTSubstring_CharT( PRUint32 flags )
|
||||
|
|
|
@ -55,6 +55,51 @@ NS_StringContainerInit(nsStringContainer &aContainer)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_STRINGAPI(nsresult)
|
||||
NS_StringContainerInit2(nsStringContainer &aContainer,
|
||||
const PRUnichar *aData,
|
||||
PRUint32 aDataLength,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
NS_ASSERTION(sizeof(nsStringContainer) >= sizeof(nsString),
|
||||
"nsStringContainer is not large enough");
|
||||
|
||||
if (!aData)
|
||||
{
|
||||
new (&aContainer) nsString();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aDataLength == PR_UINT32_MAX)
|
||||
{
|
||||
NS_ENSURE_ARG(!(aFlags & NS_STRING_CONTAINER_INIT_SUBSTRING));
|
||||
aDataLength = nsCharTraits<PRUnichar>::length(aData);
|
||||
}
|
||||
|
||||
if (aFlags & (NS_STRING_CONTAINER_INIT_DEPEND |
|
||||
NS_STRING_CONTAINER_INIT_ADOPT))
|
||||
{
|
||||
PRUint32 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(NS_CONST_CAST(PRUnichar *, aData),
|
||||
aDataLength, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
new (&aContainer) nsString(aData, aDataLength);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_STRINGAPI(void)
|
||||
NS_StringContainerFinish(nsStringContainer &aContainer)
|
||||
{
|
||||
|
@ -140,6 +185,51 @@ NS_CStringContainerInit(nsCStringContainer &aContainer)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_STRINGAPI(nsresult)
|
||||
NS_CStringContainerInit2(nsCStringContainer &aContainer,
|
||||
const char *aData,
|
||||
PRUint32 aDataLength,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
NS_ASSERTION(sizeof(nsCStringContainer) >= sizeof(nsCString),
|
||||
"nsStringContainer is not large enough");
|
||||
|
||||
if (!aData)
|
||||
{
|
||||
new (&aContainer) nsCString();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aDataLength == PR_UINT32_MAX)
|
||||
{
|
||||
NS_ENSURE_ARG(!(aFlags & NS_CSTRING_CONTAINER_INIT_SUBSTRING));
|
||||
aDataLength = nsCharTraits<char>::length(aData);
|
||||
}
|
||||
|
||||
if (aFlags & (NS_CSTRING_CONTAINER_INIT_DEPEND |
|
||||
NS_CSTRING_CONTAINER_INIT_ADOPT))
|
||||
{
|
||||
PRUint32 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(NS_CONST_CAST(char *, aData),
|
||||
aDataLength, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
new (&aContainer) nsCString(aData, aDataLength);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_STRINGAPI(void)
|
||||
NS_CStringContainerFinish(nsCStringContainer &aContainer)
|
||||
{
|
||||
|
|
|
@ -77,10 +77,12 @@ static const XPCOMFunctions kFrozenFunctions = {
|
|||
&NS_StringCloneData,
|
||||
&NS_CStringCloneData,
|
||||
|
||||
// these functions were added post 1.7 (Firefox 1.0)
|
||||
// these functions were added post 1.7 (post Firefox 1.0)
|
||||
&NS_Alloc_P,
|
||||
&NS_Realloc_P,
|
||||
&NS_Free_P
|
||||
&NS_Free_P,
|
||||
&NS_StringContainerInit2,
|
||||
&NS_CStringContainerInit2
|
||||
};
|
||||
|
||||
extern "C" NS_EXPORT nsresult
|
||||
|
|
|
@ -345,6 +345,90 @@ static PRBool test_compress_ws()
|
|||
return rv;
|
||||
}
|
||||
|
||||
static PRBool test_depend()
|
||||
{
|
||||
static const char kData[] = "hello world";
|
||||
|
||||
nsCStringContainer s;
|
||||
NS_ENSURE_SUCCESS(
|
||||
NS_CStringContainerInit2(s, kData, sizeof(kData)-1,
|
||||
NS_CSTRING_CONTAINER_INIT_DEPEND),
|
||||
PR_FALSE);
|
||||
|
||||
const char *sd;
|
||||
NS_CStringGetData(s, &sd);
|
||||
|
||||
PRBool rv = (sd == kData);
|
||||
NS_CStringContainerFinish(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static PRBool test_depend_sub()
|
||||
{
|
||||
static const char kData[] = "hello world";
|
||||
|
||||
nsCStringContainer s;
|
||||
NS_ENSURE_SUCCESS(
|
||||
NS_CStringContainerInit2(s, kData, sizeof(kData)-1,
|
||||
NS_CSTRING_CONTAINER_INIT_DEPEND |
|
||||
NS_CSTRING_CONTAINER_INIT_SUBSTRING),
|
||||
PR_FALSE);
|
||||
|
||||
PRBool terminated;
|
||||
const char *sd;
|
||||
PRUint32 len = NS_CStringGetData(s, &sd, &terminated);
|
||||
|
||||
PRBool rv = (sd == kData && len == sizeof(kData)-1 && !terminated);
|
||||
NS_CStringContainerFinish(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static PRBool test_adopt()
|
||||
{
|
||||
static const char kData[] = "hello world";
|
||||
|
||||
char *data = (char *) nsMemory::Clone(kData, sizeof(kData));
|
||||
if (!data)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCStringContainer s;
|
||||
NS_ENSURE_SUCCESS(
|
||||
NS_CStringContainerInit2(s, data, PR_UINT32_MAX,
|
||||
NS_CSTRING_CONTAINER_INIT_ADOPT),
|
||||
PR_FALSE); // leaks data on failure *shrug*
|
||||
|
||||
const char *sd;
|
||||
NS_CStringGetData(s, &sd);
|
||||
|
||||
PRBool rv = (sd == data);
|
||||
NS_CStringContainerFinish(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static PRBool test_adopt_sub()
|
||||
{
|
||||
static const char kData[] = "hello world";
|
||||
|
||||
char *data = (char *) nsMemory::Clone(kData, sizeof(kData)-1);
|
||||
if (!data)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCStringContainer s;
|
||||
NS_ENSURE_SUCCESS(
|
||||
NS_CStringContainerInit2(s, data, sizeof(kData)-1,
|
||||
NS_CSTRING_CONTAINER_INIT_ADOPT |
|
||||
NS_CSTRING_CONTAINER_INIT_SUBSTRING),
|
||||
PR_FALSE); // leaks data on failure *shrug*
|
||||
|
||||
PRBool terminated;
|
||||
const char *sd;
|
||||
PRUint32 len = NS_CStringGetData(s, &sd, &terminated);
|
||||
|
||||
PRBool rv = (sd == data && len == sizeof(kData)-1 && !terminated);
|
||||
NS_CStringContainerFinish(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
//----
|
||||
|
||||
typedef PRBool (*TestFunc)();
|
||||
|
@ -362,6 +446,10 @@ tests[] =
|
|||
{ "test_append", test_append },
|
||||
{ "test_replace", test_replace },
|
||||
{ "test_compress_ws", test_compress_ws },
|
||||
{ "test_depend", test_depend },
|
||||
{ "test_depend_sub", test_depend_sub },
|
||||
{ "test_adopt", test_adopt },
|
||||
{ "test_adopt_sub", test_adopt_sub },
|
||||
{ nsnull, nsnull }
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче