nsTSubstring.cpp revision 677833bc953b6cb418c701facbdcf4aa18d6c44e
/* -*- 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
*
* 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.
*/
{
// initialize to no old data
*oldFlags = 0;
// |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 (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.
temp <<= 1;
}
}
//
// 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 ;-)
//
// case #1
{
if (!hdr->IsReadonly())
{
if (newHdr)
{
return PR_TRUE;
}
// out of memory!! put us in a consistent state at least.
mLength = 0;
return PR_FALSE;
}
}
// if we have a fixed buffer of sufficient size, then use it. this helps
// avoid heap allocations.
{
}
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.
if (!newHdr)
return PR_FALSE; // we are still in a consistent state
}
// save old data and flags
// 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
{
// mData, mLength, and mFlags are purposefully left dangling
}
void
{
// bound cut length
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
}
{
// copy suffix from old string to new offset
}
}
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.
{
}
}
// add null terminator (mutable mData always has room for the null-
// terminator).
}
nsTSubstring_CharT::Capacity() const
{
// return size_type(-1) to indicate an immutable buffer
{
// if the string is readonly, then we pretend that it has no capacity.
if (hdr->IsReadonly())
else
}
{
}
{
// 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.
}
else
{
}
return capacity;
}
void
{
return;
return;
// promote to a shared string buffer
}
// ---------------------------------------------------------------------------
void
{
// unfortunately, some callers pass null :-(
if (!data)
{
Truncate();
return;
}
{
// take advantage of sharing here...
return;
}
}
void
{
// A Unicode string can't depend on an ASCII string buffer,
// so this dependence check only applies to CStrings.
#ifdef CharT_is_char
{
// take advantage of sharing here...
return;
}
#endif
}
void
{
}
void
{
// |str| could be sharable. we need to check its flags to know how to
// deal with it.
if (&str == this)
return;
{
// nice! we can avoid a string copy :-)
// |str| should be null-terminated
// get an owning reference to the mData
}
{
// inherit the F_VOIDED attribute
}
else
{
// else, treat this like an ordinary assignment.
}
}
void
{
{
// take advantage of sharing here...
return;
}
if (length)
}
// this is non-inline to reduce codesize at the callsite
void
{
// promote to string if possible to take advantage of sharing
else
}
void
{
if (data)
{
}
else
{
}
}
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
{
{
return;
}
}
if (length > 0)
}
void
nsTSubstring_CharT::ReplaceASCII( index_type cutStart, size_type cutLength, 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
{
return;
}
#endif
if (length > 0)
}
void
nsTSubstring_CharT::Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple )
{
{
return;
}
if (length > 0)
}
void
nsTSubstring_CharT::Replace( index_type cutStart, size_type cutLength, const abstract_string_type& readable )
{
}
void
{
// capacity does not include room for the terminating null char
// if our capacity is reduced to zero, then free our buffer.
if (capacity == 0)
{
mLength = 0;
}
else
{
return; // XXX out-of-memory error occured!
// compute new string length
if (oldData)
{
// preserve old data
if (mLength > 0)
}
// adjust mLength if our buffer shrunk down in size
// always null-terminate here, even if the buffer got longer. this is
// for backwards compat with the old string implementation.
}
}
void
{
}
void
{
if (val)
{
Truncate();
}
else
{
}
}
{
}
{
}
{
}
nsTSubstring_CharT::Equals( const abstract_string_type& readable, const comparator_type& comp ) const
{
}
{
// unfortunately, some callers pass null :-(
if (!data)
{
NS_NOTREACHED("null data pointer");
return mLength == 0;
}
// XXX avoid length calculation?
}
{
// unfortunately, some callers pass null :-(
if (!data)
{
NS_NOTREACHED("null data pointer");
return mLength == 0;
}
// XXX avoid length calculation?
}
{
}
{
}
{
}
{
}
{
}
{
{
if (result)
}
return -1;
}