Adding utf-8 aware version of most functions to BString. They are named after

the corresponding normal functions but have a "Chars" in the name like
"MoveCharsInto" or "AppendChars". Also added CountBytes() and CharAt().
This should make everyday string handling with multibyte strings a bit easier.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35371 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2010-02-01 04:20:01 +00:00
parent 783930d916
commit a5b7cbe331
3 changed files with 405 additions and 27 deletions
+74 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2009, Haiku Inc. All Rights Reserved.
* Copyright 2001-2010, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef __BSTRING__
@@ -26,6 +26,8 @@ public:
const char* String() const;
int32 Length() const;
int32 CountChars() const;
int32 CountBytes(int32 fromCharOffset,
int32 charCount) const;
// Assignment
BString& operator=(const BString& string);
@@ -43,12 +45,21 @@ public:
BString& SetTo(char c, int32 count);
BString& SetToChars(const char* string, int32 charCount);
BString& SetToChars(const BString& string, int32 charCount);
BString& AdoptChars(BString& from, int32 charCount);
// Substring copying
BString& CopyInto(BString& into, int32 fromOffset,
int32 length) const;
void CopyInto(char* into, int32 fromOffset,
int32 length) const;
BString& CopyCharsInto(BString& into, int32 fromCharOffset,
int32 charCount) const;
bool CopyCharsInto(char* into, int32* intoLength,
int32 fromCharOffset, int32 charCount) const;
// Appending
BString& operator+=(const BString& string);
BString& operator+=(const char* string);
@@ -61,6 +72,9 @@ public:
BString& Append(const char* string, int32 length);
BString& Append(char c, int32 count);
BString& AppendChars(const BString& string, int32 charCount);
BString& AppendChars(const char* string, int32 charCount);
// Prepending
BString& Prepend(const char* string);
BString& Prepend(const BString& string);
@@ -68,6 +82,10 @@ public:
BString& Prepend(const BString& string, int32 length);
BString& Prepend(char c, int32 count);
BString& PrependChars(const char* string, int32 charCount);
BString& PrependChars(const BString& string,
int32 charCount);
// Inserting
BString& Insert(const char* string, int32 position);
BString& Insert(const char* string, int32 length,
@@ -81,9 +99,26 @@ public:
int32 length, int32 position);
BString& Insert(char c, int32 count, int32 position);
BString& InsertChars(const char* string, int32 charPosition);
BString& InsertChars(const char* string, int32 charCount,
int32 charPosition);
BString& InsertChars(const char* string,
int32 fromCharOffset, int32 charCount,
int32 charPosition);
BString& InsertChars(const BString& string,
int32 charPosition);
BString& InsertChars(const BString& string, int32 charCount,
int32 charPosition);
BString& InsertChars(const BString& string,
int32 fromCharOffset, int32 charCount,
int32 charPosition);
// Removing
BString& Truncate(int32 newLength, bool lazy = true);
BString& TruncateChars(int32 newCharCount, bool lazy = true);
BString& Remove(int32 from, int32 length);
BString& RemoveChars(int32 fromCharOffset, int32 charCount);
BString& RemoveFirst(const BString& string);
BString& RemoveLast(const BString& string);
@@ -93,11 +128,17 @@ public:
BString& RemoveLast(const char* string);
BString& RemoveAll(const char* string);
BString& RemoveSet(const char* setOfCharsToRemove);
BString& RemoveSet(const char* setOfBytesToRemove);
BString& RemoveCharsSet(const char* setOfCharsToRemove);
BString& MoveInto(BString& into, int32 from, int32 length);
void MoveInto(char* into, int32 from, int32 length);
BString& MoveCharsInto(BString& into, int32 fromCharOffset,
int32 charCount);
bool MoveCharsInto(char* into, int32* intoLength,
int32 fromCharOffset, int32 charCount);
// Compare functions
bool operator<(const BString& string) const;
bool operator<=(const BString& string) const;
@@ -120,6 +161,12 @@ public:
int Compare(const char* string) const;
int Compare(const BString& string, int32 length) const;
int Compare(const char* string, int32 length) const;
int CompareChars(const BString& string,
int32 charCount) const;
int CompareChars(const char* string,
int32 charCount) const;
int ICompare(const BString& string) const;
int ICompare(const char* string) const;
int ICompare(const BString& string, int32 length) const;
@@ -135,6 +182,11 @@ public:
int32 FindFirst(char c) const;
int32 FindFirst(char c, int32 fromOffset) const;
int32 FindFirstChars(const BString& string,
int32 fromCharOffset) const;
int32 FindFirstChars(const char* string,
int32 fromCharOffset) const;
int32 FindLast(const BString& string) const;
int32 FindLast(const char* string) const;
int32 FindLast(const BString& string,
@@ -144,6 +196,11 @@ public:
int32 FindLast(char c) const;
int32 FindLast(char c, int32 beforeOffset) const;
int32 FindLastChars(const BString& string,
int32 beforeCharOffset) const;
int32 FindLastChars(const char* string,
int32 beforeCharOffset) const;
int32 IFindFirst(const BString& string) const;
int32 IFindFirst(const char* string) const;
int32 IFindFirst(const BString& string,
@@ -175,6 +232,12 @@ public:
const char* withThis, int32 maxReplaceCount,
int32 fromOffset = 0);
BString& ReplaceAllChars(const char* replaceThis,
const char* withThis, int32 fromCharOffset);
BString& ReplaceChars(const char* replaceThis,
const char* withThis, int32 maxReplaceCount,
int32 fromCharOffset);
BString& IReplaceFirst(char replaceThis, char withThis);
BString& IReplaceLast(char replaceThis, char withThis);
BString& IReplaceAll(char replaceThis, char withThis,
@@ -191,8 +254,12 @@ public:
const char* withThis, int32 maxReplaceCount,
int32 fromOffset = 0);
BString& ReplaceSet(const char* setOfChars, char with);
BString& ReplaceSet(const char* setOfChars, const char* with);
BString& ReplaceSet(const char* setOfBytes, char with);
BString& ReplaceSet(const char* setOfBytes,
const char* with);
BString& ReplaceCharsSet(const char* setOfChars,
const char* with);
// Unchecked char access
char operator[](int32 index) const;
@@ -205,6 +272,9 @@ public:
// Checked char access
char ByteAt(int32 index) const;
const char* CharAt(int32 charIndex, int32* bytes = NULL) const;
bool CharAt(int32 charIndex, char* buffer,
int32* bytes) const;
// Fast low-level manipulation
char* LockBuffer(int32 maxLength);
+1 -1
View File
@@ -2,7 +2,7 @@ SubDir HAIKU_TOP src kits support ;
SetSubDirSupportedPlatforms haiku libbe_test ;
UsePrivateHeaders shared app media support ;
UsePrivateHeaders app interface media shared support ;
MergeObject <libbe>support_kit.o :
Archivable.cpp
+330 -22
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2009, Haiku, Inc. All Rights Reserved.
* Copyright 2001-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -8,6 +8,7 @@
* Oliver Tappe ([email protected])
* Axel Dörfler, [email protected]
* Julun <[email protected]>
* Michael Lotz <[email protected]>
*/
@@ -23,6 +24,8 @@
#include <Debug.h>
#include <utf8_functions.h>
// define proper names for case-option of _DoReplace()
#define KEEP_CASE false
@@ -268,19 +271,15 @@ BString::~BString()
int32
BString::CountChars() const
{
int32 count = 0;
return UTF8CountChars(fPrivateData, Length());
}
const char* start = fPrivateData;
const char* end = fPrivateData + Length();
while (start++ != end) {
count++;
// Jump to next UTF8 character
for (; (*start & 0xc0) == 0x80; start++);
}
return count;
int32
BString::CountBytes(int32 fromCharOffset, int32 charCount) const
{
return UTF8CountBytes(
fPrivateData + UTF8CountBytes(fPrivateData, fromCharOffset), charCount);
}
@@ -404,6 +403,27 @@ BString::SetTo(char c, int32 count)
}
BString&
BString::SetToChars(const char* string, int32 charCount)
{
return SetTo(string, UTF8CountBytes(string, charCount));
}
BString&
BString::SetToChars(const BString& string, int32 charCount)
{
return SetTo(string, UTF8CountBytes(string.String(), charCount));
}
BString&
BString::AdoptChars(BString& string, int32 charCount)
{
return Adopt(string, UTF8CountBytes(string.String(), charCount));
}
// #pragma mark - Substring copying
@@ -426,6 +446,38 @@ BString::CopyInto(char* into, int32 fromOffset, int32 length) const
}
BString&
BString::CopyCharsInto(BString& into, int32 fromCharOffset,
int32 charCount) const
{
int32 fromOffset = UTF8CountBytes(fPrivateData, fromCharOffset);
int32 length = UTF8CountBytes(fPrivateData + fromOffset, charCount);
return CopyInto(into, fromOffset, length);
}
bool
BString::CopyCharsInto(char* into, int32* intoLength, int32 fromCharOffset,
int32 charCount) const
{
if (into == NULL)
return false;
int32 fromOffset = UTF8CountBytes(fPrivateData, fromCharOffset);
int32 length = UTF8CountBytes(fPrivateData + fromOffset, charCount);
length = min_clamp0(length, Length() - fromOffset);
if (intoLength != NULL) {
if (*intoLength < length)
return false;
*intoLength = length;
}
memcpy(into, fPrivateData + fromOffset, length);
return true;
}
// #pragma mark - Appending
@@ -483,6 +535,20 @@ BString::Append(char c, int32 count)
}
BString&
BString::AppendChars(const BString& string, int32 charCount)
{
return Append(string, UTF8CountBytes(string.String(), charCount));
}
BString&
BString::AppendChars(const char* string, int32 charCount)
{
return Append(string, UTF8CountBytes(string, charCount));
}
// #pragma mark - Prepending
@@ -531,6 +597,20 @@ BString::Prepend(char c, int32 count)
}
BString&
BString::PrependChars(const char* string, int32 charCount)
{
return Prepend(string, UTF8CountBytes(string, charCount));
}
BString&
BString::PrependChars(const BString& string, int32 charCount)
{
return Prepend(string, UTF8CountBytes(string.String(), charCount));
}
// #pragma mark - Inserting
@@ -626,6 +706,58 @@ BString::Insert(char c, int32 count, int32 position)
}
BString&
BString::InsertChars(const char* string, int32 charPosition)
{
return Insert(string, UTF8CountBytes(fPrivateData, charPosition));
}
BString&
BString::InsertChars(const char* string, int32 charCount, int32 charPosition)
{
return Insert(string, UTF8CountBytes(string, charCount),
UTF8CountBytes(fPrivateData, charPosition));
}
BString&
BString::InsertChars(const char* string, int32 fromCharOffset,
int32 charCount, int32 charPosition)
{
int32 fromOffset = UTF8CountBytes(string, fromCharOffset);
return Insert(string, fromOffset,
UTF8CountBytes(string + fromOffset, charCount),
UTF8CountBytes(fPrivateData, charPosition));
}
BString&
BString::InsertChars(const BString& string, int32 charPosition)
{
return Insert(string, UTF8CountBytes(fPrivateData, charPosition));
}
BString&
BString::InsertChars(const BString& string, int32 charCount, int32 charPosition)
{
return Insert(string, UTF8CountBytes(string.String(), charCount),
UTF8CountBytes(fPrivateData, charPosition));
}
BString&
BString::InsertChars(const BString& string, int32 fromCharOffset,
int32 charCount, int32 charPosition)
{
int32 fromOffset = UTF8CountBytes(string.String(), fromCharOffset);
return Insert(string, fromOffset,
UTF8CountBytes(string.String() + fromOffset, charCount),
UTF8CountBytes(fPrivateData, charPosition));
}
// #pragma mark - Removing
@@ -644,6 +776,13 @@ BString::Truncate(int32 newLength, bool lazy)
}
BString&
BString::TruncateChars(int32 newCharCount, bool lazy)
{
return Truncate(UTF8CountBytes(fPrivateData, newCharCount));
}
BString&
BString::Remove(int32 from, int32 length)
{
@@ -653,6 +792,15 @@ BString::Remove(int32 from, int32 length)
}
BString&
BString::RemoveChars(int32 fromCharOffset, int32 charCount)
{
int32 fromOffset = UTF8CountBytes(fPrivateData, fromCharOffset);
return Remove(fromOffset,
UTF8CountBytes(fPrivateData + fromOffset, charCount));
}
BString&
BString::RemoveFirst(const BString& string)
{
@@ -729,9 +877,16 @@ BString::RemoveAll(const char* string)
BString&
BString::RemoveSet(const char* setOfCharsToRemove)
BString::RemoveSet(const char* setOfBytesToRemove)
{
return ReplaceSet(setOfCharsToRemove, "");
return ReplaceSet(setOfBytesToRemove, "");
}
BString&
BString::RemoveCharsSet(const char* setOfCharsToRemove)
{
return ReplaceCharsSet(setOfCharsToRemove, "");
}
@@ -756,6 +911,30 @@ BString::MoveInto(char* into, int32 from, int32 length)
}
BString&
BString::MoveCharsInto(BString& into, int32 fromCharOffset, int32 charCount)
{
if (charCount > 0) {
CopyCharsInto(into, fromCharOffset, charCount);
RemoveChars(fromCharOffset, charCount);
}
return into;
}
bool
BString::MoveCharsInto(char* into, int32* intoLength, int32 fromCharOffset,
int32 charCount)
{
if (!CopyCharsInto(into, intoLength, fromCharOffset, charCount))
return false;
RemoveChars(fromCharOffset, charCount);
return true;
}
// #pragma mark - Compare functions
@@ -825,6 +1004,20 @@ BString::Compare(const char* string, int32 length) const
}
int
BString::CompareChars(const BString& string, int32 charCount) const
{
return Compare(string, UTF8CountBytes(fPrivateData, charCount));
}
int
BString::CompareChars(const char* string, int32 charCount) const
{
return Compare(string, UTF8CountBytes(fPrivateData, charCount));
}
int
BString::ICompare(const BString& string) const
{
@@ -939,6 +1132,20 @@ BString::FindFirst(char c, int32 fromOffset) const
}
int32
BString::FindFirstChars(const BString& string, int32 fromCharOffset) const
{
return FindFirst(string, UTF8CountBytes(fPrivateData, fromCharOffset));
}
int32
BString::FindFirstChars(const char* string, int32 fromCharOffset) const
{
return FindFirst(string, UTF8CountBytes(fPrivateData, fromCharOffset));
}
int32
BString::FindLast(const BString& string) const
{
@@ -1022,6 +1229,20 @@ BString::FindLast(char c, int32 beforeOffset) const
}
int32
BString::FindLastChars(const BString& string, int32 beforeCharOffset) const
{
return FindLast(string, UTF8CountBytes(fPrivateData, beforeCharOffset));
}
int32
BString::FindLastChars(const char* string, int32 beforeCharOffset) const
{
return FindLast(string, UTF8CountBytes(fPrivateData, beforeCharOffset));
}
int32
BString::IFindFirst(const BString& string) const
{
@@ -1244,6 +1465,24 @@ BString::Replace(const char* replaceThis, const char* withThis,
}
BString&
BString::ReplaceAllChars(const char* replaceThis, const char* withThis,
int32 fromCharOffset)
{
return ReplaceAll(replaceThis, withThis,
UTF8CountBytes(fPrivateData, fromCharOffset));
}
BString&
BString::ReplaceChars(const char* replaceThis, const char* withThis,
int32 maxReplaceCount, int32 fromCharOffset)
{
return Replace(replaceThis, withThis, maxReplaceCount,
UTF8CountBytes(fPrivateData, fromCharOffset));
}
BString&
BString::IReplaceFirst(char replaceThis, char withThis)
{
@@ -1385,9 +1624,9 @@ BString::IReplace(const char* replaceThis, const char* withThis,
BString&
BString::ReplaceSet(const char* setOfChars, char with)
BString::ReplaceSet(const char* setOfBytes, char with)
{
if (!setOfChars || strcspn(fPrivateData, setOfChars) >= uint32(Length()))
if (!setOfBytes || strcspn(fPrivateData, setOfBytes) >= uint32(Length()))
return *this;
if (_MakeWritable() != B_OK)
@@ -1396,7 +1635,7 @@ BString::ReplaceSet(const char* setOfChars, char with)
int32 offset = 0;
int32 length = Length();
for (int32 pos;;) {
pos = strcspn(fPrivateData + offset, setOfChars);
pos = strcspn(fPrivateData + offset, setOfBytes);
offset += pos;
if (offset >= length)
@@ -1411,16 +1650,16 @@ BString::ReplaceSet(const char* setOfChars, char with)
BString&
BString::ReplaceSet(const char* setOfChars, const char* with)
BString::ReplaceSet(const char* setOfBytes, const char* with)
{
if (!setOfChars || !with
|| strcspn(fPrivateData, setOfChars) >= uint32(Length()))
if (!setOfBytes || !with
|| strcspn(fPrivateData, setOfBytes) >= uint32(Length()))
return *this;
// delegate simple case
int32 withLen = strlen(with);
if (withLen == 1)
return ReplaceSet(setOfChars, *with);
return ReplaceSet(setOfBytes, *with);
if (_MakeWritable() != B_OK)
return *this;
@@ -1431,7 +1670,7 @@ BString::ReplaceSet(const char* setOfChars, const char* with)
PosVect positions;
for (int32 offset = 0; offset < len; offset += (pos + searchLen)) {
pos = strcspn(fPrivateData + offset, setOfChars);
pos = strcspn(fPrivateData + offset, setOfBytes);
if (pos + offset >= len)
break;
if (!positions.Add(offset + pos))
@@ -1443,6 +1682,49 @@ BString::ReplaceSet(const char* setOfChars, const char* with)
}
BString&
BString::ReplaceCharsSet(const char* setOfChars, const char* with)
{
if (!setOfChars || !with)
return *this;
int32 setCharCount = UTF8CountChars(setOfChars, -1);
if ((uint32)setCharCount == strlen(setOfChars)) {
// no multi-byte chars at all
return ReplaceSet(setOfChars, with);
}
BString setString(setOfChars);
BString result;
int32 withLength = withLength;
int32 charCount = CountChars();
for (int32 i = 0; i < charCount; i++) {
int32 charLength;
const char* sourceChar = CharAt(i, &charLength);
bool match = false;
for (int32 j = 0; j < setCharCount; j++) {
int32 setCharLength;
const char* setChar = setString.CharAt(j, &setCharLength);
if (charLength == setCharLength
&& memcmp(sourceChar, setChar, charLength) == 0) {
match = true;
break;
}
}
if (match)
result.Append(with, withLength);
else
result.Append(sourceChar, charLength);
}
*this = result;
return *this;
}
// #pragma mark - Unchecked char access
@@ -1469,6 +1751,32 @@ BString::operator[](int32 index)
#endif
const char*
BString::CharAt(int32 charIndex, int32* bytes) const
{
int32 offset = UTF8CountBytes(fPrivateData, charIndex);
if (bytes != NULL)
*bytes = UTF8NextCharLen(fPrivateData + offset);
return fPrivateData + offset;
}
bool
BString::CharAt(int32 charIndex, char* buffer, int32* bytes) const
{
int32 length;
const char* charAt = CharAt(charIndex, &length);
if (bytes != NULL) {
if (*bytes < length)
return false;
*bytes = length;
}
memcpy(buffer, charAt, length);
return true;
}
// #pragma mark - Fast low-level manipulation