mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
landing xpcom patch for bug 235499 "re-enable string buffer sharing between C++ and JS in xpconnect" r=dbaron sr=jst
This commit is contained in:
parent
79cb60be4a
commit
dd78f625f5
@ -91,6 +91,7 @@
|
||||
#include "nsInterfaceRequestorAgg.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsStringAPI.h"
|
||||
#include "nsStringBuffer.h"
|
||||
|
||||
void XXXNeverCalled()
|
||||
{
|
||||
@ -220,4 +221,19 @@ void XXXNeverCalled()
|
||||
NS_StringCloneData(str1);
|
||||
NS_UTF16ToCString(str1, NS_CSTRING_ENCODING_ASCII, str2);
|
||||
NS_CStringToUTF16(str2, NS_CSTRING_ENCODING_ASCII, str1);
|
||||
|
||||
// nsStringBuffer.h
|
||||
{
|
||||
nsString x;
|
||||
nsCString y;
|
||||
nsStringBuffer b;
|
||||
b.AddRef();
|
||||
b.Release();
|
||||
nsStringBuffer::Alloc(0);
|
||||
nsStringBuffer::Realloc(nsnull, 0);
|
||||
nsStringBuffer::FromString(x);
|
||||
nsStringBuffer::FromString(y);
|
||||
b.ToString(0, x);
|
||||
b.ToString(0, y);
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ EXPORTS = \
|
||||
nsPromiseFlatString.h \
|
||||
nsReadableUtils.h \
|
||||
nsString.h \
|
||||
nsStringBuffer.h \
|
||||
nsStringFwd.h \
|
||||
nsStringIterator.h \
|
||||
nsSubstring.h \
|
||||
|
170
xpcom/string/public/nsStringBuffer.h
Normal file
170
xpcom/string/public/nsStringBuffer.h
Normal file
@ -0,0 +1,170 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=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 ***** */
|
||||
|
||||
#ifndef nsStringBuffer_h__
|
||||
#define nsStringBuffer_h__
|
||||
|
||||
/**
|
||||
* This structure precedes the string buffers "we" allocate. It may be the
|
||||
* case that nsTAString::mData does not point to one of these special
|
||||
* buffers. The mFlags member variable distinguishes the buffer type.
|
||||
*
|
||||
* When this header is in use, it enables reference counting, and capacity
|
||||
* tracking. NOTE: A string buffer can be modified only if its reference
|
||||
* count is 1.
|
||||
*/
|
||||
class nsStringBuffer
|
||||
{
|
||||
private:
|
||||
|
||||
PRInt32 mRefCount;
|
||||
PRUint32 mStorageSize;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Allocates a new string buffer, with given size in bytes and a
|
||||
* reference count of one. When the string buffer is no longer needed,
|
||||
* it should be released via Release.
|
||||
*
|
||||
* It is up to the caller to set the bytes corresponding to the string
|
||||
* buffer by calling the Data method to fetch the raw data pointer. Care
|
||||
* must be taken to properly null terminate the character array. The
|
||||
* storage size can be greater than the length of the actual string
|
||||
* (i.e., it is not required that the null terminator appear in the last
|
||||
* storage unit of the string buffer's data).
|
||||
*
|
||||
* @return new string buffer or null if out of memory.
|
||||
*/
|
||||
NS_COM static nsStringBuffer* Alloc(size_t storageSize);
|
||||
|
||||
/**
|
||||
* Resizes the given string buffer to the specified storage size. This
|
||||
* method must not be called on a readonly string buffer. Use this API
|
||||
* carefully!!
|
||||
*
|
||||
* This method behaves like the ANSI-C realloc function. (i.e., If the
|
||||
* allocation fails, null will be returned and the given string buffer
|
||||
* will remain unmodified.)
|
||||
*
|
||||
* @see IsReadonly
|
||||
*/
|
||||
NS_COM static nsStringBuffer* Realloc(nsStringBuffer* buf, size_t storageSize);
|
||||
|
||||
/**
|
||||
* Increment the reference count on this string buffer.
|
||||
*/
|
||||
NS_COM void NS_FASTCALL AddRef();
|
||||
|
||||
/**
|
||||
* Decrement the reference count on this string buffer. The string
|
||||
* buffer will be destroyed when its reference count reaches zero.
|
||||
*/
|
||||
NS_COM void NS_FASTCALL Release();
|
||||
|
||||
/**
|
||||
* This method returns the string buffer corresponding to the given data
|
||||
* pointer. The data pointer must have been returned previously by a
|
||||
* call to the nsStringBuffer::Data method.
|
||||
*/
|
||||
static nsStringBuffer* FromData(void* data)
|
||||
{
|
||||
return (nsStringBuffer*) ( ((char*) data) - sizeof(nsStringBuffer) );
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the data pointer for this string buffer.
|
||||
*/
|
||||
void* Data() const
|
||||
{
|
||||
return (void*) ( ((char*) this) + sizeof(nsStringBuffer) );
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the storage size of a string buffer in bytes.
|
||||
* This value is the same value that was originally passed to Alloc (or
|
||||
* Realloc).
|
||||
*/
|
||||
PRUint32 StorageSize() const
|
||||
{
|
||||
return mStorageSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this method returns false, then the caller can be sure that their
|
||||
* reference to the string buffer is the only reference to the string
|
||||
* buffer, and therefore it has exclusive access to the string buffer and
|
||||
* associated data. However, if this function returns true, then other
|
||||
* consumers may rely on the data in this buffer being immutable and
|
||||
* other threads may access this buffer simultaneously.
|
||||
*/
|
||||
PRBool IsReadonly() const
|
||||
{
|
||||
return mRefCount > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The FromString methods return a string buffer for the given string
|
||||
* object or null if the string object does not have a string buffer.
|
||||
* The reference count of the string buffer is NOT incremented by these
|
||||
* methods. If the caller wishes to hold onto the returned value, then
|
||||
* the returned string buffer must have its reference count incremented
|
||||
* via a call to the AddRef method.
|
||||
*/
|
||||
NS_COM static nsStringBuffer* FromString(const nsAString &str);
|
||||
NS_COM static nsStringBuffer* FromString(const nsACString &str);
|
||||
|
||||
/**
|
||||
* The ToString methods assign this string buffer to a given string
|
||||
* object. If the string object does not support sharable string
|
||||
* buffers, then its value will be set to a copy of the given string
|
||||
* buffer. Otherwise, these methods increment the reference count of the
|
||||
* given string buffer. It is important to specify the length (in
|
||||
* storage units) of the string contained in the string buffer since the
|
||||
* length of the string may be less than its storage size. The string
|
||||
* must have a null terminator at the offset specified by |len|.
|
||||
*
|
||||
* NOTE: storage size is measured in bytes even for wide strings;
|
||||
* however, string length is always measured in storage units
|
||||
* (2-byte units for wide strings).
|
||||
*/
|
||||
NS_COM void ToString(PRUint32 len, nsAString &str);
|
||||
NS_COM void ToString(PRUint32 len, nsACString &str);
|
||||
};
|
||||
|
||||
#endif /* !defined(nsStringBuffer_h__ */
|
@ -47,6 +47,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "nsSubstring.h"
|
||||
#include "nsString.h"
|
||||
#include "nsStringBuffer.h"
|
||||
#include "nsDependentString.h"
|
||||
#include "nsMemory.h"
|
||||
#include "pratom.h"
|
||||
@ -105,105 +106,6 @@ static nsStringStats gStringStats;
|
||||
#define STRING_STAT_INCREMENT(_s)
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* This structure precedes the string buffers "we" allocate. It may be the
|
||||
* case that nsTSubstring::mData does not point to one of these special
|
||||
* buffers. The mFlags member variable distinguishes the buffer type.
|
||||
*
|
||||
* When this header is in use, it enables reference counting, and capacity
|
||||
* tracking. NOTE: A string buffer can be modified only if its reference
|
||||
* count is 1.
|
||||
*/
|
||||
class nsStringHeader
|
||||
{
|
||||
private:
|
||||
|
||||
PRInt32 mRefCount;
|
||||
PRUint32 mStorageSize;
|
||||
|
||||
public:
|
||||
|
||||
void AddRef()
|
||||
{
|
||||
PR_AtomicIncrement(&mRefCount);
|
||||
STRING_STAT_INCREMENT(Share);
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
if (PR_AtomicDecrement(&mRefCount) == 0)
|
||||
{
|
||||
STRING_STAT_INCREMENT(Free);
|
||||
free(this); // we were allocated with |malloc|
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alloc returns a pointer to a new string header with set capacity.
|
||||
*/
|
||||
static nsStringHeader* Alloc(size_t size)
|
||||
{
|
||||
STRING_STAT_INCREMENT(Alloc);
|
||||
|
||||
NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
|
||||
|
||||
nsStringHeader *hdr =
|
||||
(nsStringHeader *) malloc(sizeof(nsStringHeader) + size);
|
||||
if (hdr)
|
||||
{
|
||||
hdr->mRefCount = 1;
|
||||
hdr->mStorageSize = size;
|
||||
}
|
||||
return hdr;
|
||||
}
|
||||
|
||||
static nsStringHeader* Realloc(nsStringHeader* hdr, size_t size)
|
||||
{
|
||||
STRING_STAT_INCREMENT(Realloc);
|
||||
|
||||
NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
|
||||
|
||||
// no point in trying to save ourselves if we hit this assertion
|
||||
NS_ASSERTION(!hdr->IsReadonly(), "|Realloc| attempted on readonly string");
|
||||
|
||||
hdr = (nsStringHeader*) realloc(hdr, sizeof(nsStringHeader) + size);
|
||||
if (hdr)
|
||||
hdr->mStorageSize = size;
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
static nsStringHeader* FromData(void* data)
|
||||
{
|
||||
return (nsStringHeader*) ( ((char*) data) - sizeof(nsStringHeader) );
|
||||
}
|
||||
|
||||
void* Data() const
|
||||
{
|
||||
return (void*) ( ((char*) this) + sizeof(nsStringHeader) );
|
||||
}
|
||||
|
||||
PRUint32 StorageSize() const
|
||||
{
|
||||
return mStorageSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Because nsTSubstring allows only single threaded access, if this
|
||||
* method returns FALSE, then the caller can be sure that it has
|
||||
* exclusive access to the nsStringHeader and associated data.
|
||||
* However, if this function returns TRUE, then other strings may
|
||||
* rely on the data in this buffer being constant and other threads
|
||||
* may access this buffer simultaneously.
|
||||
*/
|
||||
PRBool IsReadonly() const
|
||||
{
|
||||
return mRefCount > 1;
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
inline void
|
||||
@ -211,7 +113,7 @@ ReleaseData( void* data, PRUint32 flags )
|
||||
{
|
||||
if (flags & nsSubstring::F_SHARED)
|
||||
{
|
||||
nsStringHeader::FromData(data)->Release();
|
||||
nsStringBuffer::FromData(data)->Release();
|
||||
}
|
||||
else if (flags & nsSubstring::F_OWNED)
|
||||
{
|
||||
@ -221,6 +123,180 @@ ReleaseData( void* data, PRUint32 flags )
|
||||
// otherwise, nothing to do.
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// XXX or we could make nsStringBuffer be a friend of nsTAString
|
||||
|
||||
class nsAStringAccessor : public nsAString
|
||||
{
|
||||
private:
|
||||
nsAStringAccessor(); // NOT IMPLEMENTED
|
||||
|
||||
public:
|
||||
const void *vtable() const { return mVTable; }
|
||||
char_type *data() const { return mData; }
|
||||
size_type length() const { return mLength; }
|
||||
PRUint32 flags() const { return mFlags; }
|
||||
|
||||
void set(char_type *data, size_type len, PRUint32 flags)
|
||||
{
|
||||
ReleaseData(mData, mFlags);
|
||||
mData = data;
|
||||
mLength = len;
|
||||
mFlags = flags;
|
||||
}
|
||||
};
|
||||
|
||||
class nsACStringAccessor : public nsACString
|
||||
{
|
||||
private:
|
||||
nsACStringAccessor(); // NOT IMPLEMENTED
|
||||
|
||||
public:
|
||||
const void *vtable() const { return mVTable; }
|
||||
char_type *data() const { return mData; }
|
||||
size_type length() const { return mLength; }
|
||||
PRUint32 flags() const { return mFlags; }
|
||||
|
||||
void set(char_type *data, size_type len, PRUint32 flags)
|
||||
{
|
||||
ReleaseData(mData, mFlags);
|
||||
mData = data;
|
||||
mLength = len;
|
||||
mFlags = flags;
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
nsStringBuffer::AddRef()
|
||||
{
|
||||
PR_AtomicIncrement(&mRefCount);
|
||||
STRING_STAT_INCREMENT(Share);
|
||||
}
|
||||
|
||||
void
|
||||
nsStringBuffer::Release()
|
||||
{
|
||||
if (PR_AtomicDecrement(&mRefCount) == 0)
|
||||
{
|
||||
STRING_STAT_INCREMENT(Free);
|
||||
free(this); // we were allocated with |malloc|
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alloc returns a pointer to a new string header with set capacity.
|
||||
*/
|
||||
nsStringBuffer*
|
||||
nsStringBuffer::Alloc(size_t size)
|
||||
{
|
||||
STRING_STAT_INCREMENT(Alloc);
|
||||
|
||||
NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
|
||||
|
||||
nsStringBuffer *hdr =
|
||||
(nsStringBuffer *) malloc(sizeof(nsStringBuffer) + size);
|
||||
if (hdr)
|
||||
{
|
||||
hdr->mRefCount = 1;
|
||||
hdr->mStorageSize = size;
|
||||
}
|
||||
return hdr;
|
||||
}
|
||||
|
||||
nsStringBuffer*
|
||||
nsStringBuffer::Realloc(nsStringBuffer* hdr, size_t size)
|
||||
{
|
||||
STRING_STAT_INCREMENT(Realloc);
|
||||
|
||||
NS_ASSERTION(size != 0, "zero capacity allocation not allowed");
|
||||
|
||||
// no point in trying to save ourselves if we hit this assertion
|
||||
NS_ASSERTION(!hdr->IsReadonly(), "|Realloc| attempted on readonly string");
|
||||
|
||||
hdr = (nsStringBuffer*) realloc(hdr, sizeof(nsStringBuffer) + size);
|
||||
if (hdr)
|
||||
hdr->mStorageSize = size;
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
nsStringBuffer*
|
||||
nsStringBuffer::FromString(const nsAString& str)
|
||||
{
|
||||
const nsAStringAccessor* accessor =
|
||||
NS_STATIC_CAST(const nsAStringAccessor*, &str);
|
||||
|
||||
if (accessor->vtable() != nsObsoleteAString::sCanonicalVTable ||
|
||||
!(accessor->flags() & nsSubstring::F_SHARED))
|
||||
return nsnull;
|
||||
|
||||
return FromData(accessor->data());
|
||||
}
|
||||
|
||||
nsStringBuffer*
|
||||
nsStringBuffer::FromString(const nsACString& str)
|
||||
{
|
||||
const nsACStringAccessor* accessor =
|
||||
NS_STATIC_CAST(const nsACStringAccessor*, &str);
|
||||
|
||||
if (accessor->vtable() != nsObsoleteACString::sCanonicalVTable ||
|
||||
!(accessor->flags() & nsCSubstring::F_SHARED))
|
||||
return nsnull;
|
||||
|
||||
return FromData(accessor->data());
|
||||
}
|
||||
|
||||
void
|
||||
nsStringBuffer::ToString(PRUint32 len, nsAString &str)
|
||||
{
|
||||
PRUnichar* data = NS_STATIC_CAST(PRUnichar*, Data());
|
||||
|
||||
nsAStringAccessor* accessor = NS_STATIC_CAST(nsAStringAccessor*, &str);
|
||||
if (accessor->vtable() != nsObsoleteAString::sCanonicalVTable)
|
||||
{
|
||||
str.Assign(data, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERTION(data[len] == PRUnichar(0), "data should be null terminated");
|
||||
|
||||
// preserve class flags
|
||||
PRUint32 flags = accessor->flags();
|
||||
flags = (flags & 0xFFFF0000) | nsSubstring::F_SHARED | nsSubstring::F_TERMINATED;
|
||||
|
||||
AddRef();
|
||||
accessor->set(data, len, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsStringBuffer::ToString(PRUint32 len, nsACString &str)
|
||||
{
|
||||
char* data = NS_STATIC_CAST(char*, Data());
|
||||
|
||||
nsACStringAccessor* accessor = NS_STATIC_CAST(nsACStringAccessor*, &str);
|
||||
if (accessor->vtable() != nsObsoleteACString::sCanonicalVTable)
|
||||
{
|
||||
str.Assign(data, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERTION(data[len] == char(0), "data should be null terminated");
|
||||
|
||||
// preserve class flags
|
||||
PRUint32 flags = accessor->flags();
|
||||
flags = (flags & 0xFFFF0000) | nsCSubstring::F_SHARED | nsCSubstring::F_TERMINATED;
|
||||
|
||||
AddRef();
|
||||
accessor->set(data, len, flags);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
// define nsSubstring
|
||||
#include "string-template-def-unichar.h"
|
||||
|
@ -110,10 +110,10 @@ nsTSubstring_CharT::MutatePrep( size_type capacity, char_type** oldData, PRUint3
|
||||
// case #1
|
||||
if (mFlags & F_SHARED)
|
||||
{
|
||||
nsStringHeader* hdr = nsStringHeader::FromData(mData);
|
||||
nsStringBuffer* hdr = nsStringBuffer::FromData(mData);
|
||||
if (!hdr->IsReadonly())
|
||||
{
|
||||
nsStringHeader *newHdr = nsStringHeader::Realloc(hdr, storageSize);
|
||||
nsStringBuffer *newHdr = nsStringBuffer::Realloc(hdr, storageSize);
|
||||
if (newHdr)
|
||||
{
|
||||
hdr = newHdr;
|
||||
@ -145,7 +145,7 @@ nsTSubstring_CharT::MutatePrep( size_type capacity, char_type** oldData, PRUint3
|
||||
// make use of our F_OWNED or F_FIXED buffers because they are not
|
||||
// large enough.
|
||||
|
||||
nsStringHeader* newHdr = nsStringHeader::Alloc(storageSize);
|
||||
nsStringBuffer* newHdr = nsStringBuffer::Alloc(storageSize);
|
||||
if (!newHdr)
|
||||
return PR_FALSE; // we are still in a consistent state
|
||||
|
||||
@ -247,7 +247,7 @@ nsTSubstring_CharT::Capacity() const
|
||||
if (mFlags & F_SHARED)
|
||||
{
|
||||
// if the string is readonly, then we pretend that it has no capacity.
|
||||
nsStringHeader* hdr = nsStringHeader::FromData(mData);
|
||||
nsStringBuffer* hdr = nsStringBuffer::FromData(mData);
|
||||
if (hdr->IsReadonly())
|
||||
capacity = size_type(-1);
|
||||
else
|
||||
@ -278,7 +278,7 @@ nsTSubstring_CharT::EnsureMutable()
|
||||
{
|
||||
if (mFlags & (F_FIXED | F_OWNED))
|
||||
return;
|
||||
if ((mFlags & F_SHARED) && !nsStringHeader::FromData(mData)->IsReadonly())
|
||||
if ((mFlags & F_SHARED) && !nsStringBuffer::FromData(mData)->IsReadonly())
|
||||
return;
|
||||
|
||||
// promote to a shared string buffer
|
||||
@ -358,7 +358,7 @@ nsTSubstring_CharT::Assign( const self_type& str )
|
||||
SetDataFlags(F_TERMINATED | F_SHARED);
|
||||
|
||||
// get an owning reference to the mData
|
||||
nsStringHeader::FromData(mData)->AddRef();
|
||||
nsStringBuffer::FromData(mData)->AddRef();
|
||||
}
|
||||
else if (str.mFlags & F_VOIDED)
|
||||
{
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nsString.h"
|
||||
#include "nsStringBuffer.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
@ -583,6 +584,35 @@ PRBool test_rfindcharinset()
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool test_stringbuffer()
|
||||
{
|
||||
const char kData[] = "hello world";
|
||||
|
||||
nsStringBuffer *buf;
|
||||
|
||||
buf = nsStringBuffer::Alloc(sizeof(kData));
|
||||
if (!buf)
|
||||
return PR_FALSE;
|
||||
buf->Release();
|
||||
|
||||
buf = nsStringBuffer::Alloc(sizeof(kData));
|
||||
if (!buf)
|
||||
return PR_FALSE;
|
||||
char *data = (char *) buf->Data();
|
||||
memcpy(data, kData, sizeof(kData));
|
||||
|
||||
nsCString str;
|
||||
buf->ToString(sizeof(kData)-1, str);
|
||||
|
||||
nsStringBuffer *buf2;
|
||||
buf2 = nsStringBuffer::FromString(str);
|
||||
|
||||
PRBool rv = (buf == buf2);
|
||||
|
||||
buf->Release();
|
||||
return rv;
|
||||
}
|
||||
|
||||
//----
|
||||
|
||||
typedef PRBool (*TestFunc)();
|
||||
@ -620,6 +650,7 @@ tests[] =
|
||||
{ "test_appendint64", test_appendint64 },
|
||||
{ "test_findcharinset", test_findcharinset },
|
||||
{ "test_rfindcharinset", test_rfindcharinset },
|
||||
{ "test_stringbuffer", test_stringbuffer },
|
||||
{ nsnull, nsnull }
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user