diff --git a/string/public/nsStringDefines.h b/string/public/nsStringDefines.h new file mode 100644 index 000000000000..9cf53982b0be --- /dev/null +++ b/string/public/nsStringDefines.h @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * 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 Netscape + * Communications. Portions created by Netscape Communications are + * Copyright (C) 2001 by Netscape Communications. All + * Rights Reserved. + * + * Contributor(s): + * Scott Collins (original author) + */ + +/* nsStringDefines.h --- preprocessor definitions common across all string files */ + +#ifndef nsStringDefines_h___ +#define nsStringDefines_h___ + +#if !defined(DEBUG) || !defined(DEBUG_STRING) + #define DEBUG_STRING 0 +#endif + +#if !defined(DEBUG) || !defined(DEBUG_STRING_STATS) + #define DEBUG_STRING_STATS 0 +#endif + +#endif diff --git a/string/public/nsXPIDLString.h b/string/public/nsXPIDLString.h new file mode 100644 index 000000000000..a227b4402941 --- /dev/null +++ b/string/public/nsXPIDLString.h @@ -0,0 +1,249 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * 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 Netscape + * Communications. Portions created by Netscape Communications are + * Copyright (C) 2001 by Netscape Communications. All + * Rights Reserved. + * + * Contributor(s): + * Scott Collins (original author) + */ + +#ifndef nsXPIDLString_h___ +#define nsXPIDLString_h___ + +#ifndef nsSharableString_h___ +#include "nsSharableString.h" +#endif + +#if DEBUG_STRING_STATS +#include +#endif + + + + /** + * |nsXPIDLC?String| extends |nsSharableC?String| with the ability + * to defer calculation of its length. This is crucial to allowing + * the |getter_Copies| assignment behavior. + * + * The mechanism relies on the fact that |GetSharedBufferHandle| + * must be called before any other object can share the buffer, + * and as the default implementation for |GetBufferHandle|, which is + * the operation on which all other flat string operations are based. + * A valid handle always contains a non-|NULL| data start and end. + * After use as an `out' string pointer parameter, an |nsXPIDLC?String|'s + * handle will have a non-|NULL| data start, but its data end will be + * |NULL|. This is the signal that the length needs to be recalculated. + * |GetSharedBufferHandle| detects this situation and repairs it. + * + * An |nsXPIDLC?String| is now a sharable object, just like |nsSharableC?String|. + * This simple implementation always allocates an intermediary handle + * object. This cost might turn out to be a burden, it's something we'll + * want to measure. A couple of optimizations spring to mind if allocation + * of the handle objects shows up on the performance radar: + * (1) introduce a custom allocator for the handles, e.g., keep free lists + * or arena allocate them, or (2) fatten up the |nsXPIDLC?String| with a + * local handle, and only allocate a shared handle in the event that + * someone actually wants to share. Both of these alternatives add + * complexity or space costs, and so we start with the simplest thing + * that could possibly work :-) + */ + +class NS_COM nsXPIDLString + : public nsSharableString + { + public: + nsXPIDLString() + { +#if DEBUG_STRING_STATS + ++sCreatedCount; + if ( ++sAliveCount > sHighWaterCount ) + sHighWaterCount = sAliveCount; +#endif + } + + nsXPIDLString( const nsXPIDLString& aString ) + : nsSharableString(aString.GetSharedBufferHandle()) + // copy-constructor required (or else C++ generates one for us) + { +#if DEBUG_STRING_STATS + ++sCreatedCount; + if ( ++sAliveCount > sHighWaterCount ) + sHighWaterCount = sAliveCount; +#endif + } + +#if DEBUG_STRING_STATS + ~nsXPIDLString() + { + --sAliveCount; + } +#endif + + nsXPIDLString& + operator=( const nsXPIDLString& rhs ) + // copy-assignment operator required (or else C++ generates one for us) + { + // self-assignment is handled by the underlying |nsAutoBufferHandle| + mBuffer = rhs.GetSharedBufferHandle(); + return *this; + } + + void Adopt( PRUnichar* aNewValue ) { *PrepareForUseAsOutParam() = aNewValue; } + + // deprecated, to be eliminated + operator const PRUnichar*() const { return get(); } + + + class getter_Copies_t + { + public: + getter_Copies_t( nsXPIDLString& aString ) : mString(&aString) { } + // getter_Copies_t( const getter_Copies_t& ); // auto-generated copy-constructor OK + // getter_Copies_t& operator=( const getter_Copies_t& ); // auto-generated assignment operator OK + + operator PRUnichar**() const { return mString->PrepareForUseAsOutParam(); } + + private: + nsXPIDLString* mString; + }; + + friend class getter_Copies_t; + + protected: +#if DEBUG_STRING_STATS + virtual const nsBufferHandle* GetFlatBufferHandle() const; + virtual const nsBufferHandle* GetBufferHandle() const; +#endif + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + // overridden to fix the length after `out' parameter assignment, if necessary + + PRUnichar** PrepareForUseAsOutParam(); + +#if DEBUG_STRING_STATS + static size_t sCreatedCount; // total number of |nsXPIDLString|s ever created + static size_t sAliveCount; // total number of |nsXPIDLStrings|s alive right now + static size_t sHighWaterCount; // greatest number of |nsXPIDLString|s alive at once + static size_t sAssignCount; // total number of times |nsXPIDLString|s were + // assigned into with |getter_Copies| + static size_t sShareCount; // total number times |nsXPIDLString|s were asked to share + + public: + static void DebugPrintStats( FILE* ); +#endif + }; + +inline +nsXPIDLString::getter_Copies_t +getter_Copies( nsXPIDLString& aString ) + { + return nsXPIDLString::getter_Copies_t(aString); + } + + + +class NS_COM nsXPIDLCString + : public nsSharableCString + { + public: + nsXPIDLCString() + { +#if DEBUG_STRING_STATS + ++sCreatedCount; + if ( ++sAliveCount > sHighWaterCount ) + sHighWaterCount = sAliveCount; +#endif + } + + nsXPIDLCString( const nsXPIDLCString& aString ) + : nsSharableCString(aString.GetSharedBufferHandle()) + // copy-constructor required (or else C++ generates one for us) + { +#if DEBUG_STRING_STATS + ++sCreatedCount; + if ( ++sAliveCount > sHighWaterCount ) + sHighWaterCount = sAliveCount; +#endif + } + +#if DEBUG_STRING_STATS + ~nsXPIDLCString() + { + --sAliveCount; + } +#endif + + nsXPIDLCString& + operator=( const nsXPIDLCString& rhs ) + // copy-assignment operator required (or else C++ generates one for us) + { + // self-assignment is handled by the underlying |nsAutoBufferHandle| + mBuffer = rhs.GetSharedBufferHandle(); + return *this; + } + + void Adopt( char* aNewValue ) { *PrepareForUseAsOutParam() = aNewValue; } + + // deprecated, to be eliminated + operator const char*() const { return get(); } + + + class getter_Copies_t + { + public: + getter_Copies_t( nsXPIDLCString& aString ) : mString(&aString) { } + // getter_Copies_t( const getter_Copies_t& ); // auto-generated copy-constructor OK + // getter_Copies_t& operator=( const getter_Copies_t& ); // auto-generated assignment operator OK + + operator char**() const { return mString->PrepareForUseAsOutParam(); } + + private: + nsXPIDLCString* mString; + }; + + friend class getter_Copies_t; + + protected: +#if DEBUG_STRING_STATS + virtual const nsBufferHandle* GetFlatBufferHandle() const; + virtual const nsBufferHandle* GetBufferHandle() const; +#endif + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + // overridden to fix the length after `out' parameter assignment, if necessary + + char** PrepareForUseAsOutParam(); + +#if DEBUG_STRING_STATS + static size_t sCreatedCount; // total number of |nsXPIDLCString|s ever created + static size_t sAliveCount; // total number of |nsXPIDLCStrings|s alive right now + static size_t sHighWaterCount; // greatest number of |nsXPIDLCString|s alive at once + static size_t sAssignCount; // total number of times |nsXPIDLCString|s were + // assigned into with |getter_Copies| + static size_t sShareCount; // total number times |nsXPIDLCString|s were asked to share + + public: + static void DebugPrintStats( FILE* ); +#endif + }; + +inline +nsXPIDLCString::getter_Copies_t +getter_Copies( nsXPIDLCString& aString ) + { + return nsXPIDLCString::getter_Copies_t(aString); + } + +#endif /* !defined(nsXPIDLString_h___) */ diff --git a/string/src/nsXPIDLString.cpp b/string/src/nsXPIDLString.cpp new file mode 100644 index 000000000000..18ed64fa7142 --- /dev/null +++ b/string/src/nsXPIDLString.cpp @@ -0,0 +1,182 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * 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 Netscape + * Communications. Portions created by Netscape Communications are + * Copyright (C) 2001 by Netscape Communications. All + * Rights Reserved. + * + * Contributor(s): + * Scott Collins (original author) + */ + +#include "nsXPIDLString.h" + +#if DEBUG_STRING_STATS +size_t nsXPIDLString::sCreatedCount = 0; +size_t nsXPIDLString::sAliveCount = 0; +size_t nsXPIDLString::sHighWaterCount = 0; +size_t nsXPIDLString::sAssignCount = 0; +size_t nsXPIDLString::sShareCount = 0; + +size_t nsXPIDLCString::sCreatedCount = 0; +size_t nsXPIDLCString::sAliveCount = 0; +size_t nsXPIDLCString::sHighWaterCount = 0; +size_t nsXPIDLCString::sAssignCount = 0; +size_t nsXPIDLCString::sShareCount = 0; +#endif + + +template +class nsImportedStringHandle + : public nsFlexBufferHandle + { + public: + nsImportedStringHandle() : nsFlexBufferHandle(0, 0, 0, 0) { } + + CharT** AddressOfDataStart() { return &mDataStart; } + void RecalculateBoundaries() const; + }; + + +template +void +nsImportedStringHandle::RecalculateBoundaries() const + { + size_t data_length = 0; + size_t storage_length = 0; + + CharT* data_start = NS_CONST_CAST(CharT*, DataStart()); + if ( data_start ) + { + data_length = nsCharTraits::length(data_start); + storage_length = data_length + 1; + } + + nsImportedStringHandle* mutable_this = NS_CONST_CAST(nsImportedStringHandle*, this); + mutable_this->DataEnd(data_start+data_length); + + mutable_this->StorageStart(data_start); + mutable_this->StorageEnd(data_start+storage_length); + } + + +#if DEBUG_STRING_STATS +const nsBufferHandle* +nsXPIDLString::GetFlatBufferHandle() const + { + --sShareCount; + return GetSharedBufferHandle(); + } + + +const nsBufferHandle* +nsXPIDLString::GetBufferHandle() const + { + --sShareCount; + return GetSharedBufferHandle(); + } + + +void +nsXPIDLString::DebugPrintStats( FILE* aOutFile ) + { + fprintf(aOutFile, "nsXPIDLString stats: %ld alive now [%ld max] of %ld created; %ld getter_Copies, %ld attempts to share\n", + sAliveCount, sHighWaterCount, sCreatedCount, sAssignCount, sShareCount); + } +#endif + + +const nsSharedBufferHandle* +nsXPIDLString::GetSharedBufferHandle() const + { + const nsImportedStringHandle* answer = NS_STATIC_CAST(const nsImportedStringHandle*, mBuffer.get()); + + if ( !answer->DataEnd() ) + answer->RecalculateBoundaries(); + +#if DEBUG_STRING_STATS + ++sShareCount; +#endif + return answer; + } + + +PRUnichar** +nsXPIDLString::PrepareForUseAsOutParam() + { + nsImportedStringHandle* handle = new nsImportedStringHandle(); + NS_ASSERTION(handle, "Trouble! We couldn't get a new handle during |getter_Copies|."); + + mBuffer = handle; +#if DEBUG_STRING_STATS + ++sAssignCount; +#endif + return handle->AddressOfDataStart(); + } + + +#if DEBUG_STRING_STATS +const nsBufferHandle* +nsXPIDLCString::GetFlatBufferHandle() const + { + --sShareCount; + return GetSharedBufferHandle(); + } + + +const nsBufferHandle* +nsXPIDLCString::GetBufferHandle() const + { + --sShareCount; + return GetSharedBufferHandle(); + } + + +void +nsXPIDLCString::DebugPrintStats( FILE* aOutFile ) + { + fprintf(aOutFile, "nsXPIDLCString stats: %ld alive now [%ld max] of %ld created; %ld getter_Copies, %ld attempts to share\n", + sAliveCount, sHighWaterCount, sCreatedCount, sAssignCount, sShareCount); + } +#endif + + +const nsSharedBufferHandle* +nsXPIDLCString::GetSharedBufferHandle() const + { + const nsImportedStringHandle* answer = NS_STATIC_CAST(const nsImportedStringHandle*, mBuffer.get()); + + if ( !answer->DataEnd() ) + answer->RecalculateBoundaries(); + +#if DEBUG_STRING_STATS + ++sShareCount; +#endif + return answer; + } + + +char** +nsXPIDLCString::PrepareForUseAsOutParam() + { + nsImportedStringHandle* handle = new nsImportedStringHandle(); + NS_ASSERTION(handle, "Trouble! We couldn't get a new handle during |getter_Copies|."); + + mBuffer = handle; +#if DEBUG_STRING_STATS + ++sAssignCount; +#endif + return handle->AddressOfDataStart(); + } diff --git a/xpcom/string/public/nsStringDefines.h b/xpcom/string/public/nsStringDefines.h new file mode 100644 index 000000000000..9cf53982b0be --- /dev/null +++ b/xpcom/string/public/nsStringDefines.h @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * 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 Netscape + * Communications. Portions created by Netscape Communications are + * Copyright (C) 2001 by Netscape Communications. All + * Rights Reserved. + * + * Contributor(s): + * Scott Collins (original author) + */ + +/* nsStringDefines.h --- preprocessor definitions common across all string files */ + +#ifndef nsStringDefines_h___ +#define nsStringDefines_h___ + +#if !defined(DEBUG) || !defined(DEBUG_STRING) + #define DEBUG_STRING 0 +#endif + +#if !defined(DEBUG) || !defined(DEBUG_STRING_STATS) + #define DEBUG_STRING_STATS 0 +#endif + +#endif diff --git a/xpcom/string/public/nsXPIDLString.h b/xpcom/string/public/nsXPIDLString.h new file mode 100644 index 000000000000..a227b4402941 --- /dev/null +++ b/xpcom/string/public/nsXPIDLString.h @@ -0,0 +1,249 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * 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 Netscape + * Communications. Portions created by Netscape Communications are + * Copyright (C) 2001 by Netscape Communications. All + * Rights Reserved. + * + * Contributor(s): + * Scott Collins (original author) + */ + +#ifndef nsXPIDLString_h___ +#define nsXPIDLString_h___ + +#ifndef nsSharableString_h___ +#include "nsSharableString.h" +#endif + +#if DEBUG_STRING_STATS +#include +#endif + + + + /** + * |nsXPIDLC?String| extends |nsSharableC?String| with the ability + * to defer calculation of its length. This is crucial to allowing + * the |getter_Copies| assignment behavior. + * + * The mechanism relies on the fact that |GetSharedBufferHandle| + * must be called before any other object can share the buffer, + * and as the default implementation for |GetBufferHandle|, which is + * the operation on which all other flat string operations are based. + * A valid handle always contains a non-|NULL| data start and end. + * After use as an `out' string pointer parameter, an |nsXPIDLC?String|'s + * handle will have a non-|NULL| data start, but its data end will be + * |NULL|. This is the signal that the length needs to be recalculated. + * |GetSharedBufferHandle| detects this situation and repairs it. + * + * An |nsXPIDLC?String| is now a sharable object, just like |nsSharableC?String|. + * This simple implementation always allocates an intermediary handle + * object. This cost might turn out to be a burden, it's something we'll + * want to measure. A couple of optimizations spring to mind if allocation + * of the handle objects shows up on the performance radar: + * (1) introduce a custom allocator for the handles, e.g., keep free lists + * or arena allocate them, or (2) fatten up the |nsXPIDLC?String| with a + * local handle, and only allocate a shared handle in the event that + * someone actually wants to share. Both of these alternatives add + * complexity or space costs, and so we start with the simplest thing + * that could possibly work :-) + */ + +class NS_COM nsXPIDLString + : public nsSharableString + { + public: + nsXPIDLString() + { +#if DEBUG_STRING_STATS + ++sCreatedCount; + if ( ++sAliveCount > sHighWaterCount ) + sHighWaterCount = sAliveCount; +#endif + } + + nsXPIDLString( const nsXPIDLString& aString ) + : nsSharableString(aString.GetSharedBufferHandle()) + // copy-constructor required (or else C++ generates one for us) + { +#if DEBUG_STRING_STATS + ++sCreatedCount; + if ( ++sAliveCount > sHighWaterCount ) + sHighWaterCount = sAliveCount; +#endif + } + +#if DEBUG_STRING_STATS + ~nsXPIDLString() + { + --sAliveCount; + } +#endif + + nsXPIDLString& + operator=( const nsXPIDLString& rhs ) + // copy-assignment operator required (or else C++ generates one for us) + { + // self-assignment is handled by the underlying |nsAutoBufferHandle| + mBuffer = rhs.GetSharedBufferHandle(); + return *this; + } + + void Adopt( PRUnichar* aNewValue ) { *PrepareForUseAsOutParam() = aNewValue; } + + // deprecated, to be eliminated + operator const PRUnichar*() const { return get(); } + + + class getter_Copies_t + { + public: + getter_Copies_t( nsXPIDLString& aString ) : mString(&aString) { } + // getter_Copies_t( const getter_Copies_t& ); // auto-generated copy-constructor OK + // getter_Copies_t& operator=( const getter_Copies_t& ); // auto-generated assignment operator OK + + operator PRUnichar**() const { return mString->PrepareForUseAsOutParam(); } + + private: + nsXPIDLString* mString; + }; + + friend class getter_Copies_t; + + protected: +#if DEBUG_STRING_STATS + virtual const nsBufferHandle* GetFlatBufferHandle() const; + virtual const nsBufferHandle* GetBufferHandle() const; +#endif + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + // overridden to fix the length after `out' parameter assignment, if necessary + + PRUnichar** PrepareForUseAsOutParam(); + +#if DEBUG_STRING_STATS + static size_t sCreatedCount; // total number of |nsXPIDLString|s ever created + static size_t sAliveCount; // total number of |nsXPIDLStrings|s alive right now + static size_t sHighWaterCount; // greatest number of |nsXPIDLString|s alive at once + static size_t sAssignCount; // total number of times |nsXPIDLString|s were + // assigned into with |getter_Copies| + static size_t sShareCount; // total number times |nsXPIDLString|s were asked to share + + public: + static void DebugPrintStats( FILE* ); +#endif + }; + +inline +nsXPIDLString::getter_Copies_t +getter_Copies( nsXPIDLString& aString ) + { + return nsXPIDLString::getter_Copies_t(aString); + } + + + +class NS_COM nsXPIDLCString + : public nsSharableCString + { + public: + nsXPIDLCString() + { +#if DEBUG_STRING_STATS + ++sCreatedCount; + if ( ++sAliveCount > sHighWaterCount ) + sHighWaterCount = sAliveCount; +#endif + } + + nsXPIDLCString( const nsXPIDLCString& aString ) + : nsSharableCString(aString.GetSharedBufferHandle()) + // copy-constructor required (or else C++ generates one for us) + { +#if DEBUG_STRING_STATS + ++sCreatedCount; + if ( ++sAliveCount > sHighWaterCount ) + sHighWaterCount = sAliveCount; +#endif + } + +#if DEBUG_STRING_STATS + ~nsXPIDLCString() + { + --sAliveCount; + } +#endif + + nsXPIDLCString& + operator=( const nsXPIDLCString& rhs ) + // copy-assignment operator required (or else C++ generates one for us) + { + // self-assignment is handled by the underlying |nsAutoBufferHandle| + mBuffer = rhs.GetSharedBufferHandle(); + return *this; + } + + void Adopt( char* aNewValue ) { *PrepareForUseAsOutParam() = aNewValue; } + + // deprecated, to be eliminated + operator const char*() const { return get(); } + + + class getter_Copies_t + { + public: + getter_Copies_t( nsXPIDLCString& aString ) : mString(&aString) { } + // getter_Copies_t( const getter_Copies_t& ); // auto-generated copy-constructor OK + // getter_Copies_t& operator=( const getter_Copies_t& ); // auto-generated assignment operator OK + + operator char**() const { return mString->PrepareForUseAsOutParam(); } + + private: + nsXPIDLCString* mString; + }; + + friend class getter_Copies_t; + + protected: +#if DEBUG_STRING_STATS + virtual const nsBufferHandle* GetFlatBufferHandle() const; + virtual const nsBufferHandle* GetBufferHandle() const; +#endif + virtual const nsSharedBufferHandle* GetSharedBufferHandle() const; + // overridden to fix the length after `out' parameter assignment, if necessary + + char** PrepareForUseAsOutParam(); + +#if DEBUG_STRING_STATS + static size_t sCreatedCount; // total number of |nsXPIDLCString|s ever created + static size_t sAliveCount; // total number of |nsXPIDLCStrings|s alive right now + static size_t sHighWaterCount; // greatest number of |nsXPIDLCString|s alive at once + static size_t sAssignCount; // total number of times |nsXPIDLCString|s were + // assigned into with |getter_Copies| + static size_t sShareCount; // total number times |nsXPIDLCString|s were asked to share + + public: + static void DebugPrintStats( FILE* ); +#endif + }; + +inline +nsXPIDLCString::getter_Copies_t +getter_Copies( nsXPIDLCString& aString ) + { + return nsXPIDLCString::getter_Copies_t(aString); + } + +#endif /* !defined(nsXPIDLString_h___) */ diff --git a/xpcom/string/src/nsXPIDLString.cpp b/xpcom/string/src/nsXPIDLString.cpp new file mode 100644 index 000000000000..18ed64fa7142 --- /dev/null +++ b/xpcom/string/src/nsXPIDLString.cpp @@ -0,0 +1,182 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * 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 Netscape + * Communications. Portions created by Netscape Communications are + * Copyright (C) 2001 by Netscape Communications. All + * Rights Reserved. + * + * Contributor(s): + * Scott Collins (original author) + */ + +#include "nsXPIDLString.h" + +#if DEBUG_STRING_STATS +size_t nsXPIDLString::sCreatedCount = 0; +size_t nsXPIDLString::sAliveCount = 0; +size_t nsXPIDLString::sHighWaterCount = 0; +size_t nsXPIDLString::sAssignCount = 0; +size_t nsXPIDLString::sShareCount = 0; + +size_t nsXPIDLCString::sCreatedCount = 0; +size_t nsXPIDLCString::sAliveCount = 0; +size_t nsXPIDLCString::sHighWaterCount = 0; +size_t nsXPIDLCString::sAssignCount = 0; +size_t nsXPIDLCString::sShareCount = 0; +#endif + + +template +class nsImportedStringHandle + : public nsFlexBufferHandle + { + public: + nsImportedStringHandle() : nsFlexBufferHandle(0, 0, 0, 0) { } + + CharT** AddressOfDataStart() { return &mDataStart; } + void RecalculateBoundaries() const; + }; + + +template +void +nsImportedStringHandle::RecalculateBoundaries() const + { + size_t data_length = 0; + size_t storage_length = 0; + + CharT* data_start = NS_CONST_CAST(CharT*, DataStart()); + if ( data_start ) + { + data_length = nsCharTraits::length(data_start); + storage_length = data_length + 1; + } + + nsImportedStringHandle* mutable_this = NS_CONST_CAST(nsImportedStringHandle*, this); + mutable_this->DataEnd(data_start+data_length); + + mutable_this->StorageStart(data_start); + mutable_this->StorageEnd(data_start+storage_length); + } + + +#if DEBUG_STRING_STATS +const nsBufferHandle* +nsXPIDLString::GetFlatBufferHandle() const + { + --sShareCount; + return GetSharedBufferHandle(); + } + + +const nsBufferHandle* +nsXPIDLString::GetBufferHandle() const + { + --sShareCount; + return GetSharedBufferHandle(); + } + + +void +nsXPIDLString::DebugPrintStats( FILE* aOutFile ) + { + fprintf(aOutFile, "nsXPIDLString stats: %ld alive now [%ld max] of %ld created; %ld getter_Copies, %ld attempts to share\n", + sAliveCount, sHighWaterCount, sCreatedCount, sAssignCount, sShareCount); + } +#endif + + +const nsSharedBufferHandle* +nsXPIDLString::GetSharedBufferHandle() const + { + const nsImportedStringHandle* answer = NS_STATIC_CAST(const nsImportedStringHandle*, mBuffer.get()); + + if ( !answer->DataEnd() ) + answer->RecalculateBoundaries(); + +#if DEBUG_STRING_STATS + ++sShareCount; +#endif + return answer; + } + + +PRUnichar** +nsXPIDLString::PrepareForUseAsOutParam() + { + nsImportedStringHandle* handle = new nsImportedStringHandle(); + NS_ASSERTION(handle, "Trouble! We couldn't get a new handle during |getter_Copies|."); + + mBuffer = handle; +#if DEBUG_STRING_STATS + ++sAssignCount; +#endif + return handle->AddressOfDataStart(); + } + + +#if DEBUG_STRING_STATS +const nsBufferHandle* +nsXPIDLCString::GetFlatBufferHandle() const + { + --sShareCount; + return GetSharedBufferHandle(); + } + + +const nsBufferHandle* +nsXPIDLCString::GetBufferHandle() const + { + --sShareCount; + return GetSharedBufferHandle(); + } + + +void +nsXPIDLCString::DebugPrintStats( FILE* aOutFile ) + { + fprintf(aOutFile, "nsXPIDLCString stats: %ld alive now [%ld max] of %ld created; %ld getter_Copies, %ld attempts to share\n", + sAliveCount, sHighWaterCount, sCreatedCount, sAssignCount, sShareCount); + } +#endif + + +const nsSharedBufferHandle* +nsXPIDLCString::GetSharedBufferHandle() const + { + const nsImportedStringHandle* answer = NS_STATIC_CAST(const nsImportedStringHandle*, mBuffer.get()); + + if ( !answer->DataEnd() ) + answer->RecalculateBoundaries(); + +#if DEBUG_STRING_STATS + ++sShareCount; +#endif + return answer; + } + + +char** +nsXPIDLCString::PrepareForUseAsOutParam() + { + nsImportedStringHandle* handle = new nsImportedStringHandle(); + NS_ASSERTION(handle, "Trouble! We couldn't get a new handle during |getter_Copies|."); + + mBuffer = handle; +#if DEBUG_STRING_STATS + ++sAssignCount; +#endif + return handle->AddressOfDataStart(); + }