Upcoming string class changes

0 views
Skip to first unread message

Darin Fisher

unread,
Feb 18, 2004, 1:32:03 AM2/18/04
to
-------------------------------
UPCOMING MOZILLA STRING CHANGES
-------------------------------


The Mozilla string code will be undergoing extensive revision
following the release of Mozilla 1.7 alpha. The changes will be
mostly transparent, having very little affect on the string API.
This change will be made first thing during the 1.7 beta cycle.

The work is being tracked here:
http://bugzilla.mozilla.org/show_bug.cgi?id=231995


The major API-level changes include:

(1) nsAC?String will no longer be able to represent multi-fragment
strings. This allows all implementations of nsAC?String to be
unified, resulting in a significant reduction of code.

(2) nsReadingIterator and nsWritingIterator will be limited to
iterating over a contiguous buffer. Previously, operator++ was
forced to "normalize" the iterator forward to the next fragment.
This added additional code to every consumer of iterators that
was almost never needed since multi-fragment strings are very
uncommon.

(3) nsA?String methods are now all non-virtual. This is possible
since there is now only one implementation of nsAC?String. This
helps reduce code at the call sites and improves performance.
ABI compatibility with the existing vtable is maintained (more
on this later). It is important to note that any external
components that use multi-fragment strings will be broken, but
passing multi-fragment strings in external components was
forbidden anyway (although the prohibition was poorly
documented) and none of our implementations of multi-fragment
strings were ever frozen for component developers to use outside
of the Mozilla codebase.

(4) A simplified string API is introduced for embedders and external
component developers. nsAC?String's methods are now meant to be
used only within the Mozilla code base. The nsEmbedC?String
class is now implemented in terms of the simplified string API.

(5) The following string classes have been eliminated:

nsSharableC?String

nsC?String will now allocate a sharable buffer by default. It
implements thread-safe reference counting, enabling copy-on-
write semantics for most strings. Since very little code
referenced nsSharableC?String, this class name has been
eliminated.

nsDependentSingleFragmentC?Substring

This is now equivalent to nsDependentC?Substring. Since very
little code referenced nsDependentSingleFragmentC?Substring,
this class name has been eliminated.

nsDependentC?Concatenation

Since nsA?CString can no longer represent a multi-fragment
string, nsDependentC?Concatenation could no longer inherit
from nsAC?String. Therefore, this class no longer exists.
However, efficient string concatenation is still implemented
using a very similar mechanism. More on this later.

(6) nsStringFwd.h now forward declares all string classes.

(7) nsC?Substring has been added to the string hierarchy. It will
be the core string class from which all other strings inherit.
It behaves much like the old nsSingleFragmentA?CString, except
that it does not reference the nsAC?String vtable to satisfy any
of its methods. Many of the "getter"-functions are inlined for
performance.


The revised string hierarchy is depicted below:

nsAC?String
|
|
|
nsC?Substring
|
|-------- nsDependentC?Substring
|
nsC?String
|
|------------.----------.----------.
| | | |
nsDepedentC?String | | |
| | |
nsC?AutoString | |
| |
nsXPIDLC?String |
|
nsPromiseFlatC?String


Class overview:

nsAC?String

This class is designed to be subclassed. It is never directly
instantiated. This class exists only to provide backwards
compatibility with the former string class API. It is essentially
equivalent to nsC?Substring. However, unlike nsC?Substring,
nsAC?String might be implemented by an external XPCOM component or
embedding application that has not yet migrated to the new
(simpler) embedding string API provided by XPCOM.

nsC?Substring

This class is designed to be subclassed. It is never directly
instantiated. It represents a string fragment that may or may not
be null-terminated. It has methods to access and manipulate the
string buffer. It has all of the code to manage the various
different buffer allocation schemes used by the string classes.
In many ways, the subclasses of nsC?Substring simply provide
specialized constructors that select the corresponding memory
allocation scheme. If nsC?Substring needs to re-allocate the
buffer, it will allocate a null-terminated, sharable buffer.

nsC?String

This class is designed to be instantiated directly. It is the
main string class. It provides a heap allocated string buffer.
It also provides compatibility methods with the "obsolete" string
API that used to live in xpcom/string/obsolete (i.e., the "Rick
G." string API). It always allocates a sharable buffer.

nsDependentC?String

This class is designed to be instantiated directly. It provides a
mechanism to construct a nsC?String that simply stores a raw
pointer to an externally allocated buffer. This class depends on
the user of the class to ensure that the buffer remains valid for
the lifetime of the nsDependentC?String. This class can only wrap
a null-terminated buffer.

nsAutoC?String

This class is designed to be instantiated directly. It provides a
mechanism to construct a nsC?String that optionally uses a fixed-
size, stack-based buffer. This class is designed to be allocated
on the stack. Allocating this class on the heap is usually a bad
idea ;-)

nsXPIDLC?String

This class is designed to be instantiated directly. It provides
support for the getter_Copies mechanism. It also provides support
for a null buffer. Unlike nsC?String classes, the result of
nsXPIDLC?String::get() may return null if the nsXPIDLC?String is
uninitialized or was told to adopt a null-valued string buffer.
This class can also be cast automatically to |const char_type*|
for backwards compatibility. Use this class when working with
XPCOM getter methods that return |string| or |wstring|.

nsPromiseFlatC?String

This class is designed to be instantiated via the
PromiseFlatC?String family of functions. PromiseFlatC?String
takes a nsAC?String and returns a nsPromiseFlatC?String, which
"promises" to be null-terminated. PromiseFlatC?String will
allocate a copy of the given string if necessary in order to fulfill
it's promise of a null-terminated string. The "flat" adjective
comes from the old string API that supported multi-fragment strings.
With these current string changes, PromiseFlatC?String is still very
useful for ensuring null-terminated storage. This is usually only
important when you need to pass a nsC?Substring to an API that takes
a raw character pointer.

nsDependentC?Substring

This class is designed to be instantiated via the Substring family
of functions. It represents an array of characters that are not
null-terminated. Much like nsDependentC?String, this class
depends on an externally allocated string buffer. Use this class
to create a nsC?Substring that wraps a pair of raw character
pointers, a pair of nsReadingIterator<char_type>'s, or a section
of an existing nsC?Substring.


Concatenations in the new world:

For the most part, string concatenation will continue to work just
as they always have. They continue to be the preferred way to
compose a new string from several other strings. The only
difference in the new world is that the string concatenation class
no longer inherits from nsAC?String, so it cannot be passed to
functions expecting a nsAC?String. However, for compatibility with
existing code, a concatenation of strings will automatically flatten
itself into a nsC?String when necessary.

For example:

void foo( const nsAString& s )
{
nsCAutoString buf;
buf = NS_LITERAL_STRING("prefix") + e;
...
}

In this case, the two strings "prefix" and |e| are written directly
to the buffer owned by |buf|.

Here's another example:

void bar( const nsAString& s );

{
nsString a, b;
...
bar( a + b );
}

In this case, a temporary nsString is created to hold the result of
the concatenation of |a| and |b| prior to calling |bar|. This
temporary nsString would not have been generated with the previous
string implementation that supported multi-fragment nsAStrings.
However, there was a serious bug in the older implementation that
made doing this kind of thing crash-prone (especially if the
definition of |bar| looked something like the definition of |foo| in
the previous example). See bug 231995 for more details.

The main point here is that string concatenations will continue to
work as they have in the past, with a few minor exceptions.

For example, code such as the following will no longer compile:

{
nsString a, b;
...
const nsAString& s = a + b;
...
}

Such code is uncommon. It should be rewritten like this:

{
nsString a, b;
...
nsString r( a + b );
...
}

|r| could also be declared a nsAutoString to avoid heap-allocating
the result of the concatenation. However, since nsString allocates
a sharable buffer, the programmer should consider nsString if it is
expected that |r| might need to be copied elsewhere.


Maintaining string ABI compatibility:

nsA?CString exists for backwards compatibility with the frozen
nsAC?String vtable. ABI compatibility is maintained even though
nsAC?String's methods are all non-virtual. While this sounds like a
contradiction, compatibility exists by having nsAC?String (in the
new world) store a pointer to an implementation of the old vtable.
The vtable methods all cast |this| to nsC?Substring and invoke the
corresponding methods on nsC?Substring. (Yes, we are utilizing
knowledge of how the compiler implements virtual functions, but that's
not unfamiliar territory -- xpconnect!) This allows a new nsAC?String
to have the same binary signature as an old nsAC?String. Likewise,
every method on the new nsAC?String must first check the value of its
vtable pointer to determine if |this| is really a nsC?Substring
derived class or actually some other nsAC?String implementation (such
as the old nsEmbedC?String).

An advantage of this approach is that it eliminates virtual function
calls in most cases (especially for internal Gecko code). Common
nsAC?String methods like BeginReading and Length are made much
faster by avoiding virtual function calls. Code at the callsite is
also reduced since there is no need to dereference the |this|
pointer and the vtable pointer in order to gain access to the
address of the virtual function. Now, the callsites make DSO/DLL
calls which are significantly less costly in terms of codesize and
runtime.


New string API for XPCOM component developers:

Going forward, external components and embedding applications should
not call methods directly on nsA?CString. These classes should be
viewed as opaque references to string objects. This is important
because it will allow Gecko more flexibility to improve its string
implementation in the future.

The new external string API consists of a small set of functions
exported from the XPCOM library as well as a number of inline helper
functions. Include nsStringAPI.h to use these functions.

nsEmbedString has been re-implemented in terms of this new external
string API. For Gecko embedders and XPCOM component authors, the
XPCOM glue provides stub implementations of the new external string
API. All one needs to do to use these functions in external code is
link to the XPCOM glue standalone library (xpcomglue_s).

If a component is developed against this new API, then it will only
work in versions of Mozilla that support this new API (obviously).
This means that component authors interested in compatibility with
Mozilla 1.4 (for example) will need to develop their components
against Mozilla 1.4 instead of the later versions of Mozilla. New
versions of Mozilla will continue to be binary compatible with
FROZEN interfaces defined by older versions of Mozilla (see
"Maintaining string ABI compatibility" above).


So, are we supposed to stop using nsAString?

The answer is that it depends. AString in XPIDL will continue to
map to nsAString. Gecko interfaces make extensive use of AString,
ACString, and AUTF8String, and this isn't going to change. So,
nsAC?String will continue to be very important to code that
interacts with XPCOM interfaces. However, when it makes sense
nsC?Substring should be used to pass around string references inside
the Mozilla codebase. nsC?Substring unlike nsAC?String can be more
efficient since it does not need to inspect and possibly jump
through the vtable on each method call.

Moving code from nsA?CString to nsC?Substring is consistent with the
overall strategy of deCOMification that is on-going within Gecko.
If it ever happens that we are able to break binary compatibility
with Mozilla 1.0, then we would want to equate nsAC?String to
nsC?Substring. Of course, I'm not counting on this happening
anytime soon.

Embedders and external component developers should treat nsAC?String
as an opaque handle to a string object. They should use the new
external string API and nsEmbedC?String to work with Mozilla
strings. <= I'm repeating myself here ;-)


I've tried to minimize the impact of these changes. I don't expect
Mozilla hackers to have to re-learn a new string API. If you are
writing an external XPCOM component, I hope you will find the new API
easier to work with. I should add that my goal is to freeze the new
external string API for Mozilla 1.7 final.

Please let me know if you have any questions or concerns about these
changes.


Darin Fisher (da...@meer.net)
2004-02-17

Dmitriy B.

unread,
Feb 18, 2004, 2:51:44 AM2/18/04
to
Hello.
In my opinion that is realy cool to have StringAPI to use in embeded
application.
I would like to see this API. Is it available already?
What happen with nsIStringService? Does it has any changes?

Best regards, Dmitriy

PS> Sorry for my English.

"Darin Fisher" <da...@meer.net> wrote in message
news:c0v0sv$p9...@ripley.netscape.com...

Darin Fisher

unread,
Feb 18, 2004, 3:14:20 AM2/18/04
to Dmitriy B.
Here you go:

( I've also attached the header files: nsStringAPI.h and nsEmbedString.h )

-----------------------------
New External String API Notes
-----------------------------

The methods are:

NS_C?StringContainerInit
NS_C?StringContainerFinish
NS_C?StringGetData
NS_C?StringSetData
NS_C?StringSetDataRange
NS_C?StringCopy

Here's an overview of these methods (showing the wide versions only):

NS_StringContainerInit(nsStringContainer& aString)

Given a reference to a nsStringContainer struct, this function
initializes the struct for use as a nsAString to be used with XPCOM
methods. This acts like a constructor for |aString|. This method
provides external code with the ability to create a string object. The
nsStringContainer struct can be allocated in any way the caller sees
fit. (It turns out that nsStringContainer is large enough to hold a
nsString, and NS_StringContainerInit simply calls the C++ placement new
operator to construct a nsString into the given nsStringContainer.)
nsStringContainer can be passed to any function expecting a nsAString.

NS_StringContainerFinish(nsStringContainer& aString)

Given a reference to a nsStringContainer struct, this function
finalizes the struct. This acts like a destructor for |aString|.
This method does not free the |aString| reference, it only frees
any data pointers stored in the |aString| members.

PRUint32
NS_StringGetData(const nsAString& aString,
const PRUnichar** aData,
PRBool *aIsTerminated)

Given a reference to a nsAString, this function returns the length of
the string buffer, a pointer to the string buffer, and optionally a
boolean indicating whether or not the string buffer is null-terminated.
This function can be used to access the data of any nsAString.

NS_StringSetData(nsAString& aString,
const PRUnichar* aData,
PRUint32 aDataLength);

Given a reference to a nsAString, this functions sets the contents of
the internal string buffer to a copy of |aData|.

NS_StringSetDataRange(nsAString& aString,
PRUint32 aCutOffset,
PRUint32 aCutLength,
const PRUnichar* aData,
PRUint32 aDataLength)

Given a reference to a nsAString, this functions sets a range of
characters in the internal string buffer to the given values. This
function allows the caller to append, insert, or replace characters in
the nsAString. There are inline wrapper functions that simplify these
tasks.

NS_StringCopy(nsAString& aDest, const nsAString& aSrc)

Given references to two nsAString objects, this function copies the
value of |aSrc| to |aDest|. This function exists to take advantage of
the copy-on-write feature of the new string classes.

-Darin


Dmitriy B. wrote:

>_______________________________________________
>Mozilla-seamonkey mailing list
>Mozilla-...@mozilla.org
>http://mail.mozilla.org/listinfo/mozilla-seamonkey
>
>

nsEmbedString.h
nsStringAPI.h

Dmitriy B.

unread,
Feb 18, 2004, 4:55:58 AM2/18/04
to
I am using nsIStringServive as a factory of nsAString objects.
Would be great if this service become a part of String API.

NS_IMETHOD NS_CreateAString(const PRUnichar *aString, PRInt32 aLength,
nsAString * *_retval)
NS_IMETHOD NS_CreateACString(const char *aString, PRInt32 aLength,
nsACString * *_retval);
NS_IMETHOD NS_DeleteAString(nsAString* str);
NS_IMETHOD NS_DeleteACString(nsACString* str);

NS_METHOD SetBlah(const nsAString &aBlah);
void MyCode()
{
nsAString* sc;
if (NS_CreateAString(sc, '', 0))
{
const PRUnichar kData[] = {'x','y','z','\0'};
NS_StringSetData(*sc, kData, sizeof(kData)-1);
SetBlah(*sc);
NS_DeleteString(sc);
}
}
Are you planing to do something like this?

PS> Sorry for my English.

"Darin Fisher" <da...@meer.net> wrote in message

news:40331EDC...@meer.net...


----------------------------------------------------------------------------
----


> /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset:
4 -*- */
> /* ***** 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 a small implementation of the nsAString and
nsACString.
> *
> * The Initial Developer of the Original Code is
> * Peter Annema <jagge...@netscape.com>.
> *
> * Portions created by the Initial Developer are Copyright (C) 2002
> * the Initial Developer. All Rights Reserved.
> *
> * Contributor(s):
> * Darin Fisher <da...@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 nsEmbedString_h___
> #define nsEmbedString_h___
>
> #include "nsStringAPI.h"
>
> class nsEmbedString : public nsStringContainer
> {
> public:
> typedef PRUnichar char_type;
> typedef nsEmbedString self_type;
> typedef nsAString abstract_string_type;
> typedef PRUint32 size_type;
> typedef PRUint32 index_type;
>
> nsEmbedString()
> {
> NS_StringContainerInit(*this);
> }
>
> nsEmbedString(const self_type& aString)
> {
> NS_StringContainerInit(*this);
> NS_StringCopy(*this, aString);
> }
>
> explicit
> nsEmbedString(const abstract_string_type& aReadable)
> {
> NS_StringContainerInit(*this);
> NS_StringCopy(*this, aReadable);
> }
>
> explicit
> nsEmbedString(const char_type* aData, size_type aLength =
PR_UINT32_MAX)
> {
> NS_StringContainerInit(*this);
> NS_StringSetData(*this, aData, aLength);
> }
>
> ~nsEmbedString()
> {
> NS_StringContainerFinish(*this);
> }
>
> const char_type* get() const
> {
> const char_type* data;
> NS_StringGetData(*this, &data);
> return data;
> }
>
> size_type Length() const
> {
> const char_type* data;
> return NS_StringGetData(*this, &data);
> }
>
> void Assign(const self_type& aString)
> {
> NS_StringCopy(*this, aString);
> }
> void Assign(const abstract_string_type& aReadable)
> {
> NS_StringCopy(*this, aReadable);
> }
> void Assign(const char_type* aData, size_type aLength =
PR_UINT32_MAX)
> {
> NS_StringSetData(*this, aData, aLength);
> }
> void Assign(char_type aChar)
> {
> NS_StringSetData(*this, &aChar, 1);
> }
>
> self_type& operator=(const self_type& aString) {
Assign(aString); return *this; }
> self_type& operator=(const abstract_string_type& aReadable) {
Assign(aReadable); return *this; }
> self_type& operator=(const char_type* aPtr) {
Assign(aPtr); return *this; }
> self_type& operator=(char_type aChar) {
Assign(aChar); return *this; }
>
> void Replace( index_type cutStart, size_type cutLength, const
char_type* data, size_type length = size_type(-1) )
> {
> NS_StringSetDataRange(*this, cutStart, cutLength, data, length);
> }
> void Replace( index_type cutStart, size_type cutLength, char_type
c )
> {
> Replace(cutStart, cutLength, &c, 1);
> }
> void Replace( index_type cutStart, size_type cutLength, const
abstract_string_type& readable )
> {
> const char_type* data;
> PRUint32 dataLen = NS_StringGetData(readable, &data);
> NS_StringSetDataRange(*this, cutStart, cutLength, data,
dataLen);
> }
>
> void Append( char_type c )
{ Replace(size_type(-1), 0, c); }
> void Append( const char_type* data, size_type length =
size_type(-1) ) { Replace(size_type(-1), 0, data,
length); }
> void Append( const abstract_string_type& readable )
{ Replace(size_type(-1), 0, readable); }
>
> self_type& operator+=( char_type c )
{ Append(c); return *this; }
> self_type& operator+=( const char_type* data )
{ Append(data); return *this; }
> self_type& operator+=( const abstract_string_type& readable )
{ Append(readable); return *this; }
>
> void Insert( char_type c, index_type pos )
{ Replace(pos, 0, c); }
> void Insert( const char_type* data, index_type pos, size_type length
= size_type(-1) ) { Replace(pos, 0, data, length); }
> void Insert( const abstract_string_type& readable, index_type pos )
{ Replace(pos, 0, readable); }
>
> void Cut( index_type cutStart, size_type cutLength )
{ Replace(cutStart, cutLength, nsnull, 0); }
> };
>
> class nsEmbedCString : public nsCStringContainer
> {
> public:
> typedef char char_type;
> typedef nsEmbedCString self_type;
> typedef nsACString abstract_string_type;
> typedef PRUint32 size_type;
> typedef PRUint32 index_type;
>
> nsEmbedCString()
> {
> NS_CStringContainerInit(*this);
> }
>
> nsEmbedCString(const self_type& aString)
> {
> NS_CStringContainerInit(*this);
> NS_CStringCopy(*this, aString);
> }
>
> explicit
> nsEmbedCString(const abstract_string_type& aReadable)
> {
> NS_CStringContainerInit(*this);
> NS_CStringCopy(*this, aReadable);
> }
>
> explicit
> nsEmbedCString(const char_type* aData, size_type aLength =
PR_UINT32_MAX)
> {
> NS_CStringContainerInit(*this);
> NS_CStringSetData(*this, aData, aLength);
> }
>
> ~nsEmbedCString()
> {
> NS_CStringContainerFinish(*this);
> }
>
> const char_type* get() const
> {
> const char_type* data;
> NS_CStringGetData(*this, &data);
> return data;
> }
>
> size_type Length() const
> {
> const char_type* data;
> return NS_CStringGetData(*this, &data);
> }
>
> void Assign(const self_type& aString)
> {
> NS_CStringCopy(*this, aString);
> }
> void Assign(const abstract_string_type& aReadable)
> {
> NS_CStringCopy(*this, aReadable);
> }
> void Assign(const char_type* aData, size_type aLength =
PR_UINT32_MAX)
> {
> NS_CStringSetData(*this, aData, aLength);
> }
> void Assign(char_type aChar)
> {
> NS_CStringSetData(*this, &aChar, 1);
> }
>
> self_type& operator=(const self_type& aString) {
Assign(aString); return *this; }
> self_type& operator=(const abstract_string_type& aReadable) {
Assign(aReadable); return *this; }
> self_type& operator=(const char_type* aPtr) {
Assign(aPtr); return *this; }
> self_type& operator=(char_type aChar) {
Assign(aChar); return *this; }
>
> void Replace( index_type cutStart, size_type cutLength, const
char_type* data, size_type length = size_type(-1) )
> {
> NS_CStringSetDataRange(*this, cutStart, cutLength, data,
length);
> }
> void Replace( index_type cutStart, size_type cutLength, char_type
c )
> {
> Replace(cutStart, cutLength, &c, 1);
> }
> void Replace( index_type cutStart, size_type cutLength, const
abstract_string_type& readable )
> {
> const char_type* data;
> PRUint32 dataLen = NS_CStringGetData(readable, &data);
> NS_CStringSetDataRange(*this, cutStart, cutLength, data,
dataLen);
> }
>
> void Append( char_type c )
{ Replace(size_type(-1), 0, c); }
> void Append( const char_type* data, size_type length =
size_type(-1) ) { Replace(size_type(-1), 0, data,
length); }
> void Append( const abstract_string_type& readable )
{ Replace(size_type(-1), 0, readable); }
>
> self_type& operator+=( char_type c )
{ Append(c); return *this; }
> self_type& operator+=( const char_type* data )
{ Append(data); return *this; }
> self_type& operator+=( const abstract_string_type& readable )
{ Append(readable); return *this; }
>
> void Insert( char_type c, index_type pos )
{ Replace(pos, 0, c); }
> void Insert( const char_type* data, index_type pos, size_type length
= size_type(-1) ) { Replace(pos, 0, data, length); }
> void Insert( const abstract_string_type& readable, index_type pos )
{ Replace(pos, 0, readable); }
>
> void Cut( index_type cutStart, size_type cutLength )
{ Replace(cutStart, cutLength, nsnull, 0); }
> };
>
> #endif // !defined(nsEmbedString_h___)
>


----------------------------------------------------------------------------
----


> /* 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 <da...@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 nsStringAPI_h__
> #define nsStringAPI_h__
>
> /**
> * nsStringAPI.h
> *
> * This file describes a minimal API for working with XPCOM's abstract
> * string classes. It divorces the consumer from having any run-time
> * dependency on the implementation details of the abstract string types.
> */
>
> #include "nscore.h"
> #define NS_STRINGAPI(x) extern "C" NS_COM x
>
>
/* -------------------------------------------------------------------------
*/
>
> /**
> * These are dummy class definitions for the abstract string types used in
> * XPIDL generated header files. Do not count on the structure of these
> * classes, and do not try to mix these definitions with the internal
> * definition of these classes used within the mozilla codebase.
> */
>
> #ifndef nsAString_external
> #define nsAString_external nsAString
> #endif
>
> class nsAString_external
> {
> private:
> void *v;
> };
>
> #ifndef nsACString_external
> #define nsACString_external nsACString
> #endif
>
> class nsACString_external
> {
> private:
> void *v;
> };
>
>
/* -------------------------------------------------------------------------
*/
>
> /**
> * nsStringContainer
> *
> * This is an opaque data type that is large enough to hold the canonical
> * implementation of nsAString. The binary structure of this class is an
> * implementation detail.
> *
> * The string data stored in a string container is always single fragment
> * and null-terminated.
> *
> * Typically, string containers are allocated on the stack for temporary
> * use. However, they can also be malloc'd if necessary. In either case,
> * a string container is not useful until it has been initialized with a
> * call to NS_StringContainerInit. The following example shows how to use
> * a string container to call a function that takes a |nsAString &|
out-param.
> *
> * NS_METHOD GetBlah(nsAString &aBlah);
> *
> * void MyCode()
> * {
> * nsStringContainer sc;
> * if (NS_StringContainerInit(sc))
> * {
> * nsresult rv = GetBlah(sc);
> * if (NS_SUCCEEDED(rv))
> * {
> * const PRUnichar *data = NS_StringGetDataPtr(sc);
> * //
> * // |data| now points to the result of the GetBlah function
> * //
> * }
> * NS_StringContainerFinish(sc);
> * }
> * }
> *
> * The following example show how to use a string container to pass a
string
> * parameter to a function taking a |const nsAString &| in-param.
> *
> * NS_METHOD SetBlah(const nsAString &aBlah);
> *
> * void MyCode()
> * {
> * nsStringContainer sc;
> * if (NS_StringContainerInit(sc))
> * {
> * const PRUnichar kData[] = {'x','y','z','\0'};
> * NS_StringSetData(sc, kData, sizeof(kData)-1);
> *
> * SetBlah(sc);
> *
> * NS_StringContainerFinish(sc);
> * }
> * }
> */
> class nsStringContainer : public nsAString_external
> {
> private:
> void *d1;
> PRUint32 d2;
> void *d3;
>
> public:
> nsStringContainer() {} // MSVC6 needs this
> };
>
> /**
> * NS_StringContainerInit
> *
> * @param aContainer string container reference
> * @return true if string container successfully initialized
> *
> * This function may allocate additional memory for aContainer. When
> * aContainer is no longer needed, NS_StringContainerFinish should be
called.
> */
> NS_STRINGAPI(PRBool)
> NS_StringContainerInit(nsStringContainer &aContainer);
>
> /**
> * NS_StringContainerFinish
> *
> * @param aContainer string container reference
> *
> * This function frees any memory owned by aContainer.
> */
> NS_STRINGAPI(void)
> NS_StringContainerFinish(nsStringContainer &aContainer);
>
>
/* -------------------------------------------------------------------------
*/
>
> /**
> * NS_StringGetData
> *
> * This function returns a const character pointer to the string's
internal
> * buffer, the length of the string, and a boolean value indicating
whether
> * or not the buffer is null-terminated.
> *
> * @param aStr abstract string reference
> * @param aData out param that will hold the address of aStr's
> * internal buffer
> * @param aTerminated if non-null, this out param will be set to
indicate
> * whether or not aStr's internal buffer is null-
> * terminated
> * @return length of aStr's internal buffer
> */
> NS_STRINGAPI(PRUint32)
> NS_StringGetData
> (const nsAString &aStr, const PRUnichar **aData,
> PRBool *aTerminated = nsnull);
>
> /**
> * NS_StringSetData
> *
> * This function copies aData into aStr.
> *
> * @param aStr abstract string reference
> * @param aData character buffer
> * @param aDataLength number of characters to copy from source string
(pass
> * PR_UINT32_MAX to copy until end of aData,
designated by
> * a null character)
> *
> * This function does not necessarily null-terminate aStr after copying
data
> * from aData. The behavior depends on the implementation of the abstract
> * string, aStr. If aStr is a reference to a nsStringContainer, then its
data
> * will be null-terminated by this function.
> */
> NS_STRINGAPI(void)
> NS_StringSetData
> (nsAString &aStr, const PRUnichar *aData,
> PRUint32 aDataLength = PR_UINT32_MAX);
>
> /**
> * NS_StringSetDataRange
> *
> * This function copies aData into a section of aStr. As a result it can
be
> * used to insert new characters into the string.
> *
> * @param aStr abstract string reference
> * @param aCutOffset starting index where the string's existing data
> * is to be overwritten (pass PR_UINT32_MAX to cause
> * aData to be appended to the end of aStr, in which
> * case the value of aCutLength is ignored).
> * @param aCutLength number of characters to overwrite starting at
> * aCutOffset (pass PR_UINT32_MAX to overwrite until
the
> * end of aStr).
> * @param aData character buffer (pass null to cause this function
> * to simply remove the "cut" range)
> * @param aDataLength number of characters to copy from source string
(pass
> * PR_UINT32_MAX to copy until end of aData,
designated by
> * a null character)
> *
> * This function does not necessarily null-terminate aStr after copying
data
> * from aData. The behavior depends on the implementation of the abstract
> * string, aStr. If aStr is a reference to a nsStringContainer, then its
data
> * will be null-terminated by this function.
> */
> NS_STRINGAPI(void)
> NS_StringSetDataRange
> (nsAString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength,
> const PRUnichar *aData, PRUint32 aDataLength = PR_UINT32_MAX);
>
> /**
> * NS_StringCopy
> *
> * This function makes aDestStr have the same value as aSrcStr. It is
> * provided as an optimization.
> *
> * @param aDestStr abstract string reference to be modified
> * @param aSrcStr abstract string reference containing source string
> *
> * This function does not necessarily null-terminate aDestStr after
copying
> * data from aSrcStr. The behavior depends on the implementation of the
> * abstract string, aDestStr. If aDestStr is a reference to a
> * nsStringContainer, then its data will be null-terminated by this
function.
> */
> NS_STRINGAPI(void)
> NS_StringCopy
> (nsAString &aDestStr, const nsAString &aSrcStr);
>
> /**
> * NS_StringAppendData
> *
> * This function appends data to the existing value of aStr.
> *
> * @param aStr abstract string reference to be modified
> * @param aData character buffer
> * @param aDataLength number of characters to append (pass PR_UINT32_MAX
to
> * append until a null-character is encountered)
> *
> * This function does not necessarily null-terminate aStr upon completion.
> * The behavior depends on the implementation of the abstract string,
aStr.
> * If aStr is a reference to a nsStringContainer, then its data will be
null-
> * terminated by this function.
> */
> inline void
> NS_StringAppendData(nsAString &aStr, const PRUnichar *aData,
> PRUint32 aDataLength = PR_UINT32_MAX)
> {
> NS_StringSetDataRange(aStr, PR_UINT32_MAX, 0, aData, aDataLength);
> }
>
> /**
> * NS_StringInsertData
> *
> * This function inserts data into the existing value of aStr at the
specified
> * offset.
> *
> * @param aStr abstract string reference to be modified
> * @param aOffset specifies where in the string to insert aData
> * @param aData character buffer
> * @param aDataLength number of characters to append (pass PR_UINT32_MAX
to
> * append until a null-character is encountered)
> *
> * This function does not necessarily null-terminate aStr upon completion.
> * The behavior depends on the implementation of the abstract string,
aStr.
> * If aStr is a reference to a nsStringContainer, then its data will be
null-
> * terminated by this function.
> */
> inline void
> NS_StringInsertData(nsAString &aStr, PRUint32 aOffset, const PRUnichar
*aData,
> PRUint32 aDataLength = PR_UINT32_MAX)
> {
> NS_StringSetDataRange(aStr, aOffset, 0, aData, aDataLength);
> }
>
> /**
> * NS_StringCutData
> *
> * This function shortens the existing value of aStr, by removing
characters
> * at the specified offset.
> *
> * @param aStr abstract string reference to be modified
> * @param aCutOffset specifies where in the string to insert aData
> * @param aCutLength number of characters to remove
> */
> inline void
> NS_StringCutData(nsAString &aStr, PRUint32 aCutOffset, PRUint32
aCutLength)
> {
> NS_StringSetDataRange(aStr, aCutOffset, aCutLength, nsnull, 0);
> }
>
>
/* -------------------------------------------------------------------------
*/
>
> /**
> * nsCStringContainer
> *
> * This is an opaque data type that is large enough to hold the canonical
> * implementation of nsACString. The binary structure of this class is an
> * implementation detail.
> *
> * The string data stored in a string container is always single fragment
> * and null-terminated.
> *
> * @see nsStringContainer for use cases and further documentation.
> */
> class nsCStringContainer : public nsACString_external
> {
> private:
> void *d1;
> PRUint32 d2;
> void *d3;
>
> public:
> nsCStringContainer() {} // MSVC6 needs this
> };
>
> /**
> * NS_CStringContainerInit
> *
> * @param aContainer string container reference
> * @return true if string container successfully initialized
> *
> * This function may allocate additional memory for aContainer. When
> * aContainer is no longer needed, NS_CStringContainerFinish should be
called.
> */
> NS_STRINGAPI(PRBool)
> NS_CStringContainerInit(nsCStringContainer &aContainer);
>
> /**
> * NS_CStringContainerFinish
> *
> * @param aContainer string container reference
> *
> * This function frees any memory owned by aContainer.
> */
> NS_STRINGAPI(void)
> NS_CStringContainerFinish(nsCStringContainer &aContainer);
>
>
/* -------------------------------------------------------------------------
*/
>
> /**
> * NS_CStringGetData
> *
> * This function returns a const character pointer to the string's
internal
> * buffer, the length of the string, and a boolean value indicating
whether
> * or not the buffer is null-terminated.
> *
> * @param aStr abstract string reference
> * @param aData out param that will hold the address of aStr's
> * internal buffer
> * @param aTerminated if non-null, this out param will be set to
indicate
> * whether or not aStr's internal buffer is null-
> * terminated
> * @return length of aStr's internal buffer
> */
> NS_STRINGAPI(PRUint32)
> NS_CStringGetData
> (const nsACString &aStr, const char **aData,
> PRBool *aTerminated = nsnull);
>
> /**
> * NS_CStringSetData
> *
> * This function copies aData into aStr.
> *
> * @param aStr abstract string reference
> * @param aData character buffer
> * @param aDataLength number of characters to copy from source string
(pass
> * PR_UINT32_MAX to copy until end of aData,
designated by
> * a null character)
> *
> * This function does not necessarily null-terminate aStr after copying
data
> * from aData. The behavior depends on the implementation of the abstract
> * string, aStr. If aStr is a reference to a nsStringContainer, then its
data
> * will be null-terminated by this function.
> */
> NS_STRINGAPI(void)
> NS_CStringSetData
> (nsACString &aStr, const char *aData,
> PRUint32 aDataLength = PR_UINT32_MAX);
>
> /**
> * NS_CStringSetDataRange
> *
> * This function copies aData into a section of aStr. As a result it can
be
> * used to insert new characters into the string.
> *
> * @param aStr abstract string reference
> * @param aCutOffset starting index where the string's existing data
> * is to be overwritten (pass PR_UINT32_MAX to cause
> * aData to be appended to the end of aStr, in which
> * case the value of aCutLength is ignored).
> * @param aCutLength number of characters to overwrite starting at
> * aCutOffset (pass PR_UINT32_MAX to overwrite until
the
> * end of aStr).
> * @param aData character buffer (pass null to cause this function
> * to simply remove the "cut" range)
> * @param aDataLength number of characters to copy from source string
(pass
> * PR_UINT32_MAX to copy until end of aData,
designated by
> * a null character)
> *
> * This function does not necessarily null-terminate aStr after copying
data
> * from aData. The behavior depends on the implementation of the abstract
> * string, aStr. If aStr is a reference to a nsStringContainer, then its
data
> * will be null-terminated by this function.
> */
> NS_STRINGAPI(void)
> NS_CStringSetDataRange
> (nsACString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength,
> const char *aData, PRUint32 aDataLength = PR_UINT32_MAX);
>
> /**
> * NS_CStringCopy
> *
> * This function makes aDestStr have the same value as aSrcStr. It is
> * provided as an optimization.
> *
> * @param aDestStr abstract string reference to be modified
> * @param aSrcStr abstract string reference containing source string
> *
> * This function does not necessarily null-terminate aDestStr after
copying
> * data from aSrcStr. The behavior depends on the implementation of the
> * abstract string, aDestStr. If aDestStr is a reference to a
> * nsStringContainer, then its data will be null-terminated by this
function.
> */
> NS_STRINGAPI(void)
> NS_CStringCopy
> (nsACString &aDestStr, const nsACString &aSrcStr);
>
> /**
> * NS_CStringAppendData
> *
> * This function appends data to the existing value of aStr.
> *
> * @param aStr abstract string reference to be modified
> * @param aData character buffer
> * @param aDataLength number of characters to append (pass PR_UINT32_MAX
to
> * append until a null-character is encountered)
> *
> * This function does not necessarily null-terminate aStr upon completion.
> * The behavior depends on the implementation of the abstract string,
aStr.
> * If aStr is a reference to a nsStringContainer, then its data will be
null-
> * terminated by this function.
> */
> inline void
> NS_CStringAppendData(nsACString &aStr, const char *aData,
> PRUint32 aDataLength = PR_UINT32_MAX)
> {
> NS_CStringSetDataRange(aStr, PR_UINT32_MAX, 0, aData, aDataLength);
> }
>
> /**
> * NS_CStringInsertData
> *
> * This function inserts data into the existing value of aStr at the
specified
> * offset.
> *
> * @param aStr abstract string reference to be modified
> * @param aOffset specifies where in the string to insert aData
> * @param aData character buffer
> * @param aDataLength number of characters to append (pass PR_UINT32_MAX
to
> * append until a null-character is encountered)
> *
> * This function does not necessarily null-terminate aStr upon completion.
> * The behavior depends on the implementation of the abstract string,
aStr.
> * If aStr is a reference to a nsStringContainer, then its data will be
null-
> * terminated by this function.
> */
> inline void
> NS_CStringInsertData(nsACString &aStr, PRUint32 aOffset, const char
*aData,
> PRUint32 aDataLength = PR_UINT32_MAX)
> {
> NS_CStringSetDataRange(aStr, aOffset, 0, aData, aDataLength);
> }
>
> /**
> * NS_CStringCutData
> *
> * This function shortens the existing value of aStr, by removing
characters
> * at the specified offset.
> *
> * @param aStr abstract string reference to be modified
> * @param aCutOffset specifies where in the string to insert aData
> * @param aCutLength number of characters to remove
> */
> inline void
> NS_CStringCutData(nsACString &aStr, PRUint32 aCutOffset, PRUint32
aCutLength)
> {
> NS_CStringSetDataRange(aStr, aCutOffset, aCutLength, nsnull, 0);
> }
>
> #endif // nsStringAPI_h__
>


Reply all
Reply to author
Forward
0 new messages