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
Родитель d17ed11b0c
Коммит b27f57bde0
7 изменённых файлов: 226 добавлений и 268 удалений

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

@ -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 )

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

@ -1,260 +0,0 @@
/* vim:set ts=2 sw=2 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is IBM Corporation.
* Portions created by IBM Corporation are Copyright (C) 2003
* IBM Corporation. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsString.h"
#include "nsCharTraits.h"
#include "nsStringAPI.h"
#include "nsNativeCharsetUtils.h"
/* ------------------------------------------------------------------------- */
NS_STRINGAPI(nsresult)
NS_StringContainerInit(nsStringContainer &aContainer)
{
NS_ASSERTION(sizeof(nsStringContainer) >= sizeof(nsString),
"nsStringContainer is not large enough");
// use placement new to avoid heap allocating nsString object
new (&aContainer) nsString();
return NS_OK;
}
NS_STRINGAPI(void)
NS_StringContainerFinish(nsStringContainer &aContainer)
{
// call the nsString dtor
NS_REINTERPRET_CAST(nsString *, &aContainer)->~nsString();
}
/* ------------------------------------------------------------------------- */
NS_STRINGAPI(PRUint32)
NS_StringGetData(const nsAString &aStr, const PRUnichar **aData,
PRBool *aTerminated)
{
if (aTerminated)
*aTerminated = aStr.IsTerminated();
nsAString::const_iterator begin;
aStr.BeginReading(begin);
*aData = begin.get();
return begin.size_forward();
}
NS_STRINGAPI(PRUnichar *)
NS_StringCloneData(const nsAString &aStr)
{
return ToNewUnicode(aStr);
}
NS_STRINGAPI(nsresult)
NS_StringSetData(nsAString &aStr, const PRUnichar *aData, PRUint32 aDataLength)
{
aStr.Assign(aData, aDataLength);
return NS_OK; // XXX report errors
}
NS_STRINGAPI(nsresult)
NS_StringSetDataRange(nsAString &aStr,
PRUint32 aCutOffset, PRUint32 aCutLength,
const PRUnichar *aData, PRUint32 aDataLength)
{
if (aCutOffset == PR_UINT32_MAX)
{
// append case
if (aData)
aStr.Append(aData, aDataLength);
return NS_OK; // XXX report errors
}
if (aCutLength == PR_UINT32_MAX)
aCutLength = aStr.Length() - aCutOffset;
if (aData)
{
if (aDataLength == PR_UINT32_MAX)
aStr.Replace(aCutOffset, aCutLength, nsDependentString(aData));
else
aStr.Replace(aCutOffset, aCutLength, Substring(aData, aData + aDataLength));
}
else
aStr.Cut(aCutOffset, aCutLength);
return NS_OK; // XXX report errors
}
NS_STRINGAPI(nsresult)
NS_StringCopy(nsAString &aDest, const nsAString &aSrc)
{
aDest.Assign(aSrc);
return NS_OK; // XXX report errors
}
/* ------------------------------------------------------------------------- */
NS_STRINGAPI(nsresult)
NS_CStringContainerInit(nsCStringContainer &aContainer)
{
NS_ASSERTION(sizeof(nsCStringContainer) >= sizeof(nsCString),
"nsCStringContainer is not large enough");
// use placement new to avoid heap allocating nsCString object
new (&aContainer) nsCString();
return NS_OK;
}
NS_STRINGAPI(void)
NS_CStringContainerFinish(nsCStringContainer &aContainer)
{
// call the nsCString dtor
NS_REINTERPRET_CAST(nsCString *, &aContainer)->~nsCString();
}
/* ------------------------------------------------------------------------- */
NS_STRINGAPI(PRUint32)
NS_CStringGetData(const nsACString &aStr, const char **aData,
PRBool *aTerminated)
{
if (aTerminated)
*aTerminated = aStr.IsTerminated();
nsACString::const_iterator begin;
aStr.BeginReading(begin);
*aData = begin.get();
return begin.size_forward();
}
NS_STRINGAPI(char *)
NS_CStringCloneData(const nsACString &aStr)
{
return ToNewCString(aStr);
}
NS_STRINGAPI(nsresult)
NS_CStringSetData(nsACString &aStr, const char *aData, PRUint32 aDataLength)
{
aStr.Assign(aData, aDataLength);
return NS_OK; // XXX report errors
}
NS_STRINGAPI(nsresult)
NS_CStringSetDataRange(nsACString &aStr,
PRUint32 aCutOffset, PRUint32 aCutLength,
const char *aData, PRUint32 aDataLength)
{
if (aCutOffset == PR_UINT32_MAX)
{
// append case
if (aData)
aStr.Append(aData, aDataLength);
return NS_OK; // XXX report errors
}
if (aCutLength == PR_UINT32_MAX)
aCutLength = aStr.Length() - aCutOffset;
if (aData)
{
if (aDataLength == PR_UINT32_MAX)
aStr.Replace(aCutOffset, aCutLength, nsDependentCString(aData));
else
aStr.Replace(aCutOffset, aCutLength, Substring(aData, aData + aDataLength));
}
else
aStr.Cut(aCutOffset, aCutLength);
return NS_OK; // XXX report errors
}
NS_STRINGAPI(nsresult)
NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
{
aDest.Assign(aSrc);
return NS_OK; // XXX report errors
}
/* ------------------------------------------------------------------------- */
NS_STRINGAPI(nsresult)
NS_CStringToUTF16(const nsACString &aSrc,
nsCStringEncoding aSrcEncoding,
nsAString &aDest)
{
switch (aSrcEncoding)
{
case NS_CSTRING_ENCODING_ASCII:
CopyASCIItoUTF16(aSrc, aDest);
break;
case NS_CSTRING_ENCODING_UTF8:
CopyUTF8toUTF16(aSrc, aDest);
break;
case NS_CSTRING_ENCODING_NATIVE_FILESYSTEM:
NS_CopyNativeToUnicode(aSrc, aDest);
break;
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK; // XXX report errors
}
NS_STRINGAPI(nsresult)
NS_UTF16ToCString(const nsAString &aSrc,
nsCStringEncoding aDestEncoding,
nsACString &aDest)
{
switch (aDestEncoding)
{
case NS_CSTRING_ENCODING_ASCII:
LossyCopyUTF16toASCII(aSrc, aDest);
break;
case NS_CSTRING_ENCODING_UTF8:
CopyUTF16toUTF8(aSrc, aDest);
break;
case NS_CSTRING_ENCODING_NATIVE_FILESYSTEM:
NS_CopyUnicodeToNative(aSrc, aDest);
break;
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK; // XXX report errors
}

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

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