diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
commit | f8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch) | |
tree | 26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/libs/xpcom18a4/xpcom/string | |
parent | Initial commit. (diff) | |
download | virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip |
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/libs/xpcom18a4/xpcom/string')
59 files changed, 15323 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/string/.cvsignore b/src/libs/xpcom18a4/xpcom/string/.cvsignore new file mode 100644 index 00000000..f3c7a7c5 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/src/libs/xpcom18a4/xpcom/string/Makefile.in b/src/libs/xpcom18a4/xpcom/string/Makefile.in new file mode 100644 index 00000000..6a664cb9 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/Makefile.in @@ -0,0 +1,54 @@ +# +# ***** 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 +# Netscape Communications. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Johnny Stenback <jst@netscape.com> (original author) +# +# Alternatively, the contents of this file may be used under the terms of +# either of 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 ***** + +DEPTH = ../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = string +DIRS = public src + +#ifdef ENABLE_TESTS +#DIRS += \ +# tests +#endif + +include $(topsrcdir)/config/rules.mk diff --git a/src/libs/xpcom18a4/xpcom/string/README.html b/src/libs/xpcom18a4/xpcom/string/README.html new file mode 100644 index 00000000..1fdcfdd1 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/README.html @@ -0,0 +1,44 @@ +<html> +<!-- ***** 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 + - Netscape Communications. + - Portions created by the Initial Developer are Copyright (C) 2001 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): + - Scott Collins <scc@mozilla.org> (original author) + - + - Alternatively, the contents of this file may be used under the terms of + - either of 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 ***** --> +<body> + <h1><span class="LXRSHORTDESC">managing sequences of characters</span></h1> +<p> + <span class="LXRLONGDESC"></span> +</p> +</body> +</html> diff --git a/src/libs/xpcom18a4/xpcom/string/doc/README.html b/src/libs/xpcom18a4/xpcom/string/doc/README.html new file mode 100644 index 00000000..154b7969 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/doc/README.html @@ -0,0 +1,44 @@ +<html> +<!-- ***** 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 + - Netscape Communications. + - Portions created by the Initial Developer are Copyright (C) 2001 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): + - Scott Collins <scc@mozilla.org> (original author) + - + - Alternatively, the contents of this file may be used under the terms of + - either of 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 ***** --> +<body> + <h1><span class="LXRSHORTDESC">documentation aimed at programmers who are clients of the string library</span></h1> +<p> + <span class="LXRLONGDESC"></span> +</p> +</body> +</html> diff --git a/src/libs/xpcom18a4/xpcom/string/doc/string-guide.html b/src/libs/xpcom18a4/xpcom/string/doc/string-guide.html new file mode 100644 index 00000000..41dbd217 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/doc/string-guide.html @@ -0,0 +1,2508 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> +<html> + <head> + <title>an incomplete guide to mozilla/string</title> + + <link rel="stylesheet" href="http://www.mozilla.org/projects/string/string-guide.css" title="remote stylesheet" type="text/css"> + <link rel="alternate stylesheet" href="string-guide.css" title="local stylesheet" type="text/css"> + </head> + <body> +<!-- ----|---------|---------|---------|---------|---------|---------|---------| --> +<!-- ...............................................................Front Matter --> +<h1>an incomplete guide to <a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/string/">mozilla/string</a></h1> + <h1><font color="red">This document is now deprecated in favor of <a href="http://www.mozilla.org/projects/xpcom/string-guide.html">The new string guide</a>.</font></h1> +<div class="author-note"> + <p>by <a href="http://ScottCollins.net/">Scott Collins</a><!-- /p --> + <p>last modified 8 April 2001<!-- /p --> +</div> + +<div class="abstract"> + <p> + <h1>Abstract</h1> + This document <span class="LXRSHORTDESC">provides + an <a href="#users_guide">introduction</a> to the design and use of the string classes in mozilla, + <a href="#implementors_guide">detailed information</a> on their implementation and how one may extend them, + and <a href="#faq">answers</a> to frequently asked questions about strings</span>. + </p> +</div> + + + +<h2><a name="contents">contents</a></h2> + +<div class="contents"> + <ul> + <li><a href="#users_guide" >user's guide</a></li> + <li><a href="#implementors_guide">implementor's guide</a></li> + <li><a href="#faq" >frequently asked questions</a></li> + </ul> +</div> + +<p> + Please direct all comments, requests, and contributions to, + in order of preference, + the tracking bug <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=70076">#70076</a> for this document, + the author <a class="exact-uri" href="mailto:scc@mozilla.org?subject=string-guide">scc@mozilla.org</a>, and/or + the newsgroup <a class="exact-uri" href="news:netscape.public.mozilla.xpcom">news:netscape.public.mozilla.xpcom</a> + (should there be a strings newsgroup?) +</p> + +<div class="author-note"> + <p> + A note to potential editors: + don't even <strong>consider</strong> modifying this document with an HTML editor. + That would destroy the internal formatting, + and make patches unmanagable. + </p> +</div> + + + + +<!-- ...............................................................User's Guide --> +<hr> +<h1><a name="users_guide">user's guide</a></h1> + +<div class="author-note"> + <p> + Strings in mozilla are a world apart from <span class="code">char*</span>s. + If you don't know why they are different, + this section is the place for you to start. + If you're already familiar with the hierarchy of string classes in mozilla, + then you might want to skip ahead to the <a href="#implementors_guide">implementor's guide</a> + or the <a href="#faq">FAQ</a>. + </p> +</div> + +<div class="contents"> + <ul> + <li><a href="#users_guide_introduction">introduction</a></li> + <li><a href="#users_guide_how_to" >using the string classes correctly; using the correct string class</a></li> + <li><a href="#users_guide_iterators" >using string iterators</a></li> + <li><a href="#users_guide_summary" >summary</a></li> + </ul> +</div> + +<h2><a name="users_guide_introduction">introduction</a></h2> + <h3>what and what isn't a string?</h3> +<p> + A string is an opaque container holding a, possibly zero length, linear sequence of characters. + Understanding the implications of this statement is the foundation for understanding all mozilla's string classes. +</p> + + <h3>readable and writable</h3> + <h3>dependent strings</h3> + <h3>flat strings</h3> + <h3>encoding</h3> + <h3>sharing</h3> + +<h2><a name="users_guide_how_to">using the string classes correctly; using the correct string class</a></h2> + <h3>basic string operations</h3> + <h4>comparison</h4> + <h4>concatenation</h4> + <h4>substrings</h4> + <h4>find and replace</h4> + <h3>conversions</h3> + <h4>calling a function that expects a different kind of string</h4> + <h4>converting between string classes</h4> + <h4>converting between encodings</h4> + <h3>selecting the right string class</h3> + <h4>user string classes</h4> + <h4>selecting the right string class for a parameter</h4> + <h4>selecting the right string class for a local variable</h4> + <h4>selecting the right string class for a member variable</h4> + <h4>selecting the right string class for a return value</h4> + <h4>selecting the right string class in IDL</h4> + <h3>dont's</h3> + +<h2><a name="users_guide_iterators">using string iterators</a></h2> + <h3>what is an iterator?</h3> + <h3>reading iterators and writing iterators</h3> + <h3>`chunky' iterating for efficiency</h3> + <h3><span class="code">copy_string</span>, character sources and sinks</h3> + <h3>encoding conversion iterators</h3> + +<h2><a name="users_guide_summary">summary</a></h2> + + +<!-- ........................................................Implementor's Guide --> +<hr> +<h1><a name="implementors_guide">implementor's guide</a></h1> + +<div class="author-note"> + <p> + + </p> +</div> + +<div class="contents"> + <ul> + <!-- li></li --> + </ul> +</div> + + + +<!-- ........................................................................FAQ --> +<hr> +<h1><a name="faq">frequently asked questions</a></h1> + +<div class="author-note"> +</div> + +<div class="contents"> + <ul> +<!-- + <li> + I have a wide string, i.e., an instance of a class derived from <span class="code">nsAString</span> + <ul> + <li>I want a pointer to the characters</span> + <li>I want a narrow string</li> + <li>I want to <span class="code">printf</span> it</li> + </ul> + </li> + <li> + I have a <span class="code">PRUnichar*</span> + <ul> + <li>I want a wide string</span> + <li>I want a narrow string</span> + <li>I want to <span class="code">printf</span> it</li> + </ul> + </li> + <li> + I have a narrow string, i.e., an instance of a class derived from <span class="code">nsACString</span> + <ul> + <li>I want a pointer to the characters</span> + <li>I want a narrow string</li> + <li>I want to <span class="code">printf</span> it</li> + </ul> + </li> + <li> + I have a <span class="code">char*</span> + <ul> + <li>I want a wide string</span> + <li>I want a narrow string</span> + </ul> + </li> + <li> + I have a literal character sequence, e.g., <span class="code">"Hello, World!\n"</span> + <ul> + <li>I want a wide string</span> + <li>I want a narrow string</span> + </ul> + </li> + <li>What's the best way to return a string?</li> + <li>How can I get a pointer to the characters in a string?</li> + <li>How can I <span class="code">printf</span> a string?</li> + </ul> +--> +</div> + + +<table class="chart"> + <tr> + <th></th> + <th colspan="5">you have some <span class="code">char</span>s</th> + </tr> + <tr> + <th>you want</th> + <th><span class="code">'x'</span></th> + <th><span class="code">char c</span></th> + <th><span class="code">"foo"</span></th> + <th><span class="code">char* cp</span></th> + <th><span class="code">nsACString& cs</span></th> + </tr> + <tr> + <th class="row-label"><span class="code">char</span></th> + <td colspan="2">.</td> +<!-- "foo" --> <td><span class="code">[]</span></td> +<!-- char* cp --> <td><span class="code">[]</span></td> +<!-- nsACString& cs --> <td><a href="#faq_how_to_extract_a_character">extract a character</a></td> + </tr> + <tr> + <th class="row-label"><span class="code">PRUnichar</span></th> +<!-- 'x' --> <td><span class="code">PRUnichar('x')</span></td> +<!-- char c --> <td><span class="code">PRUnichar(c)</span></td> + <td colspan="3"><a href="#faq_how_to_convert_encoding">convert encoding</a>, <a href="#faq_how_to_extract_a_character">extract a character</a></td> + </tr> + <tr> + <th class="row-label"><span class="code">char*</span></th> +<!-- 'x' --> <td><span class="code">&</span></td> +<!-- char c --> <td><span class="code">&</span></td> +<!-- "foo" --> <td><span class="code">&</span></td> +<!-- char* cp --> <td>.</td> +<!-- nsACString& cs --> <td><a href="#faq_how_to_get_a_pointer">get a pointer</a></td> + </tr> + <tr> + <th class="row-label"><span class="code">PRUnichar*</span></th> + <td colspan="5"><a href="#faq_how_to_convert_encoding">convert encoding</a>, <a href="#faq_how_to_get_a_pointer">get a pointer</a></td> + </tr> + <tr> + <th class="row-label"><span class="code">nsACString</span></th> +<!-- 'x' --> <td><span class="code">NS_LITERAL_CSTRING("x")</span></td> +<!-- char c --> <td><a href="#faq_how_to_make_a_string">make a string</a></td> +<!-- "foo" --> <td><span class="code">NS_LITERAL_CSTRING("foo")</td> +<!-- char* cp --> <td><a href="#faq_how_to_make_a_string">make a string</a></td> +<!-- nsACString& cs --> <td>.</td> + </tr> + <tr> + <th class="row-label"><span class="code">nsAString</span></th> +<!-- 'x' --> <td><span class="code">NS_LITERAL_STRING("x")</span></td> +<!-- char c --> <td><a href="#faq_how_to_convert_encoding">convert encoding</a></td> +<!-- "foo" --> <td><span class="code">NS_LITERAL_STRING("foo")</span></td> + <td colspan="2"><a href="#faq_how_to_convert_encoding">convert encoding</a></td> + </tr> + <tr> + <th class="row-label">to call <span class="code">printf</span></th> + <td colspan="4">.</td> +<!-- nsACString& cs --> <td><a href="#faq_how_to_call_printf">call <span class="code">printf</span></a></td> + </tr> +</table> + +<table class="chart"> + <tr> + <th></th> + <th colspan="3">you have some <span class="code">PRUnichar</span>s</th> + </tr> + <tr> + <th>you want</th> + <th><span class="code">PRUnichar w</span></th> + <th><span class="code">PRUnichar* wp</span></th> + <th><span class="code">nsAString& s</span></th> + </tr> + <tr> + <th class="row-label"><span class="code">char</span></th> +<!-- PRUnichar w --> <td></td> +<!-- PRUnichar* wp --> <td></td> +<!-- nsAString& s --> <td></td> + </tr> + <tr> + <th class="row-label"><span class="code">PRUnichar</span></th> +<!-- PRUnichar w --> <td></td> +<!-- PRUnichar* wp --> <td><span class="code">[]</span></td> +<!-- nsAString& s --> <td><a href="#faq_how_to_extract_a_character">extract a character</a></td> + </tr> + <tr> + <th class="row-label"><span class="code">char*</span></th> +<!-- PRUnichar w --> <td></td> +<!-- PRUnichar* wp --> <td></td> +<!-- nsAString& s --> <td></td> + </tr> + <tr> + <th class="row-label"><span class="code">PRUnichar*</span></th> +<!-- PRUnichar w --> <td><span class="code">&</span></td> +<!-- PRUnichar* wp --> <td></td> +<!-- nsAString& s --> <td><a href="#faq_how_to_get_a_pointer">get a pointer</a></td> + </tr> + <tr> + <th class="row-label"><span class="code">nsACString</span></th> +<!-- PRUnichar w --> <td></td> +<!-- PRUnichar* wp --> <td></td> +<!-- nsAString& s --> <td></td> + </tr> + <tr> + <th class="row-label"><span class="code">nsAString</span></th> +<!-- PRUnichar w --> <td></td> +<!-- PRUnichar* wp --> <td></td> +<!-- nsAString& s --> <td></td> + </tr> + <tr> + <th class="row-label">to call <span class="code">printf</span></th> +<!-- PRUnichar w --> <td></td> +<!-- PRUnichar* wp --> <td></td> +<!-- nsAString& s --> <td><a href="#faq_how_to_call_printf">call <span class="code">printf</span></a></td> + </tr> +</table> + +<div class="faq"> + <dl> + <dt> + is there any string doc? + </dt> + <dd> + Yes, you're soaking in it! + </dd> + + + +<!-- getting a pointer --> + <dt> + <a name="faq_how_to_get_a_pointer">I have a string, how do I get a pointer to the characters?</a> + </dt> + <dd> + You want to avoid this situation. + In your own interfaces, prefer string types over raw pointers. + Any interface that wants to process a string using a single pointer is making two expensive assumptions. + First, that the string is stored in one contiguous hunk; and + second, that the string is zero-terminated. + If this isn't the case, + then to get a pointer, storage must be allocated and the entire string must be copied to it and zero-terminated. + You may not be able to avoid needing a pointer when interacting with system calls. + </dd> + <dd> + Some string classes guarantee that they are `flat'. + That is, that their data is stored in one contiguous zero-terminated hunk. + This <strong>does not</strong> imply that there are no embedded nulls. Caveat emptor. + All strings that explicitly promise flatness + inherit from the class <span class="code">nsAFlatString</span> + or <span class="code">nsAFlatCString</span> + and can produce a constant pointer to their data with the <span class="code">get()</span> member function. + Even strings that don't explicitly promise to be flat + may happen to be flat. + The helper function <span class="code">PromiseFlatString</span> will produce + a <span class="code">const</span> dependent string that is guaranteed to be flat. + If you use this on a string that already happens to be flat, + the result is simply a reference through to that string. + Otherwise, + <span class="code">PromiseFlatString</span> does the work to allocate, copy, terminate, and manage + a temporary flat string. + Since the result of <span class="code">PromiseFlatString</span> is a temporary, + you must be careful not to get and hold a pointer to its data for longer than the temporary itself lives. + </dd> + <dd> +<div class="source-code"> +<pre> + /* I have a string, how do I get a pointer to the characters? */ + +extern void EvilNarrowOSFunction( const char* ); // evil OS routines that want a pointers +extern void EvilWideOSFunction( const PRUnichar* ); + +void func( const nsAString& aString, const nsACString& aCString ) + { + EvilWideOSFunction( NS_LITERAL_STRING("Hello, World!").<span class="notice">get()</span> ); + // literal strings are flat already (as are |nsString|s, et al), just use |.get()| + + EvilWideOSFunction( <span class="notice">PromiseFlatString(</span>aString<span class="notice">).get()</span> ); + // for strings that don't explicitly guarantee flatness, use |PromiseFlatString| + + + // beware holding the pointer for longer than the life of the promise + <span class="warning">const PRUnichar* wp = PromiseFlatString(aString).get(); // BAD! |wp| dangles + EvilWideOSFunction(wp);</span> + + // if you really need to use the pointer from |PromiseFlatString| in more than one expression... + const nsAFlatString& flat = <span class="notice">PromiseFlatString(</span>aString<span class="notice">)</span>; + EvilWideOSFunction(flat.<span class="notice">get()</span>); + SomeOtherFunction(flat.<span class="notice">get()</span>); + + // similarly for |char| strings + EvilNarrowOSFunction( <span class="notice">PromiseFlatCString(</span>aCString<span class="notice">).get()</span> ); + } +</pre> +</div> + </dd> + + + +<!-- extracting a character --> + <dt> + <a name="faq_how_to_extract_a_character">How do I get a particular character out of a string?</a> + </dt> + <dd> + Flat strings provide <span class="code">operator[]</span> and <span class="code">CharAt()</span>. + All strings provide <span class="code">First()</span>, <span class="code">Last()</span>, and access with iterators. + <strong>Don't</strong> promise a string flat just to do character indexing. + Prefer, instead, to get an iterator and <span class="code">advance</span> it to the position you care about. + </dd> + <dd> +<div class="source-code"> +<pre> + /* How do I get a particular character out of a string? */ + +PRUnichar Get5thCharacterOf( const nsAString& aString ) + { + if ( aString.Length() >= 5 ) + { + nsAString::const_iterator iter; + aString.BeginReading(iter); // make |iter| point to the beginning of |aString| + iter.advance(5); + return *iter; + } + + return PRUnichar(0); + } +</pre> +</div> + </dd> + <dd> + Using iterators isn't as bad as the example above makes it feel. + The typical use is for advancing through a string, examining many characters. + </dd> + + + +<!-- how to convert encoding --> + <dt> + <a name="faq_how_to_convert_encoding">How do I convert from one encoding to another?</a> + </dt> + <dd> + </dd> + + + +<!-- how to make a string --> + <dt> + <a name="faq_how_to_make_a_string">How do I create a string?</a> + </dt> + <dd> + </dd> + + +<!-- how to return a string --> + <dt> + What is the best way to return a string? + </dt> + <dd> + <p> + There are several reasonable ways to produce a string result from a function. + If you are already holding the answer as a sharable string, + you can simply return that string (pass-by-value). + Otherwise, + the most efficient and flexible way to return a string is + to assign your result into a non-<span class="code">const</span> reference parameter. + Don't bother to create a sharable string from scratch with your generated result. + </p> + <p> + Why? + The two things you want to minimize in string manipulation are, + in order of importance, + heap allocation, and + moving characters around. + </p> + </dd> + <dd> +<div class="source-code"> +<pre> + /* What is the best way to return a string? */ + +class foo + { + public: + // ... + void GetShortName( nsAString& aResult ) const; + nsCommonString GetFullName() const; + + private: + nsCommonString mFullName; + + const PRUnichar* mShortName; + PRUint32 mShortNameLength; + + }; + +nsCommonString +foo::GetFullName() const + { + return mFullName; + } + +void +foo::GetShortName( nsAString& aResult ) const + { + aResult = DependentString(mShortName, mShortNameLength); + } +</pre> +</div> + </dd> + + + <dt> + <a name="faq_how_to_call_printf">How do I <span class="code">printf</span> a string, e.g., for debugging.</a> + </dt> + <dd> + If your string is already narrow, you just have to worry about <a href="#faq_how_to_get_a_pointer">making it flat, and then getting a pointer</a>. + </dd> + <dd> + If your string happens to be wide, + you'll need to convert it before you can <span class="code">printf</span> something reasonable. + If it's just for debugging, + you probably wouldn't care if something odd was printed in the case of a Unicode character that didn't have + an ASCII equivalent. (If you have a UTF-8 terminal, the result is + perfectly legible and nothing odd is printed.) + The simplest thing in this case is to make a temporary conversion using <span class="code">NS_ConvertUTF16toUTF8</span>. + The result is conveniently flat already, so getting the pointer is simple. + Remember not to hold onto the pointer you get out of this beyond the lifetime of temporary. + </dd> + <dd> +<div class="source-code"> +<pre> + /* How do I |printf| a string? */ + + +void PrintSomeStrings( const nsAString& aString, const PRUnichar* aKey, const nsACString& aCString ) + { + // |printf|ing a narrow string is easy + printf("%s\n", <span class="notice">PromiseFlatCString(</span>aCString<span class="notice">).get()</span>); // GOOD + + // the simplest way to get a |printf|-able |const char*| out of a string + printf("%s\n", <span class="notice">NS_ConvertUTF16toUTF8(</span>aKey<span class="notice">).get()</span>); // GOOD + + // works just as well with an formal wide string type... + printf("%s\n", <span class="notice">NS_ConvertUTF16toUTF8(</span>aString<span class="notice">).get()</span>); + + + // But don't hold onto the pointer longer than the lifetime of the temporary! + <span class="warning">const char* cstring = NS_ConvertUTF16toUTF8(aKey).get(); // BAD! |cstring| is dangling + printf("%s\n", cstring);</span> + } +</pre> +</div> + </dd> + + </dl> + +<p> + Here are the email answers I have yet to format into the FAQ. + Some of the URLs may be out-dated or moved. + The messages are in order from oldest to newest. +</p> +<p class="editnote">[Note : In June, 2003, these emails were modified +to better reflect what is stored in 'wide' string +classes (UTF-16 string instead of UCS-2) and what +related methods do as a part of the patch for <a href= +"http://bugzilla.mozilla.org/show_bug.cgi?id=183156" +title="replace UCS2 in function/class/method names with UTF16">bug 183156</a>. +Therefore, they're a little different from the original emails +written by <a href="http://ScottCollins.net/">Scott Collins</a>] +</p> +<hr> +<pre> +Date: Thu, 13 Apr 2000 19:41:47 -0400 +</pre> + +<p>Encoding Wars + +<p>This message is all about strings and the various encodings that might +be used to interpret their contents, the ramifications of that, and +where we're heading. The point of this message is to say what we're +currently thinking, and get feedback. I apologize in advance for the +rambling, and for the fact that this message may accidentally mix +discussion of how things <strong>are</strong> and how they will be. + +<p>There are many different possible encodings. Three in common use in +the Mozilla source base are: ASCII, UTF-16, and UTF-8. In ASCII, every +<!--the Mozilla source base are: ASCII, UCS2, and UTF8. In ASCII, every--> +character fits in 7-bits and is typically stored in an 8-bit byte. We +usually represent ASCII strings with <span class="code">nsCString</span>s, <span class="code">nsXPIDLCString</span>s, +or <span class="code">char</span> string literals. In UTF-16, characters occupy one 16-bit code unit ( +<a href="http://www.unicode.org/glossary/index.html#BMP_character"> +<abbr title="Basic Multilingual Plane">BMP</abbr>characters</a>) +or two 16-bit code units +(<a href="http://www.unicode.org/glossary/index.html#supplementary_character"> +<abbr title="Supplementary Plane : Plane 1 through 16">non-BMP</abbr> characters</a>). +We usually represent UTF-16 strings as <span class="code">nsString</span>s, etc., i.e., two-byte +or `wide' strings. UTF-8 is a multi-byte encoding. A character might +occupy one, two, three, or four bytes. It is easiest to store and +manipulate such a string within a single-byte or `narrow' string +implementation. + +<p>None of our current string implementations know the encoding of the +data they hold at any given moment. An <span class="code">nsCString</span> might legitimately +hold data encoded in ASCII, UTF-8 or even EBCDIC for that matter. + +<p>Operations that convert from one encoding to another, or operations +that are encoding sensitive (e.g., <span class="code">to_upper</span>), rightly belong in +i18n. The fact that our current string interfaces automatically and +implicitly convert between wide and narrow strings is actually the +source of many errors in two particular categories: (1) unintended +extra work, (2) mistaken re-encoding, e.g., accidentally `converting' +a UTF-8 string to UTF-16 by pretending the UTF-8 string is ASCII and then +padding with <span class="code">'\0'</span>s. + +<p>We've known these were bad for a long time, and have been trying to +find the right way to fix them. The current thinking is to just byte +the bullet and eliminate implicit conversions. That has interesting +ramifications. + +<div class="source-code"> +<pre> +void foo( const nsString& aUTF16string ); + +foo("hello"); // works! constructs a temporary |nsString| by + // converting the ASCII literal with padding. + // Note: this requires an allocation +</pre> +</div> + +<p>Though we've always hated this form since it requires a heap +allocation. In current code, we recommend + +<div class="source-code"> +<pre> +foo( nsAutoString("hello") ); +</pre> +</div> + +<p>which still copy/converts, but at least it probably doesn't need to do +a heap allocation. In the best of all worlds, no conversion, copying, +or allocation would be necessary. To do that, you would need to be +able to directly specify a UTF-16 string, e.g., with the <span class="code">L"hello"</span> +notation, and wrap that in an interface that just held a pointer. +E.g., something like + +<div class="source-code"> +<pre> +void foo( const nsAReadableString& aUTF16string ); + +foo( nsLiteralString(L"hello") ); +</pre> +</div> + +<p>There are problems with this example, however. The <span class="code">L</span> notation +specifically makes objects that are arrays of <span class="code">wchar_t</span>, which under +GCC is a 4-byte element. This leads to incompatibility with JS, and +the annoyance of possibly bloated storage (I'm sort of minimizing the +situation here. It's worse that I make it sound). More about tricks +to get around this in a bit, but first, let me talk about what to do +in the meantime while we're just getting rid of implicit constructors. + Initially to get around this problem (what problem? The problem that +<span class="code">foo("hello")</span> stopped compiling on my machine when I threw the +switch) I made a routine called <span class="code">NS_ConvertToString</span> which looked like +this + +<div class="source-code"> +<pre> +inline +nsAutoString +NS_ConvertToString( const char* anASCIIstring ) + { + nsAutoString aUCS2string; + aUCS2string.AssignWithConversion(anASCIIstring); + return aUCS2string; + } +</pre> +</div> + +<p>Which lets me write + +<div class="source-code"> +<pre> +foo( NS_ConvertToString("hello") ); +</pre> +</div> + +<p>This was <strong>OK</strong>, but in discussion there were concerns about performance +on machines that didn't <span class="code">inline</span> well, and issues about naming. In +that meeting we came up with an alternate naming strategy that we +think has room for growth and an implementation more likely to be +efficient on every platform. The implementation is to define a new +class that derives from <span class="code">nsAutoString</span>, but allows construction from a +<span class="code">char*</span> + +<div class="source-code"> +<pre> +class NS_ConvertASCIItoUTF16 : public nsAutoString + { + public: + NS_ConvertASCIItoUTF16( const char* ); + // ... + }; +</pre> +</div> + +<p>Which gives identical (though renamed) notation for calling <span class="code">foo</span>: + +<div class="source-code"> +<pre> +foo( NS_ConvertASCIItoUTF16("hello") ); +</pre> +</div> + +<p>It looks like a function call to an explicit encoding conversion. It +acts like a function call to an explicit encoding conversion. It <strong>is</strong> +a function call to an explicit encoding conversion. We think that +this naming pattern has room for growth. In the meeting, we concluded +that the best representation for encoding conversions is a family of +functions, and <span class="code">NS_ConvertASCIItoUTF16</span> fits right in. We think that +XPCOM probably can't live without the ASCII to UTF-16 conversion (though +as explicit as possible) but that all others rightly belong in i18n +land. + +<p>You can probably deduce from the clues in <span class="code">NS_ConvertToString</span>, above, +that constructors weren't the only thing that became explicit. +Assignment, appending, comparison, et al, got renamed so that when +assigning, appending, or comparing to a value in a different encoding +the `WithConversion' form must be used. E.g., + +<div class="source-code"> +<pre> +nsString aUTF16string; +nsCString anASCIIstring; +// ... + +aUTF16string += anASCIIstring; // Currently legal, but not for long +aUTF16string.Append(anASCIIstring); // same + +aUTF16string.AppendWithConversion(anASCIIstring); // the new way + +if ( aUTF16string == anASCIIstring ) // Sorry, this is going away too + // ... + +if ( aUTF16string.EqualsWithConversion(anASCIIstring) ) + // ... +</pre> +</div> + +<p>Yes, it's long and annoying. Just like the extra work you were +implicitly asking to have done, perhaps incorrectly. There are other +reasons to rename these functions. When <span class="code">nsString</span> and <span class="code">nsCString</span> +defined a ton of, e.g., <span class="code">Append</span>s each there was no problem, because +nobody wanted to override <span class="code">Append</span>. Now, with strings inheriting from +abstract base classes we immediately run into the problem that +overriding and overloading don't mix very well in C++. Because of a +feature of C++ called name hiding, it is problematic to override only +a single signature of a name overloaded in a base class. The base +<span class="code">nsAWritableString</span> provides several <span class="code">Append</span>s, all for objects of +(hopefully) the same encoding. <span class="code">nsString</span> can't easily add a bunch of +new <span class="code">Append</span>s (the converting ones) without running face first into +the name hiding problem. The discussion of the fix for this is mostly +unrelated to encoding issues, so I'll defer it to another post. + +<p>In hindsight, after the meeting, it seemed clear that all the +`WithConversion' forms would be better named + +<div class="source-code"> +<pre> +xxxConvertingASCIItoUTF16 +xxxConvertingUTF16toASCII +</pre> +</div> + +<p>however, the <strong>real</strong> goal (probably) is to move most such conversions +into i18n. Just bringing attention to the previously implicit +conversions is a good first step. Renaming these conversions as just +suggested is probably the right thing to do, though it sort of +validates them, which I'm not sure we really want. This is a decision +we need to discuss further. + +<p>Now, back to the string literal problem above. One possible solution +is to use a macro. Imagine + +<div class="source-code"> +<pre> +NS_LITERAL_STRING("Hello") +</pre> +</div> + +<p>which on a machine where the <span class="code">L</span> trick works, turns into + +<div class="source-code"> +<pre> +nsLiteralString(L"Hello") +</pre> +</div> + +<p>but on a machine where there is trouble, turns into something less +appealing, but more likely to work, like + +<div class="source-code"> +<pre> +NS_ConvertASCIItoUTF16("Hello") +</pre> +</div> + +<p>Another solution is to add a compilation step that fixes <span class="code">L</span> strings +on bad platforms to be non-<span class="code">L</span> strings, but padded with <span class="code">\0</span>s. E.g., +<span class="code">L"Hello"</span> gets preprocessed into <span class="code">"\000H\000e\000l\000l\000o\000"</span>. +This solution is more annoying to the developer, where the prior +solution is more annoying during the runtime. + +<p>Before we go to too much trouble on this specific feature, we will +probably want to do more measurement to see just how much and how +often we are converting constant literal strings, and why. + + +<p>I'm currently ripping through the tree fixing things to use the +`WithConversion' forms where appropriate. I was also converting +things to use <span class="code">NS_ConvertToString</span> where appropriate; unless I get +talked out of it, I want to switch midstream to +<span class="code">NS_ConvertASCIItoUTF16</span>, then go back and fix up the +<span class="code">NS_ConvertToString</span> instances later. I've set things up so I can +check in as I go. After all these conversions have been done, I'll be +able to throw the switch (what switch? NEW_STRING_APIS) which will +make <span class="code">nsString</span> inherit from <span class="code">nsAWritableString</span>, etc. and allow us to +start exploiting these other opportunities (e.g., for literal strings, +shared strings, etc. See +<a class="exact-uri" href="http://bugzilla.mozilla.org/show_bug.cgi?id=28221">http://bugzilla.mozilla.org/show_bug.cgi?id=28221</a> for details and +reasoning.) + +<p>I guess I'm expecting comments on: + +<ul> + <li>how really annoying this whole topic is + <li>how bad <span class="code">L"xxx"</span> is + <li>whether to move forward with <span class="code">NS_ConvertASCIItoUTF16</span> + <li>whether we should move to xxxConvertingASCIItoUTF16 etc instead + of `WithConverting' + <li>arguments about where encoding conversions should live + <li>arguments about whether going between 1 and 2 byte storage is an + encoding conversion + <li>questions about stuff I didn't mention or didn't explain well + <li>pointing out stuff I'm just plain wrong about, or things I forgot + <li>etc +</ul> + +<p>So as not to jumble the discussion, I'll be separately posting other +requests for comments about specific features of the design of the new +string hierarchy. + +<p>I hope this helps keep everybody filled in on what we're thinking and +able to point out what we're forgetting or screwing up :-) + + + + + +<hr> +<pre> +Date: Wed, 19 Apr 2000 21:12:47 -0400 +Subject: more string info +</pre> + +<p> <a class="exact-uri" href="news://news.mozilla.org/scc-705460.16423913042000@news.mozilla.org">news://news.mozilla.org/scc-705460.16423913042000@news.mozilla.org</a> + + + + + +<hr> +<pre> +Date: Fri, 26 May 2000 15:31:37 -0400 +Subject: Re: Question on == +</pre> + +<p>I would prefer you compare with <span class="code">Equals</span> (which should really be named +<span class="code">IsEqualTo</span>) rather than <span class="code">operator==()</span> because of this: + +<div class="source-code"> +<pre> +char* a; +char* b; + +// ... + +if ( a == b ) + // ... +</pre> +</div> + +<p>Comparing two raw `string' pointers doesn't compare the characters +they point to, but instead compares the bits of the pointers. For +this reason, I may eventually make comparison of a string with a +pointer using operators just go away. + + + + + +<hr> +<pre> +Date: Wed, 14 Jun 2000 14:38:55 -0400 +Subject: Re: Fix to XprtDefs.h +</pre> + +<p>Yes, we're aware that turning off <span class="code">wchar_t</span> support makes <span class="code">wchar_t</span> be +a synonym for <span class="code">unsigned short</span> under Metrowerks. We know that the +current version of VC++ also makes these types equivalent. In theory, +though, the types are distinct even when they are the same size and +shape. By using real <span class="code">wchar_t</span> support, we are forced to recognize +the distinction and navigate it appropriately with <span class="code">reinterpret_cast</span> +(via <span class="code">NS_REINTERPRET_CAST</span>). The win here is that we aren't caught by +compiler changes that suddenly make some set of compilers compliant +and therefore break our code. We will add an autoconf test that lets +UNIX compilers opt in to our string scheme when they have an +appropriately shaped <span class="code">wchar_t</span>. If these happen to be compliant +compilers, all will be well. If they don't, the casts don't hurt, +because they are type correct. We are writing our code to meet the +standard as we move forward. + +<p>The win for us is realized by the following macros + +<div class="source-code"> +<pre> +#ifdef HAVE_CPP_2BYTE_WCHAR_T + #define NS_LITERAL_STRING(s) nsLiteralString(L##s, \ + (sizeof(L##s)/sizeof(wchar_t))-1) +#else + #define NS_LITERAL_STRING(s) NS_ConvertASCIItoUTF16(s, \ + sizeof(s)-1) +#endif +</pre> +</div> + +<p>An <span class="code">nsLiteralString</span> points directly to the literal characters. No +copying, no conversion, and the length calculation happens at compile +time. This has turned out to be as large a savings as 15% of code +space and 8% of data space, net, in our string test harness It's +faster as well, again by eliminating the copying, conversion, and +length calculation. We don't know yet what those numbers translate +into in our real code base, but we have high hopes. + +<p>I don't want to be in the position to ask you to change your code. I +don't think it's appropriate for me to do so. The AIM application +that is your client is our client as well. They need to resolve this +difference between us in whatever way they think best. That may mean +asking you if changing your apis is the right thing to do. Or it may +mean applying the casts. Our code-base and yours, Justin, are more +like cousins. I don't think you should have to change just to conform +to us. You may think my arguments for using real <span class="code">wchar_t</span> have +merit, and adopt similar usage just because you agree; but I think the +only obligation you have is to follow the technical solution you think +is right for your code. + +<p>If you decide to make this api change, it will mean shipping a new +binary (on Mac) for your library to clients who want to switch over to +the new api (since the name mangling will be different, and therefore, +the link requirements will change). + +<p>Hope this helps, + + + + + +<hr> +<pre> +Date: Thu, 15 Jun 2000 19:36:55 -0400 +Subject: Re: Checkin approval for bug 32336 +</pre> + +<div class="source-code"> +<pre> +S.Equals(NS_LITERAL_STRING("bar"), PR_TRUE, 3) +</pre> +</div> + +<p>doesn't compile because there is no three parameter form for <span class="code">Equals</span>. + For all definitions of <span class="code">Equals</span> on strings, see "nsAReadableString.h" + +<p><a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h</a> + +<p>There is an <span class="code">EqualsWithConversion</span> that takes three parameters. + +<p> <a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsString2.h#731">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsString2.h#731</a> + +<p>It is ``EqualsWithConversion'' because it admits the possibility of an +encoding specific transformation, in this case to provide +case-insensitive comparison. This also wouldn't compile, however, +since, at the moment, an <span class="code">nsLiteralString</span> doesn't provide an operator +to produce a <span class="code">const PRUnichar*</span> (though perhaps it should), and it +doesn't satisfy the other interfaces that match this call, e.g., a +<span class="code">const nsString&</span>. + +<p>Perhaps I need to move case-insensitive comparison up out of +<span class="code">nsString</span> into a global encoding specific transformations and +algorithms file (which was on its way anyway as Waterson, knows); this +use is one bit of evidence to support this. In the short term, this +can be fixed (if we think the current behavior is wrong) by providing +<span class="code">operator const CharT*() const</span> on literal string. + +<p>If you can live with out case-folding, the earlier form is preferred + +<div class="source-code"> +<pre> +S == NS_LITERAL_STRING("bar") +</pre> +</div> + +<p>if you can't, then one of the fixes I mentioned is in order. + + + + + +<hr> +<pre> +Date: Thu, 15 Jun 2000 19:47:12 -0400 +Subject: Re: [Fwd: how to use nsString ?] +</pre> + +<pre class="email-quote"> + >I see these same examples time and again in the embedding + >samples/docs, but I can't compile them. +</pre> + +<p>Apologies. Documentation mentioning strings is getting out of date. +Here are some specific answers. + + +<pre class="email-quote"> + >nsString URLString("http://www.mozilla.org"); +</pre> + +<p>...is now perhaps best expressed as + + nsString URLString( NS_LITERAL_STRING("http://www.mozilla.org") ); + +<p>since an <span class="code">nsString</span> is a sequence of 2-byte wide characters, and the +routines that implicitly convert 1-byte sequences (like the literal +sequence you specified, "http:...") are now gone. + +<p>Up until not too long ago, one would have had to say + +<div class="source-code"> +<pre> +nsString URLString; +URLString.AssignWithConversion("http://www.mozilla.org"); +</pre> +</div> + +<p>The <span class="code">NS_LITERAL_STRING</span> construction is new machinery that has the +potential to make many operations much more efficient. + +<pre class="email-quote"> + >nsString URLString; + >URLString.SetString("www.mozilla.org"); +</pre> + +<p><span class="code">SetString</span> was a synonym for <span class="code">Assign</span> or assignment with +<span class="code">operator=()</span>, it too went away. The equivalent is the second +example I gave above, that is, the one with <span class="code">AssignWithConversion</span>. + +<p><span class="code">Assign</span> still exists. <span class="code">AssignWithConversion</span> takes on that +functionality for assignments that require encoding transformations +(e.g., from ASCII to UTF16). <span class="code">SetString</span> is gone, since it was always +a synonym for <span class="code">Assign</span>. + +<p>Learn more about the general APIs for strings that we are trying to +move to by examining + +<a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h</a> +<a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAWritableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAWritableString.h</a> + +<p>Hope this helps, + + + + + +<hr> +<pre> +Date: Thu, 15 Jun 2000 21:26:51 -0400 +Subject: Re: Checkin approval for bug 32336 +</pre> + +<pre class="email-quote"> + >I *need* the count attribute, because I need to compare only the first + >chars (that's inherent to the logic). +</pre> + +<p>This is what substrings are for. In that case, you could use + +<div class="source-code"> +<pre> +Substring(S, 0, 3) == NS_LITERAL_STRING("bar") +</pre> +</div> + +<p>As for case-folding, it's best if you can case-fold everything up +front, instead of doing it repeatedly. I'll have to get back to you +on a general solution to that problem, or what my schedule for getting +it checked in would be. I'm sorry, I know that's not what you needed +to hear. If the source string is an <span class="code">nsString</span>, you can continue to +exploit its implementation of these routines, e.g., <span class="code">ToLower</span> all +up-front. + +<p>Hope this helps, + + + + + +<hr> +<pre> +Date: Mon, 19 Jun 2000 14:23:47 -0400 +Subject: Re: string fu +</pre> + +<pre class="email-quote"> + >It seems less convenient to have to first check path.IsEmpty, and + >then if false get path.Last and test it. +</pre> + +<p>What would you prefer? That extracting a character not in the string +always return <span class="code">CharT(0)</span>? Can't do it for two reasons: (1) <span class="code">0</span> may be +a valid character in a particular encoding, so it can't be used in +general as a ``no character at that position'' marker; and (2) I can't +control what an individual string implementation does when asked to +get an out-of-bounds fragment, it's explicitly undefined. That means +the result of <span class="code">CharAt</span> is explicitly undefined for indexes outside the +defined contents of the string. As a debugging convenience, I have +made this assert, but it has always been the case that retrieving such +a character had undefined results ... even in [the old] code. + +<p>OK, you might say, well at least let me ask for a character that is +only off the end by one. E.g., <span class="code">Last</span> of an empty string. Reason (1) +from above still applies. How bad is it to say, for the case you gave + +<div class="source-code"> +<pre> +PRBool needsDelim = PR_FALSE; +if ( !path.IsEmpty() ) + { + PRUnichar last = path.Last(); + needsDelim = !(last == '/' || last == '\\'); + } +</pre> +</div> + +<p>In general, you probably want to opt out of a whole lot of work when +the source string is empty. It is slightly less convenient, but it +doesn't tie us to a bunch of implementation specific mojo. + + +<pre class="email-quote"> + >Can we fix GetUnicode in this case? +</pre> + +<p>This is an annoying property of auto strings, e.g., that they always +have an allocated buffer. I'm happy to fix this bug, however, be +aware that <span class="code">GetUnicode</span> and <span class="code">GetBuffer</span> are artifacts of [the old] +implementation that we don't want to support. They are not part of +the abstract interface. We will keep them no longer than we have to. +They don't support our multi-fragment paradigm. People who require a +contiguous hunk of characters in the future, and are unwilling to +switch over to chunky-iterators, may be forced to copy the string to +their own buffer. There will be an implementation of narrow character +string that guarantees contiguous allocation and a zero-terminator, +much as <span class="code">nsCString</span> does now, for compatibility with platform uses, +but this won't be the default string class. + + + + + +<hr> +<pre> +Date: Mon, 19 Jun 2000 17:22:31 -0400 +</pre> + +<p>Clarifying String Sematics + +<p>Recently, I added an assert to the string operations that extract +characters, namely <span class="code">First()</span>, <span class="code">Last()</span>, <span class="code">CharAt()</span>, and +<span class="code">operator[]()</span>. This assert fires when any of these routines are used +to access a character outside the defined contents of the string. For +<span class="code">First()</span> and <span class="code">Last()</span> that means whenever they are applied to an +empty string. For <span class="code">CharAt()</span> and <span class="code">operator[]()</span>, that means whenever +they are used to access an index outside the range of +<span class="code">0</span>..<span class="code">Length()-1</span>. There have been some complaints, however, the +result was always undefined. What follows is extracted from an email +exchange between me and warren on this topic. I hope it clarifies +strings semantics + +<p>Warren writes: +<pre class="email-quote"> + >I hit your funky CharAt assertion tonight in this piece of code: + + >NS_IMETHODIMP + >nsIOService::ResolveRelativePath( + > const char *relativePath, + > const char* basePath, + > char **result ) + > { + > nsCAutoString name; + > nsCAutoString path(basePath); + > + > PRUnichar last = path.Last(); + > PRBool needsDelim = !(last == '/' || last == '\\' || last == + > '\0'); + > ... + + >where basePath is null. It seems less convenient to have to first + >check path.IsEmpty, and then if false get path.Last and test it. +</pre> + +<p>I replied: +<pre class="email-quote"> + >What would you prefer? That extracting a character not in the + >string always return <span class="code">CharT(0)</span>? Can't do it for two reasons: + >(1) <span class="code">0</span> may be a valid character in a particular encoding, so it + >can't be used in general as a ``no character at that position'' + >marker; and (2) I can't control what an individual string + >implementation does when asked to get an out-of-bounds fragment, + >it's explicitly undefined. That means the result of <span class="code">CharAt</span> is + >explicitly undefined for indexes outside the defined contents of + >the string. As a debugging convenience, I have made this assert, + >but it has always been the case that retrieving such a character + >had undefined results ... even in [the old] code. + + >OK, you might say, well at least let me ask for a character that + >is only off the end by one. E.g., <span class="code">Last</span> of an empty string. + >Reason (1) from above still applies. How bad is it to say, for the + >case you gave + + > PRBool needsDelim = PR_FALSE; + > if ( !path.IsEmpty() ) + > { + > PRUnichar last = path.Last(); + > needsDelim = !(last == '/' || last == '\\'); + > } + + >In general, you probably want to opt out of a whole lot of work + >when the source string is empty. It is slightly less convenient, + >but it doesn't tie us to a bunch of implementation specific mojo. +</pre> + +<p>Warren also asks: +<pre class="email-quote"> + >Here's another issue, perhaps more serious. If I say this: + + > foo(const PRUnichar* s) { + > nsAutoString str(s); + > bar(str.get()); + > } + + >where s is null, bar will get passed a zero-length PRUnichar + >sequence instead of null. This makes it so that you can't just + >test for the argument == null. You have to nsCRT::strlen(arg) == 0 + >which is much less efficient. Can we fix GetUnicode in this case? +</pre> + +<p>And I reply: +<pre class="email-quote"> + >This is an annoying property of auto strings, e.g., that they + >always have an allocated buffer. I'm happy to fix this bug, + >however, be aware that <span class="code">GetUnicode</span> and <span class="code">GetBuffer</span> are artifacts + >of [the old] implementation that we don't want to support. They + >are not part of the abstract interface. We will keep them no + >longer than we have to. They don't support our multi-fragment + >paradigm. People who require a contiguous hunk of characters in + >the future, and are unwilling to switch over to chunky-iterators, + >may be forced to copy the string to their own buffer. There will + >be an implementation of narrow character string that guarantees + >contiguous allocation and a zero-terminator, much as <span class="code">nsCString</span> + >does now, for compatibility with platform uses, but this won't be + >the default string class. +</pre> + +<p>In a later message, Chris Waterson asks a related question +<pre class="email-quote"> + >scc: should we add <span class="code">operator PRUnichar*()</span> to + >NS_ConvertASCIItoUTF16? +</pre> + +<p>And I reply: +<pre class="email-quote"> + >It seems reasonable. A lot more reasonable that forcing people to + >call <span class="code">GetUnicode()</span>. I alluded to platform specific classes in an + >earlier message to warren that you were cc'd on, Chris. I imagine + >that the <span class="code">...Convert...</span> routines would be required to produce + >contiguous allocation 0-terminated strings (though the as yet + >unimplemented <span class="code">...Copy...</span> forms, of course wouldn't. So <span class="code">operator + >const PRUnichar*() const</span> makes perfect sense to me here. +</pre> + +<p>Hope this makes sense, + + + + +<hr> +<pre> +Date: Tue, 20 Jun 2000 04:05:31 -0400 +Subject: Re: NS_LITERAL_STRING is broken +</pre> + +<p>The behavior you describe sounds exactly like when you say + +<div class="source-code"> +<pre> +const char* foobar = "foobar"; + +... NS_LITERAL_STRING(foobar).get() ... +</pre> +</div> + +<p>because in this case, the thing passed in is a <span class="code">const char*</span>. +<span class="code">NS_LITERAL_STRING</span> is not meant to be used in this way. It is only +meant to be used around a <span class="code">"</span> delimited string. The type of such is +<span class="code">const char[N]</span> where N is the number of characters in the string + 1 +for the zero terminator it helpfully adds. <span class="code">sizeof</span> such a type is +<span class="code">N</span>. + +<p>Are you sure you had the actual string as an argument, as in your +example to me? Or could the actual code have been like my sample, +above? + + + + + +<hr> +<pre> +Date: Thu, 29 Jun 2000 13:35:10 -0400 +Subject: Re: a fix +</pre> + +<pre class="email-quote"> + > + if (Length() == 0) { return nsnull; } +</pre> + + +<p>Dave, + +<p>please read + + <a class="exact-uri" href="news://news.mozilla.org/scc-314ABF.14261619062000@news.mozilla.org">news://news.mozilla.org/scc-314ABF.14261619062000@news.mozilla.org</a> + +<p>It's just plain wrong to let people try to index into a string outside +its defined contents. I can't just return <span class="code">'\0'</span> or <span class="code">PRUnichar('\0')</span> +there as that <strong>could</strong> be a legal value to have somewhere in your +string for some encodings ... and the encoding is not specified. So +your patch has the basic problem of defeating my plan to stop people +from doing this bad thing. + +<p>The second problem with your patch is that you use the symbolic +constant <span class="code">nsnull</span>, which is ostensibly a pointer value; <span class="code">Last</span> returns +a character. <span class="code">nsnull</span> is not appropriate for that purpose. In fact, +C++ gurus pretty much eschew the use of symbolic constants for <span class="code">0</span>. +<span class="code">NULL</span> is to be avoided. <span class="code">nsnull</span> is wrong-headed in that it presumes +we could have some <strong>other</strong> application specific value for <span class="code">NULL</span>. We +can't, it would never work. It's just wasted brain-print. Always use +<span class="code">0</span> for these situations, and if you want to communicate the fact that +something is a pointer type, either use a comment or a +(construction-style) cast, like so (graded examples from worst to +best:) + +<ul> + <li>F: FindChildByNameWithHint("Chuck", nsnull); + + <li>D: FindChildByNameWithHint("Chuck", NULL); + + <li>C: FindChildByNameWithHint("Chuck", /* Child* */ 0); + + <li>B: typedef Child* Child_ptr; + FindChildByNameWithHint("Chuck", Child_ptr(0)); + + <li>A: FindChildByNameWithHint("Chuck", 0); +</ul> + +<p>Don't let this discourage you; keep up the good work :-) + + + + + +<hr> +<pre> +Date: Tue, 8 Aug 2000 23:47:16 -0400 +Subject: Re: nsWritingIterator? +</pre> + +<pre class="email-quote"> + >Can you give me any pointers to examples, or docs, or just some + >general advice? +</pre> + + <a class="exact-uri" href="http://ScottCollins.net/Journal/discussion/string_iterators.html">http://ScottCollins.net/Journal/discussion/string_iterators.html</a> + +<p>does this help? + +<p>I can personally walk you through any specific scenario you need. + + + + + +<hr> +<pre> +Date: Wed, 9 Aug 2000 02:35:03 -0400 +Subject: Re: nsWritingIterator? +</pre> + +<p>You got it right... it's <span class="code">nsWritingIterator<CharT></span> for whichever +character type you care about, either <span class="code">char</span> or <span class="code">PRUnichar</span>. You +_can_ use this iterator like a character pointer ... that is, you can +dereference it, assign into its dereference, etc. It is more +efficient, though, to directly address a particular range of +characters around where it points by asking it for its actual +character pointer with <span class="code">get</span>, and knowing that there are +<span class="code">size_forward()</span> characters available ahead of that pointer and +<span class="code">size_backward()</span> characters available behind it. After examining +those characters by hand, you can advance the iterator beyond the +characters you have examined (and possibly into the next chunk, should +one exist) by adding into it (with +=) the count of the characters you +have processed. + +<p>Here are three examples of running through a string and modifying some +of the characters in it. All use <span class="code">nsWritingIterator</span>s. + + +<div class="source-code"> +<pre> + // inefficient, but works in a pinch: + // iterators can hide all details of chunks by acting like + // a raw character pointer + +nsWritingIterator<PRUnichar> s = S.BeginWriting(); +nsWritingIterator<PRUnichar> done_with_string = S.EndWriting(); + + // for each character in the string |S| +while ( s != done_with_string ) + { + // if the character is lower case, capitalize it + if ( 'a' <= *s && *s <= 'z' ) + *s = *s -'a' + 'A'; + } + + + + + // efficient + // iterators provide a mechanism by which you can process + // a chunk-at-a-time + +nsWritingIterator<PRUnichar> iter = S.BeginWriting(); +nsWritingIterator<PRUnichar> done_with_string = S.EndWriting(); + + // for each chunk of the string +while ( iter != done_with_string ) + { + size_t N = iter.size_forward(); // # of chars in this chunk + PRUnichar* s = iter.get(); + PRUnichar* done_with_chunk = s + N; + + // for each character in this chunk + for ( ; s < done_with_chunk; ++s ) + { + // if the character is lower case, capitalize it + if ( 'a' <= *s && *s <= 'z' ) + *s = *s - 'a' + 'A'; + } + + // advance the iterator past characters + // we examined (and into the next chunk, if any) + s += N; + } + + + + // elegant + // pull your transformation into a `sink', and |copy_string| + // will efficiently pump any kind of string into it + +struct Capitalize + { + // inline + PRUint32 + write( PRUnichar* s, PRUint32 N ) + // processes one chunk, called repeatedly by |copy_string| + { + PRUnichar* done_with_chunk = s + N; + + // for each character in this chunk + for ( ; s < done_with_chunk; ++s ) + { + // if the character is lower case, capitalize it + if ( 'a' <= *s && *s <= 'z' ) + *s = *s - 'a' + 'A'; + } + } + }; + +copy_string(S.BeginWriting(), S.EndWriting(), Capitalize()); +</pre> +</div> + + + +<p>Does this show it better? + + + + + +<hr> +<pre> +Date: Thu, 17 Aug 2000 18:23:22 -0400 +</pre> + +<pre class="email-quote"> + >I tried looking at the string header files but they + >are awfully complicated. +</pre> + +<p>I'll explain things in a little <strong>more</strong> detail than you need, then so +that some of the stuff you see in these headers will make more sense. +I'll also answer your questions out of order. + +<p>First: the string hierarchy looks like this + +<a class="exact-uri" href="http://ScottCollins.net/Journal/discussion/string_hierarchy.gif">http://ScottCollins.net/Journal/discussion/string_hierarchy.gif</a> + +<p>The two most important headers are: + +<a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAReadableString.h</a> +<a class="exact-uri" href="http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAWritableString.h">http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsAWritableString.h</a> + +<p>These abstract classes, <span class="code">nsAReadable[C]String</span>, and +<span class="code">nsAWritable[C]String</span> are typically what you will want to use in the +interfaces of new code. If you write a piece of code that takes a +string for input, consider, e.g., + +<div class="source-code"> +<pre> +void consumes_a_string( const nsAReadableString& aInput ); +</pre> +</div> + +<p>If you write a piece of code that modifies a string, consider + +<div class="source-code"> +<pre> +void modifies_a_string( nsAWritableString& aResult ); +</pre> +</div> + + +<p>When creating your own classes, member strings will typically be +<span class="code">nsString</span>s. When you can't avoid creating a short string that you +need only temporarily during a function, you will typically use +<span class="code">nsAutoString</span>. When someone passes you a raw pointer, or a raw +pointer and a length, representing a buffer of characters that you may +examine, but won't own, you can treat it like a string by wrapping it +in an <span class="code">nsLiteralString</span>, e.g., + +<div class="source-code"> +<pre> +void +reads_a_buffer( const PRUnichar* aInput, PRUint32 aInputLength ) + { + nsLiteralString input(aInput, aInputLength); + // doesn't allocate or copy + + // ... + } +</pre> +</div> + +<p>You will use <span class="code">nsLiteralString</span> around quoted constant strings as well, +though typically through the <span class="code">NS_LITERAL_STRING</span> macro, to avoid doing +a length calculation + +<div class="source-code"> +<pre> +NS_LITERAL_STRING("x") +</pre> +</div> + +<p>expands to + +<div class="source-code"> +<pre> +nsLiteralString(L"x", (sizeof(L"x")/sizeof(PRUnichar) - 1)) +</pre> +</div> + +<p>if <span class="code">L</span> notation works as needed on your platform. + +Those are the basics. Now onto your questions: + + +<pre class="email-quote"> + >For example this won't compile. [...] + + >str1 += L"abc " + str2 + L"def"; +</pre> + + +<p><span class="code">L"abc "</span> makes a an object that is a <span class="code">const wchar_t[5]</span>, and none of +the string code knows about <span class="code">wchar_t</span>. The main reason is that +<span class="code">wchar_t</span> is not necessarily the right size (it can be 4 bytes under +gcc). If you wrap these constant expressions in <span class="code">NS_LITERAL_STRING</span>, +as described above, you should get the right thing, e.g., + +<div class="source-code"> +<pre> +str1 += NS_LITERAL_STRING("abc ") + str2 + NS_LITERAL_STRING("def"); +</pre> +</div> + + +<pre class="email-quote"> + >Another one is: + >function(const PRUnichar *foo); + >call function(L"abc " + str2); + + >It won't create a temporary nsString. +</pre> + +<p>This one, I have a quick and easy explanation for. If <span class="code">function</span> was +declared like this + +<div class="source-code"> +<pre> +function( const nsAReadableString& ) +</pre> +</div> + +<p>then, no problem, since a <span class="code">nsPromiseConcatenation</span> (which was the +result of adding those two things together) <strong>is</strong> a readable string. +No other objects need to be created; no copying needs to be performed. + +<p>In all cases, we want the creation of <span class="code">nsString</span>s et al, to be +<span class="code">explicit</span>, since creation is unbelievably expensive, requiring heap +allocation, locks, copying, etc. + +<p>I hope this answers both your posts, + + + + + +<hr> +<pre> +Date: Thu, 17 Aug 2000 20:57:08 -0400 +Subject: re our conversation +</pre> + + return ToNewUnicode( nsLiteralCString(buffer) ); + + + + + + +<hr> +<pre> +Date: Fri, 18 Aug 2000 02:52:45 -0400 +Subject: Re: More questions and new string API +</pre> + +<pre class="email-quote"> + >1) How do I return a static string? + + >const nsAReadableString& foo() {return NS_LITERAL_STRING("x");} + >errors on taking the address of a temporary variable. +</pre> + +<p>Unfortunately, <span class="code">NS_LITERAL_STRING</span>s definition is not particularly +amenable to this use. Instead, you would have to say something like +this: + +<div class="source-code"> +<pre> +const nsAReadableString& +foo() + { +#ifdef HAVE_CPP_2BYTE_WCHAR_T + static nsLiteralString static_foo(L"x", 1); +#else + static nsLiteralString static_foo; + static PRBool initialized = PR_FALSE; + if ( !initialized ) + { + static_foo.AssignWithConversion("x", 1); + initialized = PR_TRUE; + } +#endif + return static_foo; + } +</pre> +</div> + + +<pre class="email-quote"> + >2) I'm using these with the STL library in an XPCOM component. + >What type should I use with map? This doesn't work... + + >typedef map<const nsAReadableString&, myType*> mapStringMyType; + >mapStringMyType foo; + >foo.find(nsAReadableString); - I want to find on a ReadableString +</pre> + +<p>I don't know what errors you are getting; but it probably doesn't work +because a reference isn't an assignable type. This is just a guess. +You may need to use + +<div class="source-code"> +<pre> +map<const nsAReadableString*, myType*> +</pre> +</div> + +<p>If you actually want the map to manage ownership of the keys, then +you'll want to use a concrete type, e.g., + +<div class="source-code"> +<pre> +map<nsString, myType*> +</pre> +</div> + +<p>or perhaps + +<div class="source-code"> +<pre> +map<nsSharedStringPtr, myType*> +</pre> +</div> + +<p>Or maybe there's something else wrong. Send me the error messages. +If you end up using a pointer, then of course you'll have to supply a +comparison function to the <span class="code">map</span> template. You won't be satisfied +with the default comparison of pointers :-) Sorry I couldn't answer +this one more completely. + + +<pre class="email-quote"> + >3) How do a get a raw PRUnichar pointer out of nsAReadableString + >when I need to call something that wants 'unsigned short *'? +</pre> + +<p>The problem with this scenario is that an <span class="code">nsAReadableString</span> doesn't +promise that all its data is contiguous, nor that it is +zero-terminated, which is what I suspect you want in this case. If +the function you want to call can take {pointer, length} tuples, and +can consume the string in hunks without zero termination ... then you +can use <span class="code">copy_string</span> to pump the string into your function, see + + <a class="exact-uri" href="http://ScottCollins.net/Journal/discussion/string_iterators.html">http://ScottCollins.net/Journal/discussion/string_iterators.html</a> + +<p>If not, and you absolutely have to have a contiguous zero-terminated +buffer, then there is a new facility (part of the DOMAPI branch) that +does what you need. It's not checked in on the trunk; it should +be in early next week. It is <span class="code">nsPromiseFlatString</span>. This class +promises a contiguous zero-terminated buffer; and has an <span class="code">operator +PRUnichar*</span> to produce a pointer to that buffer automatically. If the +underlying class <strong>is</strong> one that happens to be a single fragment and +zero-terminated, then, like <span class="code">nsPromiseSubstring</span> and +<span class="code">nsPromiseConcatenation</span>, this class merely holds a reference into the +original data. If, however, the underlying string is multi-fragment +or not zero-terminated, then <span class="code">nsPromiseFlatString</span> allocates a +contiguous buffer of appropriate size and copies the fragmented string +data to it. So given + +<div class="source-code"> +<pre> +void ReadBuffer( PRUnichar* ); +</pre> +</div> + +<p>You can call this as efficiently as possible with an arbitrary string +like so + +<div class="source-code"> +<pre> +ReadBuffer( nsPromiseFlatString(aString) ); +</pre> +</div> + + +<p>If the function you are calling needs to take ownership of the buffer +you hand it, then you will probably call <span class="code">ToNewUnicode</span> like so + +<div class="source-code"> +<pre> +void ConsumeBuffer( PRUnichar* ); + +ConsumeBuffer( ToNewUnicode(aString) ); +</pre> +</div> + +<p>The global function <span class="code">ToNewUnicode</span> is declared in "nsReadableUtils.h", +and was only recently added to the build. It is currently being used +in the DOMAPI branch. It is part of the build, but the file +"dlldeps.c" in XPCOM may need to be modified to ensure it is exported +on your platform if you are building the tip. + +Needless to say, you want to avoid functions that require bare +pointers for several reasons: (a) they typically assume +zero-termination, which is not guaranteed by the normal encodings; (b) +they require contiguous allocation, which may not be possible; (c) +they scan for the end of the string, at linear cost (if the encoding +makes it possible at all), when the length could be known in advance. +If you have to do it, the above mechanisms work, but be aware of the +cost and the potential need to copy. + + +<pre class="email-quote"> + >4) How do I declare a local variable to hold a nsAReadableString? + >and a member variable? +</pre> + +<p><span class="code">nsAReadableString</span> is an abstract type. So you can't have a concrete +instance of it. All strings in the hierarchy are readable strings. +If you just want a reference to a readable string, you can say, e.g., + +<div class="source-code"> +<pre> +struct foo + { + const nsAReadableString& mString; + // ... + + foo( const nsAReadableString& aString ) : mString(aString) { } + }; +</pre> +</div> + +<p>...similarly with pointers; but I suspect you are looking for +something more concrete. An <span class="code">nsString</span> is a <span class="code">nsAReadableString</span>, and +is the typical thing you want as a member variable. An <span class="code">nsAutoString</span> +is also an <span class="code">nsAReadableString</span> and is typically what you would use for +a short (in length) temporary (in lifetime) local variable, as I +mentioned in my previous post. + + +<pre class="email-quote"> + >5) If I call a function that returns a PRUnichar* and I want t + >use it as a nsAReadableString should I wrap it in a + >nsLiteralString? +</pre> + +<p>Yes, though remember, an <span class="code">nsLiteralString</span> assumes the lifetime of the +underlying data is under someone else's control. If the called +function gives you a buffer that you need to <span class="code">delete</span>, you will have +to manage that yourself. Currently, people often use <span class="code">nsXPIDLString</span> +to handle that. XPIDL strings are <strong>not</strong> part of the hierarchy. They +are only used as a sort of string-<span class="code">auto_ptr</span>. However, I'm +integrating their functionality into <span class="code">nsString</span>. There is no problem +in wrapping the same pointer in both as two separate local variables, +one to give you the readable interface, and one to manage the +lifetime. + +<p>If it's OK with you, I'd like to post this reply (including your +quoted questions) to n.p.m.xpcom and also put a copy near the string +iterator discussion I provided a link to above, so that other people +with similar questions can see these answers. + +<p>Hope this helps, + + + + + +<hr> +<pre> +Date: Sun, 3 Sep 2000 03:52:17 -0400 +</pre> + +<p>In article <8nu9m2$eo14@secnews.netscape.com>, "Jon Smirl" +<jonsmirl@mediaone.com> wrote: + +> I have the new strings up and running in my app. They work as +> advertised and +> I haven't found any bugs. Thanks for the good job in designing and +> implementing them. Here's are a summary of issues I've encountered +> so far... + +<p>Thanks, and I appreciate your comments and insights. + + +> +> 1) Should there be a nsSegmentedString derived from nsString instead +> of building segment support into nsString? None of my strings are +> segmented but +> I keep executing code that is supports it. nsPromiseFlatString would +> be trivial in the non-segmented case. + +<p>The general case is that a string does not promise to have contiguous +data. A specific case is that, for some implementations, it does. +You couldn't do it the other way around, because a segmented string +couldn't satisfy all the promises of a flat string. However, through +the use of chunky iterators, operating on strings that happen to be +flat is very efficient. In fact, <span class="code">nsPromiseFlatString</span> is trivial in +the non-segmented case. In addition, I'll be adding an abstract flat +class into the hierarchy, which will present additional interface ... +in your local routines where you actually have declared a concrete +string instance that happens to be flat, the compiler will give you +the benefit of using the flat specific routines (e.g., a substring +object over a flat string is simpler than the general purpose +substring). I need to be cautious about this, though, since I don't +automatically want people propagating the flat type through their +interfaces. That would put us in the same boat we're in right now ... +where routines only work on a specific kind of string, which denies +other parts of the code the opportunity to use an implementation +beneficial to its specific needs, and typically for no good reason. + +> +> 2) Should nsAWritableString have a way to get the buffer and then +> return it? +> I need to get the buffer to pass it to OS calls. I'm doing this now +> by passing around nsStrings instead of the interface. If I just use +> the interface I encur an extra copy since I have to use a temporary +> buffer. + +<p>A specific string implementation could promise this, but in general, a +writable could not. After all, a writable doesn't even guarantee +contiguous storage. To some degree, this is what +<span class="code">nsPromiseFlatString</span> is for. However, this is a readable promise +only. It will also be the case that <span class="code">ns[C]String</span>s, in the very near +future will be able to just assume ownership of an arbitrary buffer +allocated on the free store with the XPCOM allocators ... getting one +to give up its buffer, on the other hand, presents some problems. Do +you have a lot of places where the system writes into your string +buffer space? Or do you have a lot of system routines that return you +new buffers? I can imagine using <span class="code">nsPromiseFlatString</span> for this, but +what happens when the OS alters the underlying data? If the promise +had generated that flat data on behalf of a multi-fragment string, +should it now put the changes back? It's possible to do, I just want +to know if it's correct to allow this situation to happen. + + + +> +> 3) There needs to be a NS_LITERAL_CHAR() to go along with +> NS_LITERAL_STRING(). + +<p>OK. + + + +> Having NS_LITERAL_STRING() all over the code clutters +> it up and makes it hard to tell what the code is doing, could we +> have a standard short alias for this? + +<p>Yes, I'll try to think of something ... perhaps <span class="code">NS_LSTR</span>? + + +> 4) nsLiteralString should support n.ToInteger(&error); + +<p><span class="code">ToInteger</span> is actually a bad interface. It's only good if your +entire string is the number; this encourages you to edit your string +until it is one, or perhaps copy the numeric part to another string. +Better if you just <span class="code">sscanf</span> a string (don't know if I can provide +that in the general case, but I'm thinking about it), or else use +regular C++ extractors (which wouldn't be too hard for me to +provide), or else I could give you a <span class="code">ToInteger</span> that works on a pair +of iterators, extracting the integer from the digits between them. + +> +> 5) There should be a global define for an interface to a readonly +> empty string. + +<p>Yes, there will be. + + +> +> 6) Something is wrong with concatenation.... + +<p>Hopefully I've fixed this now. + + + +> 8) A forward definition is missing in the h files + +<p>I'll check it out. + + + +<p>My understanding is that you have already found the answers to your +other questions. + +<p>I hope this helps, + + + + +<hr> +<pre> +Date: Wed, 20 Sep 2000 17:32:13 -0400 +Subject: Re: how to free an nsString::ToNewCString +</pre> + +<pre class="email-quote"> + >What's the current approved way to free an nsString::ToNewCString? +</pre> + +<p><span class="code">nsMemory::Free</span> + + + + + +<hr> + +<p>You use several <span class="code">NS_ConvertASCIItoUTF16("...").get()</span>, these should be + + NS_LITERAL_STRING("...").get() + +<p>Don't do this to the very first case where you aren't wrapping an actual literal string. +The first instance would should exploit <span class="code">NS_LITERAL_STRING</span> technology as well, +around the initial declarations of the strings ... probably want to do this with +<span class="code">NS_NAMED_LITERAL_STRING</span>. + + + +<hr> +<pre> +Date: Thu, 12 Oct 2000 00:57:28 -0400 +Subject: string answers +</pre> + +<div class="source-code"> +<pre> +nsresult +DoSomething( nsAWritableString& answer ) + { + nsresult rv; + + nsXPIDLString registry_data; + Fetch("key", getter_Shares(registry_data)); + + nsLiteralString path(not_my_string); + + PRInt32 first_colon = path.FindChar(PRUnichar(':')); + if ( first_colon != -1 ) + { + // convert ... extract path from |path| + nsCOMPtr<nsILocalFile> localFile( do_CreateInstance(CID, &rv) +); + if ( localFile ) + { + +localFile->SetPersistentDescriptor(NS_ConvertUTF16toUTF8(path)); + + nsXPIDLString converted_path; + localFile->GetUnicodePath(getter_Copies(converted_path)); + answer = converted_path.get(); + } + } + else + { + answer = path; + } + + + return rv; + } +</pre> +</div> + + + + + +<hr> +<pre> +Date: Thu, 12 Oct 2000 02:03:49 -0400 +Subject: Re: and the answer is ... +</pre> + +<p>You can see from the line of code that you're on, that this should +have been fine. <span class="code">nsMemory::Alloc</span> would be asked to allocate a 1 byte +object. But it failed trying to allocate that. Which suggests that +the allocator was busy and non-reentrant and the debugger tried to +misuse it. Yes? + +<p>Of course, this doesn't solve your problem. Perhaps we need to go +back to the idea of a function that returns a pointer to the first +hunk of the string. + +<div class="source-code"> +<pre> +const char* +debug_string( const nsAReadableCString& aCString ) + { + nsReadingIterator<char> iter; + aCString.BeginReading(iter); + return aCString.IsEmpty() ? "" : iter.get(); + } +</pre> +</div> + +<p>This code should work regardless of what the allocator is doing. The +downsides are (a) it only returns the first hunk of the string, in the +case of a multi-fragment string; and (b) that hunk <strong>might</strong> not be +zero-terminated. + +<p>Hope this helps, + + + + + +<hr> +<pre> +Date: Thu, 12 Oct 2000 08:30:32 -0400 +Subject: Re: Self healing the cache :-) +</pre> + +<p>At 3:04 PM -0400 10/11/00, Mike Shaver wrote: +<pre class="email-quote"> + >NS_LITERAL_STRING(NS_XPCOM_SHUTDOWN_OBSERVER_ID); +</pre> + +<p>Macro ugliness makes <span class="code">NS_LITERAL_STRING</span> inappropriate for use over +other macros. In other words: + +<div class="source-code"> +<pre> +NS_LITERAL_STRING("foo") +</pre> +</div> + +<p>is <strong>good</strong>. + +<div class="source-code"> +<pre> +#define FOO "foo" +NS_LITERAL_STRING(FOO) +</pre> +</div> + +<p>is <strong>bad</strong>. Why? Because it turns into + +<div class="source-code"> +<pre> +nsLiteralString(LFOO, sizeof(LFOO)... +</pre> +</div> + +<p>and there is no <span class="code">LFOO</span>. Sorry. If you have to do this to a +macro-ized string, do the magic by hand, e.g., + +<div class="source-code"> +<pre> +nsLiteralString(FOO, sizeof(FOO)/sizeof(PRUnichar) + + sizeof(PRUnichar('\0'))) +</pre> +</div> + +<p>or else if you don't care that <span class="code">nsLiteralString</span> will scan for the +length, just say + +<div class="source-code"> +<pre> +nsLiteralString(FOO) +</pre> +</div> + +<p>Hope this helps, + + + + + +<hr> +<pre> +Date: Thu, 12 Oct 2000 08:36:14 -0400 +Subject: Re: Self healing the cache :-) +</pre> + +<p>Actually, I'm not even sure you can do it by hand, since you didn't + +<div class="source-code"> +<pre> +#define FOO L"foo" +</pre> +</div> + +<p>and <strong>can't</strong> do that cross-platform. The other way around this is to +define a global instead of a macro, that is, instead of saying + +<div class="source-code"> +<pre> +#define FOO "foo" +</pre> +</div> + +<p>at the top of your file, say + +<div class="source-code"> +<pre> +NS_NAMED_LITERAL_STRING(FOO, "foo") +</pre> +</div> + +<p>or else, if the macro was used only in one spot ... perhaps you could +just eliminate the macro in favor of <span class="code">NS_NAMED_LITERAL</span> in situ. + +<p>Arghh. In this case, you may be stuck with the extra work of +<span class="code">AssignWithConversion</span>. + + + + + +<hr> +<pre> +Date: Sun, 3 Dec 2000 16:38:07 -0400 +Subject: Re: another copy_string question +</pre> + +<pre class="email-quote"> + >Is there a way to tell, inside the write() sink, if one is in the + >final hunk? I need to do some special processing at the end. +</pre> + +<p>No, there isn't. But you could move such special processing into the +destructor of the sink. Remember, the sink is passed by reference, so +you can exactly control its lifetime. + +<div class="source-code"> +<pre> +{ + MySink sink; + nsReadingIterator<PRUnichar> sourceStart = aStr.BeginReading(); + nsReadingIterator<PRUnichar> sourceEnd = aStr.EndReading(); + copy_string(sourceStart, sourceEnd, sink); + // |sink| destructor executed here +} +</pre> +</div> + +<p>Hope this helps, + + + + + +<hr> +<pre> +Date: Fri, 15 Dec 2000 20:02:08 -0400 +Subject: fragment of code +</pre> + +<div class="source-code"> +<pre> +nsPromiseFlatString flatKey(aReadable); + +flatKey.get() +</pre> +</div> + + + + + + +<hr> +<pre> +Date: Tue, 16 Jan 2001 16:47:37 -0400 +Subject: Re: a few string questions... +</pre> + +>I've accumulated a few questions I've been wanting to ask you, mostly +>about string stuff. Nothing urgent, but I want to ask them before I +>forget. So here goes...: +> +>1) Is it acceptable to use nsLiteralCString or nsLiteralString on +>something that's not a literal? This can be useful in some places, +>for example, to convert a char* to PRUnichar*: +> +>PRUnichar* new = ToNewUnicode(nsLiteralCString(myCharPtr)); + +<p>This is explicitly allowed. That's why I'm proposing to change the +names of those classes to <span class="code">nsLocal[C]String</span>. + + +>2) Should nsString2x.h and nsString2x.cpp go away? They look like a +>never-completed rewrite or something... + +<p>Yes. They should go away. They are uncompleted [old] bullshit, +exactly as you diagnosed. + +<p>I'll look into the other two questions. + + + + + +<hr> +<pre> +Date: Thu, 1 Feb 2001 15:12:41 -0400 +Subject: Re: [Fwd: bad string, bad string] +</pre> + +<p>We've been removing implicit conversion operators because they +_always_ lead to trouble. Usually they make it harder to pick the +right function when overloading is involved and in the past they have +led to huge performance suckage because we ended up doing conversions +when we didn't need to because the implicit operator made us pick the +wrong function. + +<p>It's borderline when the class implements something that is <strong>so</strong> +close, as with a guaranteed flat string or an <span class="code">nsCOMPtr</span> ... but the +general recommendation is to avoid implicit conversions. + +<p>See bug #53057. + + + + + +<hr> +<pre> +Date: Tue, 6 Feb 2001 18:52:23 -0400 +Subject: seeking review for bug #57087 +</pre> + +<p> bug: + <a class="exact-uri" href="http://bugzilla.mozilla.org/show_bug.cgi?id=57087">http://bugzilla.mozilla.org/show_bug.cgi?id=57087</a> + + patch: + <a class="exact-uri" href="http://bugzilla.mozilla.org/showattachment.cgi?attach_id=24576">http://bugzilla.mozilla.org/showattachment.cgi?attach_id=24576</a> + +<p>This patch is supposed to add the ability to define very long literal +strings more easily by breaking lines, e.g., + +<div class="source-code"> +<pre> +NS_MULTILINE_LITERAL( NS_L("This is the start of a very long line") + NS_L(" which actually continues across") + NS_L(" a couple more.") ) +</pre> +</div> + +<p>The main danger in this scheme is callers who omit the inner <span class="code">NS_L</span> +wrapping. Though I believe this will be caught at compile time as the +wrong type initializer. + +<p>Seeking input from everybody, and waterson in particular. + + + + + +<hr> +<pre> +Date: Wed, 14 Feb 2001 16:09:10 -0400 +Subject: Re: Question... +</pre> + +<p>There are some utilities in "xpcom/ds/nsReadableUtils.h". In +particular, if you want to get back a new heap-allocated ASCII string +with the minimal work, you would say + +<div class="source-code"> +<pre> +PRUnichar* sourceChars = ...; + +char* destChars = ToNewCString(nsLiteralString(sourceChars)); +</pre> +</div> + + +<p>It's more efficient if you happen to already know the length. If you +don't, don't bother counting, that's what I'll do in the constructor +for <span class="code">nsLiteralString</span>. If you do, then call like this + +<div class="source-code"> +<pre> +destChars = ToNewCString( nsLiteralString(sourceChars, length) ); +</pre> +</div> + +<p>Other routines in that file will help you if, for instance, you wanted +to translate into a buffer you had already allocated. + +<p>Hope this helps, + + + + + +<hr> +<pre> +Date: Fri, 23 Feb 2001 03:12:58 -0400 +Subject: string snippet +</pre> + +<div class="source-code"> +<pre> +nsCString aInput; + + + +nsReadingIterator<char> search_start; +aInput.BeginReading(search_start); + +nsReadingIterator<char> search_end; +aInput.EndReading(search_end); + +if ( FindCharInReadable(':', search_start, search_end) ) + { + ++search_start; + return ToNewCString( Substring(aInput, search_start, search_end) +); + } +</pre> +</div> + + + + + + +<hr> +<pre> +Date: Wed, 7 Mar 2001 19:44:08 -0400 +Subject: string help +</pre> + +<p>Here you go, Mike: + + http://scottcollins.net/journal/discussion/mjudge-scratch.cpp + + + + + + +<hr> +<pre> +Date: Fri, 9 Mar 2001 20:56:07 -0400 +Subject: Re: string assertions +</pre> + +<p>If you get an iterator into a string and you advance it all the way to +the end of the string, and then <strong>keep</strong> trying to advance it, you hit +this assert. This could happen, for example if you tried to copy 10 +characters out of a 9 character string. I've tried to make this +impossible to get to. As far as I know, all my routines trim requests +in advance of manipulating iterators. When you see this, you should +get the stack. That will take you right to the bad spot. + + + + + +<hr> +<pre> +Date: Sat, 31 Mar 2001 11:04:03 -0400 +Subject: Re: Sun bustage and string advice +</pre> + +<p>You do know you are comparing two pointers now? It seems unlikely +those two pointers would ever be the same pointer. You probably want +to say something like + +<div class="source-code"> +<pre> +NS_LITERAL_STRING("foo").Equals(aTopic) // or + +NS_LITERAL_STRING("foo") == nsLiteralString(aTopic) +</pre> +</div> + +<p>...so that you compare the <strong>contents</strong> of two strings. Right now, +you're just testing to see if two pointers both point to the same +location in memory. A lot of people make this mistake. I would like +to make it obvious to people that comparing two pointers does not +compare strings. Can you tell me what gave you that impression so +that I can figure out how to better educate people not to do this? By +the way, it's not that I don't <strong>want</strong> to make this compare two +strings; it's that in C++, you can't override operations for built-in +types. And pointers are built-in types. So I can't make +<span class="code">operator==(const PRUnichar*, const PRUnichar*)</span> do anything different +than it already does, which is the same thing it does for any other +pointer. + + + + + + +</div> + + + +<!-- .................................................................End Matter --> + + + + </body> +</html> diff --git a/src/libs/xpcom18a4/xpcom/string/public/.cvsignore b/src/libs/xpcom18a4/xpcom/string/public/.cvsignore new file mode 100644 index 00000000..f3c7a7c5 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/src/libs/xpcom18a4/xpcom/string/public/Makefile.in b/src/libs/xpcom18a4/xpcom/string/public/Makefile.in new file mode 100644 index 00000000..d3582bcc --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/Makefile.in @@ -0,0 +1,86 @@ +# vim:set ts=8 sw=8 sts=8 noet: +# +# ***** 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 +# Netscape Communications. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Johnny Stenback <jst@netscape.com> (original author) +# Scott Collins <scc@mozilla.org> +# +# Alternatively, the contents of this file may be used under the terms of +# either of 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 ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = string + +EXPORTS = \ + nsAString.h \ + nsAlgorithm.h \ + nsCharTraits.h \ + nsDependentString.h \ + nsDependentSubstring.h \ + nsLiteralString.h \ + nsObsoleteAString.h \ + nsPrintfCString.h \ + nsPromiseFlatString.h \ + nsReadableUtils.h \ + nsString.h \ + nsStringFwd.h \ + nsStringIterator.h \ + nsSubstring.h \ + nsSubstringTuple.h \ + nsTAString.h \ + nsTDependentString.h \ + nsTDependentSubstring.h \ + nsTObsoleteAString.h \ + nsTPromiseFlatString.h \ + nsTString.h \ + nsTSubstring.h \ + nsTSubstringTuple.h \ + nsUTF8Utils.h \ + nsXPIDLString.h \ + string-template-def-unichar.h \ + string-template-def-char.h \ + string-template-undef.h \ + $(NULL) + +SDK_HEADERS = \ + nsStringAPI.h \ + nsEmbedString.h \ + $(NULL) + +include $(topsrcdir)/config/rules.mk diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsAString.h b/src/libs/xpcom18a4/xpcom/string/public/nsAString.h new file mode 100644 index 00000000..3675989c --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsAString.h @@ -0,0 +1,96 @@ +/* -*- 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 nsAString_h___ +#define nsAString_h___ + +#ifndef nsStringFwd_h___ +#include "nsStringFwd.h" +#endif + +#ifndef nsStringIterator_h___ +#include "nsStringIterator.h" +#endif + +#ifndef nsObsoleteAString_h___ +#include "nsObsoleteAString.h" +#endif + +// If some platform(s) can't handle our template that matches literal strings, +// then we'll disable it on those platforms. +#ifndef NS_DISABLE_LITERAL_TEMPLATE +# if (defined(_MSC_VER) && (_MSC_VER < 1310)) || (defined(__SUNPRO_CC) & (__SUNPRO_CC < 0x560)) || (defined(__HP_aCC) && (__HP_aCC <= 012100)) +# define NS_DISABLE_LITERAL_TEMPLATE +# endif +#endif /* !NS_DISABLE_LITERAL_TEMPLATE */ + +#include <string.h> + + // declare nsAString +#include "string-template-def-unichar.h" +#include "nsTAString.h" +#include "string-template-undef.h" + + + // declare nsACString +#include "string-template-def-char.h" +#include "nsTAString.h" +#include "string-template-undef.h" + + + /** + * ASCII case-insensitive comparator. (for Unicode case-insensitive + * comparision, see nsUnicharUtils.h) + */ +class NS_COM nsCaseInsensitiveCStringComparator + : public nsCStringComparator + { + public: + typedef char char_type; + + virtual int operator()( const char_type*, const char_type*, PRUint32 length ) const; + virtual int operator()( char_type, char_type ) const; + }; + + + // included here for backwards compatibility +#ifndef nsSubstringTuple_h___ +#include "nsSubstringTuple.h" +#endif + +#endif // !defined(nsAString_h___) diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsAlgorithm.h b/src/libs/xpcom18a4/xpcom/string/public/nsAlgorithm.h new file mode 100644 index 00000000..e81e6f57 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsAlgorithm.h @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott Collins <scc@mozilla.org> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 nsAlgorithm_h___ +#define nsAlgorithm_h___ + +#ifndef nsCharTraits_h___ +#include "nsCharTraits.h" + // for |nsCharSourceTraits|, |nsCharSinkTraits| +#endif + +#ifndef prtypes_h___ +#include "prtypes.h" + // for |PRUint32|... +#endif + +#ifndef nsDebug_h___ +#include "nsDebug.h" + // for NS_ASSERTION +#endif + +template <class T> +inline +const T& +NS_MIN( const T& a, const T& b ) + { + return b < a ? b : a; + } + +template <class T> +inline +const T& +NS_MAX( const T& a, const T& b ) + { + return a > b ? a : b; + } + +template <class InputIterator, class T> +inline +PRUint32 +NS_COUNT( InputIterator& first, const InputIterator& last, const T& value ) + { + PRUint32 result = 0; + for ( ; first != last; ++first ) + if ( *first == value ) + ++result; + return result; + } + +template <class InputIterator, class OutputIterator> +inline +OutputIterator& +copy_string( InputIterator& first, const InputIterator& last, OutputIterator& result ) + { + typedef nsCharSourceTraits<InputIterator> source_traits; + typedef nsCharSinkTraits<OutputIterator> sink_traits; + + while ( first != last ) + { + PRInt32 count_copied = PRInt32(sink_traits::write(result, source_traits::read(first), source_traits::readable_distance(first, last))); + NS_ASSERTION(count_copied > 0, "|copy_string| will never terminate"); + source_traits::advance(first, count_copied); + } + + return result; + } + +template <class InputIterator, class OutputIterator> +OutputIterator& +copy_string_backward( const InputIterator& first, InputIterator& last, OutputIterator& result ) + { + while ( first != last ) + { + last.normalize_backward(); + result.normalize_backward(); + PRUint32 lengthToCopy = PRUint32( NS_MIN(last.size_backward(), result.size_backward()) ); + if ( first.fragment().mStart == last.fragment().mStart ) + lengthToCopy = NS_MIN(lengthToCopy, PRUint32(last.get() - first.get())); + + NS_ASSERTION(lengthToCopy, "|copy_string_backward| will never terminate"); + +#ifdef _MSC_VER + // XXX Visual C++ can't stomach 'typename' where it rightfully should + nsCharTraits<OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy); +#else + nsCharTraits<typename OutputIterator::value_type>::move(result.get()-lengthToCopy, last.get()-lengthToCopy, lengthToCopy); +#endif + + last.advance( -PRInt32(lengthToCopy) ); + result.advance( -PRInt32(lengthToCopy) ); + } + + return result; + } + +#endif // !defined(nsAlgorithm_h___) diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsCharTraits.h b/src/libs/xpcom18a4/xpcom/string/public/nsCharTraits.h new file mode 100644 index 00000000..e7713c95 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsCharTraits.h @@ -0,0 +1,784 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott Collins <scc@mozilla.org> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 nsCharTraits_h___ +#define nsCharTraits_h___ + +#include <ctype.h> + // for |EOF|, |WEOF| + +#define FORCED_CPP_2BYTE_WCHAR_T + // disable special optimizations for now through this hack + +#if defined(HAVE_CPP_2BYTE_WCHAR_T) && !defined(FORCED_CPP_2BYTE_WCHAR_T) +#define USE_CPP_WCHAR_FUNCS +#endif + +#ifdef USE_CPP_WCHAR_FUNCS +#include <wchar.h> + // for |wmemset|, et al +#endif + +#include <string.h> + // for |memcpy|, et al + +#ifndef nscore_h___ +#include "nscore.h" + // for |PRUnichar| +#endif + +#ifndef nsDebug_h__ +#include "nsDebug.h" + // for NS_ASSERTION +#endif + +#ifdef HAVE_CPP_BOOL + typedef bool nsCharTraits_bool; +#else + typedef PRBool nsCharTraits_bool; +#endif + +template <class CharT> struct nsCharTraits {}; + +NS_SPECIALIZE_TEMPLATE +struct nsCharTraits<PRUnichar> + { + typedef PRUnichar char_type; + typedef PRUint16 unsigned_char_type; + typedef char incompatible_char_type; + + NS_COM static const char_type *sEmptyBuffer; + + static + void + assign( char_type& lhs, char_type rhs ) + { + lhs = rhs; + } + + + // integer representation of characters: + +#ifdef USE_CPP_WCHAR_FUNCS + typedef wint_t int_type; +#else + typedef int int_type; +#endif + + static + char_type + to_char_type( int_type c ) + { + return char_type(c); + } + + static + int_type + to_int_type( char_type c ) + { + return int_type( NS_STATIC_CAST(unsigned_char_type, c) ); + } + + static + nsCharTraits_bool + eq_int_type( int_type lhs, int_type rhs ) + { + return lhs == rhs; + } + + + // |char_type| comparisons: + + static + nsCharTraits_bool + eq( char_type lhs, char_type rhs ) + { + return lhs == rhs; + } + + static + nsCharTraits_bool + lt( char_type lhs, char_type rhs ) + { + return lhs < rhs; + } + + + // operations on s[n] arrays: + + static + char_type* + move( char_type* s1, const char_type* s2, size_t n ) + { + return NS_STATIC_CAST(char_type*, memmove(s1, s2, n * sizeof(char_type))); + } + + static + char_type* + copy( char_type* s1, const char_type* s2, size_t n ) + { + return NS_STATIC_CAST(char_type*, memcpy(s1, s2, n * sizeof(char_type))); + } + + static + char_type* + copyASCII( char_type* s1, const char* s2, size_t n ) + { + for (char_type* s = s1; n--; ++s, ++s2) { + NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character"); + *s = *s2; + } + return s1; + } + + static + char_type* + assign( char_type* s, size_t n, char_type c ) + { +#ifdef USE_CPP_WCHAR_FUNCS + return NS_STATIC_CAST(char_type*, wmemset(s, to_int_type(c), n)); +#else + char_type* result = s; + while ( n-- ) + assign(*s++, c); + return result; +#endif + } + + static + int + compare( const char_type* s1, const char_type* s2, size_t n ) + { +#ifdef USE_CPP_WCHAR_FUNCS + return wmemcmp(s1, s2, n); +#else + for ( ; n--; ++s1, ++s2 ) + { + if ( !eq(*s1, *s2) ) + return to_int_type(*s1) - to_int_type(*s2); + } + + return 0; +#endif + } + + static + int + compareASCII( const char_type* s1, const char* s2, size_t n ) + { + for ( ; n--; ++s1, ++s2 ) + { + NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character"); + if ( !eq_int_type(to_int_type(*s1), to_int_type(*s2)) ) + return to_int_type(*s1) - to_int_type(*s2); + } + + return 0; + } + + // this version assumes that s2 is null-terminated and s1 has length n. + // if s1 is shorter than s2 then we return -1; if s1 is longer than s2, + // we return 1. + static + int + compareASCIINullTerminated( const char_type* s1, size_t n, const char* s2 ) + { + for ( ; n--; ++s1, ++s2 ) + { + if ( !*s2 ) + return 1; + NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character"); + if ( !eq_int_type(to_int_type(*s1), to_int_type(*s2)) ) + return to_int_type(*s1) - to_int_type(*s2); + } + + if ( *s2 ) + return -1; + + return 0; + } + + /** + * Convert c to its lower-case form, but only if the lower-case form is + * ASCII. Otherwise leave it alone. + * + * There are only two non-ASCII Unicode characters whose lowercase + * equivalents are ASCII: KELVIN SIGN and LATIN CAPITAL LETTER I WITH + * DOT ABOVE. So it's a simple matter to handle those explicitly. + */ + static + char_type + ASCIIToLower( char_type c ) + { + if (c < 0x100) + return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; + else + { + if (c == 0x212A) // KELVIN SIGN + return 'k'; + if (c == 0x0130) // LATIN CAPITAL LETTER I WITH DOT ABOVE + return 'i'; + return c; + } + } + + static + int + compareLowerCaseToASCII( const char_type* s1, const char* s2, size_t n ) + { + for ( ; n--; ++s1, ++s2 ) + { + NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character"); + NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'), + "Unexpected uppercase character"); + char_type lower_s1 = ASCIIToLower(*s1); + if ( lower_s1 != to_char_type(*s2) ) + return to_int_type(lower_s1) - to_int_type(*s2); + } + + return 0; + } + + // this version assumes that s2 is null-terminated and s1 has length n. + // if s1 is shorter than s2 then we return -1; if s1 is longer than s2, + // we return 1. + static + int + compareLowerCaseToASCIINullTerminated( const char_type* s1, size_t n, const char* s2 ) + { + for ( ; n--; ++s1, ++s2 ) + { + if ( !*s2 ) + return 1; + NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character"); + NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'), + "Unexpected uppercase character"); + char_type lower_s1 = ASCIIToLower(*s1); + if ( lower_s1 != to_char_type(*s2) ) + return to_int_type(lower_s1) - to_int_type(*s2); + } + + if ( *s2 ) + return -1; + + return 0; + } + + static + size_t + length( const char_type* s ) + { +#ifdef USE_CPP_WCHAR_FUNCS + return wcslen(s); +#else + size_t result = 0; + while ( !eq(*s++, char_type(0)) ) + ++result; + return result; +#endif + } + + static + const char_type* + find( const char_type* s, size_t n, char_type c ) + { +#ifdef USE_CPP_WCHAR_FUNCS + return NS_REINTERPRET_CAST(const char_type*, wmemchr(s, to_int_type(c), n)); +#else + while ( n-- ) + { + if ( eq(*s, c) ) + return s; + ++s; + } + + return 0; +#endif + } + +#if 0 + // I/O related: + + typedef streamoff off_type; + typedef streampos pos_type; + typedef mbstate_t state_type; + + static + int_type + eof() + { +#ifdef USE_CPP_WCHAR_FUNCS + return WEOF; +#else + return EOF; +#endif + } + + static + int_type + not_eof( int_type c ) + { + return eq_int_type(c, eof()) ? ~eof() : c; + } + + // static state_type get_state( pos_type ); +#endif + }; + +NS_SPECIALIZE_TEMPLATE +struct nsCharTraits<char> + { + typedef char char_type; + typedef unsigned char unsigned_char_type; + typedef PRUnichar incompatible_char_type; + + NS_COM static const char_type *sEmptyBuffer; + + static + void + assign( char_type& lhs, char_type rhs ) + { + lhs = rhs; + } + + + // integer representation of characters: + + typedef int int_type; + + static + char_type + to_char_type( int_type c ) + { + return char_type(c); + } + + static + int_type + to_int_type( char_type c ) + { + return int_type( NS_STATIC_CAST(unsigned_char_type, c) ); + } + + static + nsCharTraits_bool + eq_int_type( int_type lhs, int_type rhs ) + { + return lhs == rhs; + } + + + // |char_type| comparisons: + + static + nsCharTraits_bool + eq( char_type lhs, char_type rhs ) + { + return lhs == rhs; + } + + static + nsCharTraits_bool + lt( char_type lhs, char_type rhs ) + { + return lhs < rhs; + } + + + // operations on s[n] arrays: + + static + char_type* + move( char_type* s1, const char_type* s2, size_t n ) + { + return NS_STATIC_CAST(char_type*, memmove(s1, s2, n * sizeof(char_type))); + } + + static + char_type* + copy( char_type* s1, const char_type* s2, size_t n ) + { + return NS_STATIC_CAST(char_type*, memcpy(s1, s2, n * sizeof(char_type))); + } + + static + char_type* + copyASCII( char_type* s1, const char* s2, size_t n ) + { + return copy(s1, s2, n); + } + + static + char_type* + assign( char_type* s, size_t n, char_type c ) + { + return NS_STATIC_CAST(char_type*, memset(s, to_int_type(c), n)); + } + + static + int + compare( const char_type* s1, const char_type* s2, size_t n ) + { + return memcmp(s1, s2, n); + } + + static + int + compareASCII( const char_type* s1, const char* s2, size_t n ) + { +#ifdef DEBUG + for (size_t i = 0; i < n; ++i) + { + NS_ASSERTION(!(s2[i] & ~0x7F), "Unexpected non-ASCII character"); + } +#endif + return compare(s1, s2, n); + } + + // this version assumes that s2 is null-terminated and s1 has length n. + // if s1 is shorter than s2 then we return -1; if s1 is longer than s2, + // we return 1. + static + int + compareASCIINullTerminated( const char_type* s1, size_t n, const char* s2 ) + { + // can't use strcmp here because we don't want to stop when s1 + // contains a null + for ( ; n--; ++s1, ++s2 ) + { + if ( !*s2 ) + return 1; + NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character"); + if ( *s1 != *s2 ) + return to_int_type(*s1) - to_int_type(*s2); + } + + if ( *s2 ) + return -1; + + return 0; + } + + /** + * Convert c to its lower-case form, but only if c is ASCII. + */ + static + char_type + ASCIIToLower( char_type c ) + { + return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c; + } + + static + int + compareLowerCaseToASCII( const char_type* s1, const char* s2, size_t n ) + { + for ( ; n--; ++s1, ++s2 ) + { + NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character"); + NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'), + "Unexpected uppercase character"); + char_type lower_s1 = ASCIIToLower(*s1); + if ( lower_s1 != *s2 ) + return to_int_type(lower_s1) - to_int_type(*s2); + } + return 0; + } + + // this version assumes that s2 is null-terminated and s1 has length n. + // if s1 is shorter than s2 then we return -1; if s1 is longer than s2, + // we return 1. + static + int + compareLowerCaseToASCIINullTerminated( const char_type* s1, size_t n, const char* s2 ) + { + for ( ; n--; ++s1, ++s2 ) + { + if ( !*s2 ) + return 1; + NS_ASSERTION(!(*s2 & ~0x7F), "Unexpected non-ASCII character"); + NS_ASSERTION(!(*s2 >= 'A' && *s2 <= 'Z'), + "Unexpected uppercase character"); + char_type lower_s1 = ASCIIToLower(*s1); + if ( lower_s1 != *s2 ) + return to_int_type(lower_s1) - to_int_type(*s2); + } + + if ( *s2 ) + return -1; + + return 0; + } + + static + size_t + length( const char_type* s ) + { + return strlen(s); + } + + static + const char_type* + find( const char_type* s, size_t n, char_type c ) + { + return NS_REINTERPRET_CAST(const char_type*, memchr(s, to_int_type(c), n)); + } + +#if 0 + // I/O related: + + typedef streamoff off_type; + typedef streampos pos_type; + typedef mbstate_t state_type; + + static + int_type + eof() + { + return EOF; + } + + static + int_type + not_eof( int_type c ) + { + return eq_int_type(c, eof()) ? ~eof() : c; + } + + // static state_type get_state( pos_type ); +#endif + }; + +template <class InputIterator> +struct nsCharSourceTraits + { + typedef typename InputIterator::difference_type difference_type; + + static + PRUint32 + readable_distance( const InputIterator& first, const InputIterator& last ) + { + // assumes single fragment + return last.get() - first.get(); + } + + static + const typename InputIterator::value_type* + read( const InputIterator& iter ) + { + return iter.get(); + } + + static + void + advance( InputIterator& s, difference_type n ) + { + s.advance(n); + } + }; + +#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION + +template <class CharT> +struct nsCharSourceTraits<CharT*> + { + typedef ptrdiff_t difference_type; + + static + PRUint32 + readable_distance( CharT* s ) + { + return PRUint32(nsCharTraits<CharT>::length(s)); +// return numeric_limits<PRUint32>::max(); + } + + static + PRUint32 + readable_distance( CharT* first, CharT* last ) + { + return PRUint32(last-first); + } + + static + const CharT* + read( CharT* s ) + { + return s; + } + + static + void + advance( CharT*& s, difference_type n ) + { + s += n; + } + }; + +#else + +NS_SPECIALIZE_TEMPLATE +struct nsCharSourceTraits<const char*> + { + typedef ptrdiff_t difference_type; + + static + PRUint32 + readable_distance( const char* s ) + { + return PRUint32(nsCharTraits<char>::length(s)); +// return numeric_limits<PRUint32>::max(); + } + + static + PRUint32 + readable_distance( const char* first, const char* last ) + { + return PRUint32(last-first); + } + + static + const char* + read( const char* s ) + { + return s; + } + + static + void + advance( const char*& s, difference_type n ) + { + s += n; + } + }; + + +NS_SPECIALIZE_TEMPLATE +struct nsCharSourceTraits<const PRUnichar*> + { + typedef ptrdiff_t difference_type; + + static + PRUint32 + readable_distance( const PRUnichar* s ) + { + return PRUint32(nsCharTraits<PRUnichar>::length(s)); +// return numeric_limits<PRUint32>::max(); + } + + static + PRUint32 + readable_distance( const PRUnichar* first, const PRUnichar* last ) + { + return PRUint32(last-first); + } + + static + const PRUnichar* + read( const PRUnichar* s ) + { + return s; + } + + static + void + advance( const PRUnichar*& s, difference_type n ) + { + s += n; + } + }; + +#endif + + +template <class OutputIterator> +struct nsCharSinkTraits + { + static + PRUint32 + write( OutputIterator& iter, const typename OutputIterator::value_type* s, PRUint32 n ) + { + return iter.write(s, n); + } + }; + +#ifdef HAVE_CPP_PARTIAL_SPECIALIZATION + +template <class CharT> +struct nsCharSinkTraits<CharT*> + { + static + PRUint32 + write( CharT*& iter, const CharT* s, PRUint32 n ) + { + nsCharTraits<CharT>::move(iter, s, n); + iter += n; + return n; + } + }; + +#else + +NS_SPECIALIZE_TEMPLATE +struct nsCharSinkTraits<char*> + { + static + PRUint32 + write( char*& iter, const char* s, PRUint32 n ) + { + nsCharTraits<char>::move(iter, s, n); + iter += n; + return n; + } + }; + +NS_SPECIALIZE_TEMPLATE +struct nsCharSinkTraits<PRUnichar*> + { + static + PRUint32 + write( PRUnichar*& iter, const PRUnichar* s, PRUint32 n ) + { + nsCharTraits<PRUnichar>::move(iter, s, n); + iter += n; + return n; + } + }; + +#endif + +#endif // !defined(nsCharTraits_h___) diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsDependentString.h b/src/libs/xpcom18a4/xpcom/string/public/nsDependentString.h new file mode 100644 index 00000000..22e05b31 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsDependentString.h @@ -0,0 +1,60 @@ +/* -*- 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 nsDependentString_h___ +#define nsDependentString_h___ + +#ifndef nsString_h___ +#include "nsString.h" +#endif + +#ifndef nsDebug_h___ +#include "nsDebug.h" +#endif + + // declare nsDependentString +#include "string-template-def-unichar.h" +#include "nsTDependentString.h" +#include "string-template-undef.h" + + // declare nsDependentCString +#include "string-template-def-char.h" +#include "nsTDependentString.h" +#include "string-template-undef.h" + +#endif /* !defined(nsDependentString_h___) */ diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsDependentSubstring.h b/src/libs/xpcom18a4/xpcom/string/public/nsDependentSubstring.h new file mode 100644 index 00000000..c6459436 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsDependentSubstring.h @@ -0,0 +1,56 @@ +/* -*- 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 nsDependentSubstring_h___ +#define nsDependentSubstring_h___ + +#ifndef nsSubstring_h___ +#include "nsSubstring.h" +#endif + + // declare nsDependentSubstring +#include "string-template-def-unichar.h" +#include "nsTDependentSubstring.h" +#include "string-template-undef.h" + + // declare nsDependentCSubstring +#include "string-template-def-char.h" +#include "nsTDependentSubstring.h" +#include "string-template-undef.h" + +#endif /* !defined(nsDependentSubstring_h___) */ diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsEmbedString.h b/src/libs/xpcom18a4/xpcom/string/public/nsEmbedString.h new file mode 100644 index 00000000..7af03ee3 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsEmbedString.h @@ -0,0 +1,158 @@ +/* -*- 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 <jaggernaut@netscape.com>. + * + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. 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 nsEmbedString_h___ +#define nsEmbedString_h___ + +#include "nsStringAPI.h" + +class nsEmbedString : public nsStringContainer + { + public: + typedef nsEmbedString self_type; + typedef nsAString abstract_string_type; + + nsEmbedString() + { + NS_StringContainerInit(*this); + } + + nsEmbedString(const self_type& aString) +#ifdef VBOX + : nsStringContainer() +#endif + { + 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; + } + + 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; } + }; + +class nsEmbedCString : public nsCStringContainer + { + public: + typedef nsEmbedCString self_type; + typedef nsACString abstract_string_type; + + nsEmbedCString() +#ifdef VBOX + : nsCStringContainer() +#endif + { + NS_CStringContainerInit(*this); + } + + nsEmbedCString(const self_type& aString) +#ifdef VBOX + : nsCStringContainer() +#endif + { + NS_CStringContainerInit(*this); + NS_CStringCopy(*this, aString); + } + + explicit + nsEmbedCString(const abstract_string_type& aReadable) +#ifdef VBOX + : nsCStringContainer() +#endif + { + NS_CStringContainerInit(*this); + NS_CStringCopy(*this, aReadable); + } + + explicit + nsEmbedCString(const char_type* aData, size_type aLength = PR_UINT32_MAX) +#ifdef VBOX + : nsCStringContainer() +#endif + { + 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; + } + + 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; } + }; + +#endif // !defined(nsEmbedString_h___) diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsLiteralString.h b/src/libs/xpcom18a4/xpcom/string/public/nsLiteralString.h new file mode 100644 index 00000000..ba536297 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsLiteralString.h @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 + * Netscape Communications. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott Collins <scc@mozilla.org> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 nsLiteralString_h___ +#define nsLiteralString_h___ + +#ifndef nscore_h___ +#include "nscore.h" +#endif + +#ifndef nsDependentString_h___ +#include "nsDependentString.h" +#endif + + +#if 0 +inline +const nsDependentString +literal_string( const nsAString::char_type* aPtr ) + { + return nsDependentString(aPtr); + } + +inline +const nsDependentString +literal_string( const nsAString::char_type* aPtr, PRUint32 aLength ) + { + return nsDependentString(aPtr, aLength); + } + +inline +const nsDependentCString +literal_string( const nsACString::char_type* aPtr ) + { + return nsDependentCString(aPtr); + } + +inline +const nsDependentCString +literal_string( const nsACString::char_type* aPtr, PRUint32 aLength ) + { + return nsDependentCString(aPtr, aLength); + } +#endif + +#ifdef HAVE_CPP_2BYTE_WCHAR_T + #define NS_LL(s) L##s + #define NS_MULTILINE_LITERAL_STRING(s) nsDependentString(NS_REINTERPRET_CAST(const nsAString::char_type*, s), PRUint32((sizeof(s)/sizeof(wchar_t))-1)) + #define NS_MULTILINE_LITERAL_STRING_INIT(n,s) n(NS_REINTERPRET_CAST(const nsAString::char_type*, s), PRUint32((sizeof(s)/sizeof(wchar_t))-1)) + #define NS_NAMED_MULTILINE_LITERAL_STRING(n,s) const nsDependentString n(NS_REINTERPRET_CAST(const nsAString::char_type*, s), PRUint32((sizeof(s)/sizeof(wchar_t))-1)) + typedef nsDependentString nsLiteralString; +#else + #define NS_LL(s) s + #define NS_MULTILINE_LITERAL_STRING(s) NS_ConvertASCIItoUTF16(s, PRUint32(sizeof(s)-1)) + #define NS_MULTILINE_LITERAL_STRING_INIT(n,s) n(s, PRUint32(sizeof(s)-1)) + #define NS_NAMED_MULTILINE_LITERAL_STRING(n,s) const NS_ConvertASCIItoUTF16 n(s, PRUint32(sizeof(s)-1)) + typedef NS_ConvertASCIItoUTF16 nsLiteralString; +#endif + +/* + * Macro arguments used in concatenation or stringification won't be expanded. + * Therefore, in order for |NS_L(FOO)| to work as expected (which is to expand + * |FOO| before doing whatever |NS_L| needs to do to it) a helper macro needs + * to be inserted in between to allow the macro argument to expand. + * See "3.10.6 Separate Expansion of Macro Arguments" of the CPP manual for a + * more accurate and precise explanation. + */ + +#define NS_L(s) NS_LL(s) + +#define NS_LITERAL_STRING(s) NS_STATIC_CAST(const nsAFlatString&, NS_MULTILINE_LITERAL_STRING(NS_LL(s))) +#define NS_LITERAL_STRING_INIT(n,s) NS_MULTILINE_LITERAL_STRING_INIT(n, NS_LL(s)) +#define NS_NAMED_LITERAL_STRING(n,s) NS_NAMED_MULTILINE_LITERAL_STRING(n, NS_LL(s)) + +#define NS_LITERAL_CSTRING(s) NS_STATIC_CAST(const nsDependentCString&, nsDependentCString(s, PRUint32(sizeof(s)-1))) +#define NS_LITERAL_CSTRING_INIT(n,s) n(s, PRUint32(sizeof(s)-1)) +#define NS_NAMED_LITERAL_CSTRING(n,s) const nsDependentCString n(s, PRUint32(sizeof(s)-1)) + +typedef nsDependentCString nsLiteralCString; + +#endif /* !defined(nsLiteralString_h___) */ diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsObsoleteAString.h b/src/libs/xpcom18a4/xpcom/string/public/nsObsoleteAString.h new file mode 100644 index 00000000..00d5892e --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsObsoleteAString.h @@ -0,0 +1,102 @@ +/* -*- 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 nsObsoleteAString_h___ +#define nsObsoleteAString_h___ + +/* + STRING INTERNALS + + This file defines nsObsoleteAString and nsObsoleteACString. These are + abstract classes (interfaces), containing only virtual functions + corresponding to the FROZEN nsA[C]String classes. They exist to provide + the new non-abstract nsA[C]String classes with a mechanism to maintain + backwards binary compatability. + + From a binary point-of-view, the new nsA[C]String classes appear to have a + vtable pointer to the vtable of nsObsoleteA[C]StringThunk. + nsObsoleteA[C]StringThunk is a subclass of nsObsoleteA[C]String that serves + as a simple bridge between the virtual functions that make up the FROZEN + nsA[C]String contract and the new ns[C]Substring, which is now our only + subclass of nsA[C]String. + + The methods on the new nsA[C]String are now all non-virtual. This reduces + codesize at the callsite, and reduces the number of memory dereferences and + jumps required to invoke a method on nsA[C]String. The result is improved + performance and reduced codesize. However, to maintain binary + compatibility, each method on nsA[C]String must check the value of its + vtable to determine if it corresponds to the built-in implementation of + nsObsoleteA[C]String (i.e., the address of the canonical vtable). If it + does, then the vtable can be ignored, and the nsA[C]String object (i.e., + |this|) can be cast to ns[C]Substring directly. In which case, the + nsA[C]String methods can be satisfied by invoking the corresponding methods + directly on ns[C]Substring. If the vtable address does not correspond to + the built-in implementation, then the virtual functions on + nsObsoleteA[C]String must be invoked instead. + + So, if a nsA[C]String reference corresponds to an external implementation + (such as the old nsEmbed[C]String that shipped with previous versions of + Mozilla), then methods invoked on that nsA[C]String will still act like + virtual function calls. This ensures binary compatibility while avoiding + virtual function calls in most cases. + + Finally, nsObsoleteA[C]String (i.e., the FROZEN nsA[C]String vtable) is + now a DEPRECATED interface. See nsStringAPI.h and nsEmbedString.h for + the new preferred way to access nsA[C]String references in an external + component or Gecko embedding application. + */ + +#ifndef nsStringFwd_h___ +#include "nsStringFwd.h" +#endif + +#ifndef nscore_h___ +#include "nscore.h" +#endif + + // declare nsObsoleteAString +#include "string-template-def-unichar.h" +#include "nsTObsoleteAString.h" +#include "string-template-undef.h" + + // declare nsObsoleteACString +#include "string-template-def-char.h" +#include "nsTObsoleteAString.h" +#include "string-template-undef.h" + +#endif // !defined(nsObsoleteAString_h___) diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsPrintfCString.h b/src/libs/xpcom18a4/xpcom/string/public/nsPrintfCString.h new file mode 100644 index 00000000..3f3d04d3 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsPrintfCString.h @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 nsPrintfCString_h___ +#define nsPrintfCString_h___ + +#ifndef nsString_h___ +#include "nsString.h" +#endif + + + /** + * |nsPrintfCString| lets you use a formated |printf| string as an |const nsACString|. + * + * myCStr += nsPrintfCString("%f", 13.917); + * // ...a general purpose substitute for |AppendFloat| + * + * For longer patterns, you'll want to use the constructor that takes a length + * + * nsPrintfCString(128, "%f, %f, %f, %f, %f, %f, %f, %i, %f", x, y, z, 3.2, j, k, l, 3, 3.1); + * + * Exceding the default size (which you must specify in the constructor, it is not determined) + * causes an allocation, so avoid that. If your formatted string exceeds the allocated space, it is + * cut off at the size of the buffer, no error is reported (and no out-of-bounds writing occurs). + * This class is intended to be useful for numbers and short + * strings, not arbitrary formatting of other strings (e.g., with %s). There is currently no + * wide version of this class, since wide |printf| is not generally available. That means + * to get a wide version of your formatted data, you must, e.g., + * + * CopyASCIItoUTF16(nsPrintfCString("%f", 13.917"), myStr); + * + * That's another good reason to avoid this class for anything but numbers ... as strings can be + * much more efficiently handled with |NS_LITERAL_[C]STRING| and |nsLiteral[C]String|. + */ + +class NS_COM nsPrintfCString : public nsCString + { + typedef nsCString string_type; + + enum { kLocalBufferSize=15 }; + // ought to be large enough for most things ... a |long long| needs at most 20 (so you'd better ask) + // pinkerton suggests 7. We should measure and decide what's appropriate + + public: + // XXX don't these need to be declared CDECL ?? + explicit nsPrintfCString( const char_type* format, ... ); + nsPrintfCString( size_type n, const char_type* format, ...); + + private: + char_type mLocalBuffer[ kLocalBufferSize + 1 ]; + }; + +#endif // !defined(nsPrintfCString_h___) diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsPromiseFlatString.h b/src/libs/xpcom18a4/xpcom/string/public/nsPromiseFlatString.h new file mode 100644 index 00000000..b98aa1a2 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsPromiseFlatString.h @@ -0,0 +1,56 @@ +/* -*- 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 nsPromiseFlatString_h___ +#define nsPromiseFlatString_h___ + +#ifndef nsString_h___ +#include "nsString.h" +#endif + + // declare nsPromiseFlatString +#include "string-template-def-unichar.h" +#include "nsTPromiseFlatString.h" +#include "string-template-undef.h" + + // declare nsPromiseFlatCString +#include "string-template-def-char.h" +#include "nsTPromiseFlatString.h" +#include "string-template-undef.h" + +#endif /* !defined(nsPromiseFlatString_h___) */ diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsReadableUtils.h b/src/libs/xpcom18a4/xpcom/string/public/nsReadableUtils.h new file mode 100644 index 00000000..13f94c09 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsReadableUtils.h @@ -0,0 +1,370 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott Collins <scc@mozilla.org> (original author) + * Johnny Stenbeck <jst@netscape.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 nsReadableUtils_h___ +#define nsReadableUtils_h___ + + /** + * I guess all the routines in this file are all mis-named. + * According to our conventions, they should be |NS_xxx|. + */ + +#ifndef nsAString_h___ +#include "nsAString.h" +#endif + +inline size_t Distance( const nsReadingIterator<PRUnichar>& start, const nsReadingIterator<PRUnichar>& end ) + { + return end.get() - start.get(); + } +inline size_t Distance( const nsReadingIterator<char>& start, const nsReadingIterator<char>& end ) + { + return end.get() - start.get(); + } + +NS_COM void LossyCopyUTF16toASCII( const nsAString& aSource, nsACString& aDest ); +NS_COM void CopyASCIItoUTF16( const nsACString& aSource, nsAString& aDest ); + +NS_COM void LossyCopyUTF16toASCII( const PRUnichar* aSource, nsACString& aDest ); +NS_COM void CopyASCIItoUTF16( const char* aSource, nsAString& aDest ); + +NS_COM void CopyUTF16toUTF8( const nsAString& aSource, nsACString& aDest ); +NS_COM void CopyUTF8toUTF16( const nsACString& aSource, nsAString& aDest ); + +NS_COM void CopyUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest ); +NS_COM void CopyUTF8toUTF16( const char* aSource, nsAString& aDest ); + +NS_COM void LossyAppendUTF16toASCII( const nsAString& aSource, nsACString& aDest ); +NS_COM void AppendASCIItoUTF16( const nsACString& aSource, nsAString& aDest ); + +NS_COM void LossyAppendUTF16toASCII( const PRUnichar* aSource, nsACString& aDest ); +NS_COM void AppendASCIItoUTF16( const char* aSource, nsAString& aDest ); + +NS_COM void AppendUTF16toUTF8( const nsAString& aSource, nsACString& aDest ); +NS_COM void AppendUTF8toUTF16( const nsACString& aSource, nsAString& aDest ); + +NS_COM void AppendUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest ); +NS_COM void AppendUTF8toUTF16( const char* aSource, nsAString& aDest ); + +// Backward compatibility +inline +NS_COM void CopyUCS2toASCII( const nsAString& aSource, nsACString& aDest ) +{ LossyCopyUTF16toASCII(aSource, aDest); } +inline +NS_COM void CopyASCIItoUCS2( const nsACString& aSource, nsAString& aDest ) +{ CopyASCIItoUTF16(aSource, aDest); } + + /** + * Returns a new |char| buffer containing a zero-terminated copy of |aSource|. + * + * Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|. + * Performs a lossy encoding conversion by chopping 16-bit wide characters down to 8-bits wide while copying |aSource| to your new buffer. + * This conversion is not well defined; but it reproduces legacy string behavior. + * The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls. + * + * @param aSource a 16-bit wide string + * @return a new |char| buffer you must free with |nsMemory::Free|. + */ +NS_COM char* ToNewCString( const nsAString& aSource ); + + + /** + * Returns a new |char| buffer containing a zero-terminated copy of |aSource|. + * + * Allocates and returns a new |char| buffer which you must free with |nsMemory::Free|. + * The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls. + * + * @param aSource an 8-bit wide string + * @return a new |char| buffer you must free with |nsMemory::Free|. + */ +NS_COM char* ToNewCString( const nsACString& aSource ); + + /** + * Returns a new |char| buffer containing a zero-terminated copy of |aSource|. + * + * Allocates and returns a new |char| buffer which you must free with + * |nsMemory::Free|. + * Performs an encoding conversion from a UTF-16 string to a UTF-8 string + * copying |aSource| to your new buffer. + * The new buffer is zero-terminated, but that may not help you if |aSource| + * contains embedded nulls. + * + * @param aSource a UTF-16 string (made of PRUnichar's) + * @param aUTF8Count the number of 8-bit units that was returned + * @return a new |char| buffer you must free with |nsMemory::Free|. + */ + +NS_COM char* ToNewUTF8String( const nsAString& aSource, PRUint32 *aUTF8Count = nsnull ); + + + /** + * Returns a new |PRUnichar| buffer containing a zero-terminated copy of + * |aSource|. + * + * Allocates and returns a new |PRUnichar| buffer which you must free with + * |nsMemory::Free|. + * The new buffer is zero-terminated, but that may not help you if |aSource| + * contains embedded nulls. + * + * @param aSource a UTF-16 string + * @return a new |PRUnichar| buffer you must free with |nsMemory::Free|. + */ +NS_COM PRUnichar* ToNewUnicode( const nsAString& aSource ); + + + /** + * Returns a new |PRUnichar| buffer containing a zero-terminated copy of |aSource|. + * + * Allocates and returns a new |PRUnichar| buffer which you must free with |nsMemory::Free|. + * Performs an encoding conversion by 0-padding 8-bit wide characters up to 16-bits wide while copying |aSource| to your new buffer. + * This conversion is not well defined; but it reproduces legacy string behavior. + * The new buffer is zero-terminated, but that may not help you if |aSource| contains embedded nulls. + * + * @param aSource an 8-bit wide string (a C-string, NOT UTF-8) + * @return a new |PRUnichar| buffer you must free with |nsMemory::Free|. + */ +NS_COM PRUnichar* ToNewUnicode( const nsACString& aSource ); + + /** + * Returns a new |PRUnichar| buffer containing a zero-terminated copy + * of |aSource|. + * + * Allocates and returns a new |char| buffer which you must free with + * |nsMemory::Free|. Performs an encoding conversion from UTF-8 to UTF-16 + * while copying |aSource| to your new buffer. This conversion is well defined + * for a valid UTF-8 string. The new buffer is zero-terminated, but that + * may not help you if |aSource| contains embedded nulls. + * + * @param aSource an 8-bit wide string, UTF-8 encoded + * @param aUTF16Count the number of 16-bit units that was returned + * @return a new |PRUnichar| buffer you must free with |nsMemory::Free|. + * (UTF-16 encoded) + */ +NS_COM PRUnichar* UTF8ToNewUnicode( const nsACString& aSource, PRUint32 *aUTF16Count = nsnull ); + + /** + * Copies |aLength| 16-bit code units from the start of |aSource| to the + * |PRUnichar| buffer |aDest|. + * + * After this operation |aDest| is not null terminated. + * + * @param aSource a UTF-16 string + * @param aSrcOffset start offset in the source string + * @param aDest a |PRUnichar| buffer + * @param aLength the number of 16-bit code units to copy + * @return pointer to destination buffer - identical to |aDest| + */ +NS_COM PRUnichar* CopyUnicodeTo( const nsAString& aSource, + PRUint32 aSrcOffset, + PRUnichar* aDest, + PRUint32 aLength ); + + + /** + * Copies 16-bit characters between iterators |aSrcStart| and + * |aSrcEnd| to the writable string |aDest|. Similar to the + * |nsString::Mid| method. + * + * After this operation |aDest| is not null terminated. + * + * @param aSrcStart start source iterator + * @param aSrcEnd end source iterator + * @param aDest destination for the copy + */ +NS_COM void CopyUnicodeTo( const nsAString::const_iterator& aSrcStart, + const nsAString::const_iterator& aSrcEnd, + nsAString& aDest ); + + /** + * Appends 16-bit characters between iterators |aSrcStart| and + * |aSrcEnd| to the writable string |aDest|. + * + * After this operation |aDest| is not null terminated. + * + * @param aSrcStart start source iterator + * @param aSrcEnd end source iterator + * @param aDest destination for the copy + */ +NS_COM void AppendUnicodeTo( const nsAString::const_iterator& aSrcStart, + const nsAString::const_iterator& aSrcEnd, + nsAString& aDest ); + + /** + * Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F). + * + * @param aString a 16-bit wide string to scan + */ +NS_COM PRBool IsASCII( const nsAString& aString ); + + /** + * Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F). + * + * @param aString a 8-bit wide string to scan + */ +NS_COM PRBool IsASCII( const nsACString& aString ); + + + /** + * Returns |PR_TRUE| if |aString| is a valid UTF-8 string. + * XXX This is not bullet-proof and nor an all-purpose UTF-8 validator. + * It is mainly written to replace and roughly equivalent to + * + * str.Equals(NS_ConvertUTF16toUTF8(NS_ConvertUTF8toUTF16(str))) + * + * (see bug 191541) + * As such, it does not check for non-UTF-8 7bit encodings such as + * ISO-2022-JP and HZ. However, it filters out UTF-8 representation + * of surrogate codepoints and non-characters ( 0xFFFE and 0xFFFF + * in planes 0 through 16.) as well as overlong UTF-8 sequences. + * Also note that it regards UTF-8 sequences corresponding to + * codepoints above 0x10FFFF as invalid in accordance with + * http://www.ietf.org/internet-drafts/draft-yergeau-rfc2279bis-04.txt + * + * @param aString an 8-bit wide string to scan + */ +NS_COM PRBool IsUTF8( const nsACString& aString ); + + + /** + * Converts case in place in the argument string. + */ +NS_COM void ToUpperCase( nsACString& ); + +NS_COM void ToLowerCase( nsACString& ); + +NS_COM void ToUpperCase( nsCSubstring& ); + +NS_COM void ToLowerCase( nsCSubstring& ); + + /** + * Converts case from string aSource to aDest. + */ +NS_COM void ToUpperCase( const nsACString& aSource, nsACString& aDest ); + +NS_COM void ToLowerCase( const nsACString& aSource, nsACString& aDest ); + + /** + * Finds the leftmost occurance of |aPattern|, if any in the range |aSearchStart|..|aSearchEnd|. + * + * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to + * point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|. + * + * Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|. + * If we need something faster, then we can implement that later. + */ + +NS_COM PRBool FindInReadable( const nsAString& aPattern, nsAString::const_iterator&, nsAString::const_iterator&, const nsStringComparator& = nsDefaultStringComparator() ); +NS_COM PRBool FindInReadable( const nsACString& aPattern, nsACString::const_iterator&, nsACString::const_iterator&, const nsCStringComparator& = nsDefaultCStringComparator() ); + +/* sometimes we don't care about where the string was, just that we + * found it or not */ +inline PRBool FindInReadable( const nsAString& aPattern, const nsAString& aSource, const nsStringComparator& compare = nsDefaultStringComparator() ) +{ + nsAString::const_iterator start, end; + aSource.BeginReading(start); + aSource.EndReading(end); + return FindInReadable(aPattern, start, end, compare); +} + +inline PRBool FindInReadable( const nsACString& aPattern, const nsACString& aSource, const nsCStringComparator& compare = nsDefaultCStringComparator() ) +{ + nsACString::const_iterator start, end; + aSource.BeginReading(start); + aSource.EndReading(end); + return FindInReadable(aPattern, start, end, compare); +} + + +NS_COM PRBool CaseInsensitiveFindInReadable( const nsACString& aPattern, nsACString::const_iterator&, nsACString::const_iterator& ); + + /** + * Finds the rightmost occurance of |aPattern| + * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to + * point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|. + * + * Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|. + * If we need something faster, then we can implement that later. + */ +NS_COM PRBool RFindInReadable( const nsAString& aPattern, nsAString::const_iterator&, nsAString::const_iterator&, const nsStringComparator& = nsDefaultStringComparator() ); +NS_COM PRBool RFindInReadable( const nsACString& aPattern, nsACString::const_iterator&, nsACString::const_iterator&, const nsCStringComparator& = nsDefaultCStringComparator() ); + + /** + * Finds the leftmost occurance of |aChar|, if any in the range + * |aSearchStart|..|aSearchEnd|. + * + * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| to + * point to the match. If no match was found, returns |PR_FALSE| and + * makes |aSearchStart == aSearchEnd|. + */ +NS_COM PRBool FindCharInReadable( PRUnichar aChar, nsAString::const_iterator& aSearchStart, const nsAString::const_iterator& aSearchEnd ); +NS_COM PRBool FindCharInReadable( char aChar, nsACString::const_iterator& aSearchStart, const nsACString::const_iterator& aSearchEnd ); + + /** + * Finds the number of occurences of |aChar| in the string |aStr| + */ +NS_COM PRUint32 CountCharInReadable( const nsAString& aStr, + PRUnichar aChar ); +NS_COM PRUint32 CountCharInReadable( const nsACString& aStr, + char aChar ); + +NS_COM PRBool +StringBeginsWith( const nsAString& aSource, const nsAString& aSubstring, + const nsStringComparator& aComparator = + nsDefaultStringComparator() ); +NS_COM PRBool +StringBeginsWith( const nsACString& aSource, const nsACString& aSubstring, + const nsCStringComparator& aComparator = + nsDefaultCStringComparator() ); +NS_COM PRBool +StringEndsWith( const nsAString& aSource, const nsAString& aSubstring, + const nsStringComparator& aComparator = + nsDefaultStringComparator() ); +NS_COM PRBool +StringEndsWith( const nsACString& aSource, const nsACString& aSubstring, + const nsCStringComparator& aComparator = + nsDefaultCStringComparator() ); + +NS_COM PRUint32 HashString( const nsAString& aStr ); +NS_COM PRUint32 HashString( const nsACString& aStr ); + +NS_COM const nsAFlatString& EmptyString(); +NS_COM const nsAFlatCString& EmptyCString(); + + +#endif // !defined(nsReadableUtils_h___) diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsString.h b/src/libs/xpcom18a4/xpcom/string/public/nsString.h new file mode 100644 index 00000000..67376d19 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsString.h @@ -0,0 +1,237 @@ +/* -*- 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 nsString_h___ +#define nsString_h___ + + +#ifndef nsSubstring_h___ +#include "nsSubstring.h" +#endif + +#ifndef nsDependentSubstring_h___ +#include "nsDependentSubstring.h" +#endif + +#ifndef nsReadableUtils_h___ +#include "nsReadableUtils.h" +#endif + +#include NEW_H + + // enable support for the obsolete string API if not explicitly disabled +#ifndef MOZ_STRING_WITH_OBSOLETE_API +#define MOZ_STRING_WITH_OBSOLETE_API 1 +#endif + +#if MOZ_STRING_WITH_OBSOLETE_API + // radix values for ToInteger/AppendInt +#define kRadix10 (10) +#define kRadix16 (16) +#define kAutoDetect (100) +#define kRadixUnknown (kAutoDetect+1) +#define IGNORE_CASE (PR_TRUE) +#endif + + + // declare nsString, et. al. +#include "string-template-def-unichar.h" +#include "nsTString.h" +#include "string-template-undef.h" + + // declare nsCString, et. al. +#include "string-template-def-char.h" +#include "nsTString.h" +#include "string-template-undef.h" + + + /** + * A helper class that converts a UTF-16 string to ASCII in a lossy manner + */ +class NS_LossyConvertUTF16toASCII : public nsCAutoString + { + public: + explicit + NS_LossyConvertUTF16toASCII( const PRUnichar* aString ) + { + LossyAppendUTF16toASCII(aString, *this); + } + + NS_LossyConvertUTF16toASCII( const PRUnichar* aString, PRUint32 aLength ) + { + LossyAppendUTF16toASCII(Substring(aString, aString + aLength), *this); + } + + explicit + NS_LossyConvertUTF16toASCII( const nsAString& aString ) + { + LossyAppendUTF16toASCII(aString, *this); + } + + private: + // NOT TO BE IMPLEMENTED + NS_LossyConvertUTF16toASCII( char ); + }; + + +class NS_ConvertASCIItoUTF16 : public nsAutoString + { + public: + explicit + NS_ConvertASCIItoUTF16( const char* aCString ) + { + AppendASCIItoUTF16(aCString, *this); + } + + NS_ConvertASCIItoUTF16( const char* aCString, PRUint32 aLength ) + { + AppendASCIItoUTF16(Substring(aCString, aCString + aLength), *this); + } + + explicit + NS_ConvertASCIItoUTF16( const nsACString& aCString ) + { + AppendASCIItoUTF16(aCString, *this); + } + + private: + // NOT TO BE IMPLEMENTED + NS_ConvertASCIItoUTF16( PRUnichar ); + }; + + + /** + * A helper class that converts a UTF-16 string to UTF-8 + */ +class NS_ConvertUTF16toUTF8 : public nsCAutoString + { + public: + explicit + NS_ConvertUTF16toUTF8( const PRUnichar* aString ) + { + AppendUTF16toUTF8(aString, *this); + } + + NS_ConvertUTF16toUTF8( const PRUnichar* aString, PRUint32 aLength ) + { + AppendUTF16toUTF8(Substring(aString, aString + aLength), *this); + } + + explicit + NS_ConvertUTF16toUTF8( const nsAString& aString ) + { + AppendUTF16toUTF8(aString, *this); + } + + private: + // NOT TO BE IMPLEMENTED + NS_ConvertUTF16toUTF8( char ); + }; + + +class NS_ConvertUTF8toUTF16 : public nsAutoString + { + public: + explicit + NS_ConvertUTF8toUTF16( const char* aCString ) + { + AppendUTF8toUTF16(aCString, *this); + } + + NS_ConvertUTF8toUTF16( const char* aCString, PRUint32 aLength ) + { + AppendUTF8toUTF16(Substring(aCString, aCString + aLength), *this); + } + + explicit + NS_ConvertUTF8toUTF16( const nsACString& aCString ) + { + AppendUTF8toUTF16(aCString, *this); + } + + private: + // NOT TO BE IMPLEMENTED + NS_ConvertUTF8toUTF16( PRUnichar ); + }; + + +// the following are included/declared for backwards compatibility + +typedef NS_ConvertUTF16toUTF8 NS_ConvertUCS2toUTF8; +typedef NS_LossyConvertUTF16toASCII NS_LossyConvertUCS2toASCII; +typedef NS_ConvertASCIItoUTF16 NS_ConvertASCIItoUCS2; +typedef NS_ConvertUTF8toUTF16 NS_ConvertUTF8toUCS2; +typedef nsAutoString nsVoidableString; + +#ifndef nsDependentString_h___ +#include "nsDependentString.h" +#endif + +#ifndef nsLiteralString_h___ +#include "nsLiteralString.h" +#endif + +#ifndef nsPromiseFlatString_h___ +#include "nsPromiseFlatString.h" +#endif + +// need to include these for backwards compatibility +#include "nsMemory.h" +#include <string.h> +#include <stdio.h> +#include "plhash.h" + +inline PRInt32 MinInt(PRInt32 x, PRInt32 y) + { + return NS_MIN(x, y); + } + +inline PRInt32 MaxInt(PRInt32 x, PRInt32 y) + { + return NS_MAX(x, y); + } + +/** + * Deprecated: don't use |Recycle|, just call |nsMemory::Free| directly + * + * Return the given buffer to the heap manager. Calls allocator::Free() + */ +inline void Recycle( char* aBuffer) { nsMemory::Free(aBuffer); } +inline void Recycle( PRUnichar* aBuffer) { nsMemory::Free(aBuffer); } + +#endif // !defined(nsString_h___) diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsStringAPI.h b/src/libs/xpcom18a4/xpcom/string/public/nsStringAPI.h new file mode 100644 index 00000000..cc0818b6 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsStringAPI.h @@ -0,0 +1,853 @@ +/* vim:set ts=2 sw=2 et cindent: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla. + * + * The Initial Developer of the Original Code is IBM Corporation. + * Portions created by IBM Corporation are Copyright (C) 2003 + * IBM Corporation. All Rights Reserved. + * + * Contributor(s): + * Darin Fisher <darin@meer.net> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#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" + +#ifdef VBOX_WITH_XPCOM_NAMESPACE_CLEANUP +#define NS_CStringContainerInit VBoxNsxpNS_CStringContainerInit +#define NS_CStringContainerFinish VBoxNsxpNS_CStringContainerFinish +#define NS_CStringCloneData VBoxNsxpNS_CStringCloneData +#define NS_CStringCopy VBoxNsxpNS_CStringCopy +#define NS_CStringGetData VBoxNsxpNS_CStringGetData +#define NS_CStringSetData VBoxNsxpNS_CStringSetData +#define NS_CStringSetDataRange VBoxNsxpNS_CStringSetDataRange +#define NS_UTF16ToCString VBoxNsxpNS_UTF16ToCString +#define NS_CStringToUTF16 VBoxNsxpNS_CStringToUTF16 +#define NS_StringContainerInit VBoxNsxpNS_StringContainerInit +#define NS_StringContainerFinish VBoxNsxpNS_StringContainerFinish +#define NS_StringCloneData VBoxNsxpNS_StringCloneData +#define NS_StringCopy VBoxNsxpNS_StringCopy +#define NS_StringGetData VBoxNsxpNS_StringGetData +#define NS_StringSetData VBoxNsxpNS_StringSetData +#define NS_StringSetDataRange VBoxNsxpNS_StringSetDataRange +#endif /* VBOX_WITH_XPCOM_NAMESPACE_CLEANUP */ + +#define NS_STRINGAPI(x) extern "C" NS_COM x + +/* The base string types */ +class nsAString; +class nsACString; + +/* ------------------------------------------------------------------------- */ + +/** + * 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); + * + * nsresult MyCode() + * { + * nsresult rv; + * + * nsStringContainer sc; + * rv = NS_StringContainerInit(sc); + * if (NS_FAILED(rv)) + * return rv; + * + * rv = GetBlah(sc); + * if (NS_SUCCEEDED(rv)) + * { + * const PRUnichar *data; + * NS_StringGetData(sc, &data); + * // + * // |data| now points to the result of the GetBlah function + * // + * } + * + * NS_StringContainerFinish(sc); + * return rv; + * } + * + * 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); + * + * nsresult MyCode() + * { + * nsresult rv; + * + * nsStringContainer sc; + * rv = NS_StringContainerInit(sc); + * if (NS_FAILED(rv)) + * return rv; + * + * const PRUnichar kData[] = {'x','y','z','\0'}; + * rv = NS_StringSetData(sc, kData, sizeof(kData)/2 - 1); + * if (NS_SUCCEEDED(rv)) + * rv = SetBlah(sc); + * + * NS_StringContainerFinish(sc); + * return rv; + * } + */ +class nsStringContainer; + +/** + * NS_StringContainerInit + * + * @param aContainer string container reference + * @return NS_OK if string container successfully initialized + * + * This function may allocate additional memory for aContainer. When + * aContainer is no longer needed, NS_StringContainerFinish should be called. + * + * @status FROZEN + */ +NS_STRINGAPI(nsresult) +NS_StringContainerInit(nsStringContainer &aContainer); + +/** + * NS_StringContainerFinish + * + * @param aContainer string container reference + * + * This function frees any memory owned by aContainer. + * + * @status FROZEN + */ +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 + * + * @status FROZEN + */ +NS_STRINGAPI(PRUint32) +NS_StringGetData + (const nsAString &aStr, const PRUnichar **aData, + PRBool *aTerminated = nsnull); + +/** + * NS_StringCloneData + * + * This function returns a null-terminated copy of the string's + * internal buffer. + * + * @param aStr abstract string reference + * @return null-terminated copy of the string's internal buffer + * (it must be free'd using using nsMemory::Free) + * + * @status FROZEN + */ +NS_STRINGAPI(PRUnichar *) +NS_StringCloneData + (const nsAString &aStr); + +/** + * 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) + * @return NS_OK if function succeeded + * + * 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. + * + * @status FROZEN + */ +NS_STRINGAPI(nsresult) +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) + * @return NS_OK if function succeeded + * + * 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. + * + * @status FROZEN + */ +NS_STRINGAPI(nsresult) +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 + * @return NS_OK if function succeeded + * + * 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. + * + * @status FROZEN + */ +NS_STRINGAPI(nsresult) +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) + * @return NS_OK if function succeeded + * + * 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 NS_HIDDEN_(nsresult) +NS_StringAppendData(nsAString &aStr, const PRUnichar *aData, + PRUint32 aDataLength = PR_UINT32_MAX) +{ + return 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) + * @return NS_OK if function succeeded + * + * 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 NS_HIDDEN_(nsresult) +NS_StringInsertData(nsAString &aStr, PRUint32 aOffset, const PRUnichar *aData, + PRUint32 aDataLength = PR_UINT32_MAX) +{ + return 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 + * @return NS_OK if function succeeded + */ +inline NS_HIDDEN_(nsresult) +NS_StringCutData(nsAString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength) +{ + return 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; + +/** + * NS_CStringContainerInit + * + * @param aContainer string container reference + * @return NS_OK if string container successfully initialized + * + * This function may allocate additional memory for aContainer. When + * aContainer is no longer needed, NS_CStringContainerFinish should be called. + * + * @status FROZEN + */ +NS_STRINGAPI(nsresult) +NS_CStringContainerInit(nsCStringContainer &aContainer); + +/** + * NS_CStringContainerFinish + * + * @param aContainer string container reference + * + * This function frees any memory owned by aContainer. + * + * @status FROZEN + */ +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 + * + * @status FROZEN + */ +NS_STRINGAPI(PRUint32) +NS_CStringGetData + (const nsACString &aStr, const char **aData, + PRBool *aTerminated = nsnull); + +/** + * NS_CStringCloneData + * + * This function returns a null-terminated copy of the string's + * internal buffer. + * + * @param aStr abstract string reference + * @return null-terminated copy of the string's internal buffer + * (it must be free'd using using nsMemory::Free) + * + * @status FROZEN + */ +NS_STRINGAPI(char *) +NS_CStringCloneData + (const nsACString &aStr); + +/** + * 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) + * @return NS_OK if function succeeded + * + * 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. + * + * @status FROZEN + */ +NS_STRINGAPI(nsresult) +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) + * @return NS_OK if function succeeded + * + * 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. + * + * @status FROZEN + */ +NS_STRINGAPI(nsresult) +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 + * @return NS_OK if function succeeded + * + * 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. + * + * @status FROZEN + */ +NS_STRINGAPI(nsresult) +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) + * @return NS_OK if function succeeded + * + * 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 NS_HIDDEN_(nsresult) +NS_CStringAppendData(nsACString &aStr, const char *aData, + PRUint32 aDataLength = PR_UINT32_MAX) +{ + return 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) + * @return NS_OK if function succeeded + * + * 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 NS_HIDDEN_(nsresult) +NS_CStringInsertData(nsACString &aStr, PRUint32 aOffset, const char *aData, + PRUint32 aDataLength = PR_UINT32_MAX) +{ + return 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 + * @return NS_OK if function succeeded + */ +inline NS_HIDDEN_(nsresult) +NS_CStringCutData(nsACString &aStr, PRUint32 aCutOffset, PRUint32 aCutLength) +{ + return NS_CStringSetDataRange(aStr, aCutOffset, aCutLength, nsnull, 0); +} + +/* ------------------------------------------------------------------------- */ + +/** + * Encodings that can be used with the following conversion routines. + */ +enum nsCStringEncoding { + /* Conversion between ASCII and UTF-16 assumes that all bytes in the source + * string are 7-bit ASCII and can be inflated to UTF-16 by inserting null + * bytes. Reverse conversion is done by truncating every other byte. The + * conversion may result in loss and/or corruption of information if the + * strings do not strictly contain ASCII data. */ + NS_CSTRING_ENCODING_ASCII = 0, + + /* Conversion between UTF-8 and UTF-16 is non-lossy. */ + NS_CSTRING_ENCODING_UTF8 = 1, + + /* Conversion from UTF-16 to the native filesystem charset may result in a + * loss of information. No attempt is made to protect against data loss in + * this case. The native filesystem charset applies to strings passed to + * the "Native" method variants on nsIFile and nsILocalFile. */ + NS_CSTRING_ENCODING_NATIVE_FILESYSTEM = 2 +}; + +/** + * NS_CStringToUTF16 + * + * This function converts the characters in a nsACString to an array of UTF-16 + * characters, in the platform endianness. The result is stored in a nsAString + * object. + * + * @param aSource abstract string reference containing source string + * @param aSrcEncoding character encoding of the source string + * @param aDest abstract string reference to hold the result + * + * @status FROZEN + */ +NS_STRINGAPI(nsresult) +NS_CStringToUTF16(const nsACString &aSource, nsCStringEncoding aSrcEncoding, + nsAString &aDest); + +/** + * NS_UTF16ToCString + * + * This function converts the UTF-16 characters in a nsAString to a single-byte + * encoding. The result is stored in a nsACString object. In some cases this + * conversion may be lossy. In such cases, the conversion may succeed with a + * return code indicating loss of information. The exact behavior is not + * specified at this time. + * + * @param aSource abstract string reference containing source string + * @param aDestEncoding character encoding of the resulting string + * @param aDest abstract string reference to hold the result + * + * @status FROZEN + */ +NS_STRINGAPI(nsresult) +NS_UTF16ToCString(const nsAString &aSource, nsCStringEncoding aDestEncoding, + nsACString &aDest); + +/* ------------------------------------------------------------------------- */ + +/** + * Below we define nsAString and nsACString. The "_external" suffix is an + * implementation detail. nsAString_external is the name of the external + * representation of nsAString from the point of view of the Mozilla codebase. + * To a user of this API, nsAString_external is exactly nsAString. + * + * These classes should be treated as abstract classes with unspecified + * structure. The inline methods are provided as helper functions around the + * C-style API provided above. + * + * Do not try to mix these definitions of nsAString and nsACString with the + * internal definition of these classes from nsAString.h in the Mozilla tree. + */ + +#ifndef NS_STRINGAPI_IMPL +#define nsAString_external nsAString +#define nsACString_external nsACString +#endif + +class nsAString_external +{ +#ifndef NS_STRINGAPI_IMPL + +public: + typedef PRUnichar char_type; + typedef nsAString_external self_type; + typedef PRUint32 size_type; + typedef PRUint32 index_type; + + NS_HIDDEN_(const char_type*) BeginReading() const + { + const char_type *data; + NS_StringGetData(*this, &data); + return data; + } + + NS_HIDDEN_(const char_type*) EndReading() const + { + const char_type *data; + PRUint32 len = NS_StringGetData(*this, &data); + return data + len; + } + + NS_HIDDEN_(size_type) Length() const + { + const char_type* data; + return NS_StringGetData(*this, &data); + } + + NS_HIDDEN_(void) Assign(const self_type& aString) + { + NS_StringCopy(*this, aString); + } + NS_HIDDEN_(void) Assign(const char_type* aData, size_type aLength = PR_UINT32_MAX) + { + NS_StringSetData(*this, aData, aLength); + } + NS_HIDDEN_(void) Assign(char_type aChar) + { + NS_StringSetData(*this, &aChar, 1); + } + + NS_HIDDEN_(self_type&) operator=(const self_type& aString) { Assign(aString); return *this; } + NS_HIDDEN_(self_type&) operator=(const char_type* aPtr) { Assign(aPtr); return *this; } + NS_HIDDEN_(self_type&) operator=(char_type aChar) { Assign(aChar); return *this; } + + NS_HIDDEN_(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); + } + NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, char_type c ) + { + Replace(cutStart, cutLength, &c, 1); + } + NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, const self_type& readable ) + { + const char_type* data; + PRUint32 dataLen = NS_StringGetData(readable, &data); + NS_StringSetDataRange(*this, cutStart, cutLength, data, dataLen); + } + + NS_HIDDEN_(void) Append( char_type c ) { Replace(size_type(-1), 0, c); } + NS_HIDDEN_(void) Append( const char_type* data, size_type length = size_type(-1) ) { Replace(size_type(-1), 0, data, length); } + NS_HIDDEN_(void) Append( const self_type& readable ) { Replace(size_type(-1), 0, readable); } + + NS_HIDDEN_(self_type&) operator+=( char_type c ) { Append(c); return *this; } + NS_HIDDEN_(self_type&) operator+=( const char_type* data ) { Append(data); return *this; } + NS_HIDDEN_(self_type&) operator+=( const self_type& readable ) { Append(readable); return *this; } + + NS_HIDDEN_(void) Insert( char_type c, index_type pos ) { Replace(pos, 0, c); } + NS_HIDDEN_(void) Insert( const char_type* data, index_type pos, size_type length = size_type(-1) ) { Replace(pos, 0, data, length); } + NS_HIDDEN_(void) Insert( const self_type& readable, index_type pos ) { Replace(pos, 0, readable); } + + NS_HIDDEN_(void) Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, nsnull, 0); } + +#endif // NS_STRINGAPI_IMPL + +private: + void *v; +}; + +class nsACString_external +{ +#ifndef NS_STRINGAPI_IMPL + +public: + typedef char char_type; + typedef nsACString_external self_type; + typedef PRUint32 size_type; + typedef PRUint32 index_type; + + NS_HIDDEN_(const char_type*) BeginReading() const + { + const char_type *data; + NS_CStringGetData(*this, &data); + return data; + } + + NS_HIDDEN_(const char_type*) EndReading() const + { + const char_type *data; + PRUint32 len = NS_CStringGetData(*this, &data); + return data + len; + } + + NS_HIDDEN_(size_type) Length() const + { + const char_type* data; + return NS_CStringGetData(*this, &data); + } + + NS_HIDDEN_(void) Assign(const self_type& aString) + { + NS_CStringCopy(*this, aString); + } + NS_HIDDEN_(void) Assign(const char_type* aData, size_type aLength = PR_UINT32_MAX) + { + NS_CStringSetData(*this, aData, aLength); + } + NS_HIDDEN_(void) Assign(char_type aChar) + { + NS_CStringSetData(*this, &aChar, 1); + } + + NS_HIDDEN_(self_type&) operator=(const self_type& aString) { Assign(aString); return *this; } + NS_HIDDEN_(self_type&) operator=(const char_type* aPtr) { Assign(aPtr); return *this; } + NS_HIDDEN_(self_type&) operator=(char_type aChar) { Assign(aChar); return *this; } + + NS_HIDDEN_(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); + } + NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, char_type c ) + { + Replace(cutStart, cutLength, &c, 1); + } + NS_HIDDEN_(void) Replace( index_type cutStart, size_type cutLength, const self_type& readable ) + { + const char_type* data; + PRUint32 dataLen = NS_CStringGetData(readable, &data); + NS_CStringSetDataRange(*this, cutStart, cutLength, data, dataLen); + } + + NS_HIDDEN_(void) Append( char_type c ) { Replace(size_type(-1), 0, c); } + NS_HIDDEN_(void) Append( const char_type* data, size_type length = size_type(-1) ) { Replace(size_type(-1), 0, data, length); } + NS_HIDDEN_(void) Append( const self_type& readable ) { Replace(size_type(-1), 0, readable); } + + NS_HIDDEN_(self_type&) operator+=( char_type c ) { Append(c); return *this; } + NS_HIDDEN_(self_type&) operator+=( const char_type* data ) { Append(data); return *this; } + NS_HIDDEN_(self_type&) operator+=( const self_type& readable ) { Append(readable); return *this; } + + NS_HIDDEN_(void) Insert( char_type c, index_type pos ) { Replace(pos, 0, c); } + NS_HIDDEN_(void) Insert( const char_type* data, index_type pos, size_type length = size_type(-1) ) { Replace(pos, 0, data, length); } + NS_HIDDEN_(void) Insert( const self_type& readable, index_type pos ) { Replace(pos, 0, readable); } + + NS_HIDDEN_(void) Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, nsnull, 0); } + +#endif // NS_STRINGAPI_IMPL + +private: + void *v; +}; + +/* ------------------------------------------------------------------------- */ + +/** + * Below we define nsStringContainer and nsCStringContainer. These classes + * have unspecified structure. In most cases, your code should use + * nsEmbedString instead of these classes; however, if you prefer C-style + * programming, then look no further... + */ + +class nsStringContainer : public nsAString_external +{ +private: + void *d1; + PRUint32 d2; + void *d3; + +public: + nsStringContainer() {} // MSVC6 needs this +}; + +class nsCStringContainer : public nsACString_external +{ +private: + void *d1; + PRUint32 d2; + void *d3; + +public: + nsCStringContainer() {} // MSVC6 needs this +}; + +#endif // nsStringAPI_h__ diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsStringFwd.h b/src/libs/xpcom18a4/xpcom/string/public/nsStringFwd.h new file mode 100644 index 00000000..4c664011 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsStringFwd.h @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 + * Netscape Communications. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott Collins <scc@mozilla.org> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 ***** */ + +/* nsStringFwd.h --- forward declarations for string classes */ + +#ifndef nsStringFwd_h___ +#define nsStringFwd_h___ + +#ifndef nscore_h___ +#include "nscore.h" +#endif + + + /** + * double-byte (PRUnichar) string types + */ + +class nsAString; +class nsObsoleteAString; +class nsSubstring; +class nsSubstringTuple; +class nsString; +class nsAutoString; +class nsDependentString; +class nsDependentSubstring; +class nsPromiseFlatString; +class nsStringComparator; +class nsDefaultStringComparator; +class nsXPIDLString; + + + /** + * single-byte (char) string types + */ + +class nsACString; +class nsObsoleteACString; +class nsCSubstring; +class nsCSubstringTuple; +class nsCString; +class nsCAutoString; +class nsDependentCString; +class nsDependentCSubstring; +class nsPromiseFlatCString; +class nsCStringComparator; +class nsDefaultCStringComparator; +class nsXPIDLCString; + + + /** + * typedefs for backwards compatibility + */ + +typedef nsString nsAFlatString; +typedef nsSubstring nsASingleFragmentString; + +typedef nsCString nsAFlatCString; +typedef nsCSubstring nsASingleFragmentCString; + + +#endif /* !defined(nsStringFwd_h___) */ diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsStringIterator.h b/src/libs/xpcom18a4/xpcom/string/public/nsStringIterator.h new file mode 100644 index 00000000..1848594c --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsStringIterator.h @@ -0,0 +1,373 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 + * Netscape Communications. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott Collins <scc@mozilla.org> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 nsStringIterator_h___ +#define nsStringIterator_h___ + +#ifndef nsCharTraits_h___ +#include "nsCharTraits.h" +#endif + +#ifndef nsAlgorithm_h___ +#include "nsAlgorithm.h" +#endif + +#ifndef nsDebug_h___ +#include "nsDebug.h" +#endif + + /** + * @see nsTAString + */ + +template <class CharT> +class nsReadingIterator + { + public: + typedef nsReadingIterator<CharT> self_type; + typedef ptrdiff_t difference_type; + typedef CharT value_type; + typedef const CharT* pointer; + typedef const CharT& reference; + + private: + friend class nsAString; + friend class nsACString; + friend class nsSubstring; + friend class nsCSubstring; + + // unfortunately, the API for nsReadingIterator requires that the + // iterator know its start and end positions. this was needed when + // we supported multi-fragment strings, but now it is really just + // extra baggage. we should remove mStart and mEnd at some point. + + const CharT* mStart; + const CharT* mEnd; + const CharT* mPosition; + + public: + nsReadingIterator() { } + // nsReadingIterator( const nsReadingIterator<CharT>& ); // auto-generated copy-constructor OK + // nsReadingIterator<CharT>& operator=( const nsReadingIterator<CharT>& ); // auto-generated copy-assignment operator OK + + inline void normalize_forward() {} + inline void normalize_backward() {} + + pointer + start() const + { + return mStart; + } + + pointer + end() const + { + return mEnd; + } + + pointer + get() const + { + return mPosition; + } + + CharT + operator*() const + { + return *get(); + } + +#if 0 + // An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2) + // don't like this when |CharT| is a type without members. + pointer + operator->() const + { + return get(); + } +#endif + + self_type& + operator++() + { + ++mPosition; + return *this; + } + + self_type + operator++( int ) + { + self_type result(*this); + ++mPosition; + return result; + } + + self_type& + operator--() + { + --mPosition; + return *this; + } + + self_type + operator--( int ) + { + self_type result(*this); + --mPosition; + return result; + } + + difference_type + size_forward() const + { + return mEnd - mPosition; + } + + difference_type + size_backward() const + { + return mPosition - mStart; + } + + self_type& + advance( difference_type n ) + { + if (n > 0) + { + difference_type step = NS_MIN(n, size_forward()); + + NS_ASSERTION(step>0, "can't advance a reading iterator beyond the end of a string"); + + mPosition += step; + } + else if (n < 0) + { + difference_type step = NS_MAX(n, -size_backward()); + + NS_ASSERTION(step<0, "can't advance (backward) a reading iterator beyond the end of a string"); + + mPosition += step; + } + return *this; + } + }; + + /** + * @see nsTAString + */ + +template <class CharT> +class nsWritingIterator + { + public: + typedef nsWritingIterator<CharT> self_type; + typedef ptrdiff_t difference_type; + typedef CharT value_type; + typedef CharT* pointer; + typedef CharT& reference; + + private: + friend class nsAString; + friend class nsACString; + friend class nsSubstring; + friend class nsCSubstring; + + // unfortunately, the API for nsWritingIterator requires that the + // iterator know its start and end positions. this was needed when + // we supported multi-fragment strings, but now it is really just + // extra baggage. we should remove mStart and mEnd at some point. + + CharT* mStart; + CharT* mEnd; + CharT* mPosition; + + public: + nsWritingIterator() { } + // nsWritingIterator( const nsWritingIterator<CharT>& ); // auto-generated copy-constructor OK + // nsWritingIterator<CharT>& operator=( const nsWritingIterator<CharT>& ); // auto-generated copy-assignment operator OK + + inline void normalize_forward() {} + inline void normalize_backward() {} + + pointer + start() const + { + return mStart; + } + + pointer + end() const + { + return mEnd; + } + + pointer + get() const + { + return mPosition; + } + + reference + operator*() const + { + return *get(); + } + +#if 0 + // An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2) + // don't like this when |CharT| is a type without members. + pointer + operator->() const + { + return get(); + } +#endif + + self_type& + operator++() + { + ++mPosition; + return *this; + } + + self_type + operator++( int ) + { + self_type result(*this); + ++mPosition; + return result; + } + + self_type& + operator--() + { + --mPosition; + return *this; + } + + self_type + operator--( int ) + { + self_type result(*this); + --mPosition; + return result; + } + + difference_type + size_forward() const + { + return mEnd - mPosition; + } + + difference_type + size_backward() const + { + return mPosition - mStart; + } + + self_type& + advance( difference_type n ) + { + if (n > 0) + { + difference_type step = NS_MIN(n, size_forward()); + + NS_ASSERTION(step>0, "can't advance a writing iterator beyond the end of a string"); + + mPosition += step; + } + else if (n < 0) + { + difference_type step = NS_MAX(n, -size_backward()); + + NS_ASSERTION(step<0, "can't advance (backward) a writing iterator beyond the end of a string"); + + mPosition += step; + } + return *this; + } + + PRUint32 + write( const value_type* s, PRUint32 n ) + { + NS_ASSERTION(size_forward() > 0, "You can't |write| into an |nsWritingIterator| with no space!"); + + nsCharTraits<value_type>::move(mPosition, s, n); + advance( difference_type(n) ); + return n; + } + }; + +template <class CharT> +inline +PRBool +operator==( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs ) + { + return lhs.get() == rhs.get(); + } + +template <class CharT> +inline +PRBool +operator!=( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs ) + { + return lhs.get() != rhs.get(); + } + + + // + // |nsWritingIterator|s + // + +template <class CharT> +inline +PRBool +operator==( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs ) + { + return lhs.get() == rhs.get(); + } + +template <class CharT> +inline +PRBool +operator!=( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs ) + { + return lhs.get() != rhs.get(); + } + +#endif /* !defined(nsStringIterator_h___) */ diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsSubstring.h b/src/libs/xpcom18a4/xpcom/string/public/nsSubstring.h new file mode 100644 index 00000000..35a1a568 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsSubstring.h @@ -0,0 +1,74 @@ +/* -*- 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 nsSubstring_h___ +#define nsSubstring_h___ + +#ifndef nsAString_h___ +#include "nsAString.h" +#endif + +#define kNotFound -1 + +// If some platform(s) can't handle our template that matches literal strings, +// then we'll disable it on those platforms. +#ifndef NS_DISABLE_LITERAL_TEMPLATE +# if (defined(_MSC_VER) && (_MSC_VER < 1310)) || (defined(__SUNPRO_CC) & (__SUNPRO_CC < 0x560)) || (defined(__HP_aCC) && (__HP_aCC <= 012100)) +# define NS_DISABLE_LITERAL_TEMPLATE +# endif +#endif /* !NS_DISABLE_LITERAL_TEMPLATE */ + +#include <string.h> + + // declare nsSubstring +#include "string-template-def-unichar.h" +#include "nsTSubstring.h" +#include "string-template-undef.h" + + + // declare nsCSubstring +#include "string-template-def-char.h" +#include "nsTSubstring.h" +#include "string-template-undef.h" + + +#ifndef nsSubstringTuple_h___ +#include "nsSubstringTuple.h" +#endif + +#endif // !defined(nsSubstring_h___) diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsSubstringTuple.h b/src/libs/xpcom18a4/xpcom/string/public/nsSubstringTuple.h new file mode 100644 index 00000000..8cf6f803 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsSubstringTuple.h @@ -0,0 +1,56 @@ +/* -*- 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 nsSubstringTuple_h___ +#define nsSubstringTuple_h___ + +#ifndef nsSubstring_h___ +#include "nsSubstring.h" +#endif + + // declare nsSubstringTuple +#include "string-template-def-unichar.h" +#include "nsTSubstringTuple.h" +#include "string-template-undef.h" + + // declare nsCSubstringTuple +#include "string-template-def-char.h" +#include "nsTSubstringTuple.h" +#include "string-template-undef.h" + +#endif // !defined(nsSubstringTuple_h___) diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTAString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTAString.h new file mode 100644 index 00000000..93b88443 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsTAString.h @@ -0,0 +1,618 @@ +/* -*- 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): + * Scott Collins <scc@mozilla.org> (original author) + * 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 ***** */ + + + /** + * The base for string comparators + */ +class NS_COM nsTStringComparator_CharT + { + public: + typedef CharT char_type; + + nsTStringComparator_CharT() {} + + virtual int operator()( const char_type*, const char_type*, PRUint32 length ) const = 0; + virtual int operator()( char_type, char_type ) const = 0; + }; + + + /** + * The default string comparator (case-sensitive comparision) + */ +class NS_COM nsTDefaultStringComparator_CharT + : public nsTStringComparator_CharT + { + public: + typedef CharT char_type; + + nsTDefaultStringComparator_CharT() {} + + virtual int operator()( const char_type*, const char_type*, PRUint32 length ) const; + virtual int operator()( char_type, char_type ) const; + }; + + + /** + * nsTAString is the most abstract class in the string hierarchy. + * + * In its original inception, nsTAString was designed to allow the data + * storage for a string to be separated into multiple fragments. This was + * intended to enable lazy string flattening or avoid string flattening + * altogether in some cases. This abstraction, however, meant that every + * single string operation (including simple operations such as IsEmpty() and + * BeginReading()) required virtual function calls. A virtual destructor was + * also required. This not only meant additional overhead for invoking + * string methods but also added to additional codesize at every callsite (to + * load the virtual function address). + * + * Today nsTAString exists mainly for backwards compatibility of the string + * API. It is restricted to representing a contiguous array of characters, + * where the character array is not necessarily null-terminated. Moreover, + * since nsTAString's virtual function table was frozen for Mozilla 1.0, + * nsTAString necessarily maintains ABI compatibility with older versions of + * Gecko. (nsTObsoleteAString provides that frozen ABI. See + * nsObsoleteAString.h for a description of how we solve the ABI + * compatibility requirement while eliminating virtual function calls on + * nsTAString.) + * + * XPIDL still generates C++ header files with references to nsTAStrings, so + * nsTAString will still be heavily used in real code. + * + * If the opportunity to break ABI compatibility with Mozilla 1.0 were to + * ever arise, our first move should be to make nsTAString equate to + * nsTSubstring. This may in fact be an option today for some Gecko-based + * products. + */ +class nsTAString_CharT + { + public: + + typedef CharT char_type; + typedef nsCharTraits<char_type> char_traits; + + typedef char_traits::incompatible_char_type incompatible_char_type; + + typedef nsTAString_CharT self_type; + typedef nsTAString_CharT abstract_string_type; + typedef nsTObsoleteAString_CharT obsolete_string_type; + typedef nsTSubstring_CharT substring_type; + typedef nsTSubstringTuple_CharT substring_tuple_type; + + typedef nsReadingIterator<char_type> const_iterator; + typedef nsWritingIterator<char_type> iterator; + + typedef nsTStringComparator_CharT comparator_type; + + typedef PRUint32 size_type; + typedef PRUint32 index_type; + + public: + + // this acts like a virtual destructor + NS_COM NS_FASTCALL ~nsTAString_CharT(); + + + /** + * BeginReading/EndReading can be used to get immutable access to the + * string's underlying buffer. EndReading returns a pointer to the + * end of the string's buffer. nsReadableUtils.h provides a collection + * of utility functions that work with these iterators. + */ + + inline const_iterator& BeginReading( const_iterator& iter ) const + { + size_type len = GetReadableBuffer(&iter.mStart); + iter.mEnd = iter.mStart + len; + iter.mPosition = iter.mStart; + return iter; + } + + inline const_iterator& EndReading( const_iterator& iter ) const + { + size_type len = GetReadableBuffer(&iter.mStart); + iter.mEnd = iter.mStart + len; + iter.mPosition = iter.mEnd; + return iter; + } + + + /** + * BeginWriting/EndWriting can be used to get mutable access to the + * string's underlying buffer. EndWriting returns a pointer to the + * end of the string's buffer. This iterator API cannot be used to + * grow a buffer. Use SetLength to resize the string's buffer. + */ + + inline iterator& BeginWriting( iterator& iter ) + { + size_type len = GetWritableBuffer(&iter.mStart); + iter.mEnd = iter.mStart + len; + iter.mPosition = iter.mStart; + return iter; + } + + inline iterator& EndWriting( iterator& iter ) + { + size_type len = GetWritableBuffer(&iter.mStart); + iter.mEnd = iter.mStart + len; + iter.mPosition = iter.mEnd; + return iter; + } + + + /** + * Length checking functions. IsEmpty is a helper function to avoid + * writing code like: |if (str.Length() == 0)| + */ + + NS_COM size_type NS_FASTCALL Length() const; + PRBool IsEmpty() const { return Length() == 0; } + + + /** + * String equality tests. Pass a string comparator if you want to + * control how the strings are compared. By default, a binary + * "case-sensitive" comparision is performed. + */ + + NS_COM PRBool NS_FASTCALL Equals( const self_type& ) const; + NS_COM PRBool NS_FASTCALL Equals( const self_type&, const comparator_type& ) const; + NS_COM PRBool NS_FASTCALL Equals( const char_type* ) const; + NS_COM PRBool NS_FASTCALL Equals( const char_type*, const comparator_type& ) const; + + /** + * An efficient comparison with ASCII that can be used even + * for wide strings. Call this version when you know the + * length of 'data'. + */ + NS_COM PRBool NS_FASTCALL EqualsASCII( const char* data, size_type len ) const; + /** + * An efficient comparison with ASCII that can be used even + * for wide strings. Call this version when 'data' is + * null-terminated. + */ + NS_COM PRBool NS_FASTCALL EqualsASCII( const char* data ) const; + + // EqualsLiteral must ONLY be applied to an actual literal string. + // Do not attempt to use it with a regular char* pointer, or with a char + // array variable. + // The template trick to acquire the array length at compile time without + // using a macro is due to Corey Kosak, with much thanks. +#ifdef NS_DISABLE_LITERAL_TEMPLATE + inline PRBool EqualsLiteral( const char* str ) const + { + return EqualsASCII(str); + } +#else + template<int N> + inline PRBool EqualsLiteral( const char (&str)[N] ) const + { + return EqualsASCII(str, N-1); + } + template<int N> + inline PRBool EqualsLiteral( char (&str)[N] ) const + { + const char* s = str; + return EqualsASCII(s, N-1); + } +#endif + + // The LowerCaseEquals methods compare the lower case version of + // this string to some ASCII/Literal string. The ASCII string is + // *not* lowercased for you. If you compare to an ASCII or literal + // string that contains an uppercase character, it is guaranteed to + // return false. We will throw assertions too. + NS_COM PRBool NS_FASTCALL LowerCaseEqualsASCII( const char* data, size_type len ) const; + NS_COM PRBool NS_FASTCALL LowerCaseEqualsASCII( const char* data ) const; + + // LowerCaseEqualsLiteral must ONLY be applied to an actual + // literal string. Do not attempt to use it with a regular char* + // pointer, or with a char array variable. Use + // LowerCaseEqualsASCII for them. +#ifdef NS_DISABLE_LITERAL_TEMPLATE + inline PRBool LowerCaseEqualsLiteral( const char* str ) const + { + return LowerCaseEqualsASCII(str); + } +#else + template<int N> + inline PRBool LowerCaseEqualsLiteral( const char (&str)[N] ) const + { + return LowerCaseEqualsASCII(str, N-1); + } + template<int N> + inline PRBool LowerCaseEqualsLiteral( char (&str)[N] ) const + { + const char* s = str; + return LowerCaseEqualsASCII(s, N-1); + } +#endif + + /** + * A string always references a non-null data pointer. In some + * applications (e.g., the DOM) it is necessary for a string class + * to have some way to distinguish an empty string from a null (or + * void) string. These methods enable support for the concept of + * a void string. + */ + + NS_COM PRBool NS_FASTCALL IsVoid() const; + NS_COM void NS_FASTCALL SetIsVoid( PRBool ); + + + /** + * This method returns true if the string's underlying buffer is + * null-terminated. This should rarely be needed by applications. + * The PromiseFlatTString method should be used to ensure that a + * string's underlying buffer is null-terminated. + */ + + NS_COM PRBool NS_FASTCALL IsTerminated() const; + + + /** + * These are contant time since nsTAString uses flat storage + */ + NS_COM char_type NS_FASTCALL First() const; + NS_COM char_type NS_FASTCALL Last() const; + + + /** + * Returns the number of occurances of the given character. + */ + NS_COM size_type NS_FASTCALL CountChar( char_type ) const; + + + /** + * Locates the offset of the first occurance of the character. Pass a + * non-zero offset to control where the search begins. + */ + + NS_COM PRInt32 NS_FASTCALL FindChar( char_type, index_type offset = 0 ) const; + + + /** + * SetCapacity is not required to do anything; however, it can be used + * as a hint to the implementation to reduce allocations. + * + * SetCapacity(0) is a suggestion to discard all associated storage. + */ + NS_COM void NS_FASTCALL SetCapacity( size_type ); + + + /** + * XXX talk to dbaron about this comment. we do need a method that + * XXX allows someone to resize a string's buffer so that it can be + * XXX populated using writing iterators. SetLength seems to be the + * XXX right method for the job, and we do use it in this capacity + * XXX in certain places. + * + * SetLength is used in two ways: + * 1) to |Cut| a suffix of the string; + * 2) to prepare to |Append| or move characters around. + * + * External callers are not allowed to use |SetLength| in this + * latter capacity, and should prefer |Truncate| for the former. + * In other words, |SetLength| is deprecated for all use outside + * of the string library and the internal use may at some point + * be replaced as well. + * + * This distinction makes me think the two different uses should + * be split into two distinct functions. + */ + NS_COM void NS_FASTCALL SetLength( size_type ); + + + /** + * Can't use |Truncate| to make a string longer! + */ + void Truncate( size_type aNewLength=0 ) + { + NS_ASSERTION(aNewLength <= Length(), "Truncate cannot make string longer"); + SetLength(aNewLength); + } + + + /** + * |Assign| and |operator=| make |this| equivalent to the string or + * buffer given as an argument. If possible, they do this by sharing + * a reference counted buffer (see |nsTSubstring|). If not, they copy + * the buffer into their own buffer. + */ + + NS_COM void NS_FASTCALL Assign( const self_type& readable ); + NS_COM void NS_FASTCALL Assign( const substring_tuple_type& tuple ); + NS_COM void NS_FASTCALL Assign( const char_type* data ); + NS_COM void NS_FASTCALL Assign( const char_type* data, size_type length ); + NS_COM void NS_FASTCALL Assign( char_type c ); + + NS_COM void NS_FASTCALL AssignASCII( const char* data, size_type length ); + NS_COM void NS_FASTCALL AssignASCII( const char* data ); + + // AssignLiteral must ONLY be applied to an actual literal string. + // Do not attempt to use it with a regular char* pointer, or with a char + // array variable. Use AssignASCII for those. +#ifdef NS_DISABLE_LITERAL_TEMPLATE + void AssignLiteral( const char* str ) + { AssignASCII(str); } +#else + template<int N> + void AssignLiteral( const char (&str)[N] ) + { AssignASCII(str, N-1); } + template<int N> + void AssignLiteral( char (&str)[N] ) + { AssignASCII(str, N-1); } +#endif + + // copy-assignment operator. I must define my own if I don't want the compiler to make me one + self_type& operator=( const self_type& readable ) { Assign(readable); return *this; } + self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } + self_type& operator=( const char_type* data ) { Assign(data); return *this; } + self_type& operator=( char_type c ) { Assign(c); return *this; } + + + + /** + * |Append|, |operator+=| are used to add characters to the end of this string. + */ + + NS_COM void NS_FASTCALL Append( const self_type& readable ); + NS_COM void NS_FASTCALL Append( const substring_tuple_type& tuple ); + NS_COM void NS_FASTCALL Append( const char_type* data ); + NS_COM void NS_FASTCALL Append( const char_type* data, size_type length ); + NS_COM void NS_FASTCALL Append( char_type c ); + + NS_COM void NS_FASTCALL AppendASCII( const char* data, size_type length ); + NS_COM void NS_FASTCALL AppendASCII( const char* data ); + + // AppendLiteral must ONLY be applied to an actual literal string. + // Do not attempt to use it with a regular char* pointer, or with a char + // array variable. Use AppendASCII for those. +#ifdef NS_DISABLE_LITERAL_TEMPLATE + void AppendLiteral( const char* str ) + { AppendASCII(str); } +#else + template<int N> + void AppendLiteral( const char (&str)[N] ) + { AppendASCII(str, N-1); } + template<int N> + void AppendLiteral( char (&str)[N] ) + { AppendASCII(str, N-1); } +#endif + + self_type& operator+=( const self_type& readable ) { Append(readable); return *this; } + self_type& operator+=( const substring_tuple_type& tuple ) { Append(tuple); return *this; } + self_type& operator+=( const char_type* data ) { Append(data); return *this; } + self_type& operator+=( char_type c ) { Append(c); return *this; } + + + /** + * |Insert| is used to add characters into this string at a given position. + * NOTE: It's a shame the |pos| parameter isn't at the front of the arg list. + */ + + NS_COM void NS_FASTCALL Insert( const self_type& readable, index_type pos ); + NS_COM void NS_FASTCALL Insert( const substring_tuple_type& tuple, index_type pos ); + NS_COM void NS_FASTCALL Insert( const char_type* data, index_type pos ); + NS_COM void NS_FASTCALL Insert( const char_type* data, index_type pos, size_type length ); + NS_COM void NS_FASTCALL Insert( char_type c, index_type pos ); + + + /** + * |Cut| is used to remove a range of characters from this string. + */ + + NS_COM void NS_FASTCALL Cut( index_type cutStart, size_type cutLength ); + + + /** + * |Replace| is used overwrite a range of characters from this string. + */ + + NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const self_type& readable ); + NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& readable ); + + + /** + * this is public to support automatic conversion of tuple to abstract + * string, which is necessary to support our API. + */ + nsTAString_CharT(const substring_tuple_type& tuple) + : mVTable(obsolete_string_type::sCanonicalVTable) + , mData(nsnull) + , mLength(0) + , mFlags(0) + { + Assign(tuple); + } + + protected: + + friend class nsTSubstringTuple_CharT; + + // GCC 3.2 erroneously needs these (even though they are subclasses!) + friend class nsTSubstring_CharT; + friend class nsTDependentSubstring_CharT; + friend class nsTPromiseFlatString_CharT; + + /** + * the address of our virtual function table. required for backwards + * compatibility with Mozilla 1.0 frozen nsAC?String interface. + */ + const void* mVTable; + + /** + * these fields are "here" only when mVTable == sCanonicalVTable. + * + * they exist to support automatic construction of a nsTAString + * from a nsTSubstringTuple. + */ + char_type* mData; + size_type mLength; + PRUint32 mFlags; + + /** + * nsTAString must be subclassed before it can be instantiated. + */ + nsTAString_CharT(char_type* data, size_type length, PRUint32 flags) + : mVTable(obsolete_string_type::sCanonicalVTable) + , mData(data) + , mLength(length) + , mFlags(flags) + {} + + /** + * optional ctor for use by subclasses. + * + * NOTE: mData and mLength are intentionally left uninitialized. + */ + explicit + nsTAString_CharT(PRUint32 flags) + : mVTable(obsolete_string_type::sCanonicalVTable) + , mFlags(flags) + {} + + /** + * get pointer to internal string buffer (may not be null terminated). + * return length of buffer. + */ + NS_COM size_type NS_FASTCALL GetReadableBuffer( const char_type **data ) const; + NS_COM size_type NS_FASTCALL GetWritableBuffer( char_type **data ); + + /** + * returns true if this tuple is dependent on (i.e., overlapping with) + * the given char sequence. + */ + PRBool NS_FASTCALL IsDependentOn(const char_type *start, const char_type *end) const; + + /** + * we can be converted to a const nsTSubstring (dependent on this) + */ + const substring_type NS_FASTCALL ToSubstring() const; + + /** + * type cast helpers + */ + + const obsolete_string_type* AsObsoleteString() const + { + return NS_REINTERPRET_CAST(const obsolete_string_type*, this); + } + + obsolete_string_type* AsObsoleteString() + { + return NS_REINTERPRET_CAST(obsolete_string_type*, this); + } + + const substring_type* AsSubstring() const + { + return NS_REINTERPRET_CAST(const substring_type*, this); + } + + substring_type* AsSubstring() + { + return NS_REINTERPRET_CAST(substring_type*, this); + } + + private: + + // GCC 2.95.3, EGCS-2.91.66, Sun Workshop/Forte, and IBM VisualAge C++ + // require a public copy-constructor in order to support automatic + // construction of a nsTAString from a nsTSubstringTuple. I believe + // enabling the default copy-constructor is harmless, but I do not want + // it to be enabled by default because that might tempt people into + // using it (where it would be invalid). +#if !defined(__SUNPRO_CC) && \ + !(defined(_AIX) && defined(__IBMCPP__)) && \ + (!defined(__GNUC__) || __GNUC__ > 2 || __GNUC_MINOR__ > 95) + + // NOT TO BE IMPLEMENTED + nsTAString_CharT( const self_type& ); + +#endif + + // NOT TO BE IMPLEMENTED + void operator= ( incompatible_char_type ); + void Assign ( incompatible_char_type ); + void operator+= ( incompatible_char_type ); + void Append ( incompatible_char_type ); + void Insert ( incompatible_char_type, index_type ); + }; + + +NS_COM +int NS_FASTCALL Compare( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs, const nsTStringComparator_CharT& = nsTDefaultStringComparator_CharT() ); + + +inline +PRBool operator!=( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs ) + { + return !lhs.Equals(rhs); + } + +inline +PRBool operator< ( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs ) + { + return Compare(lhs, rhs)< 0; + } + +inline +PRBool operator<=( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs ) + { + return Compare(lhs, rhs)<=0; + } + +inline +PRBool operator==( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs ) + { + return lhs.Equals(rhs); + } + +inline +PRBool operator>=( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs ) + { + return Compare(lhs, rhs)>=0; + } + +inline +PRBool operator> ( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs ) + { + return Compare(lhs, rhs)> 0; + } diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTDependentString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTDependentString.h new file mode 100644 index 00000000..91a2b53e --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsTDependentString.h @@ -0,0 +1,137 @@ +/* -*- 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): + * Scott Collins <scc@mozilla.org> (original author) + * 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 ***** */ + + + /** + * nsTDependentString_CharT + * + * Stores a null-terminated, immutable sequence of characters. + * + * Subclass of nsTString that restricts string value to an immutable + * character sequence. This class does not own its data, so the creator + * of objects of this type must take care to ensure that a + * nsTDependentString continues to reference valid memory for the + * duration of its use. + */ +class nsTDependentString_CharT : public nsTString_CharT + { + public: + + typedef nsTDependentString_CharT self_type; + + public: + + /** + * verify restrictions + */ + void AssertValid() + { + NS_ASSERTION(mData, "nsTDependentString must wrap a non-NULL buffer"); + NS_ASSERTION(mLength != size_type(-1), "nsTDependentString has bogus length"); + NS_ASSERTION(mData[mLength] == 0, "nsTDependentString must wrap only null-terminated strings"); + } + + + /** + * constructors + */ + + nsTDependentString_CharT( const char_type* start, const char_type* end ) + : string_type(NS_CONST_CAST(char_type*, start), end - start, F_TERMINATED) + { + AssertValid(); + } + + nsTDependentString_CharT( const char_type* data, PRUint32 length ) + : string_type(NS_CONST_CAST(char_type*, data), length, F_TERMINATED) + { + AssertValid(); + } + + explicit + nsTDependentString_CharT( const char_type* data ) + : string_type(NS_CONST_CAST(char_type*, data), char_traits::length(data), F_TERMINATED) + { + AssertValid(); + } + + explicit + nsTDependentString_CharT( const substring_type& str ) + : string_type(NS_CONST_CAST(char_type*, str.Data()), str.Length(), F_TERMINATED) + { + AssertValid(); + } + + // XXX are you sure?? + // auto-generated copy-constructor OK + // auto-generated copy-assignment operator OK + // auto-generated destructor OK + + + /** + * allow this class to be bound to a different string... + */ + + void Rebind( const char_type* data ) + { + mData = NS_CONST_CAST(char_type*, data); + mLength = char_traits::length(data); + SetDataFlags(F_TERMINATED); + AssertValid(); + } + + void Rebind( const char_type* data, size_type length ) + { + mData = NS_CONST_CAST(char_type*, data); + mLength = length; + SetDataFlags(F_TERMINATED); + AssertValid(); + } + + void Rebind( const char_type* start, const char_type* end ) + { + Rebind(start, end - start); + } + + private: + + // NOT USED + nsTDependentString_CharT( const substring_tuple_type& ); + nsTDependentString_CharT( const abstract_string_type& ); + }; diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTDependentSubstring.h b/src/libs/xpcom18a4/xpcom/string/public/nsTDependentSubstring.h new file mode 100644 index 00000000..89d96e13 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsTDependentSubstring.h @@ -0,0 +1,142 @@ +/* -*- 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): + * Scott Collins <scc@mozilla.org> (original author) + * 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 ***** */ + + + /** + * nsTDependentSubstring_CharT + */ +class nsTDependentSubstring_CharT : public nsTSubstring_CharT + { + public: + + typedef nsTDependentSubstring_CharT self_type; + + public: + + NS_COM void Rebind( const abstract_string_type&, PRUint32 startPos, PRUint32 length = size_type(-1) ); + NS_COM void Rebind( const substring_type&, PRUint32 startPos, PRUint32 length = size_type(-1) ); + + void Rebind( const char_type* start, const char_type* end ) + { + NS_ASSERTION(start && end, "nsTDependentSubstring must wrap a non-NULL buffer"); + mData = NS_CONST_CAST(char_type*, start); + mLength = end - start; + SetDataFlags(F_NONE); + } + + nsTDependentSubstring_CharT( const abstract_string_type& str, PRUint32 startPos, PRUint32 length = size_type(-1) ) + : substring_type(F_NONE) + { + Rebind(str, startPos, length); + } + + nsTDependentSubstring_CharT( const substring_type& str, PRUint32 startPos, PRUint32 length = size_type(-1) ) + : substring_type(F_NONE) + { + Rebind(str, startPos, length); + } + + nsTDependentSubstring_CharT( const char_type* start, const char_type* end ) + : substring_type(NS_CONST_CAST(char_type*, start), end - start, F_NONE) {} + + nsTDependentSubstring_CharT( const const_iterator& start, const const_iterator& end ) + : substring_type(NS_CONST_CAST(char_type*, start.get()), end.get() - start.get(), F_NONE) {} + + // auto-generated copy-constructor OK (XXX really?? what about base class copy-ctor?) + + private: + // NOT USED + void operator=( const self_type& ); // we're immutable, you can't assign into a substring + }; + +inline +const nsTDependentSubstring_CharT +Substring( const nsTAString_CharT& str, PRUint32 startPos, PRUint32 length = PRUint32(-1) ) + { + return nsTDependentSubstring_CharT(str, startPos, length); + } + +inline +const nsTDependentSubstring_CharT +Substring( const nsTSubstring_CharT& str, PRUint32 startPos, PRUint32 length = PRUint32(-1) ) + { + return nsTDependentSubstring_CharT(str, startPos, length); + } + +inline +const nsTDependentSubstring_CharT +Substring( const nsReadingIterator<CharT>& start, const nsReadingIterator<CharT>& end ) + { + return nsTDependentSubstring_CharT(start.get(), end.get()); + } + +inline +const nsTDependentSubstring_CharT +Substring( const CharT* start, const CharT* end ) + { + return nsTDependentSubstring_CharT(start, end); + } + +inline +const nsTDependentSubstring_CharT +StringHead( const nsTAString_CharT& str, PRUint32 count ) + { + return nsTDependentSubstring_CharT(str, 0, count); + } + +inline +const nsTDependentSubstring_CharT +StringHead( const nsTSubstring_CharT& str, PRUint32 count ) + { + return nsTDependentSubstring_CharT(str, 0, count); + } + +inline +const nsTDependentSubstring_CharT +StringTail( const nsTAString_CharT& str, PRUint32 count ) + { + return nsTDependentSubstring_CharT(str, str.Length() - count, count); + } + +inline +const nsTDependentSubstring_CharT +StringTail( const nsTSubstring_CharT& str, PRUint32 count ) + { + return nsTDependentSubstring_CharT(str, str.Length() - count, count); + } diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTObsoleteAString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTObsoleteAString.h new file mode 100644 index 00000000..82d5f56c --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsTObsoleteAString.h @@ -0,0 +1,165 @@ +/* -*- 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 ***** */ + + + /** + * nsTObsoleteAString_CharT : binary compatible with old nsAC?String vtable + * + * @status FROZEN + */ +class nsTObsoleteAString_CharT + { + public: + /** + * This is holds the address of the vtable for the canonical string + * implementation (i.e., nsTString). + */ + NS_COM static const void *sCanonicalVTable; + + /** + * An |nsFragmentRequest| is used to tell |GetReadableFragment| and + * |GetWritableFragment| what to do. + * + * @see GetReadableFragment + */ + enum nsFragmentRequest { kPrevFragment, kFirstFragment, kLastFragment, kNextFragment, kFragmentAt }; + + /** + * A |nsReadableFragment| provides |const| access to a contiguous hunk of + * string of homogenous units, e.g., bytes (|char|). This doesn't mean it + * represents a flat hunk. It could be a variable length encoding, for + * instance UTF-8. And the fragment itself need not be zero-terminated. + * + * An |nsReadableFragment| is the underlying machinery that lets + * |nsReadingIterator|s work. + * + * @see nsReadingIterator + * @status FROZEN + */ + struct nsReadableFragment + { + const CharT* mStart; + const CharT* mEnd; + const void* mFragmentIdentifier; + + nsReadableFragment() : mStart(0), mEnd(0), mFragmentIdentifier(0) {} + }; + + + /** + * A |nsWritableFragment| provides non-|const| access to a contiguous hunk of + * string of homogenous units, e.g., bytes (|char|). This doesn't mean it + * represents a flat hunk. It could be a variable length encoding, for + * instance UTF-8. And the fragment itself need not be zero-terminated. + * + * An |nsWritableFragment| is the underlying machinery that lets + * |nsWritingIterator|s work. + * + * @see nsWritingIterator + * @status FROZEN + */ + struct nsWritableFragment + { + CharT* mStart; + CharT* mEnd; + void* mFragmentIdentifier; + + nsWritableFragment() : mStart(0), mEnd(0), mFragmentIdentifier(0) {} + }; + + protected: + + typedef CharT char_type; + + typedef void buffer_handle_type; + typedef void shared_buffer_handle_type; + typedef nsReadableFragment const_fragment_type; + typedef nsWritableFragment fragment_type; + + typedef nsTAString_CharT abstract_string_type; + + typedef PRUint32 size_type; + typedef PRUint32 index_type; + + protected: + + friend class nsTAString_CharT; + friend class nsTSubstring_CharT; + + /** here's the old nsAC?String vtable **/ + + virtual ~nsTObsoleteAString_CharT() { } + + virtual PRUint32 GetImplementationFlags() const = 0; + virtual const buffer_handle_type* GetFlatBufferHandle() const = 0; + virtual const buffer_handle_type* GetBufferHandle() const = 0; + virtual const shared_buffer_handle_type* GetSharedBufferHandle() const = 0; + + virtual size_type Length() const = 0; + + virtual PRBool IsVoid() const = 0; + virtual void SetIsVoid( PRBool ) = 0; + + virtual void SetCapacity( size_type ) = 0; + virtual void SetLength( size_type ) = 0; + + virtual void Cut( index_type cutStart, size_type cutLength ) = 0; + + virtual void do_AssignFromReadable( const abstract_string_type& ) = 0; + virtual void do_AssignFromElementPtr( const char_type* ) = 0; + virtual void do_AssignFromElementPtrLength( const char_type*, size_type ) = 0; + virtual void do_AssignFromElement( char_type ) = 0; + + virtual void do_AppendFromReadable( const abstract_string_type& ) = 0; + virtual void do_AppendFromElementPtr( const char_type* ) = 0; + virtual void do_AppendFromElementPtrLength( const char_type*, size_type ) = 0; + virtual void do_AppendFromElement( char_type ) = 0; + + virtual void do_InsertFromReadable( const abstract_string_type&, index_type ) = 0; + virtual void do_InsertFromElementPtr( const char_type*, index_type ) = 0; + virtual void do_InsertFromElementPtrLength( const char_type*, index_type, size_type ) = 0; + virtual void do_InsertFromElement( char_type, index_type ) = 0; + + virtual void do_ReplaceFromReadable( index_type, size_type, const abstract_string_type& ) = 0; + + virtual const char_type* GetReadableFragment( const_fragment_type&, nsFragmentRequest, PRUint32 = 0 ) const = 0; + virtual char_type* GetWritableFragment( fragment_type&, nsFragmentRequest, PRUint32 = 0 ) = 0; + }; + + // forward declare implementation +class nsTObsoleteAStringThunk_CharT; diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTPromiseFlatString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTPromiseFlatString.h new file mode 100644 index 00000000..6cf82f60 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsTPromiseFlatString.h @@ -0,0 +1,158 @@ +/* -*- 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): + * Scott Collins <scc@mozilla.org> (original author) + * 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 ***** */ + + + /** + * NOTE: + * + * Try to avoid flat strings. |PromiseFlat[C]String| will help you as a last + * resort, and this may be necessary when dealing with legacy or OS calls, + * but in general, requiring a null-terminated array of characters kills many + * of the performance wins the string classes offer. Write your own code to + * use |nsA[C]String&|s for parameters. Write your string proccessing + * algorithms to exploit iterators. If you do this, you will benefit from + * being able to chain operations without copying or allocating and your code + * will be significantly more efficient. Remember, a function that takes an + * |const nsA[C]String&| can always be passed a raw character pointer by + * wrapping it (for free) in a |nsDependent[C]String|. But a function that + * takes a character pointer always has the potential to force allocation and + * copying. + * + * + * How to use it: + * + * A |nsPromiseFlat[C]String| doesn't necessarily own the characters it + * promises. You must never use it to promise characters out of a string + * with a shorter lifespan. The typical use will be something like this: + * + * SomeOSFunction( PromiseFlatCString(aCString).get() ); // GOOD + * + * Here's a BAD use: + * + * const char* buffer = PromiseFlatCString(aCString).get(); + * SomeOSFunction(buffer); // BAD!! |buffer| is a dangling pointer + * + * The only way to make one is with the function |PromiseFlat[C]String|, + * which produce a |const| instance. ``What if I need to keep a promise + * around for a little while?'' you might ask. In that case, you can keep a + * reference, like so + * + * const nsPromiseFlatString& flat = PromiseFlatString(aString); + * // this reference holds the anonymous temporary alive, but remember, + * // it must _still_ have a lifetime shorter than that of |aString| + * + * SomeOSFunction(flat.get()); + * SomeOtherOSFunction(flat.get()); + * + * + * How does it work? + * + * A |nsPromiseFlat[C]String| is just a wrapper for another string. If you + * apply it to a string that happens to be flat, your promise is just a + * dependent reference to the string's data. If you apply it to a non-flat + * string, then a temporary flat string is created for you, by allocating and + * copying. In the event that you end up assigning the result into a sharing + * string (e.g., |nsTString|), the right thing happens. + */ + +class nsTPromiseFlatString_CharT : public nsTString_CharT + { + public: + + typedef nsTPromiseFlatString_CharT self_type; + + private: + + NS_COM void Init( const substring_type& ); + NS_COM void Init( const abstract_string_type& ); + + // NOT TO BE IMPLEMENTED + void operator=( const self_type& ); + + // NOT TO BE IMPLEMENTED + nsTPromiseFlatString_CharT(); + + public: + + explicit + nsTPromiseFlatString_CharT( const substring_type& str ) + : string_type() + { + Init(str); + } + + explicit + nsTPromiseFlatString_CharT( const abstract_string_type& readable ) + : string_type() + { + Init(readable); + } + + explicit + nsTPromiseFlatString_CharT( const substring_tuple_type& tuple ) + : string_type() + { + // nothing else to do here except assign the value of the tuple + // into ourselves. + Assign(tuple); + } + }; + +inline +const nsTPromiseFlatString_CharT +TPromiseFlatString_CharT( const nsTAString_CharT& str ) + { + return nsTPromiseFlatString_CharT(str); + } + + // e.g., PromiseFlatCString(Substring(s)) +inline +const nsTPromiseFlatString_CharT +TPromiseFlatString_CharT( const nsTSubstring_CharT& frag ) + { + return nsTPromiseFlatString_CharT(frag); + } + + // e.g., PromiseFlatCString(a + b) +inline +const nsTPromiseFlatString_CharT +TPromiseFlatString_CharT( const nsTSubstringTuple_CharT& tuple ) + { + return nsTPromiseFlatString_CharT(tuple); + } diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTString.h b/src/libs/xpcom18a4/xpcom/string/public/nsTString.h new file mode 100644 index 00000000..2ef241b2 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsTString.h @@ -0,0 +1,721 @@ +/* -*- 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): + * Rick Gessner <rickg@netscape.com> (original author) + * Scott Collins <scc@mozilla.org> + * 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 ***** */ + + + /** + * This is the canonical null-terminated string class. All subclasses + * promise null-terminated storage. Instances of this class allocate + * strings on the heap. + * + * This class is also known as nsAFlat[C]String, where "flat" is used + * to denote a null-terminated string. + */ +class nsTString_CharT : public nsTSubstring_CharT + { + public: + + typedef nsTString_CharT self_type; + + public: + + /** + * constructors + */ + + nsTString_CharT() + : substring_type() {} + + explicit + nsTString_CharT( char_type c ) + : substring_type() + { + Assign(c); + } + + explicit + nsTString_CharT( const char_type* data, size_type length = size_type(-1) ) + : substring_type() + { + Assign(data, length); + } + + nsTString_CharT( const self_type& str ) + : substring_type() + { + Assign(str); + } + + nsTString_CharT( const substring_tuple_type& tuple ) + : substring_type() + { + Assign(tuple); + } + + explicit + nsTString_CharT( const abstract_string_type& readable ) + : substring_type() + { + Assign(readable); + } + + + // |operator=| does not inherit, so we must define our own + self_type& operator=( char_type c ) { Assign(c); return *this; } + self_type& operator=( const char_type* data ) { Assign(data); return *this; } + self_type& operator=( const self_type& str ) { Assign(str); return *this; } + self_type& operator=( const substring_type& str ) { Assign(str); return *this; } + self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } + self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; } + + + /** + * returns the null-terminated string + */ + + const char_type* get() const + { + return mData; + } + + + /** + * returns character at specified index. + * + * NOTE: unlike nsTSubstring::CharAt, this function allows you to index + * the null terminator character. + */ + + char_type CharAt( index_type i ) const + { + NS_ASSERTION(i <= mLength, "index exceeds allowable range"); + return mData[i]; + } + + char_type operator[]( index_type i ) const + { + return CharAt(i); + } + + +#if MOZ_STRING_WITH_OBSOLETE_API + + + /** + * Search for the given substring within this string. + * + * @param aString is substring to be sought in this + * @param aIgnoreCase selects case sensitivity + * @param aOffset tells us where in this string to start searching + * @param aCount tells us how far from the offset we are to search. Use + * -1 to search the whole string. + * @return offset in string, or kNotFound + */ + + NS_COM PRInt32 Find( const nsCString& aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const; + NS_COM PRInt32 Find( const char* aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const; + +#ifdef CharT_is_PRUnichar + NS_COM PRInt32 Find( const nsAFlatString& aString, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const; + NS_COM PRInt32 Find( const PRUnichar* aString, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const; +#endif + + + /** + * This methods scans the string backwards, looking for the given string + * + * @param aString is substring to be sought in this + * @param aIgnoreCase tells us whether or not to do caseless compare + * @param aOffset tells us where in this string to start searching. + * Use -1 to search from the end of the string. + * @param aCount tells us how many iterations to make starting at the + * given offset. + * @return offset in string, or kNotFound + */ + + NS_COM PRInt32 RFind( const nsCString& aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const; + NS_COM PRInt32 RFind( const char* aCString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const; + +#ifdef CharT_is_PRUnichar + NS_COM PRInt32 RFind( const nsAFlatString& aString, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const; + NS_COM PRInt32 RFind( const PRUnichar* aString, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const; +#endif + + + /** + * Search for given char within this string + * + * @param aChar is the character to search for + * @param aOffset tells us where in this strig to start searching + * @param aCount tells us how far from the offset we are to search. + * Use -1 to search the whole string. + * @return offset in string, or kNotFound + */ + + // PRInt32 FindChar( PRUnichar aChar, PRInt32 aOffset=0, PRInt32 aCount=-1 ) const; + NS_COM PRInt32 RFindChar( PRUnichar aChar, PRInt32 aOffset=-1, PRInt32 aCount=-1 ) const; + + + /** + * This method searches this string for the first character found in + * the given string. + * + * @param aString contains set of chars to be found + * @param aOffset tells us where in this string to start searching + * (counting from left) + * @return offset in string, or kNotFound + */ + + NS_COM PRInt32 FindCharInSet( const char* aString, PRInt32 aOffset=0 ) const; + PRInt32 FindCharInSet( const self_type& aString, PRInt32 aOffset=0 ) const + { + return FindCharInSet(aString.get(), aOffset); + } + +#ifdef CharT_is_PRUnichar + NS_COM PRInt32 FindCharInSet( const PRUnichar* aString, PRInt32 aOffset=0 ) const; +#endif + + + /** + * This method searches this string for the last character found in + * the given string. + * + * @param aString contains set of chars to be found + * @param aOffset tells us where in this string to start searching + * (counting from left) + * @return offset in string, or kNotFound + */ + + NS_COM PRInt32 RFindCharInSet( const char_type* aString, PRInt32 aOffset=-1 ) const; + PRInt32 RFindCharInSet( const self_type& aString, PRInt32 aOffset=-1 ) const + { + return RFindCharInSet(aString.get(), aOffset); + } + + + /** + * Compares a given string to this string. + * + * @param aString is the string to be compared + * @param aIgnoreCase tells us how to treat case + * @param aCount tells us how many chars to compare + * @return -1,0,1 + */ + +#ifdef CharT_is_char + NS_COM PRInt32 Compare( const char* aString, PRBool aIgnoreCase=PR_FALSE, PRInt32 aCount=-1 ) const; +#endif + + + /** + * Equality check between given string and this string. + * + * @param aString is the string to check + * @param aIgnoreCase tells us how to treat case + * @param aCount tells us how many chars to compare + * @return boolean + */ +#ifdef CharT_is_char + PRBool EqualsIgnoreCase( const char* aString, PRInt32 aCount=-1 ) const { + return Compare(aString, PR_TRUE, aCount) == 0; + } +#else + NS_COM PRBool EqualsIgnoreCase( const char* aString, PRInt32 aCount=-1 ) const; + + + /** + * Copies data from internal buffer onto given char* buffer + * + * NOTE: This only copies as many chars as will fit in given buffer (clips) + * @param aBuf is the buffer where data is stored + * @param aBuflength is the max # of chars to move to buffer + * @param aOffset is the offset to copy from + * @return ptr to given buffer + */ + + NS_COM char* ToCString( char* aBuf, PRUint32 aBufLength, PRUint32 aOffset=0 ) const; + +#endif // !CharT_is_PRUnichar + + /** + * Perform string to float conversion. + * + * @param aErrorCode will contain error if one occurs + * @return float rep of string value + */ + NS_COM float ToFloat( PRInt32* aErrorCode ) const; + + + /** + * Perform string to int conversion. + * @param aErrorCode will contain error if one occurs + * @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you. + * @return int rep of string value, and possible (out) error code + */ + NS_COM PRInt32 ToInteger( PRInt32* aErrorCode, PRUint32 aRadix=kRadix10 ) const; + + + /** + * |Left|, |Mid|, and |Right| are annoying signatures that seem better almost + * any _other_ way than they are now. Consider these alternatives + * + * aWritable = aReadable.Left(17); // ...a member function that returns a |Substring| + * aWritable = Left(aReadable, 17); // ...a global function that returns a |Substring| + * Left(aReadable, 17, aWritable); // ...a global function that does the assignment + * + * as opposed to the current signature + * + * aReadable.Left(aWritable, 17); // ...a member function that does the assignment + * + * or maybe just stamping them out in favor of |Substring|, they are just duplicate functionality + * + * aWritable = Substring(aReadable, 0, 17); + */ + + NS_COM size_type Mid( self_type& aResult, PRUint32 aStartPos, PRUint32 aCount ) const; + + size_type Left( self_type& aResult, size_type aCount ) const + { + return Mid(aResult, 0, aCount); + } + + size_type Right( self_type& aResult, size_type aCount ) const + { + aCount = NS_MIN(mLength, aCount); + return Mid(aResult, mLength - aCount, aCount); + } + + + /** + * Set a char inside this string at given index + * + * @param aChar is the char you want to write into this string + * @param anIndex is the ofs where you want to write the given char + * @return TRUE if successful + */ + + NS_COM PRBool SetCharAt( PRUnichar aChar, PRUint32 aIndex ); + + + /** + * These methods are used to remove all occurances of the + * characters found in aSet from this string. + * + * @param aSet -- characters to be cut from this + */ + NS_COM void StripChars( const char* aSet ); + + + /** + * This method is used to remove all occurances of aChar from this + * string. + * + * @param aChar -- char to be stripped + * @param aOffset -- where in this string to start stripping chars + */ + + NS_COM void StripChar( char_type aChar, PRInt32 aOffset=0 ); + + + /** + * This method strips whitespace throughout the string. + */ + NS_COM void StripWhitespace(); + + + /** + * swaps occurence of 1 string for another + */ + + NS_COM void ReplaceChar( char_type aOldChar, char_type aNewChar ); + NS_COM void ReplaceChar( const char* aSet, char_type aNewChar ); + NS_COM void ReplaceSubstring( const self_type& aTarget, const self_type& aNewValue); + NS_COM void ReplaceSubstring( const char_type* aTarget, const char_type* aNewValue); + + + /** + * This method trims characters found in aTrimSet from + * either end of the underlying string. + * + * @param aSet -- contains chars to be trimmed from both ends + * @param aEliminateLeading + * @param aEliminateTrailing + * @param aIgnoreQuotes -- if true, causes surrounding quotes to be ignored + * @return this + */ + NS_COM void Trim( const char* aSet, PRBool aEliminateLeading=PR_TRUE, PRBool aEliminateTrailing=PR_TRUE, PRBool aIgnoreQuotes=PR_FALSE ); + + /** + * This method strips whitespace from string. + * You can control whether whitespace is yanked from start and end of + * string as well. + * + * @param aEliminateLeading controls stripping of leading ws + * @param aEliminateTrailing controls stripping of trailing ws + */ + NS_COM void CompressWhitespace( PRBool aEliminateLeading=PR_TRUE, PRBool aEliminateTrailing=PR_TRUE ); + + + /** + * assign/append/insert with _LOSSY_ conversion + */ + + NS_COM void AssignWithConversion( const nsTAString_IncompatibleCharT& aString ); + NS_COM void AssignWithConversion( const incompatible_char_type* aData, PRInt32 aLength=-1 ); + + NS_COM void AppendWithConversion( const nsTAString_IncompatibleCharT& aString ); + NS_COM void AppendWithConversion( const incompatible_char_type* aData, PRInt32 aLength=-1 ); + + /** + * Append the given integer to this string + */ + NS_COM void AppendInt( PRInt32 aInteger, PRInt32 aRadix=kRadix10 ); //radix=8,10 or 16 + + /** + * Append the given unsigned integer to this string + */ + inline void AppendInt( PRUint32 aInteger, PRInt32 aRadix = kRadix10 ) + { + AppendInt(PRInt32(aInteger), aRadix); + } + + /** + * Append the given 64-bit integer to this string. + * @param aInteger The integer to append + * @param aRadix The radix to use; can be 8, 10 or 16. + */ + NS_COM void AppendInt( PRInt64 aInteger, PRInt32 aRadix=kRadix10 ); + + /** + * Append the given float to this string + */ + + NS_COM void AppendFloat( double aFloat ); + +#endif // !MOZ_STRING_WITH_OBSOLETE_API + + + protected: + + explicit + nsTString_CharT( PRUint32 flags ) + : substring_type(flags) {} + + // allow subclasses to initialize fields directly + nsTString_CharT( char_type* data, size_type length, PRUint32 flags ) + : substring_type(data, length, flags) {} + }; + + +class nsTFixedString_CharT : public nsTString_CharT + { + public: + + typedef nsTFixedString_CharT self_type; + typedef nsTFixedString_CharT fixed_string_type; + + public: + + /** + * @param data + * fixed-size buffer to be used by the string (the contents of + * this buffer may be modified by the string) + * @param storageSize + * the size of the fixed buffer + * @param length (optional) + * the length of the string already contained in the buffer + */ + + nsTFixedString_CharT( char_type* data, size_type storageSize ) + : string_type(data, char_traits::length(data), F_TERMINATED | F_FIXED | F_CLASS_FIXED) + , mFixedCapacity(storageSize - 1) + , mFixedBuf(data) + {} + + nsTFixedString_CharT( char_type* data, size_type storageSize, size_type length ) + : string_type(data, length, F_TERMINATED | F_FIXED | F_CLASS_FIXED) + , mFixedCapacity(storageSize - 1) + , mFixedBuf(data) + { + // null-terminate + mFixedBuf[length] = char_type(0); + } + + // |operator=| does not inherit, so we must define our own + self_type& operator=( char_type c ) { Assign(c); return *this; } + self_type& operator=( const char_type* data ) { Assign(data); return *this; } + self_type& operator=( const substring_type& str ) { Assign(str); return *this; } + self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } + self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; } + + protected: + + friend class nsTSubstring_CharT; + + size_type mFixedCapacity; + char_type *mFixedBuf; + }; + + + /** + * nsTAutoString_CharT + * + * Subclass of nsTString_CharT that adds support for stack-based string + * allocation. Do not allocate this class on the heap! ;-) + */ +class nsTAutoString_CharT : public nsTFixedString_CharT + { + public: + + typedef nsTAutoString_CharT self_type; + + public: + + /** + * constructors + */ + + nsTAutoString_CharT() + : fixed_string_type(mStorage, kDefaultStorageSize, 0) + {} + + explicit + nsTAutoString_CharT( char_type c ) + : fixed_string_type(mStorage, kDefaultStorageSize, 0) + { + Assign(c); + } + + explicit + nsTAutoString_CharT( const char_type* data, size_type length = size_type(-1) ) + : fixed_string_type(mStorage, kDefaultStorageSize, 0) + { + Assign(data, length); + } + + nsTAutoString_CharT( const self_type& str ) + : fixed_string_type(mStorage, kDefaultStorageSize, 0) + { + Assign(str); + } + + explicit + nsTAutoString_CharT( const substring_type& str ) + : fixed_string_type(mStorage, kDefaultStorageSize, 0) + { + Assign(str); + } + + nsTAutoString_CharT( const substring_tuple_type& tuple ) + : fixed_string_type(mStorage, kDefaultStorageSize, 0) + { + Assign(tuple); + } + + explicit + nsTAutoString_CharT( const abstract_string_type& readable ) + : fixed_string_type(mStorage, kDefaultStorageSize, 0) + { + Assign(readable); + } + + // |operator=| does not inherit, so we must define our own + self_type& operator=( char_type c ) { Assign(c); return *this; } + self_type& operator=( const char_type* data ) { Assign(data); return *this; } + self_type& operator=( const self_type& str ) { Assign(str); return *this; } + self_type& operator=( const substring_type& str ) { Assign(str); return *this; } + self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } + self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; } + + enum { kDefaultStorageSize = 64 }; + + private: + + char_type mStorage[kDefaultStorageSize]; + }; + + + /** + * nsTXPIDLString extends nsTString such that: + * + * (1) mData can be null + * (2) objects of this type can be automatically cast to |const CharT*| + * (3) getter_Copies method is supported to adopt data + */ +class nsTXPIDLString_CharT : public nsTString_CharT + { + public: + + typedef nsTXPIDLString_CharT self_type; + + public: + + nsTXPIDLString_CharT() + : string_type(NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer), 0, F_TERMINATED | F_VOIDED) {} + + // copy-constructor required to avoid default + nsTXPIDLString_CharT( const self_type& str ) + : string_type(NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer), 0, F_TERMINATED | F_VOIDED) + { + Assign(str); + } + + // return nsnull if we are voided + const char_type* get() const + { + return (mFlags & F_VOIDED) ? nsnull : mData; + } + + // this case operator is the reason why this class cannot just be a + // typedef for nsTString + operator const char_type*() const + { + return get(); + } + + // need this to diambiguous operator[int] + char_type operator[]( PRInt32 i ) const + { + return CharAt(index_type(i)); + } + + // |operator=| does not inherit, so we must define our own + self_type& operator=( char_type c ) { Assign(c); return *this; } + self_type& operator=( const char_type* data ) { Assign(data); return *this; } + self_type& operator=( const self_type& str ) { Assign(str); return *this; } + self_type& operator=( const substring_type& str ) { Assign(str); return *this; } + self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } + self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; } + }; + + + /** + * getter_Copies support for use with raw string out params: + * + * NS_IMETHOD GetBlah(char**); + * + * void some_function() + * { + * nsXPIDLCString blah; + * GetBlah(getter_Copies(blah)); + * // ... + * } + */ +class nsTGetterCopies_CharT + { + public: + typedef CharT char_type; + + nsTGetterCopies_CharT(nsTXPIDLString_CharT& str) + : mString(str), mData(nsnull) {} + + ~nsTGetterCopies_CharT() + { + mString.Adopt(mData); // OK if mData is null + } + + operator char_type**() + { + return &mData; + } + + private: + nsTXPIDLString_CharT& mString; + char_type* mData; + }; + +inline +nsTGetterCopies_CharT +getter_Copies( nsTXPIDLString_CharT& aString ) + { + return nsTGetterCopies_CharT(aString); + } + + + /** + * nsTAdoptingString extends nsTXPIDLString such that: + * + * (1) Adopt given string on construction or assignment, i.e. take + * the value of what's given, and make what's given forget its + * value. Note that this class violates constness in a few + * places. Be careful! + */ +class nsTAdoptingString_CharT : public nsTXPIDLString_CharT + { + public: + + typedef nsTAdoptingString_CharT self_type; + + public: + + explicit nsTAdoptingString_CharT() {} + explicit nsTAdoptingString_CharT(char_type* str, size_type length = size_type(-1)) + { + Adopt(str, length); + } + + // copy-constructor required to adopt on copy. Note that this + // will violate the constness of |str| in the operator=() + // call. |str| will be truncated as a side-effect of this + // constructor. + nsTAdoptingString_CharT( const self_type& str ) +#ifdef VBOX /* bird: shut up annoying warnings */ + : nsTXPIDLString_CharT() +#endif + { + *this = str; + } + + // |operator=| does not inherit, so we must define our own + self_type& operator=( const substring_type& str ) { Assign(str); return *this; } + self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } + self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; } + + // Adopt(), if possible, when assigning to a self_type&. Note + // that this violates the constness of str, str is always + // truncated when this operator is called. + NS_COM self_type& operator=( const self_type& str ); + + private: + // NOT TO BE IMPLEMENTED. + self_type& operator=( const char_type* data ); + self_type& operator=( char_type* data ); + }; + diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTSubstring.h b/src/libs/xpcom18a4/xpcom/string/public/nsTSubstring.h new file mode 100644 index 00000000..aaaf5a64 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsTSubstring.h @@ -0,0 +1,575 @@ +/* -*- 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 ***** */ + + + /** + * nsTSubstring + * + * The base string type. This type is not instantiated directly. A sub- + * class is instantiated instead. For example, see nsTString. + * + * This type works like nsTAString except that it does not have the ABI + * requirements of that interface. Like nsTAString, nsTSubstring + * represents a single contiguous array of characters that may or may not + * be null-terminated. + * + * Many of the accessors on nsTSubstring are inlined as an optimization. + * + * This class is also known as "nsASingleFragmentC?String". + */ +class nsTSubstring_CharT : public nsTAString_CharT + { + public: + + typedef nsTSubstring_CharT self_type; + typedef nsTString_CharT string_type; + + typedef char_type* char_iterator; + typedef const char_type* const_char_iterator; + + public: + + /** + * reading iterators + */ + + const_char_iterator BeginReading() const { return mData; } + const_char_iterator EndReading() const { return mData + mLength; } + + /** + * deprecated reading iterators + */ + + const_iterator& BeginReading( const_iterator& iter ) const + { + iter.mStart = mData; + iter.mEnd = mData + mLength; + iter.mPosition = iter.mStart; + return iter; + } + + const_iterator& EndReading( const_iterator& iter ) const + { + iter.mStart = mData; + iter.mEnd = mData + mLength; + iter.mPosition = iter.mEnd; + return iter; + } + + const_char_iterator& BeginReading( const_char_iterator& iter ) const + { + return iter = mData; + } + + const_char_iterator& EndReading( const_char_iterator& iter ) const + { + return iter = mData + mLength; + } + + + /** + * writing iterators + */ + + char_iterator BeginWriting() { EnsureMutable(); return mData; } + char_iterator EndWriting() { EnsureMutable(); return mData + mLength; } + + /** + * deprecated writing iterators + */ + + iterator& BeginWriting( iterator& iter ) + { + EnsureMutable(); + iter.mStart = mData; + iter.mEnd = mData + mLength; + iter.mPosition = iter.mStart; + return iter; + } + + iterator& EndWriting( iterator& iter ) + { + EnsureMutable(); + iter.mStart = mData; + iter.mEnd = mData + mLength; + iter.mPosition = iter.mEnd; + return iter; + } + + char_iterator& BeginWriting( char_iterator& iter ) + { + EnsureMutable(); + return iter = mData; + } + + char_iterator& EndWriting( char_iterator& iter ) + { + EnsureMutable(); + return iter = mData + mLength; + } + + + /** + * accessors + */ + + // returns pointer to string data (not necessarily null-terminated) + const char_type *Data() const + { + return mData; + } + + size_type Length() const + { + return mLength; + } + + PRBool IsEmpty() const + { + return mLength == 0; + } + + PRBool IsVoid() const + { + return mFlags & F_VOIDED; + } + + PRBool IsTerminated() const + { + return mFlags & F_TERMINATED; + } + + char_type CharAt( index_type i ) const + { + NS_ASSERTION(i < mLength, "index exceeds allowable range"); + return mData[i]; + } + + char_type operator[]( index_type i ) const + { + return CharAt(i); + } + + char_type First() const + { + NS_ASSERTION(mLength > 0, "|First()| called on an empty string"); + return mData[0]; + } + + inline + char_type Last() const + { + NS_ASSERTION(mLength > 0, "|Last()| called on an empty string"); + return mData[mLength - 1]; + } + + NS_COM size_type NS_FASTCALL CountChar( char_type ) const; + NS_COM PRInt32 NS_FASTCALL FindChar( char_type, index_type offset = 0 ) const; + + + /** + * equality + */ + + NS_COM PRBool NS_FASTCALL Equals( const self_type& ) const; + NS_COM PRBool NS_FASTCALL Equals( const self_type&, const comparator_type& ) const; + + NS_COM PRBool NS_FASTCALL Equals( const abstract_string_type& readable ) const; + NS_COM PRBool NS_FASTCALL Equals( const abstract_string_type& readable, const comparator_type& comp ) const; + + NS_COM PRBool NS_FASTCALL Equals( const char_type* data ) const; + NS_COM PRBool NS_FASTCALL Equals( const char_type* data, const comparator_type& comp ) const; + + /** + * An efficient comparison with ASCII that can be used even + * for wide strings. Call this version when you know the + * length of 'data'. + */ + NS_COM PRBool NS_FASTCALL EqualsASCII( const char* data, size_type len ) const; + /** + * An efficient comparison with ASCII that can be used even + * for wide strings. Call this version when 'data' is + * null-terminated. + */ + NS_COM PRBool NS_FASTCALL EqualsASCII( const char* data ) const; + + // EqualsLiteral must ONLY be applied to an actual literal string. + // Do not attempt to use it with a regular char* pointer, or with a char + // array variable. + // The template trick to acquire the array length at compile time without + // using a macro is due to Corey Kosak, with much thanks. +#ifdef NS_DISABLE_LITERAL_TEMPLATE + inline PRBool EqualsLiteral( const char* str ) const + { + return EqualsASCII(str); + } +#else + template<int N> + inline PRBool EqualsLiteral( const char (&str)[N] ) const + { + return EqualsASCII(str, N-1); + } + template<int N> + inline PRBool EqualsLiteral( char (&str)[N] ) const + { + const char* s = str; + return EqualsASCII(s, N-1); + } +#endif + + // The LowerCaseEquals methods compare the lower case version of + // this string to some ASCII/Literal string. The ASCII string is + // *not* lowercased for you. If you compare to an ASCII or literal + // string that contains an uppercase character, it is guaranteed to + // return false. We will throw assertions too. + NS_COM PRBool NS_FASTCALL LowerCaseEqualsASCII( const char* data, size_type len ) const; + NS_COM PRBool NS_FASTCALL LowerCaseEqualsASCII( const char* data ) const; + + // LowerCaseEqualsLiteral must ONLY be applied to an actual + // literal string. Do not attempt to use it with a regular char* + // pointer, or with a char array variable. Use + // LowerCaseEqualsASCII for them. +#ifdef NS_DISABLE_LITERAL_TEMPLATE + inline PRBool LowerCaseEqualsLiteral( const char* str ) const + { + return LowerCaseEqualsASCII(str); + } +#else + template<int N> + inline PRBool LowerCaseEqualsLiteral( const char (&str)[N] ) const + { + return LowerCaseEqualsASCII(str, N-1); + } + template<int N> + inline PRBool LowerCaseEqualsLiteral( char (&str)[N] ) const + { + const char* s = str; + return LowerCaseEqualsASCII(s, N-1); + } +#endif + + /** + * assignment + */ + + void Assign( char_type c ) { Assign(&c, 1); } + NS_COM void NS_FASTCALL Assign( const char_type* data, size_type length = size_type(-1) ); + NS_COM void NS_FASTCALL Assign( const self_type& ); + NS_COM void NS_FASTCALL Assign( const substring_tuple_type& ); + NS_COM void NS_FASTCALL Assign( const abstract_string_type& ); + + NS_COM void NS_FASTCALL AssignASCII( const char* data, size_type length ); + NS_COM void NS_FASTCALL AssignASCII( const char* data ); + + // AssignLiteral must ONLY be applied to an actual literal string. + // Do not attempt to use it with a regular char* pointer, or with a char + // array variable. Use AssignASCII for those. +#ifdef NS_DISABLE_LITERAL_TEMPLATE + void AssignLiteral( const char* str ) + { AssignASCII(str); } +#else + template<int N> + void AssignLiteral( const char (&str)[N] ) + { AssignASCII(str, N-1); } + template<int N> + void AssignLiteral( char (&str)[N] ) + { AssignASCII(str, N-1); } +#endif + + self_type& operator=( char_type c ) { Assign(c); return *this; } + self_type& operator=( const char_type* data ) { Assign(data); return *this; } + self_type& operator=( const self_type& str ) { Assign(str); return *this; } + self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } + self_type& operator=( const abstract_string_type& readable ) { Assign(readable); return *this; } + + NS_COM void NS_FASTCALL Adopt( char_type* data, size_type length = size_type(-1) ); + + + /** + * buffer manipulation + */ + + void Replace( index_type cutStart, size_type cutLength, char_type c ) { Replace(cutStart, cutLength, &c, 1); } + NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length = size_type(-1) ); + void Replace( index_type cutStart, size_type cutLength, const self_type& str ) { Replace(cutStart, cutLength, str.Data(), str.Length()); } + NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple ); + NS_COM void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const abstract_string_type& readable ); + + NS_COM void NS_FASTCALL ReplaceASCII( index_type cutStart, size_type cutLength, const char* data, size_type length = size_type(-1) ); + + void Append( char_type c ) { Replace(mLength, 0, c); } + void Append( const char_type* data, size_type length = size_type(-1) ) { Replace(mLength, 0, data, length); } + void Append( const self_type& str ) { Replace(mLength, 0, str); } + void Append( const substring_tuple_type& tuple ) { Replace(mLength, 0, tuple); } + void Append( const abstract_string_type& readable ) { Replace(mLength, 0, readable); } + + void AppendASCII( const char* data, size_type length = size_type(-1) ) { ReplaceASCII(mLength, 0, data, length); } + + // AppendLiteral must ONLY be applied to an actual literal string. + // Do not attempt to use it with a regular char* pointer, or with a char + // array variable. Use AppendASCII for those. +#ifdef NS_DISABLE_LITERAL_TEMPLATE + void AppendLiteral( const char* str ) + { AppendASCII(str); } +#else + template<int N> + void AppendLiteral( const char (&str)[N] ) + { AppendASCII(str, N-1); } + template<int N> + void AppendLiteral( char (&str)[N] ) + { AppendASCII(str, N-1); } +#endif + + 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 self_type& str ) { Append(str); return *this; } + self_type& operator+=( const substring_tuple_type& tuple ) { Append(tuple); 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 self_type& str, index_type pos ) { Replace(pos, 0, str); } + void Insert( const substring_tuple_type& tuple, index_type pos ) { Replace(pos, 0, tuple); } + 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, char_traits::sEmptyBuffer, 0); } + + + /** + * buffer sizing + */ + + NS_COM void NS_FASTCALL SetCapacity( size_type capacity ); + + NS_COM void NS_FASTCALL SetLength( size_type ); + + void Truncate( size_type newLength = 0 ) + { + NS_ASSERTION(newLength <= mLength, "Truncate cannot make string longer"); + SetLength(newLength); + } + + + /** + * string data is never null, but can be marked void. if true, the + * string will be truncated. @see nsTSubstring::IsVoid + */ + + NS_COM void NS_FASTCALL SetIsVoid( PRBool ); + + + public: + + /** + * this is public to support automatic conversion of tuple to string + * base type, which helps avoid converting to nsTAString. + */ + nsTSubstring_CharT(const substring_tuple_type& tuple) + : abstract_string_type(nsnull, 0, F_NONE) + { + Assign(tuple); + } + + protected: + + friend class nsTObsoleteAStringThunk_CharT; + friend class nsTAString_CharT; + friend class nsTSubstringTuple_CharT; + + // XXX GCC 3.4 needs this :-( + friend class nsTPromiseFlatString_CharT; + + // default initialization + nsTSubstring_CharT() + : abstract_string_type( + NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer), 0, F_TERMINATED) {} + + // allow subclasses to initialize fields directly + nsTSubstring_CharT( char_type *data, size_type length, PRUint32 flags ) + : abstract_string_type(data, length, flags) {} + + // version of constructor that leaves mData and mLength uninitialized + explicit + nsTSubstring_CharT( PRUint32 flags ) + : abstract_string_type(flags) {} + + // copy-constructor, constructs as dependent on given object + // (NOTE: this is for internal use only) + nsTSubstring_CharT( const self_type& str ) + : abstract_string_type( + str.mData, str.mLength, str.mFlags & (F_TERMINATED | F_VOIDED)) {} + + /** + * this function releases mData and does not change the value of + * any of its member variables. inotherwords, this function acts + * like a destructor. + */ + void NS_FASTCALL Finalize(); + + /** + * this function prepares mData to be mutated. + * + * @param capacity specifies the required capacity of mData + * @param old_data returns null or the old value of mData + * @param old_flags returns 0 or the old value of mFlags + * + * if mData is already mutable and of sufficient capacity, then this + * function will return immediately. otherwise, it will either resize + * mData or allocate a new shared buffer. if it needs to allocate a + * new buffer, then it will return the old buffer and the corresponding + * flags. this allows the caller to decide when to free the old data. + * + * XXX we should expose a way for subclasses to free old_data. + */ + PRBool NS_FASTCALL MutatePrep( size_type capacity, char_type** old_data, PRUint32* old_flags ); + + /** + * this function prepares a section of mData to be modified. if + * necessary, this function will reallocate mData and possibly move + * existing data to open up the specified section. + * + * @param cutStart specifies the starting offset of the section + * @param cutLength specifies the length of the section to be replaced + * @param newLength specifies the length of the new section + * + * for example, suppose mData contains the string "abcdef" then + * + * ReplacePrep(2, 3, 4); + * + * would cause mData to look like "ab____f" where the characters + * indicated by '_' have an unspecified value and can be freely + * modified. this function will null-terminate mData upon return. + */ + void NS_FASTCALL ReplacePrep( index_type cutStart, size_type cutLength, size_type newLength ); + + /** + * returns the number of writable storage units starting at mData. + * the value does not include space for the null-terminator character. + * + * NOTE: this function returns size_type(-1) if mData is immutable. + */ + size_type NS_FASTCALL Capacity() const; + + /** + * this helper function can be called prior to directly manipulating + * the contents of mData. see, for example, BeginWriting. + */ + NS_COM void NS_FASTCALL EnsureMutable(); + + /** + * returns true if this string overlaps with the given string fragment. + */ + PRBool IsDependentOn( const char_type *start, const char_type *end ) const + { + /** + * if it _isn't_ the case that one fragment starts after the other ends, + * or ends before the other starts, then, they conflict: + * + * !(f2.begin >= f1.end || f2.end <= f1.begin) + * + * Simplified, that gives us: + */ + return ( start < (mData + mLength) && end > mData ); + } + + /** + * this helper function stores the specified dataFlags in mFlags + */ + void SetDataFlags(PRUint32 dataFlags) + { + NS_ASSERTION((dataFlags & 0xFFFF0000) == 0, "bad flags"); + mFlags = dataFlags | (mFlags & 0xFFFF0000); + } + + public: + + // mFlags is a bitwise combination of the following flags. the meaning + // and interpretation of these flags is an implementation detail. + // + // NOTE: these flags are declared public _only_ for convenience inside + // the string implementation. + + enum + { + F_NONE = 0, // no flags + + // data flags are in the lower 16-bits + F_TERMINATED = 1 << 0, // IsTerminated returns true + F_VOIDED = 1 << 1, // IsVoid returns true + F_SHARED = 1 << 2, // mData points to a heap-allocated, shared buffer + F_OWNED = 1 << 3, // mData points to a heap-allocated, raw buffer + F_FIXED = 1 << 4, // mData points to a fixed-size writable, dependent buffer + + // class flags are in the upper 16-bits + F_CLASS_FIXED = 1 << 16 // indicates that |this| is of type nsTFixedString + }; + + // + // Some terminology: + // + // "dependent buffer" A dependent buffer is one that the string class + // does not own. The string class relies on some + // external code to ensure the lifetime of the + // dependent buffer. + // + // "shared buffer" A shared buffer is one that the string class + // allocates. When it allocates a shared string + // buffer, it allocates some additional space at + // the beginning of the buffer for additional + // fields, including a reference count and a + // buffer length. See nsStringHeader. + // + // "adopted buffer" An adopted buffer is a raw string buffer + // allocated on the heap (using nsMemory::Alloc) + // of which the string class subsumes ownership. + // + // Some comments about the string flags: + // + // F_SHARED, F_OWNED, and F_FIXED are all mutually exlusive. They + // indicate the allocation type of mData. If none of these flags + // are set, then the string buffer is dependent. + // + // F_SHARED, F_OWNED, or F_FIXED imply F_TERMINATED. This is because + // the string classes always allocate null-terminated buffers, and + // non-terminated substrings are always dependent. + // + // F_VOIDED implies F_TERMINATED, and moreover it implies that mData + // points to char_traits::sEmptyBuffer. Therefore, F_VOIDED is + // mutually exclusive with F_SHARED, F_OWNED, and F_FIXED. + // + }; diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsTSubstringTuple.h b/src/libs/xpcom18a4/xpcom/string/public/nsTSubstringTuple.h new file mode 100644 index 00000000..2ded17d5 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsTSubstringTuple.h @@ -0,0 +1,113 @@ +/* -*- 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 ***** */ + + + /** + * nsTSubstringTuple_CharT + * + * Represents a tuple of string fragments. Built as a recursive binary tree. + * It is used to implement the concatenation of two or more string objects. + * + * NOTE: This class is a private implementation detail and should never be + * referenced outside the string code. + */ +class nsTSubstringTuple_CharT + { + public: + + typedef CharT char_type; + typedef nsCharTraits<char_type> char_traits; + + typedef nsTSubstringTuple_CharT self_type; + typedef nsTSubstring_CharT substring_type; + typedef nsTString_CharT string_type; + typedef nsTAString_CharT abstract_string_type; + typedef nsTObsoleteAString_CharT obsolete_string_type; + + typedef PRUint32 size_type; + + public: + + nsTSubstringTuple_CharT(const abstract_string_type* a, const abstract_string_type* b) + : mHead(nsnull) + , mFragA(a) + , mFragB(b) {} + + nsTSubstringTuple_CharT(const self_type& head, const abstract_string_type* b) + : mHead(&head) + , mFragA(nsnull) // this fragment is ignored when head != nsnull + , mFragB(b) {} + + /** + * computes the aggregate string length + */ + NS_COM size_type Length() const; + + /** + * writes the aggregate string to the given buffer. bufLen is assumed + * to be equal to or greater than the value returned by the Length() + * method. the string written to |buf| is not null-terminated. + */ + NS_COM void WriteTo(char_type *buf, PRUint32 bufLen) const; + + /** + * returns true if this tuple is dependent on (i.e., overlapping with) + * the given char sequence. + */ + NS_COM PRBool IsDependentOn(const char_type *start, const char_type *end) const; + + private: + + const self_type* mHead; + const abstract_string_type* mFragA; + const abstract_string_type* mFragB; + }; + +inline +const nsTSubstringTuple_CharT +operator+(const nsTAString_CharT& a, const nsTAString_CharT& b) + { + return nsTSubstringTuple_CharT(&a, &b); + } + +inline +const nsTSubstringTuple_CharT +operator+(const nsTSubstringTuple_CharT& head, const nsTAString_CharT& b) + { + return nsTSubstringTuple_CharT(head, &b); + } diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsUTF8Utils.h b/src/libs/xpcom18a4/xpcom/string/public/nsUTF8Utils.h new file mode 100644 index 00000000..c91079c2 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsUTF8Utils.h @@ -0,0 +1,462 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2001 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Peter Annema <jaggernaut@netscape.com> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 nsUTF8Utils_h_ +#define nsUTF8Utils_h_ + +class UTF8traits + { + public: + static PRBool isASCII(char c) { return (c & 0x80) == 0x00; } + static PRBool isInSeq(char c) { return (c & 0xC0) == 0x80; } + static PRBool is2byte(char c) { return (c & 0xE0) == 0xC0; } + static PRBool is3byte(char c) { return (c & 0xF0) == 0xE0; } + static PRBool is4byte(char c) { return (c & 0xF8) == 0xF0; } + static PRBool is5byte(char c) { return (c & 0xFC) == 0xF8; } + static PRBool is6byte(char c) { return (c & 0xFE) == 0xFC; } + }; + +#define PLANE1_BASE 0x00010000 +#define UCS2_REPLACEMENT_CHAR 0xfffd + +#ifdef __GNUC__ +#define NS_ALWAYS_INLINE __attribute__((always_inline)) +#else +#define NS_ALWAYS_INLINE +#endif + +/** + * A character sink (see |copy_string| in nsAlgorithm.h) for converting + * UTF-8 to UTF-16 + */ +class ConvertUTF8toUTF16 + { + public: + typedef nsACString::char_type value_type; + typedef nsAString::char_type buffer_type; + + ConvertUTF8toUTF16( buffer_type* aBuffer ) + : mStart(aBuffer), mBuffer(aBuffer), mErrorEncountered(PR_FALSE) {} + + size_t Length() const { return mBuffer - mStart; } + + PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N ) + { + if ( mErrorEncountered ) + return N; + + // algorithm assumes utf8 units won't + // be spread across fragments + const value_type* p = start; + const value_type* end = start + N; + buffer_type* out = mBuffer; + for ( ; p != end /* && *p */; ) + { + char c = *p++; + + if ( UTF8traits::isASCII(c) ) + { + *out++ = buffer_type(c); + continue; + } + + PRUint32 ucs4; + PRUint32 minUcs4; + PRInt32 state = 0; + + if ( UTF8traits::is2byte(c) ) + { + ucs4 = (PRUint32(c) << 6) & 0x000007C0L; + state = 1; + minUcs4 = 0x00000080; + } + else if ( UTF8traits::is3byte(c) ) + { + ucs4 = (PRUint32(c) << 12) & 0x0000F000L; + state = 2; + minUcs4 = 0x00000800; + } + else if ( UTF8traits::is4byte(c) ) + { + ucs4 = (PRUint32(c) << 18) & 0x001F0000L; + state = 3; + minUcs4 = 0x00010000; + } + else if ( UTF8traits::is5byte(c) ) + { + ucs4 = (PRUint32(c) << 24) & 0x03000000L; + state = 4; + minUcs4 = 0x00200000; + } + else if ( UTF8traits::is6byte(c) ) + { + ucs4 = (PRUint32(c) << 30) & 0x40000000L; + state = 5; + minUcs4 = 0x04000000; + } + else + { + NS_ERROR("Not a UTF-8 string. This code should only be used for converting from known UTF-8 strings."); + mErrorEncountered = PR_TRUE; + mBuffer = out; + return N; + } + + while ( state-- ) + { + c = *p++; + + if ( UTF8traits::isInSeq(c) ) + { + PRInt32 shift = state * 6; + ucs4 |= (PRUint32(c) & 0x3F) << shift; + } + else + { + NS_ERROR("not a UTF8 string"); + mErrorEncountered = PR_TRUE; + mBuffer = out; + return N; + } + } + + if ( ucs4 < minUcs4 ) + { + // Overlong sequence + *out++ = UCS2_REPLACEMENT_CHAR; + } + else if ( ucs4 <= 0xD7FF ) + { + *out++ = ucs4; + } + else if ( /* ucs4 >= 0xD800 && */ ucs4 <= 0xDFFF ) + { + // Surrogates + *out++ = UCS2_REPLACEMENT_CHAR; + } + else if ( ucs4 == 0xFFFE || ucs4 == 0xFFFF ) + { + // Prohibited characters + *out++ = UCS2_REPLACEMENT_CHAR; + } + else if ( ucs4 >= PLANE1_BASE ) + { + if ( ucs4 >= 0x00110000 ) + *out++ = UCS2_REPLACEMENT_CHAR; + else { + // surrogate, see unicode specification 3.7 for following math. + ucs4 -= PLANE1_BASE; + *out++ = (PRUnichar)(ucs4 >> 10) | 0xd800u; + *out++ = (PRUnichar)(ucs4 & 0x3ff) | 0xdc00u; + } + } + else + { + *out++ = ucs4; + } + } + mBuffer = out; + return p - start; + } + + void write_terminator() + { + *mBuffer = buffer_type(0); + } + + private: + buffer_type* const mStart; + buffer_type* mBuffer; + PRBool mErrorEncountered; + }; + +/** + * A character sink (see |copy_string| in nsAlgorithm.h) for computing + * the length of the UTF-16 string equivalent to a UTF-8 string. + */ +class CalculateUTF8Length + { + public: + typedef nsACString::char_type value_type; + + CalculateUTF8Length() : mLength(0), mErrorEncountered(PR_FALSE) { } + + size_t Length() const { return mLength; } + + PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N ) + { + // ignore any further requests + if ( mErrorEncountered ) + return N; + + // algorithm assumes utf8 units won't + // be spread across fragments + const value_type* p = start; + const value_type* end = start + N; + for ( ; p < end /* && *p */; ++mLength ) + { + if ( UTF8traits::isASCII(*p) ) + p += 1; + else if ( UTF8traits::is2byte(*p) ) + p += 2; + else if ( UTF8traits::is3byte(*p) ) + p += 3; + else if ( UTF8traits::is4byte(*p) ) { + p += 4; + // Because a UTF-8 sequence of 4 bytes represents a codepoint + // greater than 0xFFFF, it will become a surrogate pair in the + // UTF-16 string, so add 1 more to mLength. + // This doesn't happen with is5byte and is6byte because they + // are illegal UTF-8 sequences (greater than 0x10FFFF) so get + // converted to a single replacement character. + // + // XXX: if the 4-byte sequence is an illegal non-shortest form, + // it also gets converted to a replacement character, so + // mLength will be off by one in this case. + ++mLength; + } + else if ( UTF8traits::is5byte(*p) ) + p += 5; + else if ( UTF8traits::is6byte(*p) ) + p += 6; + else + { + break; + } + } + if ( p != end ) + { + NS_ERROR("Not a UTF-8 string. This code should only be used for converting from known UTF-8 strings."); + mErrorEncountered = PR_TRUE; + mLength = 0; + return N; + } + return p - start; + } + + private: + size_t mLength; + PRBool mErrorEncountered; + }; + +/** + * A character sink (see |copy_string| in nsAlgorithm.h) for converting + * UTF-16 to UTF-8. + */ +class ConvertUTF16toUTF8 + { + public: + typedef nsAString::char_type value_type; + typedef nsACString::char_type buffer_type; + + // The error handling here is more lenient than that in + // |ConvertUTF8toUTF16|, but it's that way for backwards + // compatibility. + + ConvertUTF16toUTF8( buffer_type* aBuffer ) + : mStart(aBuffer), mBuffer(aBuffer) {} + + size_t Size() const { return mBuffer - mStart; } + + PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N ) + { + buffer_type *out = mBuffer; // gcc isn't smart enough to do this! + + for (const value_type *p = start, *end = start + N; p < end; ++p ) + { + value_type c = *p; + if (! (c & 0xFF80)) // U+0000 - U+007F + { + *out++ = (char)c; + } + else if (! (c & 0xF800)) // U+0100 - U+07FF + { + *out++ = 0xC0 | (char)(c >> 6); + *out++ = 0x80 | (char)(0x003F & c); + } + else if (0xD800 != (0xF800 & c)) // U+0800 - U+D7FF,U+E000 - U+FFFF + { + *out++ = 0xE0 | (char)(c >> 12); + *out++ = 0x80 | (char)(0x003F & (c >> 6)); + *out++ = 0x80 | (char)(0x003F & c ); + } + else if (0xD800 == (0xFC00 & c)) // U+D800 - U+DBFF + { + // D800- DBFF - High Surrogate + // N = (H- D800) *400 + 10000 + ... + PRUint32 ucs4 = 0x10000 + ((0x03FF & c) << 10); + + ++p; + if (p == end) + { + NS_ERROR("Surrogate pair split between fragments"); + mBuffer = out; + return N; + } + c = *p; + + if (0xDC00 == (0xFC00 & c)) + { + // DC00- DFFF - Low Surrogate + // N += ( L - DC00 ) + ucs4 |= (0x03FF & c); + + // 0001 0000-001F FFFF + *out++ = 0xF0 | (char)(ucs4 >> 18); + *out++ = 0x80 | (char)(0x003F & (ucs4 >> 12)); + *out++ = 0x80 | (char)(0x003F & (ucs4 >> 6)); + *out++ = 0x80 | (char)(0x003F & ucs4); + } + else + { + NS_ERROR("got a High Surrogate but no low surrogate"); + // output nothing. + } + } + else // U+DC00 - U+DFFF + { + // DC00- DFFF - Low Surrogate + NS_ERROR("got a low Surrogate but no high surrogate"); + // output nothing. + } + } + + mBuffer = out; + return N; + } + + void write_terminator() + { + *mBuffer = buffer_type(0); + } + + private: + buffer_type* const mStart; + buffer_type* mBuffer; + }; + +/** + * A character sink (see |copy_string| in nsAlgorithm.h) for computing + * the number of bytes a UTF-16 would occupy in UTF-8. + */ +class CalculateUTF8Size + { + public: + typedef nsAString::char_type value_type; + + CalculateUTF8Size() + : mSize(0) { } + + size_t Size() const { return mSize; } + + PRUint32 NS_ALWAYS_INLINE write( const value_type* start, PRUint32 N ) + { + // Assume UCS2 surrogate pairs won't be spread across fragments. + for (const value_type *p = start, *end = start + N; p < end; ++p ) + { + value_type c = *p; + if (! (c & 0xFF80)) // U+0000 - U+007F + mSize += 1; + else if (! (c & 0xF800)) // U+0100 - U+07FF + mSize += 2; + else if (0xD800 != (0xF800 & c)) // U+0800 - U+D7FF,U+E000 - U+FFFF + mSize += 3; + else if (0xD800 == (0xFC00 & c)) // U+D800 - U+DBFF + { + ++p; + if (p == end) + { + NS_ERROR("Surrogate pair split between fragments"); + return N; + } + c = *p; + + if (0xDC00 == (0xFC00 & c)) + mSize += 4; + else + NS_ERROR("got a high Surrogate but no low surrogate"); + } + else // U+DC00 - U+DFFF + NS_ERROR("got a low Surrogate but no high surrogate"); + } + + return N; + } + + private: + size_t mSize; + }; + +/** + * A character sink that performs a |reinterpret_cast| style conversion + * between character types. + */ +template <class FromCharT, class ToCharT> +class LossyConvertEncoding + { + public: + typedef FromCharT value_type; + + typedef FromCharT input_type; + typedef ToCharT output_type; + + typedef typename nsCharTraits<FromCharT>::unsigned_char_type unsigned_input_type; + + public: + LossyConvertEncoding( output_type* aDestination ) : mDestination(aDestination) { } + + PRUint32 + write( const input_type* aSource, PRUint32 aSourceLength ) + { + const input_type* done_writing = aSource + aSourceLength; + while ( aSource < done_writing ) + *mDestination++ = (output_type)(unsigned_input_type)(*aSource++); // use old-style cast to mimic old |ns[C]String| behavior + return aSourceLength; + } + + void + write_terminator() + { + *mDestination = output_type(0); + } + + private: + output_type* mDestination; + }; + +#endif /* !defined(nsUTF8Utils_h_) */ diff --git a/src/libs/xpcom18a4/xpcom/string/public/nsXPIDLString.h b/src/libs/xpcom18a4/xpcom/string/public/nsXPIDLString.h new file mode 100644 index 00000000..c66a2d7a --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/nsXPIDLString.h @@ -0,0 +1,46 @@ +/* -*- 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 nsXPIDLString_h___ +#define nsXPIDLString_h___ + +#ifndef nsString_h___ +#include "nsString.h" +#endif + +#endif /* !defined(nsXPIDLString_h___) */ diff --git a/src/libs/xpcom18a4/xpcom/string/public/string-template-def-char.h b/src/libs/xpcom18a4/xpcom/string/public/string-template-def-char.h new file mode 100644 index 00000000..d0f3a907 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/string-template-def-char.h @@ -0,0 +1,58 @@ +/* -*- 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 ***** */ + +#define CharT char +#define CharT_is_char 1 +#define nsTObsoleteAString_CharT nsObsoleteACString +#define nsTObsoleteAStringThunk_CharT nsObsoleteACStringThunk +#define nsTAString_CharT nsACString +#define nsTAString_IncompatibleCharT nsAString +#define nsTString_CharT nsCString +#define nsTFixedString_CharT nsFixedCString +#define nsTAutoString_CharT nsCAutoString +#define nsTSubstring_CharT nsCSubstring +#define nsTSubstringTuple_CharT nsCSubstringTuple +#define nsTStringComparator_CharT nsCStringComparator +#define nsTDefaultStringComparator_CharT nsDefaultCStringComparator +#define nsTDependentString_CharT nsDependentCString +#define nsTDependentSubstring_CharT nsDependentCSubstring +#define nsTXPIDLString_CharT nsXPIDLCString +#define nsTGetterCopies_CharT nsCGetterCopies +#define nsTAdoptingString_CharT nsAdoptingCString +#define nsTPromiseFlatString_CharT nsPromiseFlatCString +#define TPromiseFlatString_CharT PromiseFlatCString diff --git a/src/libs/xpcom18a4/xpcom/string/public/string-template-def-unichar.h b/src/libs/xpcom18a4/xpcom/string/public/string-template-def-unichar.h new file mode 100644 index 00000000..c966dfbe --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/string-template-def-unichar.h @@ -0,0 +1,58 @@ +/* -*- 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 ***** */ + +#define CharT PRUnichar +#define CharT_is_PRUnichar 1 +#define nsTObsoleteAString_CharT nsObsoleteAString +#define nsTObsoleteAStringThunk_CharT nsObsoleteAStringThunk +#define nsTAString_CharT nsAString +#define nsTAString_IncompatibleCharT nsACString +#define nsTString_CharT nsString +#define nsTFixedString_CharT nsFixedString +#define nsTAutoString_CharT nsAutoString +#define nsTSubstring_CharT nsSubstring +#define nsTSubstringTuple_CharT nsSubstringTuple +#define nsTStringComparator_CharT nsStringComparator +#define nsTDefaultStringComparator_CharT nsDefaultStringComparator +#define nsTDependentString_CharT nsDependentString +#define nsTDependentSubstring_CharT nsDependentSubstring +#define nsTXPIDLString_CharT nsXPIDLString +#define nsTGetterCopies_CharT nsGetterCopies +#define nsTAdoptingString_CharT nsAdoptingString +#define nsTPromiseFlatString_CharT nsPromiseFlatString +#define TPromiseFlatString_CharT PromiseFlatString diff --git a/src/libs/xpcom18a4/xpcom/string/public/string-template-undef.h b/src/libs/xpcom18a4/xpcom/string/public/string-template-undef.h new file mode 100644 index 00000000..45344370 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/public/string-template-undef.h @@ -0,0 +1,59 @@ +/* -*- 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 ***** */ + +#undef CharT +#undef CharT_is_PRUnichar +#undef CharT_is_char +#undef nsTObsoleteAString_CharT +#undef nsTObsoleteAStringThunk_CharT +#undef nsTAString_CharT +#undef nsTAString_IncompatibleCharT +#undef nsTString_CharT +#undef nsTFixedString_CharT +#undef nsTAutoString_CharT +#undef nsTSubstring_CharT +#undef nsTSubstringTuple_CharT +#undef nsTStringComparator_CharT +#undef nsTDefaultStringComparator_CharT +#undef nsTDependentString_CharT +#undef nsTDependentSubstring_CharT +#undef nsTXPIDLString_CharT +#undef nsTGetterCopies_CharT +#undef nsTAdoptingString_CharT +#undef nsTPromiseFlatString_CharT +#undef TPromiseFlatString_CharT diff --git a/src/libs/xpcom18a4/xpcom/string/src/.cvsignore b/src/libs/xpcom18a4/xpcom/string/src/.cvsignore new file mode 100644 index 00000000..f3c7a7c5 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/src/libs/xpcom18a4/xpcom/string/src/Makefile.in b/src/libs/xpcom18a4/xpcom/string/src/Makefile.in new file mode 100644 index 00000000..81033c6c --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/Makefile.in @@ -0,0 +1,77 @@ +# vim:set ts=8 sw=8 sts=8 noet: +# +# ***** 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 +# Netscape Communications. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Johnny Stenback <jst@netscape.com> (original author) +# Scott Collins <scc@mozilla.org> +# +# Alternatively, the contents of this file may be used under the terms of +# either of 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 ***** + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = string +LIBRARY_NAME = string_s + +REQUIRES = xpcom \ + $(NULL) + +CPPSRCS = \ + nsAString.cpp \ + nsDependentSubstring.cpp \ + nsObsoleteAStringThunk.cpp \ + nsPrintfCString.cpp \ + nsPromiseFlatString.cpp \ + nsReadableUtils.cpp \ + nsSubstring.cpp \ + nsSubstringTuple.cpp \ + nsString.cpp \ + nsStringComparator.cpp \ + nsStringObsolete.cpp \ + $(NULL) + +# we don't want the shared lib, but we want to force the creation of a +# static lib. +FORCE_STATIC_LIB = 1 + +# Force use of PIC +FORCE_USE_PIC = 1 + +include $(topsrcdir)/config/rules.mk + +DEFINES += -D_IMPL_NS_COM diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsAString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsAString.cpp new file mode 100644 index 00000000..5b481662 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsAString.cpp @@ -0,0 +1,51 @@ +/* -*- 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 ***** */ + +#include "nsAString.h" +#include "nsObsoleteAString.h" +#include "nsString.h" + + // define nsAString +#include "string-template-def-unichar.h" +#include "nsTAString.cpp" +#include "string-template-undef.h" + + // define nsACString +#include "string-template-def-char.h" +#include "nsTAString.cpp" +#include "string-template-undef.h" diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsDependentSubstring.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsDependentSubstring.cpp new file mode 100644 index 00000000..971defc8 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsDependentSubstring.cpp @@ -0,0 +1,50 @@ +/* -*- 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 ***** */ + +#include "nsDependentSubstring.h" +#include "nsAlgorithm.h" + + // define nsDependentSubstring +#include "string-template-def-unichar.h" +#include "nsTDependentSubstring.cpp" +#include "string-template-undef.h" + + // define nsDependentCSubstring +#include "string-template-def-char.h" +#include "nsTDependentSubstring.cpp" +#include "string-template-undef.h" diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsObsoleteAStringThunk.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsObsoleteAStringThunk.cpp new file mode 100644 index 00000000..8b511d1e --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsObsoleteAStringThunk.cpp @@ -0,0 +1,52 @@ +/* -*- 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 ***** */ + +#include "nsObsoleteAString.h" +#include "nsString.h" + + + // define nsObsoleteAStringThunk +#include "string-template-def-unichar.h" +#include "nsTObsoleteAStringThunk.cpp" +#include "string-template-undef.h" + + + // define nsObsoleteACStringThunk +#include "string-template-def-char.h" +#include "nsTObsoleteAStringThunk.cpp" +#include "string-template-undef.h" diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsPrintfCString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsPrintfCString.cpp new file mode 100644 index 00000000..8bb06da6 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsPrintfCString.cpp @@ -0,0 +1,83 @@ +/* -*- 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.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsPrintfCString.h" +#include <stdarg.h> +#include "prprf.h" + + +// though these classes define a fixed buffer, they do not set the F_FIXED +// flag. this is because they are not intended to be modified after they have +// been constructed. we could change this but it would require adding a new +// class to the hierarchy, one that both this class and nsCAutoString would +// inherit from. for now, we populate the fixed buffer, and then let the +// nsCString code treat the buffer as if it were a dependent buffer. + +nsPrintfCString::nsPrintfCString( const char_type* format, ... ) + : string_type(mLocalBuffer, 0, F_TERMINATED) + { + va_list ap; + + size_type logical_capacity = kLocalBufferSize; + size_type physical_capacity = logical_capacity + 1; + + va_start(ap, format); + mLength = PR_vsnprintf(mData, physical_capacity, format, ap); + va_end(ap); + } + +nsPrintfCString::nsPrintfCString( size_type n, const char_type* format, ... ) + : string_type(mLocalBuffer, 0, F_TERMINATED) + { + va_list ap; + + // make sure there's at least |n| space + size_type logical_capacity = kLocalBufferSize; + if ( n > logical_capacity ) + { + SetCapacity(n); + if (Capacity() < n) + return; // out of memory !! + logical_capacity = n; + } + size_type physical_capacity = logical_capacity + 1; + + va_start(ap, format); + mLength = PR_vsnprintf(mData, physical_capacity, format, ap); + va_end(ap); + } diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsPromiseFlatString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsPromiseFlatString.cpp new file mode 100644 index 00000000..aab4f209 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsPromiseFlatString.cpp @@ -0,0 +1,49 @@ +/* -*- 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 ***** */ + +#include "nsPromiseFlatString.h" + + // define nsPromiseFlatString +#include "string-template-def-unichar.h" +#include "nsTPromiseFlatString.cpp" +#include "string-template-undef.h" + + // define nsPromiseFlatCString +#include "string-template-def-char.h" +#include "nsTPromiseFlatString.cpp" +#include "string-template-undef.h" diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsReadableUtils.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsReadableUtils.cpp new file mode 100644 index 00000000..24305b6a --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsReadableUtils.cpp @@ -0,0 +1,1122 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Scott Collins <scc@mozilla.org> (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsReadableUtils.h" +#include "nsMemory.h" +#include "nsString.h" +#include "nsUTF8Utils.h" + +NS_COM +void +LossyCopyUTF16toASCII( const nsAString& aSource, nsACString& aDest ) + { + aDest.Truncate(); + LossyAppendUTF16toASCII(aSource, aDest); + } + +NS_COM +void +CopyASCIItoUTF16( const nsACString& aSource, nsAString& aDest ) + { + aDest.Truncate(); + AppendASCIItoUTF16(aSource, aDest); + } + +NS_COM +void +LossyCopyUTF16toASCII( const PRUnichar* aSource, nsACString& aDest ) + { + aDest.Truncate(); + if (aSource) { + LossyAppendUTF16toASCII(nsDependentString(aSource), aDest); + } + } + +NS_COM +void +CopyASCIItoUTF16( const char* aSource, nsAString& aDest ) + { + aDest.Truncate(); + if (aSource) { + AppendASCIItoUTF16(nsDependentCString(aSource), aDest); + } + } + +NS_COM +void +CopyUTF16toUTF8( const nsAString& aSource, nsACString& aDest ) + { + aDest.Truncate(); + AppendUTF16toUTF8(aSource, aDest); + } + +NS_COM +void +CopyUTF8toUTF16( const nsACString& aSource, nsAString& aDest ) + { + aDest.Truncate(); + AppendUTF8toUTF16(aSource, aDest); + } + +NS_COM +void +CopyUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest ) + { + aDest.Truncate(); + AppendUTF16toUTF8(aSource, aDest); + } + +NS_COM +void +CopyUTF8toUTF16( const char* aSource, nsAString& aDest ) + { + aDest.Truncate(); + AppendUTF8toUTF16(aSource, aDest); + } + +NS_COM +void +LossyAppendUTF16toASCII( const nsAString& aSource, nsACString& aDest ) + { + PRUint32 old_dest_length = aDest.Length(); + aDest.SetLength(old_dest_length + aSource.Length()); + + nsAString::const_iterator fromBegin, fromEnd; + + nsACString::iterator dest; + aDest.BeginWriting(dest); + + dest.advance(old_dest_length); + + // right now, this won't work on multi-fragment destinations + LossyConvertEncoding<PRUnichar, char> converter(dest.get()); + + copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter); + } + +NS_COM +void +AppendASCIItoUTF16( const nsACString& aSource, nsAString& aDest ) + { + PRUint32 old_dest_length = aDest.Length(); + aDest.SetLength(old_dest_length + aSource.Length()); + + nsACString::const_iterator fromBegin, fromEnd; + + nsAString::iterator dest; + aDest.BeginWriting(dest); + + dest.advance(old_dest_length); + + // right now, this won't work on multi-fragment destinations + LossyConvertEncoding<char, PRUnichar> converter(dest.get()); + + copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter); + } + +NS_COM +void +LossyAppendUTF16toASCII( const PRUnichar* aSource, nsACString& aDest ) + { + if (aSource) { + LossyAppendUTF16toASCII(nsDependentString(aSource), aDest); + } + } + +NS_COM +void +AppendASCIItoUTF16( const char* aSource, nsAString& aDest ) + { + if (aSource) { + AppendASCIItoUTF16(nsDependentCString(aSource), aDest); + } + } + +NS_COM +void +AppendUTF16toUTF8( const nsAString& aSource, nsACString& aDest ) + { + nsAString::const_iterator source_start, source_end; + CalculateUTF8Size calculator; + copy_string(aSource.BeginReading(source_start), + aSource.EndReading(source_end), calculator); + + PRUint32 count = calculator.Size(); + + if (count) + { + PRUint32 old_dest_length = aDest.Length(); + + // Grow the buffer if we need to. + aDest.SetLength(old_dest_length + count); + + nsACString::iterator dest; + aDest.BeginWriting(dest); + + dest.advance(old_dest_length); + + if (count <= (PRUint32)dest.size_forward()) + { + // aDest has enough room in the fragment just past the end + // of its old data that it can hold what we're about to + // append. Append using copy_string(). + + // All ready? Time to convert + + ConvertUTF16toUTF8 converter(dest.get()); + copy_string(aSource.BeginReading(source_start), + aSource.EndReading(source_end), converter); + + if (converter.Size() != count) + { + NS_ERROR("Input invalid or incorrect length was calculated"); + + aDest.SetLength(old_dest_length); + } + } + else + { + // This isn't the fastest way to do this, but it gets + // complicated to convert UTF16 into a fragmented UTF8 + // string, so we'll take the easy way out here in this + // rare situation. + + aDest.Replace(old_dest_length, count, + NS_ConvertUTF16toUTF8(aSource)); + } + } + } + +NS_COM +void +AppendUTF8toUTF16( const nsACString& aSource, nsAString& aDest ) + { + nsACString::const_iterator source_start, source_end; + CalculateUTF8Length calculator; + copy_string(aSource.BeginReading(source_start), + aSource.EndReading(source_end), calculator); + + PRUint32 count = calculator.Length(); + + if (count) + { + PRUint32 old_dest_length = aDest.Length(); + + // Grow the buffer if we need to. + aDest.SetLength(old_dest_length + count); + + nsAString::iterator dest; + aDest.BeginWriting(dest); + + dest.advance(old_dest_length); + + if (count <= (PRUint32)dest.size_forward()) + { + // aDest has enough room in the fragment just past the end + // of its old data that it can hold what we're about to + // append. Append using copy_string(). + + // All ready? Time to convert + + ConvertUTF8toUTF16 converter(dest.get()); + copy_string(aSource.BeginReading(source_start), + aSource.EndReading(source_end), converter); + + if (converter.Length() != count) + { + NS_ERROR("Input wasn't UTF8 or incorrect length was calculated"); + aDest.SetLength(old_dest_length); + } + } + else + { + // This isn't the fastest way to do this, but it gets + // complicated to convert parts of a UTF8 string into a + // UTF16 string, so we'll take the easy way out here in + // this rare situation. + + aDest.Replace(old_dest_length, count, + NS_ConvertUTF8toUTF16(aSource)); + } + } + } + +NS_COM +void +AppendUTF16toUTF8( const PRUnichar* aSource, nsACString& aDest ) + { + if (aSource) { + AppendUTF16toUTF8(nsDependentString(aSource), aDest); + } + } + +NS_COM +void +AppendUTF8toUTF16( const char* aSource, nsAString& aDest ) + { + if (aSource) { + AppendUTF8toUTF16(nsDependentCString(aSource), aDest); + } + } + + + /** + * A helper function that allocates a buffer of the desired character type big enough to hold a copy of the supplied string (plus a zero terminator). + * + * @param aSource an string you will eventually be making a copy of + * @return a new buffer (of the type specified by the second parameter) which you must free with |nsMemory::Free|. + * + */ +template <class FromStringT, class ToCharT> +inline +ToCharT* +AllocateStringCopy( const FromStringT& aSource, ToCharT* ) + { + return NS_STATIC_CAST(ToCharT*, nsMemory::Alloc((aSource.Length()+1) * sizeof(ToCharT))); + } + + +NS_COM +char* +ToNewCString( const nsAString& aSource ) + { + char* result = AllocateStringCopy(aSource, (char*)0); + + nsAString::const_iterator fromBegin, fromEnd; + LossyConvertEncoding<PRUnichar, char> converter(result); + copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter).write_terminator(); + return result; + } + +NS_COM +char* +ToNewUTF8String( const nsAString& aSource, PRUint32 *aUTF8Count ) + { + nsAString::const_iterator start, end; + CalculateUTF8Size calculator; + copy_string(aSource.BeginReading(start), aSource.EndReading(end), + calculator); + + if (aUTF8Count) + *aUTF8Count = calculator.Size(); + + char *result = NS_STATIC_CAST(char*, + nsMemory::Alloc(calculator.Size() + 1)); + + ConvertUTF16toUTF8 converter(result); + copy_string(aSource.BeginReading(start), aSource.EndReading(end), + converter).write_terminator(); + NS_ASSERTION(calculator.Size() == converter.Size(), "length mismatch"); + + return result; + } + +NS_COM +char* +ToNewCString( const nsACString& aSource ) + { + // no conversion needed, just allocate a buffer of the correct length and copy into it + + char* result = AllocateStringCopy(aSource, (char*)0); + + nsACString::const_iterator fromBegin, fromEnd; + char* toBegin = result; + *copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), toBegin) = char(0); + return result; + } + +NS_COM +PRUnichar* +ToNewUnicode( const nsAString& aSource ) + { + // no conversion needed, just allocate a buffer of the correct length and copy into it + + PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0); + + nsAString::const_iterator fromBegin, fromEnd; + PRUnichar* toBegin = result; + *copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), toBegin) = PRUnichar(0); + return result; + } + +NS_COM +PRUnichar* +ToNewUnicode( const nsACString& aSource ) + { + PRUnichar* result = AllocateStringCopy(aSource, (PRUnichar*)0); + + nsACString::const_iterator fromBegin, fromEnd; + LossyConvertEncoding<char, PRUnichar> converter(result); + copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter).write_terminator(); + return result; + } + +NS_COM +PRUnichar* +UTF8ToNewUnicode( const nsACString& aSource, PRUint32 *aUTF16Count ) + { + nsACString::const_iterator start, end; + CalculateUTF8Length calculator; + copy_string(aSource.BeginReading(start), aSource.EndReading(end), + calculator); + + if (aUTF16Count) + *aUTF16Count = calculator.Length(); + + PRUnichar *result = NS_STATIC_CAST(PRUnichar*, + nsMemory::Alloc(sizeof(PRUnichar) * (calculator.Length() + 1))); + + ConvertUTF8toUTF16 converter(result); + copy_string(aSource.BeginReading(start), aSource.EndReading(end), + converter).write_terminator(); + NS_ASSERTION(calculator.Length() == converter.Length(), "length mismatch"); + + return result; + } + +NS_COM +PRUnichar* +CopyUnicodeTo( const nsAString& aSource, PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength ) + { + nsAString::const_iterator fromBegin, fromEnd; + PRUnichar* toBegin = aDest; + copy_string(aSource.BeginReading(fromBegin).advance( PRInt32(aSrcOffset) ), aSource.BeginReading(fromEnd).advance( PRInt32(aSrcOffset+aLength) ), toBegin); + return aDest; + } + +NS_COM +void +CopyUnicodeTo( const nsAString::const_iterator& aSrcStart, + const nsAString::const_iterator& aSrcEnd, + nsAString& aDest ) + { + nsAString::iterator writer; + aDest.SetLength(Distance(aSrcStart, aSrcEnd)); + aDest.BeginWriting(writer); + nsAString::const_iterator fromBegin(aSrcStart); + + copy_string(fromBegin, aSrcEnd, writer); + } + +NS_COM +void +AppendUnicodeTo( const nsAString::const_iterator& aSrcStart, + const nsAString::const_iterator& aSrcEnd, + nsAString& aDest ) + { + nsAString::iterator writer; + PRUint32 oldLength = aDest.Length(); + aDest.SetLength(oldLength + Distance(aSrcStart, aSrcEnd)); + aDest.BeginWriting(writer).advance(oldLength); + nsAString::const_iterator fromBegin(aSrcStart); + + copy_string(fromBegin, aSrcEnd, writer); + } + +NS_COM +PRBool +IsASCII( const nsAString& aString ) + { + static const PRUnichar NOT_ASCII = PRUnichar(~0x007F); + + + // Don't want to use |copy_string| for this task, since we can stop at the first non-ASCII character + + nsAString::const_iterator done_reading; + aString.EndReading(done_reading); + + // for each chunk of |aString|... + PRUint32 fragmentLength = 0; + nsAString::const_iterator iter; + for ( aString.BeginReading(iter); iter != done_reading; iter.advance( PRInt32(fragmentLength) ) ) + { + fragmentLength = PRUint32(iter.size_forward()); + const PRUnichar* c = iter.get(); + const PRUnichar* fragmentEnd = c + fragmentLength; + + // for each character in this chunk... + while ( c < fragmentEnd ) + if ( *c++ & NOT_ASCII ) + return PR_FALSE; + } + + return PR_TRUE; + } + +NS_COM +PRBool +IsASCII( const nsACString& aString ) + { + static const char NOT_ASCII = char(~0x7F); + + + // Don't want to use |copy_string| for this task, since we can stop at the first non-ASCII character + + nsACString::const_iterator done_reading; + aString.EndReading(done_reading); + + // for each chunk of |aString|... + PRUint32 fragmentLength = 0; + nsACString::const_iterator iter; + for ( aString.BeginReading(iter); iter != done_reading; iter.advance( PRInt32(fragmentLength) ) ) + { + fragmentLength = PRUint32(iter.size_forward()); + const char* c = iter.get(); + const char* fragmentEnd = c + fragmentLength; + + // for each character in this chunk... + while ( c < fragmentEnd ) + if ( *c++ & NOT_ASCII ) + return PR_FALSE; + } + + return PR_TRUE; + } + +NS_COM +PRBool +IsUTF8( const nsACString& aString ) + { + nsReadingIterator<char> done_reading; + aString.EndReading(done_reading); + + PRInt32 state = 0; + PRBool overlong = PR_FALSE; + PRBool surrogate = PR_FALSE; + PRBool nonchar = PR_FALSE; + PRUint16 olupper = 0; // overlong byte upper bound. + PRUint16 slower = 0; // surrogate byte lower bound. + + // for each chunk of |aString|... + PRUint32 fragmentLength = 0; + nsReadingIterator<char> iter; + + for ( aString.BeginReading(iter); iter != done_reading; iter.advance( PRInt32(fragmentLength) ) ) + { + fragmentLength = PRUint32(iter.size_forward()); + const char* ptr = iter.get(); + const char* fragmentEnd = ptr + fragmentLength; + + // for each character in this chunk... + while ( ptr < fragmentEnd ) + { + PRUint8 c; + + if (0 == state) + { + c = *ptr++; + + if ( UTF8traits::isASCII(c) ) + continue; + + if ( c <= 0xC1 ) // [80-BF] where not expected, [C0-C1] for overlong. + return PR_FALSE; + else if ( UTF8traits::is2byte(c) ) + state = 1; + else if ( UTF8traits::is3byte(c) ) + { + state = 2; + if ( c == 0xE0 ) // to exclude E0[80-9F][80-BF] + { + overlong = PR_TRUE; + olupper = 0x9F; + } + else if ( c == 0xED ) // ED[A0-BF][80-BF] : surrogate codepoint + { + surrogate = PR_TRUE; + slower = 0xA0; + } + else if ( c == 0xEF ) // EF BF [BE-BF] : non-character + nonchar = PR_TRUE; + } + else if ( c <= 0xF4 ) // XXX replace /w UTF8traits::is4byte when it's updated to exclude [F5-F7].(bug 199090) + { + state = 3; + nonchar = PR_TRUE; + if ( c == 0xF0 ) // to exclude F0[80-8F][80-BF]{2} + { + overlong = PR_TRUE; + olupper = 0x8F; + } + else if ( c == 0xF4 ) // to exclude F4[90-BF][80-BF] + { + // actually not surrogates but codepoints beyond 0x10FFFF + surrogate = PR_TRUE; + slower = 0x90; + } + } + else + return PR_FALSE; // Not UTF-8 string + } + + while (ptr < fragmentEnd && state) + { + c = *ptr++; + --state; + + // non-character : EF BF [BE-BF] or F[0-7] [89AB]F BF [BE-BF] + if ( nonchar && ( (!state && c < 0xBE) || + (state == 1 && c != 0xBF) || + (state == 2 && 0x0F != (0x0F & c)) )) + nonchar = PR_FALSE; + + if ( !UTF8traits::isInSeq(c) || (overlong && c <= olupper) || + (surrogate && slower <= c) || (nonchar && !state) ) + return PR_FALSE; // Not UTF-8 string + overlong = surrogate = PR_FALSE; + } + } + } + return !state; // state != 0 at the end indicates an invalid UTF-8 seq. + } + + /** + * A character sink for in-place case conversion. + */ +class ConvertToUpperCase + { + public: + typedef char value_type; + + PRUint32 + write( const char* aSource, PRUint32 aSourceLength ) + { + char* cp = NS_CONST_CAST(char*,aSource); + const char* end = aSource + aSourceLength; + while (cp != end) { + char ch = *cp; + if ((ch >= 'a') && (ch <= 'z')) + *cp = ch - ('a' - 'A'); + ++cp; + } + return aSourceLength; + } + }; + +NS_COM +void +ToUpperCase( nsACString& aCString ) + { + nsACString::iterator fromBegin, fromEnd; + ConvertToUpperCase converter; + copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter); + } + +NS_COM +void +ToUpperCase( nsCSubstring& aCString ) + { + ConvertToUpperCase converter; + char* start; + converter.write(aCString.BeginWriting(start), aCString.Length()); + } + + /** + * A character sink for copying with case conversion. + */ +class CopyToUpperCase + { + public: + typedef char value_type; + + CopyToUpperCase( nsACString::iterator& aDestIter ) + : mIter(aDestIter) + { + } + + PRUint32 + write( const char* aSource, PRUint32 aSourceLength ) + { + PRUint32 len = PR_MIN(PRUint32(mIter.size_forward()), aSourceLength); + char* cp = mIter.get(); + const char* end = aSource + len; + while (aSource != end) { + char ch = *aSource; + if ((ch >= 'a') && (ch <= 'z')) + *cp = ch - ('a' - 'A'); + else + *cp = ch; + ++aSource; + ++cp; + } + mIter.advance(len); + return len; + } + + protected: + nsACString::iterator& mIter; + }; + +NS_COM +void +ToUpperCase( const nsACString& aSource, nsACString& aDest ) + { + nsACString::const_iterator fromBegin, fromEnd; + nsACString::iterator toBegin; + aDest.SetLength(aSource.Length()); + CopyToUpperCase converter(aDest.BeginWriting(toBegin)); + copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter); + } + + /** + * A character sink for case conversion. + */ +class ConvertToLowerCase + { + public: + typedef char value_type; + + PRUint32 + write( const char* aSource, PRUint32 aSourceLength ) + { + char* cp = NS_CONST_CAST(char*,aSource); + const char* end = aSource + aSourceLength; + while (cp != end) { + char ch = *cp; + if ((ch >= 'A') && (ch <= 'Z')) + *cp = ch + ('a' - 'A'); + ++cp; + } + return aSourceLength; + } + }; + +NS_COM +void +ToLowerCase( nsACString& aCString ) + { + nsACString::iterator fromBegin, fromEnd; + ConvertToLowerCase converter; + copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter); + } + +NS_COM +void +ToLowerCase( nsCSubstring& aCString ) + { + ConvertToLowerCase converter; + char* start; + converter.write(aCString.BeginWriting(start), aCString.Length()); + } + + /** + * A character sink for copying with case conversion. + */ +class CopyToLowerCase + { + public: + typedef char value_type; + + CopyToLowerCase( nsACString::iterator& aDestIter ) + : mIter(aDestIter) + { + } + + PRUint32 + write( const char* aSource, PRUint32 aSourceLength ) + { + PRUint32 len = PR_MIN(PRUint32(mIter.size_forward()), aSourceLength); + char* cp = mIter.get(); + const char* end = aSource + len; + while (aSource != end) { + char ch = *aSource; + if ((ch >= 'A') && (ch <= 'Z')) + *cp = ch + ('a' - 'A'); + else + *cp = ch; + ++aSource; + ++cp; + } + mIter.advance(len); + return len; + } + + protected: + nsACString::iterator& mIter; + }; + +NS_COM +void +ToLowerCase( const nsACString& aSource, nsACString& aDest ) + { + nsACString::const_iterator fromBegin, fromEnd; + nsACString::iterator toBegin; + aDest.SetLength(aSource.Length()); + CopyToLowerCase converter(aDest.BeginWriting(toBegin)); + copy_string(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd), converter); + } + +template <class StringT, class IteratorT, class Comparator> +PRBool +FindInReadable_Impl( const StringT& aPattern, IteratorT& aSearchStart, IteratorT& aSearchEnd, const Comparator& compare ) + { + PRBool found_it = PR_FALSE; + + // only bother searching at all if we're given a non-empty range to search + if ( aSearchStart != aSearchEnd ) + { + IteratorT aPatternStart, aPatternEnd; + aPattern.BeginReading(aPatternStart); + aPattern.EndReading(aPatternEnd); + + // outer loop keeps searching till we find it or run out of string to search + while ( !found_it ) + { + // fast inner loop (that's what it's called, not what it is) looks for a potential match + while ( aSearchStart != aSearchEnd && + compare(*aPatternStart, *aSearchStart) ) + ++aSearchStart; + + // if we broke out of the `fast' loop because we're out of string ... we're done: no match + if ( aSearchStart == aSearchEnd ) + break; + + // otherwise, we're at a potential match, let's see if we really hit one + IteratorT testPattern(aPatternStart); + IteratorT testSearch(aSearchStart); + + // slow inner loop verifies the potential match (found by the `fast' loop) at the current position + for(;;) + { + // we already compared the first character in the outer loop, + // so we'll advance before the next comparison + ++testPattern; + ++testSearch; + + // if we verified all the way to the end of the pattern, then we found it! + if ( testPattern == aPatternEnd ) + { + found_it = PR_TRUE; + aSearchEnd = testSearch; // return the exact found range through the parameters + break; + } + + // if we got to end of the string we're searching before we hit the end of the + // pattern, we'll never find what we're looking for + if ( testSearch == aSearchEnd ) + { + aSearchStart = aSearchEnd; + break; + } + + // else if we mismatched ... it's time to advance to the next search position + // and get back into the `fast' loop + if ( compare(*testPattern, *testSearch) ) + { + ++aSearchStart; + break; + } + } + } + } + + return found_it; + } + + +NS_COM +PRBool +FindInReadable( const nsAString& aPattern, nsAString::const_iterator& aSearchStart, nsAString::const_iterator& aSearchEnd, const nsStringComparator& aComparator ) + { + return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, aComparator); + } + +NS_COM +PRBool +FindInReadable( const nsACString& aPattern, nsACString::const_iterator& aSearchStart, nsACString::const_iterator& aSearchEnd, const nsCStringComparator& aComparator) + { + return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, aComparator); + } + +NS_COM +PRBool +CaseInsensitiveFindInReadable( const nsACString& aPattern, nsACString::const_iterator& aSearchStart, nsACString::const_iterator& aSearchEnd ) + { + return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd, nsCaseInsensitiveCStringComparator()); + } + + /** + * This implementation is simple, but does too much work. + * It searches the entire string from left to right, and returns the last match found, if any. + * This implementation will be replaced when I get |reverse_iterator|s working. + */ +NS_COM +PRBool +RFindInReadable( const nsAString& aPattern, nsAString::const_iterator& aSearchStart, nsAString::const_iterator& aSearchEnd, const nsStringComparator& aComparator) + { + PRBool found_it = PR_FALSE; + + nsAString::const_iterator savedSearchEnd(aSearchEnd); + nsAString::const_iterator searchStart(aSearchStart), searchEnd(aSearchEnd); + + while ( searchStart != searchEnd ) + { + if ( FindInReadable(aPattern, searchStart, searchEnd, aComparator) ) + { + found_it = PR_TRUE; + + // this is the best match so far, so remember it + aSearchStart = searchStart; + aSearchEnd = searchEnd; + + // ...and get ready to search some more + // (it's tempting to set |searchStart=searchEnd| ... but that misses overlapping patterns) + ++searchStart; + searchEnd = savedSearchEnd; + } + } + + // if we never found it, return an empty range + if ( !found_it ) + aSearchStart = aSearchEnd; + + return found_it; + } + +NS_COM +PRBool +RFindInReadable( const nsACString& aPattern, nsACString::const_iterator& aSearchStart, nsACString::const_iterator& aSearchEnd, const nsCStringComparator& aComparator) + { + PRBool found_it = PR_FALSE; + + nsACString::const_iterator savedSearchEnd(aSearchEnd); + nsACString::const_iterator searchStart(aSearchStart), searchEnd(aSearchEnd); + + while ( searchStart != searchEnd ) + { + if ( FindInReadable(aPattern, searchStart, searchEnd, aComparator) ) + { + found_it = PR_TRUE; + + // this is the best match so far, so remember it + aSearchStart = searchStart; + aSearchEnd = searchEnd; + + // ...and get ready to search some more + // (it's tempting to set |searchStart=searchEnd| ... but that misses overlapping patterns) + ++searchStart; + searchEnd = savedSearchEnd; + } + } + + // if we never found it, return an empty range + if ( !found_it ) + aSearchStart = aSearchEnd; + + return found_it; + } + +NS_COM +PRBool +FindCharInReadable( PRUnichar aChar, nsAString::const_iterator& aSearchStart, const nsAString::const_iterator& aSearchEnd ) + { + PRInt32 fragmentLength = aSearchEnd.get() - aSearchStart.get(); + + const PRUnichar* charFoundAt = nsCharTraits<PRUnichar>::find(aSearchStart.get(), fragmentLength, aChar); + if ( charFoundAt ) { + aSearchStart.advance( charFoundAt - aSearchStart.get() ); + return PR_TRUE; + } + + aSearchStart.advance(fragmentLength); + return PR_FALSE; + } + +NS_COM +PRBool +FindCharInReadable( char aChar, nsACString::const_iterator& aSearchStart, const nsACString::const_iterator& aSearchEnd ) + { + PRInt32 fragmentLength = aSearchEnd.get() - aSearchStart.get(); + + const char* charFoundAt = nsCharTraits<char>::find(aSearchStart.get(), fragmentLength, aChar); + if ( charFoundAt ) { + aSearchStart.advance( charFoundAt - aSearchStart.get() ); + return PR_TRUE; + } + + aSearchStart.advance(fragmentLength); + return PR_FALSE; + } + +NS_COM +PRUint32 +CountCharInReadable( const nsAString& aStr, + PRUnichar aChar ) +{ + PRUint32 count = 0; + nsAString::const_iterator begin, end; + + aStr.BeginReading(begin); + aStr.EndReading(end); + + while (begin != end) { + if (*begin == aChar) { + ++count; + } + ++begin; + } + + return count; +} + +NS_COM +PRUint32 +CountCharInReadable( const nsACString& aStr, + char aChar ) +{ + PRUint32 count = 0; + nsACString::const_iterator begin, end; + + aStr.BeginReading(begin); + aStr.EndReading(end); + + while (begin != end) { + if (*begin == aChar) { + ++count; + } + ++begin; + } + + return count; +} + +NS_COM PRBool +StringBeginsWith( const nsAString& aSource, const nsAString& aSubstring, + const nsStringComparator& aComparator ) + { + nsAString::size_type src_len = aSource.Length(), + sub_len = aSubstring.Length(); + if (sub_len > src_len) + return PR_FALSE; + return Substring(aSource, 0, sub_len).Equals(aSubstring, aComparator); + } + +NS_COM PRBool +StringBeginsWith( const nsACString& aSource, const nsACString& aSubstring, + const nsCStringComparator& aComparator ) + { + nsACString::size_type src_len = aSource.Length(), + sub_len = aSubstring.Length(); + if (sub_len > src_len) + return PR_FALSE; + return Substring(aSource, 0, sub_len).Equals(aSubstring, aComparator); + } + +NS_COM PRBool +StringEndsWith( const nsAString& aSource, const nsAString& aSubstring, + const nsStringComparator& aComparator ) + { + nsAString::size_type src_len = aSource.Length(), + sub_len = aSubstring.Length(); + if (sub_len > src_len) + return PR_FALSE; + return Substring(aSource, src_len - sub_len, sub_len).Equals(aSubstring, + aComparator); + } + +NS_COM PRBool +StringEndsWith( const nsACString& aSource, const nsACString& aSubstring, + const nsCStringComparator& aComparator ) + { + nsACString::size_type src_len = aSource.Length(), + sub_len = aSubstring.Length(); + if (sub_len > src_len) + return PR_FALSE; + return Substring(aSource, src_len - sub_len, sub_len).Equals(aSubstring, + aComparator); + } + + + +template <class CharT> +class CalculateHashCode + { + public: + typedef CharT char_type; + typedef PRUint32 hashcode_type; + typedef CharT value_type; + + CalculateHashCode() : mHashCode(0) { } + hashcode_type GetHashCode() const { return mHashCode; } + + PRUint32 write( const CharT* chars, PRUint32 N ) + { + for ( const CharT *end = chars + N; chars < end; ++chars) + mHashCode = (mHashCode>>28) ^ (mHashCode<<4) ^ PRUint32(*chars); + return N; + } + + private: + hashcode_type mHashCode; + }; + +NS_COM PRUint32 HashString( const nsAString& aStr ) + { + CalculateHashCode<nsAString::char_type> sink; + nsAString::const_iterator begin, end; + aStr.BeginReading(begin); + aStr.EndReading(end); + copy_string(begin, end, sink); + return sink.GetHashCode(); + } + +NS_COM PRUint32 HashString( const nsACString& aStr ) + { + CalculateHashCode<nsACString::char_type> sink; + nsACString::const_iterator begin, end; + aStr.BeginReading(begin); + aStr.EndReading(end); + copy_string(begin, end, sink); + return sink.GetHashCode(); + } + +static const PRUnichar empty_buffer[1] = { '\0' }; + +NS_COM const nsAFlatString& EmptyString() + { + static const nsDependentString sEmpty(empty_buffer); + + return sEmpty; + } + +NS_COM const nsAFlatCString& EmptyCString() + { + static const nsDependentCString sEmpty((const char *)empty_buffer); + + return sEmpty; + } diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsString.cpp new file mode 100644 index 00000000..aedf3295 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsString.cpp @@ -0,0 +1,49 @@ +/* -*- 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 ***** */ + +#include "nsString.h" + + // define nsString +#include "string-template-def-unichar.h" +#include "nsTString.cpp" +#include "string-template-undef.h" + + // define nsCString +#include "string-template-def-char.h" +#include "nsTString.cpp" +#include "string-template-undef.h" diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsStringComparator.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsStringComparator.cpp new file mode 100644 index 00000000..ced75c73 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsStringComparator.cpp @@ -0,0 +1,75 @@ +/* -*- 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 ***** */ + +#include <ctype.h> +#include "nsAString.h" +#include "plstr.h" + + + // define nsStringComparator +#include "string-template-def-unichar.h" +#include "nsTStringComparator.cpp" +#include "string-template-undef.h" + + // define nsCStringComparator +#include "string-template-def-char.h" +#include "nsTStringComparator.cpp" +#include "string-template-undef.h" + + +int +nsCaseInsensitiveCStringComparator::operator()( const char_type* lhs, const char_type* rhs, PRUint32 aLength ) const + { + PRInt32 result=PRInt32(PL_strncasecmp(lhs, rhs, aLength)); + //Egads. PL_strncasecmp is returning *very* negative numbers. + //Some folks expect -1,0,1, so let's temper its enthusiasm. + if (result<0) + result=-1; + return result; + } + +int +nsCaseInsensitiveCStringComparator::operator()( char lhs, char rhs ) const + { + if (lhs == rhs) return 0; + + lhs = tolower(lhs); + rhs = tolower(rhs); + + return lhs - rhs; + } diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp new file mode 100644 index 00000000..76106a27 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp @@ -0,0 +1,1327 @@ +/* -*- 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 ***** */ + +#include "nsString.h" + + + /** + * nsTString obsolete API support + */ + +#if MOZ_STRING_WITH_OBSOLETE_API + +#include "nsDependentString.h" +#include "nsDependentSubstring.h" +#include "nsReadableUtils.h" +#include "nsCRT.h" +#include "nsUTF8Utils.h" +#include "prdtoa.h" +#include "prprf.h" +#ifdef VBOX_USE_IPRT_IN_XPCOM +# include <iprt/mem.h> +#endif + +/* ***** BEGIN RICKG BLOCK ***** + * + * NOTE: This section of code was extracted from rickg's bufferRoutines.h file. + * For the most part it remains unmodified. We want to eliminate (or at + * least clean up) this code at some point. If you find the formatting + * in this section somewhat inconsistent, don't blame me! ;-) + */ + +// XXXdarin what is wrong with STDC's tolower? +inline char +ascii_tolower(char aChar) +{ + if (aChar >= 'A' && aChar <= 'Z') + return aChar + ('a' - 'A'); + return aChar; +} + +//----------------------------------------------------------------------------- +// +// This set of methods is used to search a buffer looking for a char. +// + + +/** + * This methods cans the given buffer for the given char + * + * @update gess 02/17/00 + * @param aDest is the buffer to be searched + * @param aDestLength is the size (in char-units, not bytes) of the buffer + * @param anOffset is the start pos to begin searching + * @param aChar is the target character we're looking for + * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length. + * @return index of pos if found, else -1 (kNotFound) + */ +static PRInt32 +FindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) { + + if(anOffset < 0) + anOffset=0; + + if(aCount < 0) + aCount = (PRInt32)aDestLength; + + if((aChar < 256) && (0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) { + + //We'll only search if the given aChar is within the normal ascii a range, + //(Since this string is definitely within the ascii range). + + if(0<aCount) { + + const char* left= aDest+anOffset; + const char* last= left+aCount; + const char* max = aDest+aDestLength; + const char* end = (last<max) ? last : max; + + PRInt32 theMax = end-left; + if(0<theMax) { + + unsigned char theChar = (unsigned char) aChar; + const char* result=(const char*)memchr(left, (int)theChar, theMax); + + if(result) + return result-aDest; + + } + } + } + + return kNotFound; +} + + +/** + * This methods cans the given buffer for the given char + * + * @update gess 3/25/98 + * @param aDest is the buffer to be searched + * @param aDestLength is the size (in char-units, not bytes) of the buffer + * @param anOffset is the start pos to begin searching + * @param aChar is the target character we're looking for + * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length. + * @return index of pos if found, else -1 (kNotFound) + */ +static PRInt32 +FindChar2(const PRUnichar* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) { + + if(anOffset < 0) + anOffset=0; + + if(aCount < 0) + aCount = (PRInt32)aDestLength; + + if((0<aDestLength) && ((PRUint32)anOffset < aDestLength)) { + + if(0<aCount) { + + const PRUnichar* root = aDest; + const PRUnichar* left = root+anOffset; + const PRUnichar* last = left+aCount; + const PRUnichar* max = root+aDestLength; + const PRUnichar* end = (last<max) ? last : max; + + while(left<end){ + + if(*left==aChar) + return (left-root); + + ++left; + } + } + } + + return kNotFound; +} + + +/** + * This methods cans the given buffer (in reverse) for the given char + * + * @update gess 02/17/00 + * @param aDest is the buffer to be searched + * @param aDestLength is the size (in char-units, not bytes) of the buffer + * @param anOffset is the start pos to begin searching + * @param aChar is the target character we're looking for + * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length. + * @return index of pos if found, else -1 (kNotFound) + */ + +static PRInt32 +RFindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) { + + if(anOffset < 0) + anOffset=(PRInt32)aDestLength-1; + + if(aCount < 0) + aCount = PRInt32(aDestLength); + + if((aChar<256) && (0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) { + + //We'll only search if the given aChar is within the normal ascii a range, + //(Since this string is definitely within the ascii range). + + if(0 < aCount) { + + const char* rightmost = aDest + anOffset; + const char* min = rightmost - aCount + 1; + const char* leftmost = (min<aDest) ? aDest: min; + + char theChar=(char)aChar; + while(leftmost <= rightmost){ + + if((*rightmost) == theChar) + return rightmost - aDest; + + --rightmost; + } + } + } + + return kNotFound; +} + + +/** + * This methods cans the given buffer for the given char + * + * @update gess 3/25/98 + * @param aDest is the buffer to be searched + * @param aDestLength is the size (in char-units, not bytes) of the buffer + * @param anOffset is the start pos to begin searching + * @param aChar is the target character we're looking for + * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length. + * @return index of pos if found, else -1 (kNotFound) + */ +static PRInt32 +RFindChar2(const PRUnichar* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) { + + if(anOffset < 0) + anOffset=(PRInt32)aDestLength-1; + + if(aCount < 0) + aCount = PRInt32(aDestLength); + + if((0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) { + + if(0 < aCount) { + + const PRUnichar* root = aDest; + const PRUnichar* rightmost = root + anOffset; + const PRUnichar* min = rightmost - aCount + 1; + const PRUnichar* leftmost = (min<root) ? root: min; + + while(leftmost <= rightmost){ + + if((*rightmost) == aChar) + return rightmost - root; + + --rightmost; + } + } + } + + return kNotFound; +} + +//----------------------------------------------------------------------------- +// +// This set of methods is used to compare one buffer onto another. The +// functions are differentiated by the size of source and dest character +// sizes. WARNING: Your destination buffer MUST be big enough to hold all the +// source bytes. We don't validate these ranges here (this should be done in +// higher level routines). +// + + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnoreCase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +static +#ifdef __SUNPRO_CC +inline +#endif /* __SUNPRO_CC */ +PRInt32 +Compare1To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){ + PRInt32 result=0; + if(aIgnoreCase) + result=PRInt32(PL_strncasecmp(aStr1, aStr2, aCount)); + else + result=nsCharTraits<char>::compare(aStr1,aStr2,aCount); + + // alien comparisons may return out-of-bound answers + // instead of the -1, 0, 1 expected by most clients + if ( result < -1 ) + result = -1; + else if ( result > 1 ) + result = 1; + return result; +} + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnoreCase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +static +#ifdef __SUNPRO_CC +inline +#endif /* __SUNPRO_CC */ +PRInt32 +Compare2To2(const PRUnichar* aStr1,const PRUnichar* aStr2,PRUint32 aCount){ + PRInt32 result; + + if ( aStr1 && aStr2 ) + result = nsCharTraits<PRUnichar>::compare(aStr1, aStr2, aCount); + + // The following cases are rare and survivable caller errors. + // Two null pointers are equal, but any string, even 0 length + // is greater than a null pointer. It might not really matter, + // but we pick something reasonable anyway. + else if ( !aStr1 && !aStr2 ) + result = 0; + else if ( aStr1 ) + result = 1; + else + result = -1; + + // alien comparisons may give answers outside the -1, 0, 1 expected by callers + if ( result < -1 ) + result = -1; + else if ( result > 1 ) + result = 1; + return result; +} + + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnoreCase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +static +#ifdef __SUNPRO_CC +inline +#endif /* __SUNPRO_CC */ +PRInt32 +Compare2To1(const PRUnichar* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){ + const PRUnichar* s1 = aStr1; + const char *s2 = aStr2; + + if (aStr1 && aStr2) { + if (aCount != 0) { + do { + + PRUnichar c1 = *s1++; + PRUnichar c2 = PRUnichar((unsigned char)*s2++); + + if (c1 != c2) { +#ifdef NS_DEBUG + // we won't warn on c1>=128 (the 2-byte value) because often + // it is just fine to compare an constant, ascii value (i.e. "body") + // against some non-ascii value (i.e. a unicode string that + // was downloaded from a web page) + if (aIgnoreCase && c2>=128) + NS_WARNING("got a non-ASCII string, but we can't do an accurate case conversion!"); +#endif + + // can't do case conversion on characters out of our range + if (aIgnoreCase && c1<128 && c2<128) { + + c1 = ascii_tolower(char(c1)); + c2 = ascii_tolower(char(c2)); + + if (c1 == c2) continue; + } + + if (c1 < c2) return -1; + return 1; + } + } while (--aCount); + } + } + return 0; +} + + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnoreCase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +inline PRInt32 +Compare1To2(const char* aStr1,const PRUnichar* aStr2,PRUint32 aCount,PRBool aIgnoreCase){ + return Compare2To1(aStr2, aStr1, aCount, aIgnoreCase) * -1; +} + + +//----------------------------------------------------------------------------- +// +// This set of methods is used compress char sequences in a buffer... +// + + +/** + * This method compresses duplicate runs of a given char from the given buffer + * + * @update rickg 03.23.2000 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to compress from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + * @return the new length of the given buffer + */ +static PRInt32 +CompressChars1(char* aString,PRUint32 aLength,const char* aSet){ + + char* from = aString; + char* end = aString + aLength; + char* to = from; + + //this code converts /n, /t, /r into normal space ' '; + //it also compresses runs of whitespace down to a single char... + if(aSet && aString && (0 < aLength)){ + PRUint32 aSetLen=strlen(aSet); + + while (from < end) { + char theChar = *from++; + + *to++=theChar; //always copy this char... + + if((kNotFound!=FindChar1(aSet,aSetLen,0,theChar,aSetLen))){ + while (from < end) { + theChar = *from++; + if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){ + *to++ = theChar; + break; + } + } //while + } //if + } //if + *to = 0; + } + return to - aString; +} + + + +/** + * This method compresses duplicate runs of a given char from the given buffer + * + * @update rickg 03.23.2000 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to compress from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + * @return the new length of the given buffer + */ +static PRInt32 +CompressChars2(PRUnichar* aString,PRUint32 aLength,const char* aSet){ + + PRUnichar* from = aString; + PRUnichar* end = from + aLength; + PRUnichar* to = from; + + //this code converts /n, /t, /r into normal space ' '; + //it also compresses runs of whitespace down to a single char... + if(aSet && aString && (0 < aLength)){ + PRUint32 aSetLen=strlen(aSet); + + while (from < end) { + PRUnichar theChar = *from++; + + *to++=theChar; //always copy this char... + + if((theChar<256) && (kNotFound!=FindChar1(aSet,aSetLen,0,theChar,aSetLen))){ + while (from < end) { + theChar = *from++; + if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){ + *to++ = theChar; + break; + } + } //while + } //if + } //if + *to = 0; + } + return to - (PRUnichar*)aString; +} + +/** + * This method strips chars in a given set from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to compress from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + * @return the new length of the given buffer + */ +static PRInt32 +StripChars1(char* aString,PRUint32 aLength,const char* aSet){ + + // XXXdarin this code should defer writing until necessary. + + char* to = aString; + char* from = aString-1; + char* end = aString + aLength; + + if(aSet && aString && (0 < aLength)){ + PRUint32 aSetLen=strlen(aSet); + while (++from < end) { + char theChar = *from; + if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){ + *to++ = theChar; + } + } + *to = 0; + } + return to - (char*)aString; +} + + +/** + * This method strips chars in a given set from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to compress from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + * @return the new length of the given buffer + */ +static PRInt32 +StripChars2(PRUnichar* aString,PRUint32 aLength,const char* aSet){ + + // XXXdarin this code should defer writing until necessary. + + PRUnichar* to = aString; + PRUnichar* from = aString-1; + PRUnichar* end = to + aLength; + + if(aSet && aString && (0 < aLength)){ + PRUint32 aSetLen=strlen(aSet); + while (++from < end) { + PRUnichar theChar = *from; + //Note the test for ascii range below. If you have a real unicode char, + //and you're searching for chars in the (given) ascii string, there's no + //point in doing the real search since it's out of the ascii range. + if((255<theChar) || (kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen))){ + *to++ = theChar; + } + } + *to = 0; + } + return to - (PRUnichar*)aString; +} + +/* ***** END RICKG BLOCK ***** */ + +static const char* kWhitespace="\b\t\r\n "; + +// This function is used to implement FindCharInSet and friends +template <class CharT> +#ifndef __SUNPRO_CC +static +#endif /* !__SUNPRO_CC */ +CharT +GetFindInSetFilter( const CharT* set) + { + CharT filter = ~CharT(0); // All bits set + while (*set) { + filter &= ~(*set); + ++set; + } + return filter; + } + +// This template class is used by our code to access rickg's buffer routines. +template <class CharT> struct nsBufferRoutines {}; + +NS_SPECIALIZE_TEMPLATE +struct nsBufferRoutines<char> + { + static + PRInt32 compare( const char* a, const char* b, PRUint32 max, PRBool ic ) + { + return Compare1To1(a, b, max, ic); + } + + static + PRInt32 compare( const char* a, const PRUnichar* b, PRUint32 max, PRBool ic ) + { + return Compare1To2(a, b, max, ic); + } + + static + PRInt32 find_char( const char* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count ) + { + return FindChar1(s, max, offset, c, count); + } + + static + PRInt32 rfind_char( const char* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count ) + { + return RFindChar1(s, max, offset, c, count); + } + + static + char get_find_in_set_filter( const char* set ) + { + return GetFindInSetFilter(set); + } + + static + PRInt32 strip_chars( char* s, PRUint32 len, const char* set ) + { + return StripChars1(s, len, set); + } + + static + PRInt32 compress_chars( char* s, PRUint32 len, const char* set ) + { + return CompressChars1(s, len, set); + } + }; + +NS_SPECIALIZE_TEMPLATE +struct nsBufferRoutines<PRUnichar> + { + static + PRInt32 compare( const PRUnichar* a, const PRUnichar* b, PRUint32 max, PRBool ic ) + { + NS_ASSERTION(!ic, "no case-insensitive compare here"); + return Compare2To2(a, b, max); + } + + static + PRInt32 compare( const PRUnichar* a, const char* b, PRUint32 max, PRBool ic ) + { + return Compare2To1(a, b, max, ic); + } + + static + PRInt32 find_char( const PRUnichar* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count ) + { + return FindChar2(s, max, offset, c, count); + } + + static + PRInt32 rfind_char( const PRUnichar* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count ) + { + return RFindChar2(s, max, offset, c, count); + } + + static + PRUnichar get_find_in_set_filter( const PRUnichar* set ) + { + return GetFindInSetFilter(set); + } + + static + PRUnichar get_find_in_set_filter( const char* set ) + { + return (~PRUnichar(0)^~char(0)) | GetFindInSetFilter(set); + } + + static + PRInt32 strip_chars( PRUnichar* s, PRUint32 max, const char* set ) + { + return StripChars2(s, max, set); + } + + static + PRInt32 compress_chars( PRUnichar* s, PRUint32 len, const char* set ) + { + return CompressChars2(s, len, set); + } + }; + +//----------------------------------------------------------------------------- + +template <class L, class R> +#ifndef __SUNPRO_CC +static +#endif /* !__SUNPRO_CC */ +PRInt32 +FindSubstring( const L* big, PRUint32 bigLen, + const R* little, PRUint32 littleLen, + PRBool ignoreCase ) + { + if (littleLen > bigLen) + return kNotFound; + + PRInt32 i, max = PRInt32(bigLen - littleLen); + for (i=0; i<=max; ++i, ++big) + { + if (nsBufferRoutines<L>::compare(big, little, littleLen, ignoreCase) == 0) + return i; + } + + return kNotFound; + } + +template <class L, class R> +#ifndef __SUNPRO_CC +static +#endif /* !__SUNPRO_CC */ +PRInt32 +RFindSubstring( const L* big, PRUint32 bigLen, + const R* little, PRUint32 littleLen, + PRBool ignoreCase ) + { + if (littleLen > bigLen) + return kNotFound; + + PRInt32 i, max = PRInt32(bigLen - littleLen); + + const L* iter = big + max; + for (i=max; iter >= big; --i, --iter) + { + if (nsBufferRoutines<L>::compare(iter, little, littleLen, ignoreCase) == 0) + return i; + } + + return kNotFound; + } + +template <class CharT, class SetCharT> +#ifndef __SUNPRO_CC +static +#endif /* !__SUNPRO_CC */ +PRInt32 +FindCharInSet( const CharT* data, PRUint32 dataLen, const SetCharT* set ) + { + CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set); + + const CharT* end = data + dataLen; + for (const CharT* iter = data; iter < end; ++iter) + { + CharT currentChar = *iter; + if (currentChar & filter) + continue; // char is not in filter set; go on with next char. + + // test all chars + const SetCharT* charInSet = set; + CharT setChar = CharT(*charInSet); + while (setChar) + { + if (setChar == currentChar) + return iter - data; // found it! return index of the found char. + + setChar = CharT(*(++charInSet)); + } + } + return kNotFound; + } + +template <class CharT, class SetCharT> +#ifndef __SUNPRO_CC +static +#endif /* !__SUNPRO_CC */ +PRInt32 +RFindCharInSet( const CharT* data, PRUint32 dataLen, const SetCharT* set ) + { + CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set); + + for (const CharT* iter = data + dataLen - 1; iter >= data; --iter) + { + CharT currentChar = *iter; + if (currentChar & filter) + continue; // char is not in filter set; go on with next char. + + // test all chars + const CharT* charInSet = set; + CharT setChar = *charInSet; + while (setChar) + { + if (setChar == currentChar) + return iter - data; // found it! return index of the found char. + + setChar = *(++charInSet); + } + } + return kNotFound; + } + +/** + * This is a copy of |PR_cnvtf| with a bug fixed. (The second argument + * of PR_dtoa is 2 rather than 1.) + * + * XXXdarin if this is the right thing, then why wasn't it fixed in NSPR?!? + */ +void +Modified_cnvtf(char *buf, int bufsz, int prcsn, double fval) +{ + PRIntn decpt, sign, numdigits; + char *num, *nump; + char *bufp = buf; + char *endnum; + + /* If anything fails, we store an empty string in 'buf' */ +#ifdef VBOX_USE_IPRT_IN_XPCOM + num = (char*)RTMemAlloc(bufsz); +#else + num = (char*)malloc(bufsz); +#endif + if (num == NULL) { + buf[0] = '\0'; + return; + } + if (PR_dtoa(fval, 2, prcsn, &decpt, &sign, &endnum, num, bufsz) + == PR_FAILURE) { + buf[0] = '\0'; + goto done; + } + numdigits = endnum - num; + nump = num; + + /* + * The NSPR code had a fancy way of checking that we weren't dealing + * with -0.0 or -NaN, but I'll just use < instead. + * XXX Should we check !isnan(fval) as well? Is it portable? We + * probably don't need to bother since NAN isn't portable. + */ + if (sign && fval < 0.0f) { + *bufp++ = '-'; + } + + if (decpt == 9999) { + while ((*bufp++ = *nump++) != 0) {} /* nothing to execute */ + goto done; + } + + if (decpt > (prcsn+1) || decpt < -(prcsn-1) || decpt < -5) { + *bufp++ = *nump++; + if (numdigits != 1) { + *bufp++ = '.'; + } + + while (*nump != '\0') { + *bufp++ = *nump++; + } + *bufp++ = 'e'; + PR_snprintf(bufp, bufsz - (bufp - buf), "%+d", decpt-1); + } + else if (decpt >= 0) { + if (decpt == 0) { + *bufp++ = '0'; + } + else { + while (decpt--) { + if (*nump != '\0') { + *bufp++ = *nump++; + } + else { + *bufp++ = '0'; + } + } + } + if (*nump != '\0') { + *bufp++ = '.'; + while (*nump != '\0') { + *bufp++ = *nump++; + } + } + *bufp++ = '\0'; + } + else if (decpt < 0) { + *bufp++ = '0'; + *bufp++ = '.'; + while (decpt++) { + *bufp++ = '0'; + } + + while (*nump != '\0') { + *bufp++ = *nump++; + } + *bufp++ = '\0'; + } +done: +#ifdef VBOX_USE_IPRT_IN_XPCOM + RTMemFree(num); +#else + free(num); +#endif +} + + /** + * this method changes the meaning of |offset| and |count|: + * + * upon return, + * |offset| specifies start of search range + * |count| specifies length of search range + */ +static void +Find_ComputeSearchRange( PRUint32 bigLen, PRUint32 littleLen, PRInt32& offset, PRInt32& count ) + { + // |count| specifies how many iterations to make from |offset| + + if (offset < 0) + { + offset = 0; + } + else if (PRUint32(offset) > bigLen) + { + count = 0; + return; + } + + PRInt32 maxCount = bigLen - offset; + if (count < 0 || count > maxCount) + { + count = maxCount; + } + else + { + count += littleLen; + if (count > maxCount) + count = maxCount; + } + } + + /** + * this method changes the meaning of |offset| and |count|: + * + * upon entry, + * |offset| specifies the end point from which to search backwards + * |count| specifies the number of iterations from |offset| + * + * upon return, + * |offset| specifies start of search range + * |count| specifies length of search range + * + * + * EXAMPLE + * + * + -- littleLen=4 -- + + * : : + * |____|____|____|____|____|____|____|____|____|____|____|____| + * : : + * offset=5 bigLen=12 + * + * if count = 4, then we expect this function to return offset = 2 and + * count = 7. + * + */ +static void +RFind_ComputeSearchRange( PRUint32 bigLen, PRUint32 littleLen, PRInt32& offset, PRInt32& count ) + { + if (littleLen > bigLen) + { + offset = 0; + count = 0; + return; + } + + if (offset < 0) + offset = bigLen - littleLen; + if (count < 0) + count = offset + 1; + + PRInt32 start = offset - count + 1; + if (start < 0) + start = 0; + + count = offset + littleLen - start; + offset = start; + } + +//----------------------------------------------------------------------------- + + // define nsString obsolete methods +#include "string-template-def-unichar.h" +#include "nsTStringObsolete.cpp" +#include "string-template-undef.h" + + // define nsCString obsolete methods +#include "string-template-def-char.h" +#include "nsTStringObsolete.cpp" +#include "string-template-undef.h" + +//----------------------------------------------------------------------------- + +// specialized methods: + +PRInt32 +nsString::Find( const nsAFlatString& aString, PRInt32 aOffset, PRInt32 aCount ) const + { + // this method changes the meaning of aOffset and aCount: + Find_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount); + + PRInt32 result = FindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), PR_FALSE); + if (result != kNotFound) + result += aOffset; + return result; + } + +PRInt32 +nsString::Find( const PRUnichar* aString, PRInt32 aOffset, PRInt32 aCount ) const + { + return Find(nsDependentString(aString), aOffset, aCount); + } + +PRInt32 +nsString::RFind( const nsAFlatString& aString, PRInt32 aOffset, PRInt32 aCount ) const + { + // this method changes the meaning of aOffset and aCount: + RFind_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount); + + PRInt32 result = RFindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), PR_FALSE); + if (result != kNotFound) + result += aOffset; + return result; + } + +PRInt32 +nsString::RFind( const PRUnichar* aString, PRInt32 aOffset, PRInt32 aCount ) const + { + return RFind(nsDependentString(aString), aOffset, aCount); + } + +PRInt32 +nsString::FindCharInSet( const PRUnichar* aSet, PRInt32 aOffset ) const + { + if (aOffset < 0) + aOffset = 0; + else if (aOffset >= PRInt32(mLength)) + return kNotFound; + + PRInt32 result = ::FindCharInSet(mData + aOffset, mLength - aOffset, aSet); + if (result != kNotFound) + result += aOffset; + return result; + } + + + /** + * nsTString::Compare,CompareWithConversion,etc. + */ + +PRInt32 +nsCString::Compare( const char* aString, PRBool aIgnoreCase, PRInt32 aCount ) const + { + PRUint32 strLen = char_traits::length(aString); + + PRInt32 maxCount = PRInt32(NS_MIN(mLength, strLen)); + + PRInt32 compareCount; + if (aCount < 0 || aCount > maxCount) + compareCount = maxCount; + else + compareCount = aCount; + + PRInt32 result = + nsBufferRoutines<char>::compare(mData, aString, compareCount, aIgnoreCase); + + if (result == 0 && + (aCount < 0 || strLen < PRUint32(aCount) || mLength < PRUint32(aCount))) + { + // Since the caller didn't give us a length to test, or strings shorter + // than aCount, and compareCount characters matched, we have to assume + // that the longer string is greater. + + if (mLength != strLen) + result = (mLength < strLen) ? -1 : 1; + } + return result; + } + +PRBool +nsString::EqualsIgnoreCase( const char* aString, PRInt32 aCount ) const + { + PRUint32 strLen = nsCharTraits<char>::length(aString); + + PRInt32 maxCount = PRInt32(NS_MIN(mLength, strLen)); + + PRInt32 compareCount; + if (aCount < 0 || aCount > maxCount) + compareCount = maxCount; + else + compareCount = aCount; + + PRInt32 result = + nsBufferRoutines<PRUnichar>::compare(mData, aString, compareCount, PR_TRUE); + + if (result == 0 && + (aCount < 0 || strLen < PRUint32(aCount) || mLength < PRUint32(aCount))) + { + // Since the caller didn't give us a length to test, or strings shorter + // than aCount, and compareCount characters matched, we have to assume + // that the longer string is greater. + + if (mLength != strLen) + result = 1; // Arbitrarily using any number != 0 + } + return result == 0; + } + + /** + * ToCString, ToFloat, ToInteger + */ + +char* +nsString::ToCString( char* aBuf, PRUint32 aBufLength, PRUint32 aOffset ) const + { + // because the old implementation checked aBuf + if (!(aBuf && aBufLength > 0 && aOffset <= mLength)) + return nsnull; + + PRUint32 maxCount = NS_MIN(aBufLength-1, mLength - aOffset); + + LossyConvertEncoding<PRUnichar, char> converter(aBuf); + converter.write(mData + aOffset, maxCount); + converter.write_terminator(); + return aBuf; + } + +float +nsCString::ToFloat(PRInt32* aErrorCode) const + { + float res = 0.0f; + if (mLength > 0) + { + char *conv_stopped; + const char *str = mData; + // Use PR_strtod, not strtod, since we don't want locale involved. + res = (float)PR_strtod(str, &conv_stopped); + if (conv_stopped == str+mLength) + *aErrorCode = (PRInt32) NS_OK; + else // Not all the string was scanned + *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE; + } + else + { + // The string was too short (0 characters) + *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE; + } + return res; + } + +float +nsString::ToFloat(PRInt32* aErrorCode) const + { + float res = 0.0f; + char buf[100]; + if (mLength > 0 && mLength < sizeof(buf)) + { + char *conv_stopped; + const char *str = ToCString(buf, sizeof(buf)); + // Use PR_strtod, not strtod, since we don't want locale involved. + res = (float)PR_strtod(str, &conv_stopped); + if (conv_stopped == str+mLength) + *aErrorCode = (PRInt32) NS_OK; + else // Not all the string was scanned + *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE; + } + else + { + // The string was too short (0 characters) or too long (sizeof(buf)) + *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE; + } + return res; + } + + + /** + * nsTString::AssignWithConversion + */ + +void +nsCString::AssignWithConversion( const nsAString& aData ) + { + LossyCopyUTF16toASCII(aData, *this); + } + +void +nsString::AssignWithConversion( const nsACString& aData ) + { + CopyASCIItoUTF16(aData, *this); + } + + + /** + * nsTString::AppendWithConversion + */ + +void +nsCString::AppendWithConversion( const nsAString& aData ) + { + LossyAppendUTF16toASCII(aData, *this); + } + +void +nsString::AppendWithConversion( const nsACString& aData ) + { + AppendASCIItoUTF16(aData, *this); + } + + + /** + * nsTString::AppendInt + */ + +void +nsCString::AppendInt( PRInt32 aInteger, PRInt32 aRadix ) + { + char buf[20]; + const char* fmt; + switch (aRadix) { + case 8: + fmt = "%o"; + break; + case 10: + fmt = "%d"; + break; + default: + NS_ASSERTION(aRadix == 16, "Invalid radix!"); + fmt = "%x"; + } + PR_snprintf(buf, sizeof(buf), fmt, aInteger); + Append(buf); + } + +void +nsString::AppendInt( PRInt32 aInteger, PRInt32 aRadix ) + { + char buf[20]; + const char* fmt; + switch (aRadix) { + case 8: + fmt = "%o"; + break; + case 10: + fmt = "%d"; + break; + default: + NS_ASSERTION(aRadix == 16, "Invalid radix!"); + fmt = "%x"; + } + PR_snprintf(buf, sizeof(buf), fmt, aInteger); + AppendASCIItoUTF16(buf, *this); + } + +void +nsCString::AppendInt( PRInt64 aInteger, PRInt32 aRadix ) + { + char buf[30]; + const char* fmt; + switch (aRadix) { + case 8: + fmt = "%llo"; + break; + case 10: + fmt = "%lld"; + break; + default: + NS_ASSERTION(aRadix == 16, "Invalid radix!"); + fmt = "%llx"; + } + PR_snprintf(buf, sizeof(buf), fmt, aInteger); + Append(buf); + } + +void +nsString::AppendInt( PRInt64 aInteger, PRInt32 aRadix ) + { + char buf[30]; + const char* fmt; + switch (aRadix) { + case 8: + fmt = "%llo"; + break; + case 10: + fmt = "%lld"; + break; + default: + NS_ASSERTION(aRadix == 16, "Invalid radix!"); + fmt = "%llx"; + } + PR_snprintf(buf, sizeof(buf), fmt, aInteger); + AppendASCIItoUTF16(buf, *this); + } + + /** + * nsTString::AppendFloat + */ + +void +nsCString::AppendFloat( double aFloat ) + { + char buf[40]; + // Use Modified_cnvtf, which is locale-insensitive, instead of the + // locale-sensitive PR_snprintf or sprintf(3) + Modified_cnvtf(buf, sizeof(buf), 6, aFloat); + Append(buf); + } + +void +nsString::AppendFloat( double aFloat ) + { + char buf[40]; + // Use Modified_cnvtf, which is locale-insensitive, instead of the + // locale-sensitive PR_snprintf or sprintf(3) + Modified_cnvtf(buf, sizeof(buf), 6, aFloat); + AppendWithConversion(buf); + } + +#endif // !MOZ_STRING_WITH_OBSOLETE_API diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsSubstring.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsSubstring.cpp new file mode 100644 index 00000000..6ed0c5c8 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsSubstring.cpp @@ -0,0 +1,250 @@ +/* -*- 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 ***** */ + +#ifdef DEBUG +#define ENABLE_STRING_STATS +#endif + +#ifdef ENABLE_STRING_STATS +#include <stdio.h> +#endif + +#include <stdlib.h> +#include "nsSubstring.h" +#include "nsString.h" +#include "nsDependentString.h" +#include "nsMemory.h" +#include "pratom.h" +#ifdef VBOX_USE_IPRT_IN_XPCOM +# include <iprt/mem.h> +#endif + +// --------------------------------------------------------------------------- + +static const PRUnichar gNullChar = 0; + +const char* nsCharTraits<char> ::sEmptyBuffer = (const char*) &gNullChar; +const PRUnichar* nsCharTraits<PRUnichar>::sEmptyBuffer = &gNullChar; + +// --------------------------------------------------------------------------- + +#ifdef ENABLE_STRING_STATS +class nsStringStats + { + public: + nsStringStats() + : mAllocCount(0), mReallocCount(0), mFreeCount(0), mShareCount(0) {} + + ~nsStringStats() + { + // this is a hack to suppress duplicate string stats printing + // in seamonkey as a result of the string code being linked + // into seamonkey and libxpcom! :-( + if (!mAllocCount && !mAdoptCount) + return; + +#ifndef VBOX + printf("nsStringStats\n"); + printf(" => mAllocCount: % 10d\n", mAllocCount); + printf(" => mReallocCount: % 10d\n", mReallocCount); + printf(" => mFreeCount: % 10d", mFreeCount); + if (mAllocCount > mFreeCount) + printf(" -- LEAKED %d !!!\n", mAllocCount - mFreeCount); + else + printf("\n"); + printf(" => mShareCount: % 10d\n", mShareCount); + printf(" => mAdoptCount: % 10d\n", mAdoptCount); + printf(" => mAdoptFreeCount: % 10d", mAdoptFreeCount); + if (mAdoptCount > mAdoptFreeCount) + printf(" -- LEAKED %d !!!\n", mAdoptCount - mAdoptFreeCount); + else + printf("\n"); +#endif + } + + PRInt32 mAllocCount; + PRInt32 mReallocCount; + PRInt32 mFreeCount; + PRInt32 mShareCount; + PRInt32 mAdoptCount; + PRInt32 mAdoptFreeCount; + }; +static nsStringStats gStringStats; +#define STRING_STAT_INCREMENT(_s) PR_AtomicIncrement(&gStringStats.m ## _s ## Count) +#else +#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); +#ifdef VBOX_USE_IPRT_IN_XPCOM + RTMemFree(this); // we were allocated with |malloc| +#else + free(this); // we were allocated with |malloc| +#endif + } + } + + /** + * 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 = +#ifdef VBOX_USE_IPRT_IN_XPCOM + (nsStringHeader *) RTMemAlloc(sizeof(nsStringHeader) + size); +#else + (nsStringHeader *) malloc(sizeof(nsStringHeader) + size); +#endif + 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"); + +#ifdef VBOX_USE_IPRT_IN_XPCOM + hdr = (nsStringHeader*) RTMemRealloc(hdr, sizeof(nsStringHeader) + size); +#else + hdr = (nsStringHeader*) realloc(hdr, sizeof(nsStringHeader) + size); +#endif + 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 +ReleaseData( void* data, PRUint32 flags ) + { + if (flags & nsSubstring::F_SHARED) + { + nsStringHeader::FromData(data)->Release(); + } + else if (flags & nsSubstring::F_OWNED) + { + nsMemory::Free(data); + STRING_STAT_INCREMENT(AdoptFree); + } + // otherwise, nothing to do. + } + + + // define nsSubstring +#include "string-template-def-unichar.h" +#include "nsTSubstring.cpp" +#include "string-template-undef.h" + + // define nsCSubstring +#include "string-template-def-char.h" +#include "nsTSubstring.cpp" +#include "string-template-undef.h" diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsSubstringTuple.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsSubstringTuple.cpp new file mode 100644 index 00000000..a5445d7a --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsSubstringTuple.cpp @@ -0,0 +1,64 @@ +/* -*- 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 ***** */ + +#include "nsSubstringTuple.h" + +#if 0 + // convert fragment to |const string_base_type&| +#define TO_SUBSTRING(_v) \ + ( (ptrdiff_t(_v) & 0x1) \ + ? NS_REINTERPRET_CAST(const abstract_string_type*, \ + ((unsigned long)_v & ~0x1))->ToSubstring() \ + : *NS_REINTERPRET_CAST(const substring_type*, (_v)) ) +#endif + + // convert fragment to |const substring_type&| +#define TO_SUBSTRING(_v) \ + ( (_v)->mVTable == obsolete_string_type::sCanonicalVTable \ + ? *(_v)->AsSubstring() \ + : (_v)->ToSubstring() ) + + // define nsSubstringTuple +#include "string-template-def-unichar.h" +#include "nsTSubstringTuple.cpp" +#include "string-template-undef.h" + + // define nsCSubstringTuple +#include "string-template-def-char.h" +#include "nsTSubstringTuple.cpp" +#include "string-template-undef.h" diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTAString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTAString.cpp new file mode 100644 index 00000000..ffd75fe8 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsTAString.cpp @@ -0,0 +1,509 @@ +/* -*- 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 ***** */ + + + /** + * Some comments on this implementation... + * + * This class is a bridge between the old string implementation and the new + * string implementation. If mVTable points to the canonical vtable for the + * new string implementation, then we can cast directly to the new string + * classes (helped by the AsSubstring() methods). However, if mVTable is not + * ours, then we need to call through the vtable to satisfy the nsTAString + * methods. + * + * In most cases we will avoid the vtable. + */ + + +nsTAString_CharT::~nsTAString_CharT() + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Finalize(); + else + AsObsoleteString()->~nsTObsoleteAString_CharT(); + } + + +nsTAString_CharT::size_type +nsTAString_CharT::Length() const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->Length(); + + return AsObsoleteString()->Length(); + } + +PRBool +nsTAString_CharT::Equals( const self_type& readable ) const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->Equals(readable); + + return ToSubstring().Equals(readable); + } + +PRBool +nsTAString_CharT::Equals( const self_type& readable, const comparator_type& comparator ) const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->Equals(readable, comparator); + + return ToSubstring().Equals(readable, comparator); + } + +PRBool +nsTAString_CharT::Equals( const char_type* data ) const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->Equals(data); + + return ToSubstring().Equals(data); + } + +PRBool +nsTAString_CharT::Equals( const char_type* data, const comparator_type& comparator ) const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->Equals(data, comparator); + + return ToSubstring().Equals(data, comparator); + } + +PRBool +nsTAString_CharT::EqualsASCII( const char* data, size_type len ) const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->EqualsASCII(data, len); + + return ToSubstring().EqualsASCII(data, len); + } + +PRBool +nsTAString_CharT::EqualsASCII( const char* data ) const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->EqualsASCII(data); + + return ToSubstring().EqualsASCII(data); + } + +PRBool +nsTAString_CharT::LowerCaseEqualsASCII( const char* data, size_type len ) const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->LowerCaseEqualsASCII(data, len); + + return ToSubstring().LowerCaseEqualsASCII(data, len); + } + +PRBool +nsTAString_CharT::LowerCaseEqualsASCII( const char* data ) const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->LowerCaseEqualsASCII(data); + + return ToSubstring().LowerCaseEqualsASCII(data); + } + +PRBool +nsTAString_CharT::IsVoid() const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->IsVoid(); + + return AsObsoleteString()->IsVoid(); + } + +void +nsTAString_CharT::SetIsVoid( PRBool val ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->SetIsVoid(val); + else + AsObsoleteString()->SetIsVoid(val); + } + +PRBool +nsTAString_CharT::IsTerminated() const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->IsTerminated(); + + return AsObsoleteString()->GetFlatBufferHandle() != nsnull; + } + +CharT +nsTAString_CharT::First() const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->First(); + + return ToSubstring().First(); + } + +CharT +nsTAString_CharT::Last() const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->Last(); + + return ToSubstring().Last(); + } + +nsTAString_CharT::size_type +nsTAString_CharT::CountChar( char_type c ) const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->CountChar(c); + + return ToSubstring().CountChar(c); + } + +PRInt32 +nsTAString_CharT::FindChar( char_type c, index_type offset ) const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->FindChar(c, offset); + + return ToSubstring().FindChar(c, offset); + } + +void +nsTAString_CharT::SetCapacity( size_type size ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->SetCapacity(size); + else + AsObsoleteString()->SetCapacity(size); + } + +void +nsTAString_CharT::SetLength( size_type size ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->SetLength(size); + else + AsObsoleteString()->SetLength(size); + } + +void +nsTAString_CharT::Assign( const self_type& readable ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Assign(readable); + else + AsObsoleteString()->do_AssignFromReadable(readable); + } + +void +nsTAString_CharT::Assign( const substring_tuple_type& tuple ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Assign(tuple); + else + AsObsoleteString()->do_AssignFromReadable(nsTAutoString_CharT(tuple)); + } + +void +nsTAString_CharT::Assign( const char_type* data ) + { + // null check and SetLength(0) cases needed for backwards compat + + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Assign(data); + else if (data) + AsObsoleteString()->do_AssignFromElementPtr(data); + else + AsObsoleteString()->SetLength(0); + } + +void +nsTAString_CharT::Assign( const char_type* data, size_type length ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Assign(data, length); + else + AsObsoleteString()->do_AssignFromElementPtrLength(data, length); + } + +void +nsTAString_CharT::AssignASCII( const char* data ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->AssignASCII(data); + else + { +#ifdef CharT_is_char + AsObsoleteString()->do_AssignFromElementPtr(data); +#else + nsTAutoString_CharT temp; + temp.AssignASCII(data); + AsObsoleteString()->do_AssignFromReadable(temp); +#endif + } + } + +void +nsTAString_CharT::AssignASCII( const char* data, size_type length ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->AssignASCII(data, length); + else + { +#ifdef CharT_is_char + AsObsoleteString()->do_AssignFromElementPtrLength(data, length); +#else + nsTAutoString_CharT temp; + temp.AssignASCII(data, length); + AsObsoleteString()->do_AssignFromReadable(temp); +#endif + } + } + +void +nsTAString_CharT::Assign( char_type c ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Assign(c); + else + AsObsoleteString()->do_AssignFromElement(c); + } + +void +nsTAString_CharT::Append( const self_type& readable ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Append(readable); + else + AsObsoleteString()->do_AppendFromReadable(readable); + } + +void +nsTAString_CharT::Append( const substring_tuple_type& tuple ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Append(tuple); + else + AsObsoleteString()->do_AppendFromReadable(nsTAutoString_CharT(tuple)); + } + +void +nsTAString_CharT::Append( const char_type* data ) + { + // null check case needed for backwards compat + + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Append(data); + else if (data) + AsObsoleteString()->do_AppendFromElementPtr(data); + } + +void +nsTAString_CharT::Append( const char_type* data, size_type length ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Append(data, length); + else + AsObsoleteString()->do_AppendFromElementPtrLength(data, length); + } + +void +nsTAString_CharT::AppendASCII( const char* data ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->AppendASCII(data); + else + { +#ifdef CharT_is_char + AsObsoleteString()->do_AppendFromElementPtr(data); +#else + nsTAutoString_CharT temp; + temp.AssignASCII(data); + AsObsoleteString()->do_AppendFromReadable(temp); +#endif + } + } + +void +nsTAString_CharT::AppendASCII( const char* data, size_type length ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->AppendASCII(data, length); + else + { +#ifdef CharT_is_char + AsObsoleteString()->do_AppendFromElementPtrLength(data, length); +#else + nsTAutoString_CharT temp; + temp.AssignASCII(data, length); + AsObsoleteString()->do_AppendFromReadable(temp); +#endif + } + } + +void +nsTAString_CharT::Append( char_type c ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Append(c); + else + AsObsoleteString()->do_AppendFromElement(c); + } + +void +nsTAString_CharT::Insert( const self_type& readable, index_type pos ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Insert(readable, pos); + else + AsObsoleteString()->do_InsertFromReadable(readable, pos); + } + +void +nsTAString_CharT::Insert( const substring_tuple_type& tuple, index_type pos ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Insert(tuple, pos); + else + AsObsoleteString()->do_InsertFromReadable(nsTAutoString_CharT(tuple), pos); + } + +void +nsTAString_CharT::Insert( const char_type* data, index_type pos ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Insert(data, pos); + else + AsObsoleteString()->do_InsertFromElementPtr(data, pos); + } + +void +nsTAString_CharT::Insert( const char_type* data, index_type pos, size_type length ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Insert(data, pos, length); + else + AsObsoleteString()->do_InsertFromElementPtrLength(data, pos, length); + } + +void +nsTAString_CharT::Insert( char_type c, index_type pos ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Insert(c, pos); + else + AsObsoleteString()->do_InsertFromElement(c, pos); + } + +void +nsTAString_CharT::Cut( index_type cutStart, size_type cutLength ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Cut(cutStart, cutLength); + else + AsObsoleteString()->Cut(cutStart, cutLength); + } + +void +nsTAString_CharT::Replace( index_type cutStart, size_type cutLength, const self_type& readable ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Replace(cutStart, cutLength, readable); + else + AsObsoleteString()->do_ReplaceFromReadable(cutStart, cutLength, readable); + } + +void +nsTAString_CharT::Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple ) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + AsSubstring()->Replace(cutStart, cutLength, tuple); + else + AsObsoleteString()->do_ReplaceFromReadable(cutStart, cutLength, nsTAutoString_CharT(tuple)); + } + +nsTAString_CharT::size_type +nsTAString_CharT::GetReadableBuffer( const char_type **data ) const + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + { + const substring_type* str = AsSubstring(); + *data = str->mData; + return str->mLength; + } + + obsolete_string_type::const_fragment_type frag; + AsObsoleteString()->GetReadableFragment(frag, obsolete_string_type::kFirstFragment, 0); + *data = frag.mStart; + return (frag.mEnd - frag.mStart); + } + +nsTAString_CharT::size_type +nsTAString_CharT::GetWritableBuffer(char_type **data) + { + if (mVTable == obsolete_string_type::sCanonicalVTable) + { + substring_type* str = AsSubstring(); + str->BeginWriting(*data); + return str->Length(); + } + + obsolete_string_type::fragment_type frag; + AsObsoleteString()->GetWritableFragment(frag, obsolete_string_type::kFirstFragment, 0); + *data = frag.mStart; + return (frag.mEnd - frag.mStart); + } + +PRBool +nsTAString_CharT::IsDependentOn(const char_type* start, const char_type *end) const + { + // this is an optimization... + if (mVTable == obsolete_string_type::sCanonicalVTable) + return AsSubstring()->IsDependentOn(start, end); + + return ToSubstring().IsDependentOn(start, end); + } + +const nsTAString_CharT::substring_type +nsTAString_CharT::ToSubstring() const + { + const char_type* data; + size_type length = GetReadableBuffer(&data); + return substring_type(NS_CONST_CAST(char_type*, data), length, 0); + } diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTDependentSubstring.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTDependentSubstring.cpp new file mode 100644 index 00000000..8421ecc0 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsTDependentSubstring.cpp @@ -0,0 +1,65 @@ +/* -*- 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 ***** */ + +void +nsTDependentSubstring_CharT::Rebind( const abstract_string_type& readable, PRUint32 startPos, PRUint32 length ) + { + size_type strLength = readable.GetReadableBuffer((const char_type**) &mData); + + if (startPos > strLength) + startPos = strLength; + + mData += startPos; + mLength = NS_MIN(length, strLength - startPos); + + SetDataFlags(F_NONE); + } + +void +nsTDependentSubstring_CharT::Rebind( const substring_type& str, PRUint32 startPos, PRUint32 length ) + { + size_type strLength = str.Length(); + + if (startPos > strLength) + startPos = strLength; + + mData = NS_CONST_CAST(char_type*, str.Data()) + startPos; + mLength = NS_MIN(length, strLength - startPos); + + SetDataFlags(F_NONE); + } diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTObsoleteAStringThunk.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTObsoleteAStringThunk.cpp new file mode 100644 index 00000000..3d1590a8 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsTObsoleteAStringThunk.cpp @@ -0,0 +1,235 @@ +/* -*- 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 ***** */ + + +class nsTObsoleteAStringThunk_CharT : public nsTObsoleteAString_CharT + { + public: + typedef nsTObsoleteAStringThunk_CharT self_type; + typedef nsTSubstring_CharT substring_type; + + public: + + nsTObsoleteAStringThunk_CharT() {} + + + static const void* get_vptr() + { + const void* result; + new (&result) self_type(); + return result; + } + + + /** + * we are a nsTSubstring in disguise! + */ + + substring_type* concrete_self() { return NS_REINTERPRET_CAST( substring_type*, this); } + const substring_type* concrete_self() const { return NS_REINTERPRET_CAST(const substring_type*, this); } + + + /** + * all virtual methods need to be redirected to appropriate nsString methods + */ + + virtual ~nsTObsoleteAStringThunk_CharT() + { + concrete_self()->Finalize(); + } + + virtual PRUint32 GetImplementationFlags() const + { + return 0; + } + + virtual const buffer_handle_type* GetFlatBufferHandle() const + { + return (const buffer_handle_type*) (concrete_self()->IsTerminated() != PR_FALSE); + } + + virtual const buffer_handle_type* GetBufferHandle() const + { + return 0; + } + + virtual const shared_buffer_handle_type* GetSharedBufferHandle() const + { + return 0; + } + + virtual size_type Length() const + { + return concrete_self()->Length(); + } + + virtual PRBool IsVoid() const + { + return concrete_self()->IsVoid(); + } + + virtual void SetIsVoid(PRBool val) + { + concrete_self()->SetIsVoid(val); + } + + virtual void SetCapacity(size_type size) + { + concrete_self()->SetCapacity(size); + } + + virtual void SetLength(size_type size) + { + concrete_self()->SetLength(size); + } + + virtual void Cut(index_type cutStart, size_type cutLength) + { + concrete_self()->Cut(cutStart, cutLength); + } + + virtual void do_AssignFromReadable(const abstract_string_type &s) + { + concrete_self()->Assign(s); + } + + virtual void do_AssignFromElementPtr(const char_type *data) + { + concrete_self()->Assign(data); + } + + virtual void do_AssignFromElementPtrLength(const char_type *data, size_type length) + { + concrete_self()->Assign(data, length); + } + + virtual void do_AssignFromElement(char_type c) + { + concrete_self()->Assign(c); + } + + virtual void do_AppendFromReadable(const abstract_string_type &s) + { + concrete_self()->Append(s); + } + + virtual void do_AppendFromElementPtr(const char_type *data) + { + concrete_self()->Append(data); + } + + virtual void do_AppendFromElementPtrLength(const char_type *data, size_type length) + { + concrete_self()->Append(data, length); + } + + virtual void do_AppendFromElement(char_type c) + { + concrete_self()->Append(c); + } + + virtual void do_InsertFromReadable(const abstract_string_type &s, index_type pos) + { + concrete_self()->Insert(s, pos); + } + + virtual void do_InsertFromElementPtr(const char_type *data, index_type pos) + { + concrete_self()->Insert(data, pos); + } + + virtual void do_InsertFromElementPtrLength(const char_type *data, index_type pos, size_type length) + { + concrete_self()->Insert(data, pos, length); + } + + virtual void do_InsertFromElement(char_type c, index_type pos) + { + concrete_self()->Insert(c, pos); + } + + virtual void do_ReplaceFromReadable(index_type cutStart, size_type cutLength, const abstract_string_type &s) + { + concrete_self()->Replace(cutStart, cutLength, s); + } + + virtual const char_type *GetReadableFragment(const_fragment_type& frag, nsFragmentRequest which, PRUint32 offset) const + { + const substring_type* s = concrete_self(); + switch (which) + { + case kFirstFragment: + case kLastFragment: + case kFragmentAt: + frag.mStart = s->Data(); + frag.mEnd = frag.mStart + s->Length(); + return frag.mStart + offset; + case kPrevFragment: + case kNextFragment: + default: + return 0; + } + } + + virtual char_type *GetWritableFragment(fragment_type& frag, nsFragmentRequest which, PRUint32 offset) + { + substring_type* s = concrete_self(); + switch (which) + { + case kFirstFragment: + case kLastFragment: + case kFragmentAt: + char_type* start; + s->BeginWriting(start); + frag.mStart = start; + frag.mEnd = start + s->Length(); + return frag.mStart + offset; + case kPrevFragment: + case kNextFragment: + default: + return 0; + } + } + }; + + + /** + * initialize the pointer to the canonical vtable... + */ + +const void *nsTObsoleteAString_CharT::sCanonicalVTable = nsTObsoleteAStringThunk_CharT::get_vptr(); diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTPromiseFlatString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTPromiseFlatString.cpp new file mode 100644 index 00000000..bf0bfc32 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsTPromiseFlatString.cpp @@ -0,0 +1,66 @@ +/* -*- 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 ***** */ + +void +nsTPromiseFlatString_CharT::Init(const substring_type& str) + { + // we have to manually set this here since we are being called on an + // unitialized object. + mVTable = nsTObsoleteAString_CharT::sCanonicalVTable; + + if (str.IsTerminated()) + { + mData = NS_CONST_CAST(char_type*, str.Data()); + mLength = str.Length(); + mFlags = F_TERMINATED; // does not promote F_VOIDED + } + else + { + Assign(str); + } + } + + // this function is non-inline to minimize codesize +void +nsTPromiseFlatString_CharT::Init(const abstract_string_type& readable) + { + if (readable.mVTable == nsTObsoleteAString_CharT::sCanonicalVTable) + Init(*readable.AsSubstring()); + else + Init(readable.ToSubstring()); + } diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTString.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTString.cpp new file mode 100644 index 00000000..84911f5f --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsTString.cpp @@ -0,0 +1,63 @@ +/* -*- 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> + * Johnny Stenback <jst@mozilla.jstenback.com> + * + * 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 ***** */ + +NS_COM nsTAdoptingString_CharT& +nsTAdoptingString_CharT::operator=( const self_type& str ) + { + // This'll violate the constness of this argument, that's just + // the nature of this class... + self_type* mutable_str = NS_CONST_CAST(self_type*, &str); + + if (str.mFlags & F_OWNED) + { + Adopt(str.mData, str.mLength); + + // Make str forget the buffer we just took ownership of. + new (mutable_str) self_type(); + } + else + { + Assign(str); + + mutable_str->Truncate(); + } + + return *this; + } + diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTStringComparator.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTStringComparator.cpp new file mode 100644 index 00000000..6d2645a1 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsTStringComparator.cpp @@ -0,0 +1,79 @@ +/* -*- 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 ***** */ + +NS_COM int +Compare( const nsTAString_CharT& lhs, const nsTAString_CharT& rhs, const nsTStringComparator_CharT& comp ) + { + typedef nsTAString_CharT::size_type size_type; + + if ( &lhs == &rhs ) + return 0; + + nsTAString_CharT::const_iterator leftIter, rightIter; + lhs.BeginReading(leftIter); + rhs.BeginReading(rightIter); + + size_type lLength = leftIter.size_forward(); + size_type rLength = rightIter.size_forward(); + size_type lengthToCompare = NS_MIN(lLength, rLength); + + int result; + if ( (result = comp(leftIter.get(), rightIter.get(), lengthToCompare)) == 0 ) + { + if ( lLength < rLength ) + result = -1; + else if ( rLength < lLength ) + result = 1; + else + result = 0; + } + + return result; + } + +int +nsTDefaultStringComparator_CharT::operator()( const char_type* lhs, const char_type* rhs, PRUint32 aLength ) const + { + return nsCharTraits<CharT>::compare(lhs, rhs, aLength); + } + +int +nsTDefaultStringComparator_CharT::operator()( char_type lhs, char_type rhs) const + { + return lhs - rhs; + } diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTStringObsolete.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTStringObsolete.cpp new file mode 100644 index 00000000..5ed065ad --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsTStringObsolete.cpp @@ -0,0 +1,518 @@ +/* -*- 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 ***** */ + + + + /** + * nsTString::Find + * + * aOffset specifies starting index + * aCount specifies number of string compares (iterations) + */ + +PRInt32 +nsTString_CharT::Find( const nsCString& aString, PRBool aIgnoreCase, PRInt32 aOffset, PRInt32 aCount) const + { + // this method changes the meaning of aOffset and aCount: + Find_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount); + + PRInt32 result = FindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), aIgnoreCase); + if (result != kNotFound) + result += aOffset; + return result; + } + +PRInt32 +nsTString_CharT::Find( const char* aString, PRBool aIgnoreCase, PRInt32 aOffset, PRInt32 aCount) const + { + return Find(nsDependentCString(aString), aIgnoreCase, aOffset, aCount); + } + + + /** + * nsTString::RFind + * + * aOffset specifies starting index + * aCount specifies number of string compares (iterations) + */ + +PRInt32 +nsTString_CharT::RFind( const nsCString& aString, PRBool aIgnoreCase, PRInt32 aOffset, PRInt32 aCount) const + { + // this method changes the meaning of aOffset and aCount: + RFind_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount); + + PRInt32 result = RFindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), aIgnoreCase); + if (result != kNotFound) + result += aOffset; + return result; + } + +PRInt32 +nsTString_CharT::RFind( const char* aString, PRBool aIgnoreCase, PRInt32 aOffset, PRInt32 aCount) const + { + return RFind(nsDependentCString(aString), aIgnoreCase, aOffset, aCount); + } + + + /** + * nsTString::RFindChar + */ + +PRInt32 +nsTString_CharT::RFindChar( PRUnichar aChar, PRInt32 aOffset, PRInt32 aCount) const + { + return nsBufferRoutines<CharT>::rfind_char(mData, mLength, aOffset, aChar, aCount); + } + + + /** + * nsTString::FindCharInSet + */ + +PRInt32 +nsTString_CharT::FindCharInSet( const char* aSet, PRInt32 aOffset ) const + { + if (aOffset < 0) + aOffset = 0; + else if (aOffset >= PRInt32(mLength)) + return kNotFound; + + PRInt32 result = ::FindCharInSet(mData + aOffset, mLength - aOffset, aSet); + if (result != kNotFound) + result += aOffset; + return result; + } + + + /** + * nsTString::RFindCharInSet + */ + +PRInt32 +nsTString_CharT::RFindCharInSet( const CharT* aSet, PRInt32 aOffset ) const + { + // We want to pass a "data length" to ::RFindCharInSet + if (aOffset < 0 || aOffset > PRInt32(mLength)) + aOffset = mLength; + else + ++aOffset; + + return ::RFindCharInSet(mData, aOffset, aSet); + } + + + // it's a shame to replicate this code. it was done this way in the past + // to help performance. this function also gets to keep the rickg style + // indentation :-/ +PRInt32 +nsTString_CharT::ToInteger( PRInt32* aErrorCode, PRUint32 aRadix ) const +{ + CharT* cp=mData; + PRInt32 theRadix=10; // base 10 unless base 16 detected, or overriden (aRadix != kAutoDetect) + PRInt32 result=0; + PRBool negate=PR_FALSE; + CharT theChar=0; + + //initial value, override if we find an integer + *aErrorCode=NS_ERROR_ILLEGAL_VALUE; + + if(cp) { + + //begin by skipping over leading chars that shouldn't be part of the number... + + CharT* endcp=cp+mLength; + PRBool done=PR_FALSE; + + while((cp<endcp) && (!done)){ + switch(*cp++) { + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + theRadix=16; + done=PR_TRUE; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + done=PR_TRUE; + break; + case '-': + negate=PR_TRUE; //fall through... + break; + case 'X': case 'x': + theRadix=16; + break; + default: + break; + } //switch + } + + if (done) { + + //integer found + *aErrorCode = NS_OK; + + if (aRadix!=kAutoDetect) theRadix = aRadix; // override + + //now iterate the numeric chars and build our result + CharT* first=--cp; //in case we have to back up. + PRBool haveValue = PR_FALSE; + + while(cp<endcp){ + theChar=*cp++; + if(('0'<=theChar) && (theChar<='9')){ + result = (theRadix * result) + (theChar-'0'); + haveValue = PR_TRUE; + } + else if((theChar>='A') && (theChar<='F')) { + if(10==theRadix) { + if(kAutoDetect==aRadix){ + theRadix=16; + cp=first; //backup + result=0; + haveValue = PR_FALSE; + } + else { + *aErrorCode=NS_ERROR_ILLEGAL_VALUE; + result=0; + break; + } + } + else { + result = (theRadix * result) + ((theChar-'A')+10); + haveValue = PR_TRUE; + } + } + else if((theChar>='a') && (theChar<='f')) { + if(10==theRadix) { + if(kAutoDetect==aRadix){ + theRadix=16; + cp=first; //backup + result=0; + haveValue = PR_FALSE; + } + else { + *aErrorCode=NS_ERROR_ILLEGAL_VALUE; + result=0; + break; + } + } + else { + result = (theRadix * result) + ((theChar-'a')+10); + haveValue = PR_TRUE; + } + } + else if((('X'==theChar) || ('x'==theChar)) && (!haveValue || result == 0)) { + continue; + } + else if((('#'==theChar) || ('+'==theChar)) && !haveValue) { + continue; + } + else { + //we've encountered a char that's not a legal number or sign + break; + } + } //while + if(negate) + result=-result; + } //if + } + return result; +} + + + /** + * nsTString::Mid + */ + +PRUint32 +nsTString_CharT::Mid( self_type& aResult, index_type aStartPos, size_type aLengthToCopy ) const + { + if (aStartPos == 0 && aLengthToCopy >= mLength) + aResult = *this; + else + aResult = Substring(*this, aStartPos, aLengthToCopy); + + return aResult.mLength; + } + + + /** + * nsTString::SetCharAt + */ + +PRBool +nsTString_CharT::SetCharAt( PRUnichar aChar, PRUint32 aIndex ) + { + if (aIndex >= mLength) + return PR_FALSE; + + EnsureMutable(); + + mData[aIndex] = CharT(aChar); + return PR_TRUE; + } + + + /** + * nsTString::StripChars,StripChar,StripWhitespace + */ + +void +nsTString_CharT::StripChars( const char* aSet ) + { + EnsureMutable(); + mLength = nsBufferRoutines<CharT>::strip_chars(mData, mLength, aSet); + } + +void +nsTString_CharT::StripChar( char_type aChar, PRInt32 aOffset ) + { + if (mLength == 0 || aOffset >= PRInt32(mLength)) + return; + + EnsureMutable(); // XXX do this lazily? + + // XXXdarin this code should defer writing until necessary. + + char_type* to = mData + aOffset; + char_type* from = mData + aOffset; + char_type* end = mData + mLength; + + while (from < end) + { + char_type theChar = *from++; + if (aChar != theChar) + *to++ = theChar; + } + *to = char_type(0); // add the null + mLength = to - mData; + } + +void +nsTString_CharT::StripWhitespace() + { + StripChars(kWhitespace); + } + + + /** + * nsTString::ReplaceChar,ReplaceSubstring + */ + +void +nsTString_CharT::ReplaceChar( char_type aOldChar, char_type aNewChar ) + { + EnsureMutable(); // XXX do this lazily? + + for (PRUint32 i=0; i<mLength; ++i) + { + if (mData[i] == aOldChar) + mData[i] = aNewChar; + } + } + +void +nsTString_CharT::ReplaceChar( const char* aSet, char_type aNewChar ) + { + EnsureMutable(); // XXX do this lazily? + + char_type* data = mData; + PRUint32 lenRemaining = mLength; + + while (lenRemaining) + { + PRInt32 i = ::FindCharInSet(data, lenRemaining, aSet); + if (i == kNotFound) + break; + + data[i++] = aNewChar; + data += i; + lenRemaining -= i; + } + } + +void +nsTString_CharT::ReplaceSubstring( const char_type* aTarget, const char_type* aNewValue ) + { + ReplaceSubstring(nsTDependentString_CharT(aTarget), + nsTDependentString_CharT(aNewValue)); + } + +void +nsTString_CharT::ReplaceSubstring( const self_type& aTarget, const self_type& aNewValue ) + { + if (aTarget.Length() == 0) + return; + + PRUint32 i = 0; + while (i < mLength) + { + PRInt32 r = FindSubstring(mData + i, mLength - i, aTarget.Data(), aTarget.Length(), PR_FALSE); + if (r == kNotFound) + break; + + Replace(i + r, aTarget.Length(), aNewValue); + i += r + aNewValue.Length(); + } + } + + + /** + * nsTString::Trim + */ + +void +nsTString_CharT::Trim( const char* aSet, PRBool aTrimLeading, PRBool aTrimTrailing, PRBool aIgnoreQuotes ) + { + // the old implementation worried about aSet being null :-/ + if (!aSet) + return; + + char_type* start = mData; + char_type* end = mData + mLength; + + // skip over quotes if requested + if (aIgnoreQuotes && mLength > 2 && mData[0] == mData[mLength - 1] && + (mData[0] == '\'' || mData[0] == '"')) + { + ++start; + --end; + } + + PRUint32 setLen = nsCharTraits<char>::length(aSet); + + if (aTrimLeading) + { + PRUint32 cutStart = start - mData; + PRUint32 cutLength = 0; + + // walk forward from start to end + for (; start != end; ++start, ++cutLength) + { + PRInt32 pos = FindChar1(aSet, setLen, 0, *start, setLen); + if (pos == kNotFound) + break; + } + + if (cutLength) + { + Cut(cutStart, cutLength); + + // reset iterators + start = mData + cutStart; + end = mData + mLength - cutStart; + } + } + + if (aTrimTrailing) + { + PRUint32 cutEnd = end - mData; + PRUint32 cutLength = 0; + + // walk backward from end to start + --end; + for (; end >= start; --end, ++cutLength) + { + PRInt32 pos = FindChar1(aSet, setLen, 0, *end, setLen); + if (pos == kNotFound) + break; + } + + if (cutLength) + Cut(cutEnd - cutLength, cutLength); + } + } + + + /** + * nsTString::CompressWhitespace + */ + +void +nsTString_CharT::CompressWhitespace( PRBool aTrimLeading, PRBool aTrimTrailing ) + { + const char* set = kWhitespace; + + ReplaceChar(set, ' '); + Trim(set, aTrimLeading, aTrimTrailing); + + // this one does some questionable fu... just copying the old code! + mLength = nsBufferRoutines<char_type>::compress_chars(mData, mLength, set); + } + + + /** + * nsTString::AssignWithConversion + */ + +void +nsTString_CharT::AssignWithConversion( const incompatible_char_type* aData, PRInt32 aLength ) + { + // for compatibility with the old string implementation, we need to allow + // for a NULL input buffer :-( + if (!aData) + { + Truncate(); + } + else + { + if (aLength < 0) + aLength = nsCharTraits<incompatible_char_type>::length(aData); + + AssignWithConversion(Substring(aData, aData + aLength)); + } + } + + + /** + * nsTString::AppendWithConversion + */ + +void +nsTString_CharT::AppendWithConversion( const incompatible_char_type* aData, PRInt32 aLength ) + { + // for compatibility with the old string implementation, we need to allow + // for a NULL input buffer :-( + if (aData) + { + if (aLength < 0) + aLength = nsCharTraits<incompatible_char_type>::length(aData); + + AppendWithConversion(Substring(aData, aData + aLength)); + } + } diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTSubstring.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTSubstring.cpp new file mode 100644 index 00000000..e36b1863 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsTSubstring.cpp @@ -0,0 +1,656 @@ +/* -*- 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 ***** */ + + + /** + * helper function for down-casting a nsTSubstring to a nsTFixedString. + */ +inline const nsTFixedString_CharT* +AsFixedString( const nsTSubstring_CharT* s ) + { + return NS_STATIC_CAST(const nsTFixedString_CharT*, s); + } + + + /** + * this function is called to prepare mData for writing. the given capacity + * indicates the required minimum storage size for mData, in sizeof(char_type) + * increments. this function returns true if the operation succeeds. it also + * returns the old data and old flags members if mData is newly allocated. + * the old data must be released by the caller. + */ +PRBool +nsTSubstring_CharT::MutatePrep( size_type capacity, char_type** oldData, PRUint32* oldFlags ) + { + // initialize to no old data + *oldData = nsnull; + *oldFlags = 0; + + size_type curCapacity = Capacity(); + + // |curCapacity == size_type(-1)| means that the buffer is immutable, so we + // need to allocate a new buffer. we cannot use the existing buffer even + // though it might be large enough. + + if (curCapacity != size_type(-1)) + { + if (capacity <= curCapacity) + return PR_TRUE; + + if (curCapacity > 0) + { + // use doubling algorithm when forced to increase available capacity, + // but always start out with exactly the requested amount. + PRUint32 temp = curCapacity; + while (temp < capacity) + temp <<= 1; + capacity = temp; + } + } + + // + // several cases: + // + // (1) we have a shared buffer (mFlags & F_SHARED) + // (2) we have an owned buffer (mFlags & F_OWNED) + // (3) we have a fixed buffer (mFlags & F_FIXED) + // (4) we have a readonly buffer + // + // requiring that we in some cases preserve the data before creating + // a new buffer complicates things just a bit ;-) + // + + size_type storageSize = (capacity + 1) * sizeof(char_type); + + // case #1 + if (mFlags & F_SHARED) + { + nsStringHeader* hdr = nsStringHeader::FromData(mData); + if (!hdr->IsReadonly()) + { + nsStringHeader *newHdr = nsStringHeader::Realloc(hdr, storageSize); + if (newHdr) + { + hdr = newHdr; + mData = (char_type*) hdr->Data(); + return PR_TRUE; + } + hdr->Release(); + // out of memory!! put us in a consistent state at least. + mData = NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer); + mLength = 0; + SetDataFlags(F_TERMINATED); + return PR_FALSE; + } + } + + char_type* newData; + PRUint32 newDataFlags; + + // if we have a fixed buffer of sufficient size, then use it. this helps + // avoid heap allocations. + if ((mFlags & F_CLASS_FIXED) && (capacity < AsFixedString(this)->mFixedCapacity)) + { + newData = AsFixedString(this)->mFixedBuf; + newDataFlags = F_TERMINATED | F_FIXED; + } + else + { + // if we reach here then, we must allocate a new buffer. we cannot + // make use of our F_OWNED or F_FIXED buffers because they are not + // large enough. + + nsStringHeader* newHdr = nsStringHeader::Alloc(storageSize); + if (!newHdr) + return PR_FALSE; // we are still in a consistent state + + newData = (char_type*) newHdr->Data(); + newDataFlags = F_TERMINATED | F_SHARED; + } + + // save old data and flags + *oldData = mData; + *oldFlags = mFlags; + + mData = newData; + SetDataFlags(newDataFlags); + + // mLength does not change + + // though we are not necessarily terminated at the moment, now is probably + // still the best time to set F_TERMINATED. + + return PR_TRUE; + } + +void +nsTSubstring_CharT::Finalize() + { + ::ReleaseData(mData, mFlags); + // mData, mLength, and mFlags are purposefully left dangling + } + +void +nsTSubstring_CharT::ReplacePrep( index_type cutStart, size_type cutLen, size_type fragLen ) + { + // bound cut length + cutLen = NS_MIN(cutLen, mLength - cutStart); + + PRUint32 newLen = mLength - cutLen + fragLen; + + char_type* oldData; + PRUint32 oldFlags; + if (!MutatePrep(newLen, &oldData, &oldFlags)) + return; // XXX out-of-memory error occured! + + if (oldData) + { + // determine whether or not we need to copy part of the old string + // over to the new string. + + if (cutStart > 0) + { + // copy prefix from old string + char_traits::copy(mData, oldData, cutStart); + } + + if (cutStart + cutLen < mLength) + { + // copy suffix from old string to new offset + size_type from = cutStart + cutLen; + size_type fromLen = mLength - from; + PRUint32 to = cutStart + fragLen; + char_traits::copy(mData + to, oldData + from, fromLen); + } + + ::ReleaseData(oldData, oldFlags); + } + else + { + // original data remains intact + + // determine whether or not we need to move part of the existing string + // to make room for the requested hole. + if (fragLen != cutLen && cutStart + cutLen < mLength) + { + PRUint32 from = cutStart + cutLen; + PRUint32 fromLen = mLength - from; + PRUint32 to = cutStart + fragLen; + char_traits::move(mData + to, mData + from, fromLen); + } + } + + // add null terminator (mutable mData always has room for the null- + // terminator). + mData[newLen] = char_type(0); + mLength = newLen; + } + +nsTSubstring_CharT::size_type +nsTSubstring_CharT::Capacity() const + { + // return size_type(-1) to indicate an immutable buffer + + size_type capacity; + if (mFlags & F_SHARED) + { + // if the string is readonly, then we pretend that it has no capacity. + nsStringHeader* hdr = nsStringHeader::FromData(mData); + if (hdr->IsReadonly()) + capacity = size_type(-1); + else + capacity = (hdr->StorageSize() / sizeof(char_type)) - 1; + } + else if (mFlags & F_FIXED) + { + capacity = AsFixedString(this)->mFixedCapacity; + } + else if (mFlags & F_OWNED) + { + // we don't store the capacity of an adopted buffer because that would + // require an additional member field. the best we can do is base the + // capacity on our length. remains to be seen if this is the right + // trade-off. + capacity = mLength; + } + else + { + capacity = size_type(-1); + } + + return capacity; + } + +void +nsTSubstring_CharT::EnsureMutable() + { + if (mFlags & (F_FIXED | F_OWNED)) + return; + if ((mFlags & F_SHARED) && !nsStringHeader::FromData(mData)->IsReadonly()) + return; + + // promote to a shared string buffer + Assign(string_type(mData, mLength)); + } + +// --------------------------------------------------------------------------- + +void +nsTSubstring_CharT::Assign( const char_type* data, size_type length ) + { + // unfortunately, some callers pass null :-( + if (!data) + { + Truncate(); + return; + } + + if (length == size_type(-1)) + length = char_traits::length(data); + + if (IsDependentOn(data, data + length)) + { + // take advantage of sharing here... + Assign(string_type(data, length)); + return; + } + + ReplacePrep(0, mLength, length); + char_traits::copy(mData, data, length); + } + +void +nsTSubstring_CharT::AssignASCII( const char* data, size_type length ) + { + // A Unicode string can't depend on an ASCII string buffer, + // so this dependence check only applies to CStrings. +#ifdef CharT_is_char + if (IsDependentOn(data, data + length)) + { + // take advantage of sharing here... + Assign(string_type(data, length)); + return; + } +#endif + + ReplacePrep(0, mLength, length); + char_traits::copyASCII(mData, data, length); + } + +void +nsTSubstring_CharT::AssignASCII( const char* data ) + { + AssignASCII(data, strlen(data)); + } + +void +nsTSubstring_CharT::Assign( const self_type& str ) + { + // |str| could be sharable. we need to check its flags to know how to + // deal with it. + + if (&str == this) + return; + + if (str.mFlags & F_SHARED) + { + // nice! we can avoid a string copy :-) + + // |str| should be null-terminated + NS_ASSERTION(str.mFlags & F_TERMINATED, "shared, but not terminated"); + + ::ReleaseData(mData, mFlags); + + mData = str.mData; + mLength = str.mLength; + SetDataFlags(F_TERMINATED | F_SHARED); + + // get an owning reference to the mData + nsStringHeader::FromData(mData)->AddRef(); + } + else if (str.mFlags & F_VOIDED) + { + // inherit the F_VOIDED attribute + SetIsVoid(PR_TRUE); + } + else + { + // else, treat this like an ordinary assignment. + Assign(str.Data(), str.Length()); + } + } + +void +nsTSubstring_CharT::Assign( const substring_tuple_type& tuple ) + { + if (tuple.IsDependentOn(mData, mData + mLength)) + { + // take advantage of sharing here... + Assign(string_type(tuple)); + return; + } + + size_type length = tuple.Length(); + + ReplacePrep(0, mLength, length); + if (length) + tuple.WriteTo(mData, length); + } + + // this is non-inline to reduce codesize at the callsite +void +nsTSubstring_CharT::Assign( const abstract_string_type& readable ) + { + // promote to string if possible to take advantage of sharing + if (readable.mVTable == nsTObsoleteAString_CharT::sCanonicalVTable) + Assign(*readable.AsSubstring()); + else + Assign(readable.ToSubstring()); + } + + +void +nsTSubstring_CharT::Adopt( char_type* data, size_type length ) + { + if (data) + { + ::ReleaseData(mData, mFlags); + + if (length == size_type(-1)) + length = char_traits::length(data); + + mData = data; + mLength = length; + SetDataFlags(F_TERMINATED | F_OWNED); + + STRING_STAT_INCREMENT(Adopt); + } + else + { + SetIsVoid(PR_TRUE); + } + } + + +void +nsTSubstring_CharT::Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length ) + { + // unfortunately, some callers pass null :-( + if (!data) + { + length = 0; + } + else + { + if (length == size_type(-1)) + length = char_traits::length(data); + + if (IsDependentOn(data, data + length)) + { + nsTAutoString_CharT temp(data, length); + Replace(cutStart, cutLength, temp); + return; + } + } + + cutStart = PR_MIN(cutStart, Length()); + + ReplacePrep(cutStart, cutLength, length); + + if (length > 0) + char_traits::copy(mData + cutStart, data, length); + } + +void +nsTSubstring_CharT::ReplaceASCII( index_type cutStart, size_type cutLength, const char* data, size_type length ) + { + if (length == size_type(-1)) + length = strlen(data); + + // A Unicode string can't depend on an ASCII string buffer, + // so this dependence check only applies to CStrings. +#ifdef CharT_is_char + if (IsDependentOn(data, data + length)) + { + nsTAutoString_CharT temp(data, length); + Replace(cutStart, cutLength, temp); + return; + } +#endif + + cutStart = PR_MIN(cutStart, Length()); + + ReplacePrep(cutStart, cutLength, length); + + if (length > 0) + char_traits::copyASCII(mData + cutStart, data, length); + } + +void +nsTSubstring_CharT::Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple ) + { + if (tuple.IsDependentOn(mData, mData + mLength)) + { + nsTAutoString_CharT temp(tuple); + Replace(cutStart, cutLength, temp); + return; + } + + size_type length = tuple.Length(); + + cutStart = PR_MIN(cutStart, Length()); + + ReplacePrep(cutStart, cutLength, length); + + if (length > 0) + tuple.WriteTo(mData + cutStart, length); + } + +void +nsTSubstring_CharT::Replace( index_type cutStart, size_type cutLength, const abstract_string_type& readable ) + { + Replace(cutStart, cutLength, readable.ToSubstring()); + } + +void +nsTSubstring_CharT::SetCapacity( size_type capacity ) + { + // capacity does not include room for the terminating null char + + // if our capacity is reduced to zero, then free our buffer. + if (capacity == 0) + { + ::ReleaseData(mData, mFlags); + mData = NS_CONST_CAST(char_type*, char_traits::sEmptyBuffer); + mLength = 0; + SetDataFlags(F_TERMINATED); + } + else + { + char_type* oldData; + PRUint32 oldFlags; + if (!MutatePrep(capacity, &oldData, &oldFlags)) + return; // XXX out-of-memory error occured! + + // compute new string length + size_type newLen = NS_MIN(mLength, capacity); + + if (oldData) + { + // preserve old data + if (mLength > 0) + char_traits::copy(mData, oldData, newLen); + + ::ReleaseData(oldData, oldFlags); + } + + // adjust mLength if our buffer shrunk down in size + if (newLen < mLength) + mLength = newLen; + + // always null-terminate here, even if the buffer got longer. this is + // for backwards compat with the old string implementation. + mData[capacity] = char_type(0); + } + } + +void +nsTSubstring_CharT::SetLength( size_type length ) + { + SetCapacity(length); + mLength = length; + } + +void +nsTSubstring_CharT::SetIsVoid( PRBool val ) + { + if (val) + { + Truncate(); + mFlags |= F_VOIDED; + } + else + { + mFlags &= ~F_VOIDED; + } + } + +PRBool +nsTSubstring_CharT::Equals( const self_type& str ) const + { + return mLength == str.mLength && char_traits::compare(mData, str.mData, mLength) == 0; + } + +PRBool +nsTSubstring_CharT::Equals( const self_type& str, const comparator_type& comp ) const + { + return mLength == str.mLength && comp(mData, str.mData, mLength) == 0; + } + +PRBool +nsTSubstring_CharT::Equals( const abstract_string_type& readable ) const + { + const char_type* data; + size_type length = readable.GetReadableBuffer(&data); + + return mLength == length && char_traits::compare(mData, data, mLength) == 0; + } + +PRBool +nsTSubstring_CharT::Equals( const abstract_string_type& readable, const comparator_type& comp ) const + { + const char_type* data; + size_type length = readable.GetReadableBuffer(&data); + + return mLength == length && comp(mData, data, mLength) == 0; + } + +PRBool +nsTSubstring_CharT::Equals( const char_type* data ) const + { + // unfortunately, some callers pass null :-( + if (!data) + { + NS_NOTREACHED("null data pointer"); + return mLength == 0; + } + + // XXX avoid length calculation? + size_type length = char_traits::length(data); + return mLength == length && char_traits::compare(mData, data, mLength) == 0; + } + +PRBool +nsTSubstring_CharT::Equals( const char_type* data, const comparator_type& comp ) const + { + // unfortunately, some callers pass null :-( + if (!data) + { + NS_NOTREACHED("null data pointer"); + return mLength == 0; + } + + // XXX avoid length calculation? + size_type length = char_traits::length(data); + return mLength == length && comp(mData, data, mLength) == 0; + } + +PRBool +nsTSubstring_CharT::EqualsASCII( const char* data, size_type len ) const + { + return mLength == len && char_traits::compareASCII(mData, data, len) == 0; + } + +PRBool +nsTSubstring_CharT::EqualsASCII( const char* data ) const + { + return char_traits::compareASCIINullTerminated(mData, mLength, data) == 0; + } + +PRBool +nsTSubstring_CharT::LowerCaseEqualsASCII( const char* data, size_type len ) const + { + return mLength == len && char_traits::compareLowerCaseToASCII(mData, data, len) == 0; + } + +PRBool +nsTSubstring_CharT::LowerCaseEqualsASCII( const char* data ) const + { + return char_traits::compareLowerCaseToASCIINullTerminated(mData, mLength, data) == 0; + } + +nsTSubstring_CharT::size_type +nsTSubstring_CharT::CountChar( char_type c ) const + { + const char_type *start = mData; + const char_type *end = mData + mLength; + + return NS_COUNT(start, end, c); + } + +PRInt32 +nsTSubstring_CharT::FindChar( char_type c, index_type offset ) const + { + if (offset < mLength) + { + const char_type* result = char_traits::find(mData + offset, mLength - offset, c); + if (result) + return result - mData; + } + return -1; + } diff --git a/src/libs/xpcom18a4/xpcom/string/src/nsTSubstringTuple.cpp b/src/libs/xpcom18a4/xpcom/string/src/nsTSubstringTuple.cpp new file mode 100644 index 00000000..7fff5175 --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/string/src/nsTSubstringTuple.cpp @@ -0,0 +1,127 @@ +/* -*- 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 ***** */ + + + /** + * computes the aggregate string length + */ + +nsTSubstringTuple_CharT::size_type +nsTSubstringTuple_CharT::Length() const + { + PRUint32 len; + if (mHead) + len = mHead->Length(); + else + len = TO_SUBSTRING(mFragA).Length(); + + return len + TO_SUBSTRING(mFragB).Length(); + } + + + /** + * writes the aggregate string to the given buffer. bufLen is assumed + * to be equal to or greater than the value returned by the Length() + * method. the string written to |buf| is not null-terminated. + */ + +void +nsTSubstringTuple_CharT::WriteTo( char_type *buf, PRUint32 bufLen ) const + { + const substring_type& b = TO_SUBSTRING(mFragB); + + NS_ASSERTION(bufLen >= b.Length(), "buffer too small"); + PRUint32 headLen = bufLen - b.Length(); + if (mHead) + { + mHead->WriteTo(buf, headLen); + } + else + { + const substring_type& a = TO_SUBSTRING(mFragA); + + NS_ASSERTION(a.Length() == headLen, "buffer incorrectly sized"); + char_traits::copy(buf, a.Data(), a.Length()); + } + + char_traits::copy(buf + headLen, b.Data(), b.Length()); + +#if 0 + // we need to write out data into |buf|, ending at |buf+bufLen|. so our + // data needs to precede |buf+bufLen| exactly. we trust that the buffer + // was properly sized! + + const substring_type& b = TO_SUBSTRING(mFragB); + + NS_ASSERTION(bufLen >= b.Length(), "buffer is too small"); + char_traits::copy(buf + bufLen - b.Length(), b.Data(), b.Length()); + + bufLen -= b.Length(); + + if (mHead) + { + mHead->WriteTo(buf, bufLen); + } + else + { + const substring_type& a = TO_SUBSTRING(mFragA); + NS_ASSERTION(bufLen == a.Length(), "buffer is too small"); + char_traits::copy(buf, a.Data(), a.Length()); + } +#endif + } + + + /** + * returns true if this tuple is dependent on (i.e., overlapping with) + * the given char sequence. + */ + +PRBool +nsTSubstringTuple_CharT::IsDependentOn( const char_type *start, const char_type *end ) const + { + // we start with the right-most fragment since it is faster to check. + + if (TO_SUBSTRING(mFragB).IsDependentOn(start, end)) + return PR_TRUE; + + if (mHead) + return mHead->IsDependentOn(start, end); + + return TO_SUBSTRING(mFragA).IsDependentOn(start, end); + } |