diff options
Diffstat (limited to 'src/libs/xpcom18a4/xpcom/string/src')
22 files changed, 5568 insertions, 0 deletions
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); + } |