From ad07ecd82172564bbf3ecad2b9cdf6e7dd3747a6 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 16 Jul 2011 15:59:49 +0200 Subject: [PATCH] BString::Private class to access BString internals --- headers/build/private/support/StringPrivate.h | 1 + headers/os/support/String.h | 15 +++- headers/private/support/StringPrivate.h | 75 +++++++++++++++++++ src/build/libbe/support/Jamfile | 2 +- src/kits/support/String.cpp | 36 ++++----- 5 files changed, 106 insertions(+), 23 deletions(-) create mode 100644 headers/build/private/support/StringPrivate.h create mode 100644 headers/private/support/StringPrivate.h diff --git a/headers/build/private/support/StringPrivate.h b/headers/build/private/support/StringPrivate.h new file mode 100644 index 0000000000..c9b2aa39a3 --- /dev/null +++ b/headers/build/private/support/StringPrivate.h @@ -0,0 +1 @@ +#include <../private/support/StringPrivate.h> diff --git a/headers/os/support/String.h b/headers/os/support/String.h index f3d5ae61d7..bbe5354d51 100644 --- a/headers/os/support/String.h +++ b/headers/os/support/String.h @@ -321,9 +321,20 @@ public: BString& operator<<(float value); BString& operator<<(double value); +public: + class Private; + friend class Private; + private: - class PosVect; - friend class BStringRef; + class PosVect; + friend class BStringRef; + + enum PrivateDataTag { + PRIVATE_DATA + }; + +private: + BString(char* privateData, PrivateDataTag tag); // Management status_t _MakeWritable(); diff --git a/headers/private/support/StringPrivate.h b/headers/private/support/StringPrivate.h new file mode 100644 index 0000000000..68a098dc21 --- /dev/null +++ b/headers/private/support/StringPrivate.h @@ -0,0 +1,75 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _SUPPORT_BSTRING_PRIVATE_H_ +#define _SUPPORT_BSTRING_PRIVATE_H_ + + +#include + +#include + + +class BString::Private { +public: + static const uint32 kPrivateDataOffset = 2 * sizeof(int32); + +public: + Private(const BString& string) + : + fString(string) + { + } + + char* Data() + { + return fString.fPrivateData; + } + + static vint32& DataRefCount(char* data) + { + return *(((int32 *)data) - 2); + } + + vint32& DataRefCount() + { + return DataRefCount(Data()); + } + + static int32& DataLength(char* data) + { + return *(((int32*)data) - 1); + } + + int32& DataLength() + { + return DataLength(Data()); + } + + static void IncrementDataRefCount(char* data) + { + if (data != NULL) + atomic_add(&DataRefCount(data), 1); + } + + static void DecrementDataRefCount(char* data) + { + if (data != NULL) { + if (atomic_add(&DataRefCount(data), -1) == 1) + free(data - kPrivateDataOffset); + } + } + + static BString StringFromData(char* data) + { + return BString(data, BString::PRIVATE_DATA); + } + +private: + const BString& fString; +}; + + +#endif // _SUPPORT_BSTRING_PRIVATE_H_ + diff --git a/src/build/libbe/support/Jamfile b/src/build/libbe/support/Jamfile index 3f7e07e499..46a34b82dc 100644 --- a/src/build/libbe/support/Jamfile +++ b/src/build/libbe/support/Jamfile @@ -1,6 +1,6 @@ SubDir HAIKU_TOP src build libbe support ; -UsePrivateBuildHeaders app interface shared ; +UsePrivateBuildHeaders app interface shared support ; USES_BE_API on support_kit.o = true ; diff --git a/src/kits/support/String.cpp b/src/kits/support/String.cpp index c658450fa1..990100f7cc 100644 --- a/src/kits/support/String.cpp +++ b/src/kits/support/String.cpp @@ -23,6 +23,7 @@ #include +#include #include @@ -34,7 +35,7 @@ #define REPLACE_ALL 0x7FFFFFFF -const uint32 kPrivateDataOffset = 2 * sizeof(int32); +static const uint32 kPrivateDataOffset = BString::Private::kPrivateDataOffset; const char* B_EMPTY_STRING = ""; @@ -79,20 +80,6 @@ safestr(const char* str) } -static inline vint32& -data_reference_count(char* data) -{ - return *(((int32 *)data) - 2); -} - - -static inline int32& -data_length(char* data) -{ - return *(((int32*)data) - 1); -} - - // #pragma mark - PosVect @@ -202,14 +189,14 @@ BStringRef::operator&() inline vint32& BString::_ReferenceCount() { - return data_reference_count(fPrivateData); + return Private::DataRefCount(fPrivateData); } inline const vint32& BString::_ReferenceCount() const { - return data_reference_count(fPrivateData); + return Private::DataRefCount(fPrivateData); } @@ -2132,6 +2119,15 @@ BString::operator<<(double value) // #pragma mark - Private or reserved +BString::BString(char* privateData, PrivateDataTag tag) + : + fPrivateData(privateData) +{ + if (fPrivateData != NULL) + atomic_add(&_ReferenceCount(), 1); +} + + /*! Detaches this string from an eventually shared fPrivateData, ie. this makes this string writable. */ @@ -2210,8 +2206,8 @@ BString::_Allocate(int32 length) newData[length] = '\0'; // initialize reference count & length - data_reference_count(newData) = 1; - data_length(newData) = length & 0x7fffffff; + Private::DataRefCount(newData) = 1; + Private::DataLength(newData) = length & 0x7fffffff; return newData; } @@ -2303,7 +2299,7 @@ BString::_ShrinkAtBy(int32 offset, int32 length) void BString::_SetLength(int32 length) { - data_length(fPrivateData) = length & 0x7fffffff; + Private::DataLength(fPrivateData) = length & 0x7fffffff; }