fixes bug 264274 "support dependent strings in frozen string API" r=biesi sr=bsmedberg

This commit is contained in:
darin%meer.net 2004-11-16 04:44:57 +00:00
Родитель 83f994441b
Коммит 90246214db
7 изменённых файлов: 316 добавлений и 8 удалений

Просмотреть файл

@ -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 }
};