* Added a work-around to _Alloc() to allow R5 NetPositive to work on Haiku;
dunno if we want to keep this, though. * Improved some methods by no longer calling strlen() more than once. * We're now using snprintf() instead of sprintf() in the << operators to make them more secure (even though the string lengths should be long enough). * Improved << operators by taking the return (the resulting string length) of snprintf() into account. * Replaced calls to _GrowBy() with a negative argument with calls to _Alloc() which actually safes some computation. * Cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16783 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+173
-151
@@ -1,42 +1,27 @@
|
|||||||
//------------------------------------------------------------------------------
|
/*
|
||||||
// Copyright (c) 2001-2003, OpenBeOS
|
* Copyright 2001-2006, Haiku, Inc. All Rights Reserved.
|
||||||
//
|
* Distributed under the terms of the MIT License.
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
*
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
* Authors:
|
||||||
// to deal in the Software without restriction, including without limitation
|
* Marc Flerackers ([email protected])
|
||||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
* Stefano Ceccherini ([email protected])
|
||||||
// and/or sell copies of the Software, and to permit persons to whom the
|
* Oliver Tappe ([email protected])
|
||||||
// Software is furnished to do so, subject to the following conditions:
|
* Axel Dörfler, [email protected]
|
||||||
//
|
*/
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
/*! String class supporting common string operations. */
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
// DEALINGS IN THE SOFTWARE.
|
|
||||||
//
|
|
||||||
// File Name: String.cpp
|
|
||||||
// Author(s): Marc Flerackers ([email protected])
|
|
||||||
// Stefano Ceccherini ([email protected])
|
|
||||||
// Oliver Tappe ([email protected])
|
|
||||||
//
|
|
||||||
// Description: String class supporting common string operations.
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Standard Includes -----------------------------------------------------------
|
|
||||||
#include <cctype>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
// System Includes -------------------------------------------------------------
|
|
||||||
#include <Debug.h>
|
#include <Debug.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#define ENABLE_INLINES 0 // Set this to 1 to make some private methods inline
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Set this to 1 to make some private methods inline
|
||||||
|
#define ENABLE_INLINES 0
|
||||||
|
|
||||||
// define proper names for case-option of _DoReplace()
|
// define proper names for case-option of _DoReplace()
|
||||||
#define KEEP_CASE false
|
#define KEEP_CASE false
|
||||||
@@ -49,18 +34,18 @@
|
|||||||
const char *B_EMPTY_STRING = "";
|
const char *B_EMPTY_STRING = "";
|
||||||
|
|
||||||
|
|
||||||
// helper function, returns minimum of two given values (but clamps to 0):
|
//! helper function, returns minimum of two given values (but clamps to 0):
|
||||||
static inline int32
|
static inline int32
|
||||||
min_clamp0(int32 num1, int32 num2)
|
min_clamp0(int32 num1, int32 num2)
|
||||||
{
|
{
|
||||||
if (num1 < num2)
|
if (num1 < num2)
|
||||||
return num1 > 0 ? num1 : 0;
|
return num1 > 0 ? num1 : 0;
|
||||||
else
|
|
||||||
return num2 > 0 ? num2 : 0;
|
return num2 > 0 ? num2 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// helper function, returns length of given string (but clamps to given maximum):
|
//! helper function, returns length of given string (but clamps to given maximum):
|
||||||
static inline int32
|
static inline int32
|
||||||
strlen_clamp(const char* str, int32 max)
|
strlen_clamp(const char* str, int32 max)
|
||||||
{ // this should yield 0 for max<0:
|
{ // this should yield 0 for max<0:
|
||||||
@@ -71,7 +56,7 @@ strlen_clamp(const char* str, int32 max)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// helper function, massages given pointer into a legal c-string:
|
//! helper function, massages given pointer into a legal c-string:
|
||||||
static inline const char *
|
static inline const char *
|
||||||
safestr(const char* str)
|
safestr(const char* str)
|
||||||
{
|
{
|
||||||
@@ -79,7 +64,7 @@ safestr(const char* str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// helper class for BString::_ReplaceAtPositions():
|
//! helper class for BString::_ReplaceAtPositions():
|
||||||
struct
|
struct
|
||||||
BString::PosVect {
|
BString::PosVect {
|
||||||
PosVect()
|
PosVect()
|
||||||
@@ -151,7 +136,9 @@ private:
|
|||||||
#define CHECK_PARAM_VOID( expr, msg)
|
#define CHECK_PARAM_VOID( expr, msg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class BString
|
\class BString
|
||||||
@@ -211,10 +198,8 @@ BString::BString(const BString &string)
|
|||||||
BString::BString(const char *str, int32 maxLength)
|
BString::BString(const char *str, int32 maxLength)
|
||||||
: _privateData(NULL)
|
: _privateData(NULL)
|
||||||
{
|
{
|
||||||
if (str != NULL) {
|
if (str != NULL)
|
||||||
int32 len = strlen_clamp(str, maxLength);
|
_Init(str, strlen_clamp(str, maxLength));
|
||||||
_Init(str, len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -262,22 +247,8 @@ BString::CountChars() const
|
|||||||
int32 count = 0;
|
int32 count = 0;
|
||||||
|
|
||||||
const char *start = _privateData;
|
const char *start = _privateData;
|
||||||
|
|
||||||
/* String's end. This way we don't have to check for '\0' */
|
|
||||||
/* but just compare two pointers (which should be faster) */
|
|
||||||
const char *end = _privateData + Length();
|
const char *end = _privateData + Length();
|
||||||
|
|
||||||
#if 0
|
|
||||||
// ejaesler: Left in memoriam of one man's foolish disregard for the
|
|
||||||
// maxim "Premature optimization is the root of all evil"
|
|
||||||
while (*ptr) {
|
|
||||||
// Jump to next UTF8 character
|
|
||||||
// ejaesler: BGA's nifty function
|
|
||||||
ptr += utf8_char_len(*ptr);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (start++ != end) {
|
while (start++ != end) {
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
@@ -317,7 +288,7 @@ BString::operator=(const char *str)
|
|||||||
if (str != NULL)
|
if (str != NULL)
|
||||||
_DoAssign(str, strlen(str));
|
_DoAssign(str, strlen(str));
|
||||||
else
|
else
|
||||||
_GrowBy(-Length()); // Empties the string
|
_Alloc(0);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -345,14 +316,12 @@ BString::operator=(char c)
|
|||||||
The function always returns \c *this .
|
The function always returns \c *this .
|
||||||
*/
|
*/
|
||||||
BString&
|
BString&
|
||||||
BString::SetTo(const char *str, int32 length)
|
BString::SetTo(const char *str, int32 maxLength)
|
||||||
{
|
{
|
||||||
if (str != NULL) {
|
if (str != NULL)
|
||||||
int32 len = strlen_clamp(str, length);
|
_DoAssign(str, strlen_clamp(str, maxLength));
|
||||||
_DoAssign(str, len);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
_GrowBy(-Length()); // Empties the string
|
_Alloc(0);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -382,8 +351,10 @@ BString::SetTo(const BString &from)
|
|||||||
BString&
|
BString&
|
||||||
BString::Adopt(BString &from)
|
BString::Adopt(BString &from)
|
||||||
{
|
{
|
||||||
if (&from == this) // Avoid auto-adoption
|
if (&from == this) {
|
||||||
|
// Avoid auto-adoption
|
||||||
return *this;
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
if (_privateData)
|
if (_privateData)
|
||||||
free(_privateData - sizeof(int32));
|
free(_privateData - sizeof(int32));
|
||||||
@@ -435,7 +406,7 @@ BString::Adopt(BString &from, int32 length)
|
|||||||
from._privateData = NULL;
|
from._privateData = NULL;
|
||||||
|
|
||||||
if (len < Length())
|
if (len < Length())
|
||||||
_GrowBy(len - Length()); // Negative, we truncate
|
_Alloc(len);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -578,8 +549,9 @@ BString::Append(char c, int32 count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*---- Prepending ----------------------------------------------------------*/
|
// #pragma mark - Prepending
|
||||||
// Prepend
|
|
||||||
|
|
||||||
/*! \brief Prepends the given string to the object.
|
/*! \brief Prepends the given string to the object.
|
||||||
\param str A pointer to the string to prepend.
|
\param str A pointer to the string to prepend.
|
||||||
\return This function always returns *this .
|
\return This function always returns *this .
|
||||||
@@ -655,8 +627,9 @@ BString::Prepend(char c, int32 count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*---- Inserting ----------------------------------------------------------*/
|
// #pragma mark - Inserting
|
||||||
// Insert
|
|
||||||
|
|
||||||
/*! \brief Inserts the given string at the given position into the object's data.
|
/*! \brief Inserts the given string at the given position into the object's data.
|
||||||
\param str A pointer to the string to insert.
|
\param str A pointer to the string to insert.
|
||||||
\param pos The offset into the BString's data where to insert the string.
|
\param pos The offset into the BString's data where to insert the string.
|
||||||
@@ -799,8 +772,9 @@ BString::Insert(char c, int32 count, int32 pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*---- Removing -----------------------------------------------------------*/
|
// #pragma mark - Removing
|
||||||
// Truncate
|
|
||||||
|
|
||||||
/*! \brief Truncate the string to the new length.
|
/*! \brief Truncate the string to the new length.
|
||||||
\param newLength The new lenght of the string.
|
\param newLength The new lenght of the string.
|
||||||
\param lazy If true, the memory-optimisation is postponed to later
|
\param lazy If true, the memory-optimisation is postponed to later
|
||||||
@@ -816,14 +790,13 @@ BString::Truncate(int32 newLength, bool lazy)
|
|||||||
|
|
||||||
if (newLength < curLen) {
|
if (newLength < curLen) {
|
||||||
if (lazy) {
|
if (lazy) {
|
||||||
// don't free memory yet, just set new length:
|
// don't free memory yet, just set new length
|
||||||
// XXX: Uhm, where do we keep track of the amount
|
|
||||||
// of memory we allocated ?
|
|
||||||
_SetLength(newLength);
|
_SetLength(newLength);
|
||||||
_privateData[newLength] = '\0';
|
_privateData[newLength] = '\0';
|
||||||
} else
|
} else
|
||||||
_GrowBy(newLength - curLen); //Negative
|
_Alloc(newLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,11 +830,11 @@ BString::Remove(int32 from, int32 length)
|
|||||||
BString&
|
BString&
|
||||||
BString::RemoveFirst(const BString &string)
|
BString::RemoveFirst(const BString &string)
|
||||||
{
|
{
|
||||||
|
if (string.Length() > 0) {
|
||||||
int32 pos = _ShortFindAfter(string.String(), string.Length());
|
int32 pos = _ShortFindAfter(string.String(), string.Length());
|
||||||
|
|
||||||
if (pos >= 0)
|
if (pos >= 0)
|
||||||
_ShrinkAtBy(pos, string.Length());
|
_ShrinkAtBy(pos, string.Length());
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -875,7 +848,6 @@ BString&
|
|||||||
BString::RemoveLast(const BString &string)
|
BString::RemoveLast(const BString &string)
|
||||||
{
|
{
|
||||||
int32 pos = _FindBefore(string.String(), Length(), string.Length());
|
int32 pos = _FindBefore(string.String(), Length(), string.Length());
|
||||||
|
|
||||||
if (pos >= 0)
|
if (pos >= 0)
|
||||||
_ShrinkAtBy(pos, string.Length());
|
_ShrinkAtBy(pos, string.Length());
|
||||||
|
|
||||||
@@ -901,12 +873,13 @@ BString::RemoveAll(const BString &string)
|
|||||||
\return This function always returns *this .
|
\return This function always returns *this .
|
||||||
*/
|
*/
|
||||||
BString&
|
BString&
|
||||||
BString::RemoveFirst(const char *str)
|
BString::RemoveFirst(const char *string)
|
||||||
{
|
{
|
||||||
if (str != NULL) {
|
int32 length = string ? strlen(string) : 0;
|
||||||
int32 pos = _ShortFindAfter(str, strlen(str));
|
if (length > 0) {
|
||||||
|
int32 pos = _ShortFindAfter(string, length);
|
||||||
if (pos >= 0)
|
if (pos >= 0)
|
||||||
_ShrinkAtBy(pos, strlen(str));
|
_ShrinkAtBy(pos, length);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -918,13 +891,13 @@ BString::RemoveFirst(const char *str)
|
|||||||
\return This function always returns *this .
|
\return This function always returns *this .
|
||||||
*/
|
*/
|
||||||
BString&
|
BString&
|
||||||
BString::RemoveLast(const char *str)
|
BString::RemoveLast(const char *string)
|
||||||
{
|
{
|
||||||
if (str != NULL) {
|
int32 length = string ? strlen(string) : 0;
|
||||||
int32 len = strlen(str);
|
if (length > 0) {
|
||||||
int32 pos = _FindBefore(str, Length(), len);
|
int32 pos = _FindBefore(string, Length(), length);
|
||||||
if (pos >= 0)
|
if (pos >= 0)
|
||||||
_ShrinkAtBy(pos, len);
|
_ShrinkAtBy(pos, length);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -1039,7 +1012,9 @@ BString::operator>(const char *string) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*---- strcmp-style compare functions --------------------------------------*/
|
// #pragma mark - Comparison
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
BString::Compare(const BString &string) const
|
BString::Compare(const BString &string) const
|
||||||
{
|
{
|
||||||
@@ -1096,8 +1071,9 @@ BString::ICompare(const char *str, int32 n) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*---- Searching -----------------------------------------------------------*/
|
// #pragma mark - Searching
|
||||||
// FindFirst
|
|
||||||
|
|
||||||
/*! \brief Find the first occurrence of the given BString.
|
/*! \brief Find the first occurrence of the given BString.
|
||||||
\param string The BString to search for.
|
\param string The BString to search for.
|
||||||
\return The offset(zero based) into the data
|
\return The offset(zero based) into the data
|
||||||
@@ -1121,6 +1097,7 @@ BString::FindFirst(const char *string) const
|
|||||||
{
|
{
|
||||||
if (string == NULL)
|
if (string == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
return _ShortFindAfter(string, strlen(string));
|
return _ShortFindAfter(string, strlen(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1138,6 +1115,7 @@ BString::FindFirst(const BString &string, int32 fromOffset) const
|
|||||||
{
|
{
|
||||||
if (fromOffset < 0)
|
if (fromOffset < 0)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
return _FindAfter(string.String(), min_clamp0(fromOffset, Length()),
|
return _FindAfter(string.String(), min_clamp0(fromOffset, Length()),
|
||||||
string.Length());
|
string.Length());
|
||||||
}
|
}
|
||||||
@@ -1158,7 +1136,9 @@ BString::FindFirst(const char *string, int32 fromOffset) const
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (fromOffset < 0)
|
if (fromOffset < 0)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
return _FindAfter(string, min_clamp0(fromOffset, Length()), strlen(string));
|
|
||||||
|
return _FindAfter(string, min_clamp0(fromOffset, Length()),
|
||||||
|
strlen(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1172,12 +1152,13 @@ int32
|
|||||||
BString::FindFirst(char c) const
|
BString::FindFirst(char c) const
|
||||||
{
|
{
|
||||||
const char *start = String();
|
const char *start = String();
|
||||||
const char *end = String() + Length(); /* String's end */
|
const char *end = String() + Length();
|
||||||
|
|
||||||
/* Scans the string until we find the character, */
|
/* Scans the string until we find the character, */
|
||||||
/* or we hit the string's end */
|
/* or we hit the string's end */
|
||||||
while(start != end && *start != c)
|
while (start != end && *start != c) {
|
||||||
start++;
|
start++;
|
||||||
|
}
|
||||||
|
|
||||||
if (start == end)
|
if (start == end)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -1201,12 +1182,13 @@ BString::FindFirst(char c, int32 fromOffset) const
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
const char *start = String() + min_clamp0(fromOffset, Length());
|
const char *start = String() + min_clamp0(fromOffset, Length());
|
||||||
const char *end = String() + Length(); /* String's end */
|
const char *end = String() + Length();
|
||||||
|
|
||||||
/* Scans the string until we found the character, */
|
/* Scans the string until we found the character, */
|
||||||
/* or we hit the string's end */
|
/* or we hit the string's end */
|
||||||
while(start < end && *start != c)
|
while (start < end && *start != c) {
|
||||||
start++;
|
start++;
|
||||||
|
}
|
||||||
|
|
||||||
if (start >= end)
|
if (start >= end)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -1239,6 +1221,7 @@ BString::FindLast(const char *string) const
|
|||||||
{
|
{
|
||||||
if (string == NULL)
|
if (string == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
return _FindBefore(string, Length(), strlen(string));
|
return _FindBefore(string, Length(), strlen(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1256,6 +1239,7 @@ BString::FindLast(const BString &string, int32 beforeOffset) const
|
|||||||
{
|
{
|
||||||
if (beforeOffset < 0)
|
if (beforeOffset < 0)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
return _FindBefore(string.String(), min_clamp0(beforeOffset, Length()),
|
return _FindBefore(string.String(), min_clamp0(beforeOffset, Length()),
|
||||||
string.Length());
|
string.Length());
|
||||||
}
|
}
|
||||||
@@ -1275,6 +1259,7 @@ BString::FindLast(const char *string, int32 beforeOffset) const
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (beforeOffset < 0)
|
if (beforeOffset < 0)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
return _FindBefore(string, min_clamp0(beforeOffset, Length()), strlen(string));
|
return _FindBefore(string, min_clamp0(beforeOffset, Length()), strlen(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1289,12 +1274,13 @@ int32
|
|||||||
BString::FindLast(char c) const
|
BString::FindLast(char c) const
|
||||||
{
|
{
|
||||||
const char *start = String();
|
const char *start = String();
|
||||||
const char *end = String() + Length(); /* String's end */
|
const char *end = String() + Length();
|
||||||
|
|
||||||
/* Scans the string backwards until we found the character, */
|
/* Scans the string backwards until we found the character, */
|
||||||
/* or we reach the string's start */
|
/* or we reach the string's start */
|
||||||
while(end != start && *end != c)
|
while (end != start && *end != c) {
|
||||||
end--;
|
end--;
|
||||||
|
}
|
||||||
|
|
||||||
if (end == start)
|
if (end == start)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -1322,8 +1308,9 @@ BString::FindLast(char c, int32 beforeOffset) const
|
|||||||
|
|
||||||
/* Scans the string backwards until we found the character, */
|
/* Scans the string backwards until we found the character, */
|
||||||
/* or we reach the string's start */
|
/* or we reach the string's start */
|
||||||
while(end > start && *end != c)
|
while (end > start && *end != c) {
|
||||||
end--;
|
end--;
|
||||||
|
}
|
||||||
|
|
||||||
if (end <= start)
|
if (end <= start)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -1344,6 +1331,7 @@ BString::IFindFirst(const char *string) const
|
|||||||
{
|
{
|
||||||
if (string == NULL)
|
if (string == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
return _IFindAfter(string, 0, strlen(string));
|
return _IFindAfter(string, 0, strlen(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1353,6 +1341,7 @@ BString::IFindFirst(const BString &string, int32 fromOffset) const
|
|||||||
{
|
{
|
||||||
if (fromOffset < 0)
|
if (fromOffset < 0)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
return _IFindAfter(string.String(), min_clamp0(fromOffset, Length()),
|
return _IFindAfter(string.String(), min_clamp0(fromOffset, Length()),
|
||||||
string.Length());
|
string.Length());
|
||||||
}
|
}
|
||||||
@@ -1365,6 +1354,7 @@ BString::IFindFirst(const char *string, int32 fromOffset) const
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (fromOffset < 0)
|
if (fromOffset < 0)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
return _IFindAfter(string, min_clamp0(fromOffset,Length()), strlen(string));
|
return _IFindAfter(string, min_clamp0(fromOffset,Length()), strlen(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1381,6 +1371,7 @@ BString::IFindLast(const char *string) const
|
|||||||
{
|
{
|
||||||
if (string == NULL)
|
if (string == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
return _IFindBefore(string, Length(), strlen(string));
|
return _IFindBefore(string, Length(), strlen(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1390,6 +1381,7 @@ BString::IFindLast(const BString &string, int32 beforeOffset) const
|
|||||||
{
|
{
|
||||||
if (beforeOffset < 0)
|
if (beforeOffset < 0)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
return _IFindBefore(string.String(), min_clamp0(beforeOffset, Length()),
|
return _IFindBefore(string.String(), min_clamp0(beforeOffset, Length()),
|
||||||
string.Length());
|
string.Length());
|
||||||
}
|
}
|
||||||
@@ -1402,17 +1394,19 @@ BString::IFindLast(const char *string, int32 beforeOffset) const
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (beforeOffset < 0)
|
if (beforeOffset < 0)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
return _IFindBefore(string, min_clamp0(beforeOffset, Length()),
|
return _IFindBefore(string, min_clamp0(beforeOffset, Length()),
|
||||||
strlen(string));
|
strlen(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*---- Replacing -----------------------------------------------------------*/
|
// #pragma mark - Replacing
|
||||||
|
|
||||||
|
|
||||||
BString&
|
BString&
|
||||||
BString::ReplaceFirst(char replaceThis, char withThis)
|
BString::ReplaceFirst(char replaceThis, char withThis)
|
||||||
{
|
{
|
||||||
int32 pos = FindFirst(replaceThis);
|
int32 pos = FindFirst(replaceThis);
|
||||||
|
|
||||||
if (pos >= 0)
|
if (pos >= 0)
|
||||||
_privateData[pos] = withThis;
|
_privateData[pos] = withThis;
|
||||||
|
|
||||||
@@ -1424,7 +1418,6 @@ BString&
|
|||||||
BString::ReplaceLast(char replaceThis, char withThis)
|
BString::ReplaceLast(char replaceThis, char withThis)
|
||||||
{
|
{
|
||||||
int32 pos = FindLast(replaceThis);
|
int32 pos = FindLast(replaceThis);
|
||||||
|
|
||||||
if (pos >= 0)
|
if (pos >= 0)
|
||||||
_privateData[pos] = withThis;
|
_privateData[pos] = withThis;
|
||||||
|
|
||||||
@@ -1520,8 +1513,8 @@ BString&
|
|||||||
BString::IReplaceFirst(char replaceThis, char withThis)
|
BString::IReplaceFirst(char replaceThis, char withThis)
|
||||||
{
|
{
|
||||||
char tmp[2] = { replaceThis, '\0' };
|
char tmp[2] = { replaceThis, '\0' };
|
||||||
int32 pos = _IFindAfter(tmp, 0, 1);
|
|
||||||
|
|
||||||
|
int32 pos = _IFindAfter(tmp, 0, 1);
|
||||||
if (pos >= 0)
|
if (pos >= 0)
|
||||||
_privateData[pos] = withThis;
|
_privateData[pos] = withThis;
|
||||||
|
|
||||||
@@ -1533,8 +1526,8 @@ BString&
|
|||||||
BString::IReplaceLast(char replaceThis, char withThis)
|
BString::IReplaceLast(char replaceThis, char withThis)
|
||||||
{
|
{
|
||||||
char tmp[2] = { replaceThis, '\0' };
|
char tmp[2] = { replaceThis, '\0' };
|
||||||
int32 pos = _IFindBefore(tmp, Length(), 1);
|
|
||||||
|
|
||||||
|
int32 pos = _IFindBefore(tmp, Length(), 1);
|
||||||
if (pos >= 0)
|
if (pos >= 0)
|
||||||
_privateData[pos] = withThis;
|
_privateData[pos] = withThis;
|
||||||
|
|
||||||
@@ -1608,7 +1601,6 @@ BString::IReplaceLast(const char *replaceThis, const char *withThis)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
memcpy(_privateData + pos, withThis, len);
|
memcpy(_privateData + pos, withThis, len);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1625,7 +1617,8 @@ BString::IReplaceAll(const char *replaceThis, const char *withThis, int32 fromOf
|
|||||||
|
|
||||||
|
|
||||||
BString&
|
BString&
|
||||||
BString::IReplace(const char *replaceThis, const char *withThis, int32 maxReplaceCount, int32 fromOffset)
|
BString::IReplace(const char *replaceThis, const char *withThis,
|
||||||
|
int32 maxReplaceCount, int32 fromOffset)
|
||||||
{
|
{
|
||||||
CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
|
CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
|
||||||
return _DoReplace(replaceThis, withThis, maxReplaceCount,
|
return _DoReplace(replaceThis, withThis, maxReplaceCount,
|
||||||
@@ -1656,13 +1649,15 @@ BString::ReplaceSet(const char *setOfChars, char with)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BString&
|
BString&
|
||||||
BString::ReplaceSet(const char *setOfChars, const char *with)
|
BString::ReplaceSet(const char *setOfChars, const char *with)
|
||||||
{
|
{
|
||||||
int32 withLen = with ? strlen(with) : 0;
|
int32 withLen = with ? strlen(with) : 0;
|
||||||
if (withLen == 1)
|
if (withLen == 1) {
|
||||||
// delegate simple case:
|
// delegate simple case:
|
||||||
return ReplaceSet(setOfChars, *with);
|
return ReplaceSet(setOfChars, *with);
|
||||||
|
}
|
||||||
|
|
||||||
if (setOfChars == NULL || _privateData == NULL)
|
if (setOfChars == NULL || _privateData == NULL)
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1672,8 +1667,7 @@ BString::ReplaceSet(const char *setOfChars, const char *with)
|
|||||||
int32 searchLen = 1;
|
int32 searchLen = 1;
|
||||||
int32 len = Length();
|
int32 len = Length();
|
||||||
int32 pos = 0;
|
int32 pos = 0;
|
||||||
for (int32 offset = 0; offset < len; offset += (pos+searchLen))
|
for (int32 offset = 0; offset < len; offset += (pos+searchLen)) {
|
||||||
{
|
|
||||||
pos = strcspn(_privateData + offset, setOfChars);
|
pos = strcspn(_privateData + offset, setOfChars);
|
||||||
if (pos + offset >= len)
|
if (pos + offset >= len)
|
||||||
break;
|
break;
|
||||||
@@ -1706,7 +1700,7 @@ BString::operator[](int32 index)
|
|||||||
char*
|
char*
|
||||||
BString::LockBuffer(int32 maxLength)
|
BString::LockBuffer(int32 maxLength)
|
||||||
{
|
{
|
||||||
_SetUsingAsCString(true); //debug
|
_SetUsingAsCString(true);
|
||||||
|
|
||||||
int32 len = Length();
|
int32 len = Length();
|
||||||
|
|
||||||
@@ -1729,7 +1723,7 @@ BString::LockBuffer(int32 maxLength)
|
|||||||
BString&
|
BString&
|
||||||
BString::UnlockBuffer(int32 length)
|
BString::UnlockBuffer(int32 length)
|
||||||
{
|
{
|
||||||
_SetUsingAsCString(false); //debug
|
_SetUsingAsCString(false);
|
||||||
|
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
length = (_privateData == NULL) ? 0 : strlen(_privateData);
|
length = (_privateData == NULL) ? 0 : strlen(_privateData);
|
||||||
@@ -1750,8 +1744,9 @@ BString&
|
|||||||
BString::ToLower()
|
BString::ToLower()
|
||||||
{
|
{
|
||||||
int32 length = Length();
|
int32 length = Length();
|
||||||
for (int32 count = 0; count < length; count++)
|
for (int32 count = 0; count < length; count++) {
|
||||||
_privateData[count] = tolower(_privateData[count]);
|
_privateData[count] = tolower(_privateData[count]);
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -1765,8 +1760,9 @@ BString&
|
|||||||
BString::ToUpper()
|
BString::ToUpper()
|
||||||
{
|
{
|
||||||
int32 length = Length();
|
int32 length = Length();
|
||||||
for (int32 count = 0; count < length; count++)
|
for (int32 count = 0; count < length; count++) {
|
||||||
_privateData[count] = toupper(_privateData[count]);
|
_privateData[count] = toupper(_privateData[count]);
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -1785,8 +1781,9 @@ BString::Capitalize()
|
|||||||
_privateData[0] = toupper(_privateData[0]);
|
_privateData[0] = toupper(_privateData[0]);
|
||||||
int32 length = Length();
|
int32 length = Length();
|
||||||
|
|
||||||
for (int32 count = 1; count < length; count++)
|
for (int32 count = 1; count < length; count++) {
|
||||||
_privateData[count] = tolower(_privateData[count]);
|
_privateData[count] = tolower(_privateData[count]);
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -1818,6 +1815,7 @@ BString::CapitalizeEachWord()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now find the first non-alphabetical character,
|
// Now find the first non-alphabetical character,
|
||||||
// and meanwhile, turn to lowercase all the alphabetical ones
|
// and meanwhile, turn to lowercase all the alphabetical ones
|
||||||
for (; count < length; count++) {
|
for (; count < length; count++) {
|
||||||
@@ -1834,7 +1832,8 @@ BString::CapitalizeEachWord()
|
|||||||
|
|
||||||
/*----- Escaping and Deescaping --------------------------------------------*/
|
/*----- Escaping and Deescaping --------------------------------------------*/
|
||||||
BString&
|
BString&
|
||||||
BString::CharacterEscape(const char *original, const char *setOfCharsToEscape, char escapeWith)
|
BString::CharacterEscape(const char *original, const char *setOfCharsToEscape,
|
||||||
|
char escapeWith)
|
||||||
{
|
{
|
||||||
SetTo(original);
|
SetTo(original);
|
||||||
CharacterEscape(setOfCharsToEscape, escapeWith);
|
CharacterEscape(setOfCharsToEscape, escapeWith);
|
||||||
@@ -1853,17 +1852,19 @@ BString::CharacterEscape(const char *setOfCharsToEscape, char escapeWith)
|
|||||||
int32 len = Length();
|
int32 len = Length();
|
||||||
int32 pos = 0;
|
int32 pos = 0;
|
||||||
for (int32 offset = 0; offset < len; offset += pos + 1) {
|
for (int32 offset = 0; offset < len; offset += pos + 1) {
|
||||||
if ((pos = strcspn(_privateData + offset, setOfCharsToEscape)) < len - offset)
|
if ((pos = strcspn(_privateData + offset, setOfCharsToEscape)) < len - offset) {
|
||||||
if (!positions.Add(offset + pos))
|
if (!positions.Add(offset + pos))
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32 count = positions.CountItems();
|
uint32 count = positions.CountItems();
|
||||||
int32 newLength = len + count;
|
int32 newLength = len + count;
|
||||||
if (!newLength) {
|
if (!newLength) {
|
||||||
_GrowBy( -len);
|
_Alloc(0);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 lastPos = 0;
|
int32 lastPos = 0;
|
||||||
char* oldAdr = _privateData;
|
char* oldAdr = _privateData;
|
||||||
char* newData = (char*)malloc(newLength + sizeof(int32) + 1);
|
char* newData = (char*)malloc(newLength + sizeof(int32) + 1);
|
||||||
@@ -1944,40 +1945,44 @@ BString::operator<<(char c)
|
|||||||
BString&
|
BString&
|
||||||
BString::operator<<(int i)
|
BString::operator<<(int i)
|
||||||
{
|
{
|
||||||
char num[64];
|
char num[32];
|
||||||
sprintf(num, "%d", i);
|
int32 length = snprintf(num, sizeof(num), "%d", i);
|
||||||
|
|
||||||
return *this << num;
|
_DoAppend(num, length);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BString&
|
BString&
|
||||||
BString::operator<<(unsigned int i)
|
BString::operator<<(unsigned int i)
|
||||||
{
|
{
|
||||||
char num[64];
|
char num[32];
|
||||||
sprintf(num, "%u", i);
|
int32 length = snprintf(num, sizeof(num), "%u", i);
|
||||||
|
|
||||||
return *this << num;
|
_DoAppend(num, length);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BString&
|
BString&
|
||||||
BString::operator<<(uint32 i)
|
BString::operator<<(uint32 i)
|
||||||
{
|
{
|
||||||
char num[64];
|
char num[32];
|
||||||
sprintf(num, "%lu", i);
|
int32 length = snprintf(num, sizeof(num), "%lu", i);
|
||||||
|
|
||||||
return *this << num;
|
_DoAppend(num, length);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BString&
|
BString&
|
||||||
BString::operator<<(int32 i)
|
BString::operator<<(int32 i)
|
||||||
{
|
{
|
||||||
char num[64];
|
char num[32];
|
||||||
sprintf(num, "%ld", i);
|
int32 length = snprintf(num, sizeof(num), "%ld", i);
|
||||||
|
|
||||||
return *this << num;
|
_DoAppend(num, length);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1985,9 +1990,10 @@ BString&
|
|||||||
BString::operator<<(uint64 i)
|
BString::operator<<(uint64 i)
|
||||||
{
|
{
|
||||||
char num[64];
|
char num[64];
|
||||||
sprintf(num, "%llu", i);
|
int32 length = snprintf(num, sizeof(num), "%llu", i);
|
||||||
|
|
||||||
return *this << num;
|
_DoAppend(num, length);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1995,9 +2001,10 @@ BString&
|
|||||||
BString::operator<<(int64 i)
|
BString::operator<<(int64 i)
|
||||||
{
|
{
|
||||||
char num[64];
|
char num[64];
|
||||||
sprintf(num, "%lld", i);
|
int32 length = snprintf(num, sizeof(num), "%lld", i);
|
||||||
|
|
||||||
return *this << num;
|
_DoAppend(num, length);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2005,31 +2012,45 @@ BString&
|
|||||||
BString::operator<<(float f)
|
BString::operator<<(float f)
|
||||||
{
|
{
|
||||||
char num[64];
|
char num[64];
|
||||||
sprintf(num, "%.2f", f);
|
int32 length = snprintf(num, sizeof(num), "%.2f", f);
|
||||||
|
|
||||||
return *this << num;
|
_DoAppend(num, length);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*---- Private or Reserved ------------------------------------------------*/
|
// #pragma mark - Private or reserved
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
BString::_Alloc(int32 dataLen)
|
BString::_Alloc(int32 dataLength)
|
||||||
{
|
{
|
||||||
char *dataPtr = _privateData ? _privateData - sizeof(int32) : NULL;
|
char *dataPtr = _privateData ? _privateData - sizeof(int32) : NULL;
|
||||||
if (dataLen <= 0) { // release buffer if requested size is 0:
|
if (dataLength <= 0) {
|
||||||
|
// release buffer
|
||||||
|
#if 0
|
||||||
free(dataPtr);
|
free(dataPtr);
|
||||||
_privateData = NULL;
|
_privateData = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
#else
|
||||||
|
// TODO: think about removing this work-around again; it lets
|
||||||
|
// BeOS R5 NetPositive run on Haiku - this is obviously ignoring
|
||||||
|
// the fact, that _privateData could be NULL at one point
|
||||||
|
// (while building the menus from resources).
|
||||||
|
dataLength = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
int32 allocLen = dataLen + sizeof(int32) + 1;
|
|
||||||
dataPtr = (char *)realloc(dataPtr, allocLen);
|
int32 allocLength = dataLength + sizeof(int32) + 1;
|
||||||
|
dataPtr = (char *)realloc(dataPtr, allocLength);
|
||||||
if (dataPtr) {
|
if (dataPtr) {
|
||||||
dataPtr += sizeof(int32);
|
dataPtr += sizeof(int32);
|
||||||
_privateData = dataPtr;
|
_privateData = dataPtr;
|
||||||
|
|
||||||
_SetLength(dataLen);
|
_SetLength(dataLength);
|
||||||
_privateData[dataLen] = '\0';
|
_privateData[dataLength] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataPtr;
|
return dataPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2069,8 +2090,7 @@ BString::_DoAppend(const char *str, int32 len)
|
|||||||
char*
|
char*
|
||||||
BString::_GrowBy(int32 size)
|
BString::_GrowBy(int32 size)
|
||||||
{
|
{
|
||||||
int32 newLen = Length() + size;
|
return _Alloc(Length() + size);
|
||||||
return _Alloc(newLen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2080,9 +2100,10 @@ BString::_OpenAtBy(int32 offset, int32 length)
|
|||||||
int32 oldLength = Length();
|
int32 oldLength = Length();
|
||||||
|
|
||||||
char* newData = _Alloc(oldLength + length);
|
char* newData = _Alloc(oldLength + length);
|
||||||
if (newData != NULL)
|
if (newData != NULL) {
|
||||||
memmove(_privateData + offset + length, _privateData + offset,
|
memmove(_privateData + offset + length, _privateData + offset,
|
||||||
oldLength - offset);
|
oldLength - offset);
|
||||||
|
}
|
||||||
|
|
||||||
return newData;
|
return newData;
|
||||||
}
|
}
|
||||||
@@ -2093,6 +2114,7 @@ BString::_ShrinkAtBy(int32 offset, int32 length)
|
|||||||
{
|
{
|
||||||
if (!_privateData)
|
if (!_privateData)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
int32 oldLength = Length();
|
int32 oldLength = Length();
|
||||||
|
|
||||||
memmove(_privateData + offset, _privateData + offset + length,
|
memmove(_privateData + offset, _privateData + offset + length,
|
||||||
@@ -2184,8 +2206,8 @@ BString::_IFindBefore(const char *str, int32 offset, int32 strlen) const
|
|||||||
|
|
||||||
|
|
||||||
BString&
|
BString&
|
||||||
BString::_DoReplace(const char *findThis, const char *replaceWith, int32 maxReplaceCount,
|
BString::_DoReplace(const char *findThis, const char *replaceWith,
|
||||||
int32 fromOffset, bool ignoreCase)
|
int32 maxReplaceCount, int32 fromOffset, bool ignoreCase)
|
||||||
{
|
{
|
||||||
if (findThis == NULL || maxReplaceCount <= 0
|
if (findThis == NULL || maxReplaceCount <= 0
|
||||||
|| fromOffset < 0 || fromOffset >= Length())
|
|| fromOffset < 0 || fromOffset >= Length())
|
||||||
@@ -2215,16 +2237,16 @@ BString::_DoReplace(const char *findThis, const char *replaceWith, int32 maxRepl
|
|||||||
|
|
||||||
void
|
void
|
||||||
BString::_ReplaceAtPositions(const PosVect* positions,
|
BString::_ReplaceAtPositions(const PosVect* positions,
|
||||||
int32 searchLen, const char* with,
|
int32 searchLen, const char* with, int32 withLen)
|
||||||
int32 withLen)
|
|
||||||
{
|
{
|
||||||
int32 len = Length();
|
int32 len = Length();
|
||||||
uint32 count = positions->CountItems();
|
uint32 count = positions->CountItems();
|
||||||
int32 newLength = len + count * (withLen - searchLen);
|
int32 newLength = len + count * (withLen - searchLen);
|
||||||
if (!newLength) {
|
if (!newLength) {
|
||||||
_GrowBy(-len);
|
_Alloc(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 pos;
|
int32 pos;
|
||||||
int32 lastPos = 0;
|
int32 lastPos = 0;
|
||||||
char *oldAdr = _privateData;
|
char *oldAdr = _privateData;
|
||||||
|
|||||||
Reference in New Issue
Block a user