Ticket #1595: BString.2.diff

File BString.2.diff, 81.8 KB (added by julun, 16 years ago)
  • headers/os/support/String.h

     
    11/*
    2  * Copyright 2001-2007, Haiku Inc. All Rights Reserved.
    3  * Distributed under the terms of the MIT License.
    4  */
     2* Copyright 2001-2008, Haiku Inc. All Rights Reserved.
     3* Distributed under the terms of the MIT License.
     4*/
    55#ifndef __BSTRING__
    66#define __BSTRING__
    77
     
    1111#include <string.h>
    1212
    1313
    14 class BString {
    15     public:
    16         BString();
    17         BString(const char* string);
    18         BString(const BString& string);
    19         BString(const char* string, int32 maxLength);
    20         ~BString();
     14class BStringRef;
    2115
    22         // Access
    23         const char*     String() const;
    2416
    25         int32           Length() const;
    26                             // length of corresponding string
    27         int32           CountChars() const;
    28                             // returns number of UTF8 characters in string
     17class BString
     18{
     19public:
     20                BString();
     21                BString(const char* string);
     22                BString(const BString& string);
     23                BString(const char* string, int32 maxLength);
     24                ~BString();
    2925
    30         // Assignment
    31         BString&        operator=(const BString& string);
    32         BString&        operator=(const char* string);
    33         BString&        operator=(char c);
     26    // Access
     27    const char* String() const;
     28    int32       Length() const;
     29    int32       CountChars() const;
     30    int32       ReferenceCount() const;
    3431
    35         BString&        SetTo(const char* string);
    36         BString&        SetTo(const char* string, int32 maxLength);
     32    // Assignment
     33    BString&    operator=(const BString& string);
     34    BString&    operator=(const char* string);
     35    BString&    operator=(char c);
    3736
    38         BString&        SetTo(const BString& string);
    39         BString&        Adopt(BString& from);
     37    BString&    SetTo(const char* string);
     38    BString&    SetTo(const char* string, int32 maxLength);
    4039
    41         BString&        SetTo(const BString& string, int32 maxLength);
    42         BString&        Adopt(BString& from, int32 maxLength);
     40    BString&    SetTo(const BString& string);
     41    BString&    Adopt(BString& from);
    4342
    44         BString&        SetTo(char c, int32 count);
     43    BString&    SetTo(const BString& string, int32 maxLength);
     44    BString&    Adopt(BString& from, int32 maxLength);
    4545
    46         // Substring copying
    47         BString&        CopyInto(BString& into, int32 fromOffset,
    48                             int32 length) const;
    49         void            CopyInto(char* into, int32 fromOffset,
    50                             int32 length) const;
     46    BString&    SetTo(char c, int32 count);
    5147
    52         // Appending
    53         BString&        operator+=(const BString& string);
    54         BString&        operator+=(const char* string);
    55         BString&        operator+=(char c);
     48    // Substring copying
     49    BString&    CopyInto(BString& into, int32 fromOffset, int32 length) const;
     50    void        CopyInto(char* into, int32 fromOffset, int32 length) const;
    5651
    57         BString&        Append(const BString& string);
    58         BString&        Append(const char* string);
     52    // Appending
     53    BString&    operator+=(const BString& string);
     54    BString&    operator+=(const char* string);
     55    BString&    operator+=(char c);
    5956
    60         BString&        Append(const BString& string, int32 length);
    61         BString&        Append(const char* string, int32 length);
    62         BString&        Append(char c, int32 count);
     57    BString&    Append(const BString& string);
     58    BString&    Append(const char* string);
    6359
    64         // Prepending
    65         BString&        Prepend(const char* string);
    66         BString&        Prepend(const BString& string);
    67         BString&        Prepend(const char* string, int32 length);
    68         BString&        Prepend(const BString& string, int32 length);
    69         BString&        Prepend(char c, int32 count);
     60    BString&    Append(const BString& string, int32 length);
     61    BString&    Append(const char* string, int32 length);
     62    BString&    Append(char c, int32 count);
    7063
    71         // Inserting
    72         BString&        Insert(const char* string, int32 pos);
    73         BString&        Insert(const char* string, int32 length, int32 pos);
    74         BString&        Insert(const char* string, int32 fromOffset,
    75                             int32 length, int32 pos);
     64    // Prepending
     65    BString&    Prepend(const char* string);
     66    BString&    Prepend(const BString& string);
     67    BString&    Prepend(const char* string, int32 length);
     68    BString&    Prepend(const BString& string, int32 length);
     69    BString&    Prepend(char c, int32 count);
    7670
    77         BString&        Insert(const BString& string, int32 pos);
    78         BString&        Insert(const BString& string, int32 length, int32 pos);
    79         BString&        Insert(const BString& string, int32 fromOffset,
    80                             int32 length, int32 pos);
    81         BString&        Insert(char, int32 count, int32 pos);
     71    // Inserting
     72    BString&    Insert(const char* string, int32 position);
     73    BString&    Insert(const char* string, int32 length, int32 position);
     74    BString&    Insert(const char* string, int32 fromOffset, int32 length,
     75                    int32 position);
     76    BString&    Insert(const BString& string, int32 position);
     77    BString&    Insert(const BString& string, int32 length, int32 position);
     78    BString&    Insert(const BString& string, int32 fromOffset, int32 length,
     79                    int32 position);
     80    BString&    Insert(char c, int32 count, int32 position);
    8281
    83         // Removing
    84         BString&        Truncate(int32 newLength, bool lazy = true);
    85         BString&        Remove(int32 from, int32 length);
     82    // Removing
     83    BString&    Truncate(int32 newLength, bool lazy = true);
     84    BString&    Remove(int32 from, int32 length);
    8685
    87         BString&        RemoveFirst(const BString& string);
    88         BString&        RemoveLast(const BString& string);
    89         BString&        RemoveAll(const BString& string);
     86    BString&    RemoveFirst(const BString& string);
     87    BString&    RemoveLast(const BString& string);
     88    BString&    RemoveAll(const BString& string);
    9089
    91         BString&        RemoveFirst(const char* string);
    92         BString&        RemoveLast(const char* string);
    93         BString&        RemoveAll(const char* string);
     90    BString&    RemoveFirst(const char* string);
     91    BString&    RemoveLast(const char* string);
     92    BString&    RemoveAll(const char* string);
    9493
    95         BString&        RemoveSet(const char* setOfCharsToRemove);
     94    BString&    RemoveSet(const char* setOfCharsToRemove);
    9695
    97         BString&        MoveInto(BString& into, int32 from, int32 length);
    98         void            MoveInto(char* into, int32 from, int32 length);
     96    BString&    MoveInto(BString& into, int32 from, int32 length);
     97    void        MoveInto(char* into, int32 from, int32 length);
    9998
    100         // Compare functions
    101         bool            operator<(const BString& string) const;
    102         bool            operator<=(const BString& string) const;
    103         bool            operator==(const BString& string) const;
    104         bool            operator>=(const BString& string) const;
    105         bool            operator>(const BString& string) const;
    106         bool            operator!=(const BString& string) const;
     99    // Compare functions
     100    bool        operator<(const BString& string) const;
     101    bool        operator<=(const BString& string) const;
     102    bool        operator==(const BString& string) const;
     103    bool        operator>=(const BString& string) const;
     104    bool        operator>(const BString& string) const;
     105    bool        operator!=(const BString& string) const;
    107106
    108         bool            operator<(const char* string) const;
    109         bool            operator<=(const char* string) const;
    110         bool            operator==(const char* string) const;
    111         bool            operator>=(const char* string) const;
    112         bool            operator>(const char* string) const;
    113         bool            operator!=(const char* string) const;
     107    bool        operator<(const char* string) const;
     108    bool        operator<=(const char* string) const;
     109    bool        operator==(const char* string) const;
     110    bool        operator>=(const char* string) const;
     111    bool        operator>(const char* string) const;
     112    bool        operator!=(const char* string) const;
    114113
    115         // strcmp()-style compare functions
    116         int             Compare(const BString& string) const;
    117         int             Compare(const char* string) const;
    118         int             Compare(const BString& string, int32 length) const;
    119         int             Compare(const char* string, int32 length) const;
    120         int             ICompare(const BString& string) const;
    121         int             ICompare(const char* string) const;
    122         int             ICompare(const BString& string, int32 length) const;
    123         int             ICompare(const char* string, int32 length) const;
     114    // strcmp()-style compare functions
     115    int         Compare(const BString& string) const;
     116    int         Compare(const char* string) const;
     117    int         Compare(const BString& string, int32 length) const;
     118    int         Compare(const char* string, int32 length) const;
     119    int         ICompare(const BString& string) const;
     120    int         ICompare(const char* string) const;
     121    int         ICompare(const BString& string, int32 length) const;
     122    int         ICompare(const char* string, int32 length) const;
    124123
    125         // Searching
    126         int32           FindFirst(const BString& string) const;
    127         int32           FindFirst(const char* string) const;
    128         int32           FindFirst(const BString& string, int32 fromOffset) const;
    129         int32           FindFirst(const char* string, int32 fromOffset) const;
    130         int32           FindFirst(char c) const;
    131         int32           FindFirst(char c, int32 fromOffset) const;
     124    // Searching
     125    int32       FindFirst(const BString& string) const;
     126    int32       FindFirst(const char* string) const;
     127    int32       FindFirst(const BString& string, int32 fromOffset) const;
     128    int32       FindFirst(const char* string, int32 fromOffset) const;
     129    int32       FindFirst(char c) const;
     130    int32       FindFirst(char c, int32 fromOffset) const;
    132131
    133         int32           FindLast(const BString& string) const;
    134         int32           FindLast(const char* string) const;
    135         int32           FindLast(const BString& string, int32 beforeOffset) const;
    136         int32           FindLast(const char* string, int32 beforeOffset) const;
    137         int32           FindLast(char c) const;
    138         int32           FindLast(char c, int32 beforeOffset) const;
     132    int32       FindLast(const BString& string) const;
     133    int32       FindLast(const char* string) const;
     134    int32       FindLast(const BString& string, int32 beforeOffset) const;
     135    int32       FindLast(const char* string, int32 beforeOffset) const;
     136    int32       FindLast(char c) const;
     137    int32       FindLast(char c, int32 beforeOffset) const;
    139138
    140         int32           IFindFirst(const BString& string) const;
    141         int32           IFindFirst(const char* string) const;
    142         int32           IFindFirst(const BString& string, int32 fromOffset) const;
    143         int32           IFindFirst(const char* string, int32 fromOffset) const;
     139    int32       IFindFirst(const BString& string) const;
     140    int32       IFindFirst(const char* string) const;
     141    int32       IFindFirst(const BString& string, int32 fromOffset) const;
     142    int32       IFindFirst(const char* string, int32 fromOffset) const;
    144143
    145         int32           IFindLast(const BString& string) const;
    146         int32           IFindLast(const char* string) const;
    147         int32           IFindLast(const BString& string, int32 beforeOffset) const;
    148         int32           IFindLast(const char* string, int32 beforeOffset) const;
     144    int32       IFindLast(const BString& string) const;
     145    int32       IFindLast(const char* string) const;
     146    int32       IFindLast(const BString& string, int32 beforeOffset) const;
     147    int32       IFindLast(const char* string, int32 beforeOffset) const;
    149148
    150         // Replacing
    151         BString&        ReplaceFirst(char replaceThis, char withThis);
    152         BString&        ReplaceLast(char replaceThis, char withThis);
    153         BString&        ReplaceAll(char replaceThis, char withThis,
    154                             int32 fromOffset = 0);
    155         BString&        Replace(char replaceThis, char withThis,
    156                             int32 maxReplaceCount, int32 fromOffset = 0);
    157         BString&        ReplaceFirst(const char* replaceThis,
    158                             const char* withThis);
    159         BString&        ReplaceLast(const char* replaceThis,
    160                             const char* withThis);
    161         BString&        ReplaceAll(const char* replaceThis,
    162                             const char* withThis, int32 fromOffset = 0);
    163         BString&        Replace(const char* replaceThis, const char* withThis,
    164                             int32 maxReplaceCount, int32 fromOffset = 0);
     149    // Replacing
     150    BString&    ReplaceFirst(char replaceThis, char withThis);
     151    BString&    ReplaceLast(char replaceThis, char withThis);
     152    BString&    ReplaceAll(char replaceThis, char withThis, int32 fromOffset = 0);
     153    BString&    Replace(char replaceThis, char withThis, int32 maxReplaceCount,
     154                    int32 fromOffset = 0);
     155    BString&    ReplaceFirst(const char* replaceThis, const char* withThis);
     156    BString&    ReplaceLast(const char* replaceThis, const char* withThis);
     157    BString&    ReplaceAll(const char* replaceThis, const char* withThis,
     158                    int32 fromOffset = 0);
     159    BString&    Replace(const char* replaceThis, const char* withThis,
     160                    int32 maxReplaceCount, int32 fromOffset = 0);
    165161
    166         BString&        IReplaceFirst(char replaceThis, char withThis);
    167         BString&        IReplaceLast(char replaceThis, char withThis);
    168         BString&        IReplaceAll(char replaceThis, char withThis,
    169                             int32 fromOffset = 0);
    170         BString&        IReplace(char replaceThis, char withThis,
    171                             int32 maxReplaceCount, int32 fromOffset = 0);
    172         BString&        IReplaceFirst(const char* replaceThis,
    173                             const char* withThis);
    174         BString&        IReplaceLast(const char* replaceThis,
    175                             const char* withThis);
    176         BString&        IReplaceAll(const char* replaceThis,
    177                             const char* withThis, int32 fromOffset = 0);
    178         BString&        IReplace(const char* replaceThis, const char* withThis,
    179                             int32 maxReplaceCount, int32 fromOffset = 0);
     162    BString&    IReplaceFirst(char replaceThis, char withThis);
     163    BString&    IReplaceLast(char replaceThis, char withThis);
     164    BString&    IReplaceAll(char replaceThis, char withThis, int32 fromOffset = 0);
     165    BString&    IReplace(char replaceThis, char withThis, int32 maxReplaceCount,
     166                    int32 fromOffset = 0);
     167    BString&    IReplaceFirst(const char* replaceThis, const char* withThis);
     168    BString&    IReplaceLast(const char* replaceThis, const char* withThis);
     169    BString&    IReplaceAll(const char* replaceThis, const char* withThis,
     170                    int32 fromOffset = 0);
     171    BString&    IReplace(const char* replaceThis, const char* withThis,
     172                    int32 maxReplaceCount, int32 fromOffset = 0);
    180173
    181         BString&        ReplaceSet(const char* setOfChars, char with);
    182         BString&        ReplaceSet(const char* setOfChars, const char *with);
     174    BString&    ReplaceSet(const char* setOfChars, char with);
     175    BString&    ReplaceSet(const char* setOfChars, const char* with);
    183176
    184         // Unchecked char access
    185         char            operator[](int32 index) const;
    186         char&           operator[](int32 index);
     177    // Unchecked char access
     178    char        operator[](int32 index) const;
    187179
    188         // Checked char access
    189         char            ByteAt(int32 index) const;
     180#if __GNUC__ > 3
     181    BStringRef  operator[](int32 index);
     182#else
     183    char&       operator[](int32 index);
     184#endif
    190185
    191         // Fast low-level manipulation
    192         char*           LockBuffer(int32 maxLength);
    193         BString&        UnlockBuffer(int32 length = -1);
     186    // Checked char access
     187    char        ByteAt(int32 index) const;
    194188
    195         // Upercase <-> Lowercase
    196         BString&        ToLower();
    197         BString&        ToUpper();
     189    // Fast low-level manipulation
     190    char*       LockBuffer(int32 maxLength);
     191    BString&    UnlockBuffer(int32 length = -1);
    198192
    199         BString&        Capitalize();
    200         BString&        CapitalizeEachWord();
     193    // Upercase <-> Lowercase
     194    BString&    ToLower();
     195    BString&    ToUpper();
    201196
    202         // Escaping and De-escaping
    203         BString&        CharacterEscape(const char* original,
    204                             const char* setOfCharsToEscape, char escapeWith);
    205         BString&        CharacterEscape(const char* setOfCharsToEscape,
    206                             char escapeWith);
     197    BString&    Capitalize();
     198    BString&    CapitalizeEachWord();
    207199
    208         BString&        CharacterDeescape(const char* original, char escapeChar);
    209         BString&        CharacterDeescape(char escapeChar);
     200    // Escaping and De-escaping
     201    BString&    CharacterEscape(const char* original, const char* setOfCharsToEscape,
     202                    char escapeWith);
     203    BString&    CharacterEscape(const char* setOfCharsToEscape, char escapeWith);
     204    BString&    CharacterDeescape(const char* original, char escapeChar);
     205    BString&    CharacterDeescape(char escapeChar);
    210206
    211         // Slower than sprintf() but type and overflow safe
    212         BString&        operator<<(const char* string);
    213         BString&        operator<<(const BString& string);
    214         BString&        operator<<(char c);
    215         BString&        operator<<(int value);
    216         BString&        operator<<(unsigned int value);
    217         BString&        operator<<(uint32 value);
    218         BString&        operator<<(int32 value);
    219         BString&        operator<<(uint64 value);
    220         BString&        operator<<(int64 value);
    221         BString&        operator<<(float value);
    222             // float output hardcodes %.2f style formatting
     207    // Insert
     208    BString&    operator<<(const char* string);
     209    BString&    operator<<(const BString& string);
     210    BString&    operator<<(char c);
     211    BString&    operator<<(int value);
     212    BString&    operator<<(unsigned int value);
     213    BString&    operator<<(uint32 value);
     214    BString&    operator<<(int32 value);
     215    BString&    operator<<(uint64 value);
     216    BString&    operator<<(int64 value);
     217    // float output hardcodes %.2f style formatting
     218    BString&    operator<<(float value);
    223219
    224     private:
    225         void            _Init(const char *, int32);
    226         void            _DoAssign(const char *, int32);
    227         void            _DoAppend(const char *, int32);
    228         char*           _GrowBy(int32);
    229         char*           _OpenAtBy(int32, int32);
    230         char*           _ShrinkAtBy(int32, int32);
    231         void            _DoPrepend(const char *, int32);
     220private:
     221    class PosVect;
     222    friend class BStringRef;
    232223
    233         int32           _FindAfter(const char *, int32, int32) const;
    234         int32           _IFindAfter(const char *, int32, int32) const;
    235         int32           _ShortFindAfter(const char *, int32) const;
    236         int32           _FindBefore(const char *, int32, int32) const;
    237         int32           _IFindBefore(const char *, int32, int32) const;
    238         BString&        _DoReplace(const char *, const char *, int32, int32,
    239                             bool);
    240         void            _SetLength(int32);
     224    // Management
     225    status_t    _Detach();
     226    char*       _Realloc(int32 length);
     227    void        _Init(const char* src, int32 length);
     228    char*       _Clone(const char* data, int32 length);
     229    char*       _OpenAtBy(int32 offset, int32 length);
     230    char*       _ShrinkAtBy(int32 offset, int32 length);
     231    status_t    _DetachWith(const char* string, int32 length);
    241232
    242 #if DEBUG
    243         void            _SetUsingAsCString(bool);
    244         void            _AssertNotUsingAsCString() const;
    245 #else
    246         void            _SetUsingAsCString(bool) {}
    247         void            _AssertNotUsingAsCString() const {}
    248 #endif
     233    // Data
     234    void        _SetLength(int32 length);
     235    void        _SetReferenceCount(int32 count);
     236    bool        _DoAppend(const char* string, int32 length);
     237    bool        _DoPrepend(const char* string, int32 length);
     238    bool        _DoInsert(const char* string, int32 offset, int32 length);
    249239
    250         char*           _Alloc(int32 size);
     240    // Search
     241    int32       _ShortFindAfter(const char* string, int32 len) const;
     242    int32       _FindAfter(const char* string, int32 offset, int32 strlen) const;
     243    int32       _IFindAfter(const char* string, int32 offset, int32 strlen) const;
    251244
    252         class PosVect;
    253         void            _ReplaceAtPositions(const PosVect* positions,
    254                            int32 searchLength, const char* with, int32 withLen);
     245    int32       _FindBefore(const char* string, int32 offset, int32 strlen) const;
     246    int32       _IFindBefore(const char* string, int32 offset, int32 strlen) const;
    255247
    256     protected:
    257         char*   fPrivateData;
     248    // Escape
     249    BString&    _DoCharacterEscape(const char* string,
     250                    const char *setOfCharsToEscape, char escapeChar);
     251    BString&    _DoCharacterDeescape(const char* string, char escapeChar);
     252
     253    // Replace
     254    BString&    _DoReplace(const char* findThis, const char* replaceWith,
     255                    int32 maxReplaceCount, int32 fromOffset, bool ignoreCase);
     256    void        _ReplaceAtPositions(const PosVect* positions, int32 searchLen,
     257                    const char* with, int32 withLen);
     258
     259private:
     260    char*               fPrivateData;
    258261};
    259262
     263
    260264// Commutative compare operators
    261265bool operator<(const char* a, const BString& b);
    262266bool operator<=(const char* a, const BString& b);
     
    265269bool operator>=(const char* a, const BString& b);
    266270bool operator!=(const char* a, const BString& b);
    267271
     272
    268273// Non-member compare for sorting, etc.
    269274int Compare(const BString& a, const BString& b);
    270275int ICompare(const BString& a, const BString& b);
     
    272277int ICompare(const BString* a, const BString* b);
    273278
    274279
    275 inline int32 
     280inline int32
    276281BString::Length() const
    277282{
    278     return fPrivateData ? (*((int32 *)fPrivateData - 1) & 0x7fffffff) : 0;
    279         /* the most significant bit is reserved; accessing
    280          * it in any way will cause the computer to explode
    281          */
     283    // the most significant bit is reserved; accessing
     284    // it in any way will cause the computer to explode
     285    return fPrivateData ? (*(((int32 *)fPrivateData) - 1) & 0x7fffffff) : 0;
    282286}
    283287
    284 inline const char *
     288
     289inline const char*
    285290BString::String() const
    286291{
    287292    if (!fPrivateData)
     
    289294    return fPrivateData;
    290295}
    291296
     297
     298inline int32
     299BString::ReferenceCount() const
     300{
     301    return fPrivateData ? (*(((int32 *)fPrivateData) - 2)) : 1;
     302}
     303
     304
    292305inline BString &
    293 BString::SetTo(const char *string)
     306BString::SetTo(const char* string)
    294307{
    295308    return operator=(string);
    296309}
    297310
    298 inline char
     311
     312inline char
    299313BString::operator[](int32 index) const
    300314{
    301315    return fPrivateData[index];
    302316}
    303317
    304 inline char
     318
     319inline char
    305320BString::ByteAt(int32 index) const
    306321{
    307322    if (!fPrivateData || index < 0 || index > Length())
     
    309324    return fPrivateData[index];
    310325}
    311326
     327
    312328inline BString &
    313329BString::operator+=(const BString &string)
    314330{
     
    316332    return *this;
    317333}
    318334
     335
    319336inline BString &
    320337BString::Append(const BString &string)
    321338{
     
    323340    return *this;
    324341}
    325342
     343
    326344inline BString &
    327 BString::Append(const char *str)
     345BString::Append(const char* string)
    328346{
    329     return operator+=(str);
     347    return operator+=(string);
    330348}
    331349
    332 inline bool
     350
     351inline bool
    333352BString::operator==(const BString &string) const
    334353{
    335354    return strcmp(String(), string.String()) == 0;
    336355}
    337356
    338 inline bool
     357
     358inline bool
    339359BString::operator<(const BString &string) const
    340360{
    341361    return strcmp(String(), string.String()) < 0;
    342362}
    343363
    344 inline bool
     364
     365inline bool
    345366BString::operator<=(const BString &string) const
    346367{
    347368    return strcmp(String(), string.String()) <= 0;
    348369}
    349370
    350 inline bool
     371
     372inline bool
    351373BString::operator>=(const BString &string) const
    352374{
    353375    return strcmp(String(), string.String()) >= 0;
    354376}
    355377
    356 inline bool
     378
     379inline bool
    357380BString::operator>(const BString &string) const
    358381{
    359382    return strcmp(String(), string.String()) > 0;
    360383}
    361384
    362 inline bool
     385
     386inline bool
    363387BString::operator!=(const BString &string) const
    364388{
    365389    return strcmp(String(), string.String()) != 0;
    366390}
    367391
    368 inline bool
    369 BString::operator!=(const char *str) const
     392
     393inline bool
     394BString::operator!=(const char* string) const
    370395{
    371     return !operator==(str);
     396    return !operator==(string);
    372397}
    373398
    374 inline bool
     399
     400inline bool
    375401operator<(const char *str, const BString &string)
    376402{
    377403    return string > str;
    378404}
    379405
    380 inline bool
     406
     407inline bool
    381408operator<=(const char *str, const BString &string)
    382409{
    383410    return string >= str;
    384411}
    385412
    386 inline bool
     413
     414inline bool
    387415operator==(const char *str, const BString &string)
    388416{
    389417    return string == str;
    390418}
    391419
    392 inline bool
     420
     421inline bool
    393422operator>(const char *str, const BString &string)
    394423{
    395424    return string < str;
    396425}
    397426
    398 inline bool
     427
     428inline bool
    399429operator>=(const char *str, const BString &string)
    400430{
    401431    return string <= str;
    402432}
    403433
    404 inline bool
     434
     435inline bool
    405436operator!=(const char *str, const BString &string)
    406437{
    407438    return string != str;
    408439}
    409440
    410 #endif /* __BSTRING__ */
     441
     442//  #pragma mark - BStringRef
     443
     444
     445class BStringRef
     446{
     447public:
     448    BStringRef(BString& string, int32 position);
     449    ~BStringRef() {}
     450   
     451    operator char() const;
     452
     453    char* operator&();
     454    const char* operator&() const;
     455
     456    BStringRef& operator=(char c);
     457    BStringRef &operator=(const BStringRef &rc);
     458
     459private:
     460    BString&    fString;
     461    int32       fPosition;
     462};
     463
     464#endif  // __BSTRING__
  • src/kits/support/String.cpp

     
    11/*
    2  * Copyright 2001-2007, Haiku, Inc. All Rights Reserved.
    3  * Distributed under the terms of the MIT License.
    4  *
    5  * Authors:
    6  *      Marc Flerackers (mflerackers@androme.be)
    7  *      Stefano Ceccherini (burton666@libero.it)
    8  *      Oliver Tappe (openbeos@hirschkaefer.de)
    9  *      Axel Dörfler, axeld@pinc-software.de
    10  */
     2* Copyright 2001-2008, Haiku, Inc. All Rights Reserved.
     3* Distributed under the terms of the MIT License.
     4*
     5* Authors:
     6*       Marc Flerackers (mflerackers@androme.be)
     7*       Stefano Ceccherini (burton666@libero.it)
     8*       Oliver Tappe (openbeos@hirschkaefer.de)
     9*       Axel Dörfler, axeld@pinc-software.de
     10*       Julun <host.haiku@gmx.de>
     11*/
    1112
    1213/* String class supporting common string operations. */
    1314
     
    3132#define REPLACE_ALL 0x7FFFFFFF
    3233
    3334
    34 // helper macro that is used to fall into debugger if a given param check fails:
    35 #ifdef DEBUG
    36     #define CHECK_PARAM( expr, msg) \
    37     if (!(expr)) \
    38         debugger( msg)
    39 
    40     #define CHECK_PARAM_RET( expr, msg, retval) \
    41     if (!(expr)) \
    42         debugger( msg)
    43 
    44     #define CHECK_PARAM_VOID( expr, msg) \
    45     if (!(expr)) \
    46         debugger( msg)
    47 #else
    48     #define CHECK_PARAM( expr, msg) \
    49     if (!(expr)) \
    50         return *this
    51 
    52     #define CHECK_PARAM_RET( expr, msg, retval) \
    53     if (!(expr)) \
    54         return (retval);
    55 
    56     #define CHECK_PARAM_VOID( expr, msg)
    57 #endif
    58 
    59 
    60 //! helper class for BString::_ReplaceAtPositions():
    61 class BString::PosVect {
    62     public:
    63         PosVect();
    64         ~PosVect();
    65 
    66         bool Add(int32 pos);
    67 
    68         inline int32 ItemAt(int32 index) const
    69             { return fBuffer[index]; }
    70         inline int32 CountItems() const
    71             { return fSize; }
    72 
    73     private:
    74         int32   fSize;
    75         int32   fBufferSize;
    76         int32*  fBuffer;
    77 };
    78 
    79 
    8035const char *B_EMPTY_STRING = "";
    8136
    8237
    8338// helper function, returns minimum of two given values (but clamps to 0):
    8439static inline int32
    85 min_clamp0(int32 num1, int32 num2) 
    86 { 
     40min_clamp0(int32 num1, int32 num2)
     41{
    8742    if (num1 < num2)
    8843        return num1 > 0 ? num1 : 0;
    8944
     
    9348
    9449//! helper function, returns length of given string (but clamps to given maximum):
    9550static inline int32
    96 strlen_clamp(const char* str, int32 max) 
     51strlen_clamp(const char* str, int32 max)
    9752{
    9853    // this should yield 0 for max<0:
    9954    int32 length = 0;
     
    10560
    10661
    10762//! helper function, massages given pointer into a legal c-string:
    108 static inline const char * 
    109 safestr(const char* str) 
     63static inline const char *
     64safestr(const char* str)
    11065{
    11166    return str ? str : "";
    11267}
    11368
    11469
    115 //  #pragma mark -
     70//  #pragma mark - PosVect
    11671
    11772
    118 BString::PosVect::PosVect()
    119     :
    120     fSize(0),
    121     fBufferSize(20),
    122     fBuffer(NULL)
     73class BString::PosVect {
     74public:
     75    PosVect()
     76        : fSize(0),
     77        fBufferSize(20),
     78        fBuffer(NULL)   { }
     79
     80    ~PosVect()
     81    {
     82        free(fBuffer);
     83    }
     84
     85    bool Add(int32 pos)
     86    {
     87        if (fBuffer == NULL || fSize == fBufferSize) {
     88            if (fBuffer != NULL)
     89                fBufferSize *= 2;
     90
     91            int32* newBuffer = NULL;
     92            newBuffer = (int32 *)realloc(fBuffer, fBufferSize * sizeof(int32));
     93            if (newBuffer == NULL)
     94                return false;
     95
     96            fBuffer = newBuffer;
     97        }
     98
     99        fBuffer[fSize++] = pos;
     100        return true;
     101    }
     102
     103    inline int32 ItemAt(int32 index) const
     104    { return fBuffer[index]; }
     105    inline int32 CountItems() const
     106    { return fSize; }
     107
     108private:
     109    int32   fSize;
     110    int32   fBufferSize;
     111    int32*  fBuffer;
     112};
     113
     114
     115//  #pragma mark - BStringRef
     116
     117
     118BStringRef::BStringRef(BString& string, int32 position)
     119    : fString(string), fPosition(position)
    123120{
    124121}
    125122
    126123
    127 BString::PosVect::~PosVect()
     124BStringRef::operator char() const
    128125{
    129     free(fBuffer);
     126    return fPosition < fString.Length() ? fString.fPrivateData[fPosition] : 0;
    130127}
    131128
    132129
    133 bool
    134 BString::PosVect::Add(int32 pos)
     130BStringRef&
     131BStringRef::operator=(char c)
    135132{
    136     if (fBuffer == NULL || fSize == fBufferSize) {
    137         if (fBuffer != NULL)
    138             fBufferSize *= 2;
     133    fString._Detach();
     134    fString.fPrivateData[fPosition] = c;
     135    return *this;
     136}
    139137
    140         int32* newBuffer = (int32 *)realloc(fBuffer, fBufferSize * sizeof(int32));
    141         if (newBuffer == NULL)
    142             return false;
    143138
    144         fBuffer = newBuffer;
    145     }
     139BStringRef&
     140BStringRef::operator=(const BStringRef &rc)
     141{
     142    return operator=(rc.fString.fPrivateData[rc.fPosition]);
     143}
    146144
    147     fBuffer[fSize++] = pos;
    148     return true;
     145
     146const char*
     147BStringRef::operator&() const
     148{
     149    return &(fString.fPrivateData[fPosition]);
    149150}
    150151
    151152
     153char*
     154BStringRef::operator&()
     155{
     156    fString._Detach();
     157    fString._SetReferenceCount(-1);
     158    return &(fString.fPrivateData[fPosition]);
     159}
     160
     161
    152162//  #pragma mark - BString
    153163
    154164
    155165BString::BString()
    156     : fPrivateData(NULL)   
     166    : fPrivateData(NULL)
    157167{
     168    _Init("", 0);
    158169}
    159170
    160171
    161172BString::BString(const char* string)
    162173    : fPrivateData(NULL)
    163174{
    164     if (string != NULL)
    165         _Init(string, strlen(string));
     175    _Init(string, strlen(safestr(string)));
    166176}
    167177
    168178
    169 BString::BString(const BString &string)
    170     : fPrivateData(NULL)           
     179BString::BString(const BString& string)
     180    : fPrivateData(NULL)
    171181{
    172     _Init(string.String(), string.Length());
     182    // check if source is sharable - if so, share else clone
     183    if (atomic_get(&(*(((vint32*)string.fPrivateData) - 2))) >= 0) {
     184        fPrivateData = string.fPrivateData;
     185        atomic_add(&(*(((vint32*)fPrivateData) - 2)), 1);
     186    } else
     187        fPrivateData = _Clone(string.fPrivateData, string.Length());
    173188}
    174189
    175190
    176 BString::BString(const char *string, int32 maxLength)
    177     : fPrivateData(NULL)       
     191BString::BString(const char* string, int32 maxLength)
     192    : fPrivateData(NULL)
    178193{
    179     if (string != NULL)
    180         _Init(string, strlen_clamp(string, maxLength));
     194    _Init(string, strlen_clamp(safestr(string), maxLength));
    181195}
    182196
    183197
    184198BString::~BString()
    185199{
    186     if (fPrivateData)
    187         free(fPrivateData - sizeof(int32));
     200    if (atomic_add(&(*(((vint32*)fPrivateData) - 2)), -1) < 1)
     201        free(fPrivateData - (2 * sizeof(int32)));
    188202}
    189203
    190204
    191205//  #pragma mark - Access
    192206
    193        
     207
    194208int32
    195209BString::CountChars() const
    196210{
     
    214228
    215229
    216230BString&
    217 BString::operator=(const BString &string)
     231BString::operator=(const BString& string)
    218232{
    219     if (&string != this) // Avoid auto-assignment
    220         _DoAssign(string.String(), string.Length());
    221     return *this;
     233    return SetTo(string);
    222234}
    223235
    224236
    225237BString&
    226 BString::operator=(const char *str)
     238BString::operator=(const char* string)
    227239{
    228     if (str != NULL)
    229         _DoAssign(str, strlen(str));   
    230     else
    231         _Alloc(0);
    232 
     240    if (string)
     241        SetTo(string, strlen(string));
    233242    return *this;
    234243}
    235244
     
    237246BString&
    238247BString::operator=(char c)
    239248{
    240     _DoAssign(&c, 1);
    241     return *this;
     249    return SetTo(c, 1);
    242250}
    243251
    244252
    245253BString&
    246 BString::SetTo(const char *str, int32 maxLength)
     254BString::SetTo(const char* string, int32 maxLength)
    247255{
    248     if (str != NULL)
    249         _DoAssign(str, strlen_clamp(str, maxLength));
    250     else
    251         _Alloc(0);
     256    maxLength = strlen_clamp(safestr(string), maxLength);
     257    if (_DetachWith("", maxLength) == B_OK)
     258        memcpy(fPrivateData, string, maxLength);
    252259
    253260    return *this;
    254261}
    255262
    256263
    257264BString&
    258 BString::SetTo(const BString &from)
     265BString::SetTo(const BString& string)
    259266{
    260     if (&from != this) {
    261         // Avoid auto-assignment
    262         _DoAssign(from.String(), from.Length());
     267    // we share the information already
     268    if (fPrivateData == string.fPrivateData)
     269        return *this;
     270
     271    // check if we are shared by someone else
     272    if (atomic_get(&(*(((vint32*)fPrivateData) - 2))) > 1) {
     273        // we share our data with someone else
     274        if (atomic_add(&(*((vint32*)fPrivateData - 2)), -1) < 1) {
     275            // someone else decrement, we are the last owner
     276            free(fPrivateData - (2 * sizeof(int32)));
     277        } else {
     278            ; // there is still someone who shares our data
     279        }
     280    } else {
     281        // we don't share our data with someone else
     282        // or we are marked as unsharable, but this will go away
     283        free(fPrivateData - (2 * sizeof(int32)));
    263284    }
     285
     286    // if source is sharable share, otherwise clone
     287    if (atomic_get(&(*(((vint32*)string.fPrivateData) - 2))) >= 0) {
     288        fPrivateData = string.fPrivateData;
     289        atomic_add(&(*(((vint32*)fPrivateData) - 2)), 1);
     290    } else
     291        fPrivateData = _Clone(string.fPrivateData, string.Length());
     292
    264293    return *this;
    265294}
    266295
    267296
    268297BString&
    269 BString::Adopt(BString &from)
     298BString::Adopt(BString& from)
    270299{
    271     if (&from == this) {
    272         // Avoid auto-adoption
    273         return *this;
    274     }
     300    SetTo(from);
     301    from.SetTo("");
    275302
    276     if (fPrivateData)
    277         free(fPrivateData - sizeof(int32));
    278 
    279     /* "steal" the data from the given BString */
    280     fPrivateData = from.fPrivateData;
    281     from.fPrivateData = NULL;
    282 
    283303    return *this;
    284304}
    285305
    286306
    287307BString&
    288 BString::SetTo(const BString &string, int32 length)
     308BString::SetTo(const BString& string, int32 maxLength)
    289309{
    290     if (&string != this) // Avoid auto-assignment
    291         _DoAssign(string.String(), min_clamp0(length, string.Length()));
     310    if (fPrivateData != string.fPrivateData
     311        // make sure we reassing in case length is different
     312        || (fPrivateData == string.fPrivateData && Length() != maxLength)) {
     313            maxLength = min_clamp0(maxLength, string.Length());
     314            if (_DetachWith("", maxLength) == B_OK)
     315                memcpy(fPrivateData, string.fPrivateData, maxLength);
     316    }
    292317    return *this;
    293318}
    294319
    295320
    296321BString&
    297 BString::Adopt(BString &from, int32 length)
     322BString::Adopt(BString& from, int32 maxLength)
    298323{
    299     if (&from == this) // Avoid auto-adoption
    300         return *this;
     324    SetTo(from, maxLength);
     325    from.SetTo("");
    301326
    302     int32 len = min_clamp0(length, from.Length());
    303 
    304     if (fPrivateData)
    305         free(fPrivateData - sizeof(int32));
    306 
    307     /* "steal" the data from the given BString */
    308     fPrivateData = from.fPrivateData;
    309     from.fPrivateData = NULL;
    310 
    311     if (len < Length())
    312         _Alloc(len);
    313 
    314327    return *this;
    315328}
    316329
     
    320333{
    321334    if (count < 0)
    322335        count = 0;
    323     int32 curLen = Length();
    324    
    325     if (curLen == count || _GrowBy(count - curLen))
     336
     337    if (_DetachWith("", count) == B_OK)
    326338        memset(fPrivateData, c, count);
    327     return *this;   
     339    return *this;
    328340}
    329341
    330342
    331343//  #pragma mark - Substring copying
    332344
    333345
    334 BString &
    335 BString::CopyInto(BString &into, int32 fromOffset, int32 length) const
     346BString&
     347BString::CopyInto(BString& into, int32 fromOffset,
     348                  int32 length) const
    336349{
    337     if (&into != this) {
    338         CHECK_PARAM_RET(fromOffset >= 0, "'fromOffset' must not be negative!",
    339                         into);
    340         CHECK_PARAM_RET(fromOffset <= Length(), "'fromOffset' exceeds length!",
    341                         into);
    342         into.SetTo(String() + fromOffset, length);
    343     }
     350    if (this != &into)
     351        into.SetTo(fPrivateData + fromOffset, length);
    344352    return into;
    345353}
    346354
    347355
    348356void
    349 BString::CopyInto(char *into, int32 fromOffset, int32 length) const
     357BString::CopyInto(char* into, int32 fromOffset, int32 length) const
    350358{
    351     if (into != NULL) {
    352         CHECK_PARAM_VOID(fromOffset >= 0, "'fromOffset' must not be negative!");
    353         CHECK_PARAM_VOID(fromOffset <= Length(), "'fromOffset' exceeds length!");
    354         int32 len = min_clamp0(length, Length() - fromOffset);
    355         memcpy(into, fPrivateData + fromOffset, len);
     359    if (into) {
     360        length = min_clamp0(length, Length() - fromOffset);
     361        memcpy(into, fPrivateData + fromOffset, length);
    356362    }
    357363}
    358364
     
    361367
    362368
    363369BString&
    364 BString::operator+=(const char *str)
     370BString::operator+=(const char* string)
    365371{
    366     if (str != NULL)
    367         _DoAppend(str, strlen(str));
     372    if (string)
     373        _DoAppend(string, strlen(string));
    368374    return *this;
    369375}
    370376
     
    378384
    379385
    380386BString&
    381 BString::Append(const BString &string, int32 length)
     387BString::Append(const BString& string, int32 length)
    382388{
    383     _DoAppend(string.String(), min_clamp0(length, string.Length()));
     389    _DoAppend(string.fPrivateData, min_clamp0(length, string.Length()));
    384390    return *this;
    385391}
    386392
    387393
    388394BString&
    389 BString::Append(const char *str, int32 length)
     395BString::Append(const char* string, int32 length)
    390396{
    391     if (str != NULL) {
    392         int32 len = strlen_clamp(str, length);
    393         _DoAppend(str, len);
    394     }   
     397    if (string)
     398        _DoAppend(string, strlen_clamp(string, length));
    395399    return *this;
    396400}
    397401
     
    400404BString::Append(char c, int32 count)
    401405{
    402406    int32 len = Length();
    403     if (count > 0 && _GrowBy(count))
     407    if (count > 0 && _DoAppend("", count))
    404408        memset(fPrivateData + len, c, count);
    405 
    406409    return *this;
    407410}
    408411
     
    411414
    412415
    413416BString&
    414 BString::Prepend(const char *str)
     417BString::Prepend(const char* string)
    415418{
    416     if (str != NULL)
    417         _DoPrepend(str, strlen(str));
     419    if (string)
     420        _DoPrepend(string, strlen(string));
    418421    return *this;
    419422}
    420423
    421424
    422 // Prepend
    423425BString&
    424 BString::Prepend(const BString &string)
     426BString::Prepend(const BString& string)
    425427{
    426     if (&string != this)
    427         _DoPrepend(string.String(), string.Length());
     428    if (fPrivateData != string.fPrivateData)
     429        _DoPrepend(string.fPrivateData, string.Length());
    428430    return *this;
    429431}
    430432
    431433
    432 // Prepend
    433434BString&
    434 BString::Prepend(const char *str, int32 length)
     435BString::Prepend(const char* string, int32 length)
    435436{
    436     if (str != NULL) {
    437         int32 len = strlen_clamp(str, length);
    438         _DoPrepend(str, len);
    439     }
     437    if (string)
     438        _DoPrepend(string, strlen_clamp(string, length));
    440439    return *this;
    441440}
    442441
    443442
    444 // Prepend
    445443BString&
    446 BString::Prepend(const BString &string, int32 len)
     444BString::Prepend(const BString& string, int32 length)
    447445{
    448     if (&string != this)
    449         _DoPrepend(string.String(), min_clamp0(len, string.Length()));
     446    if (fPrivateData != string.fPrivateData)
     447        _DoPrepend(string.fPrivateData, min_clamp0(length, string.Length()));
    450448    return *this;
    451449}
    452450
    453451
    454 // Prepend
    455452BString&
    456453BString::Prepend(char c, int32 count)
    457454{
    458     if (count > 0 && _OpenAtBy(0, count))
     455    if (count > 0 && _DoPrepend("", count))
    459456        memset(fPrivateData, c, count);
    460    
    461457    return *this;
    462458}
    463459
     
    466462
    467463
    468464BString&
    469 BString::Insert(const char *str, int32 pos)
     465BString::Insert(const char* string, int32 position)
    470466{
    471     if (str != NULL) {
    472         CHECK_PARAM(pos <= Length(), "'pos' exceeds length!");
    473         int32 len = (int32)strlen(str);
    474         if (pos < 0) {
    475             int32 skipLen = min_clamp0(-1 * pos, len);
    476             str += skipLen;
     467    if (string && position <= Length()) {
     468        int32 len = int32(strlen(string));
     469        if (position < 0) {
     470            int32 skipLen = min_clamp0(-1 * position, len);
     471            string += skipLen;
    477472            len -= skipLen;
    478             pos = 0;
    479         } else
    480             pos = min_clamp0(pos, Length());
    481         if (_OpenAtBy(pos, len))
    482             memcpy(fPrivateData + pos, str, len);
     473            position = 0;
     474        } else {
     475            position = min_clamp0(position, Length());
     476        }
     477        _DoInsert(string, position, len);
    483478    }
    484479    return *this;
    485480}
    486481
    487482
    488 // Insert
    489483BString&
    490 BString::Insert(const char *str, int32 length, int32 pos)
     484BString::Insert(const char* string, int32 length, int32 position)
    491485{
    492     if (str != NULL) {
    493         CHECK_PARAM(pos <= Length(), "'pos' exceeds length!");
    494         int32 len = strlen_clamp(str, length);
    495         if (pos < 0) {
    496             int32 skipLen = min_clamp0(-1 * pos, len);
    497             str += skipLen;
     486    if (string && position <= Length()) {
     487        int32 len = strlen_clamp(string, length);
     488        if (position < 0) {
     489            int32 skipLen = min_clamp0(-1 * position, len);
     490            string += skipLen;
    498491            len -= skipLen;
    499             pos = 0;
    500         } else
    501             pos = min_clamp0(pos, Length());
    502         if (_OpenAtBy(pos, len))
    503             memcpy(fPrivateData + pos, str, len);
     492            position = 0;
     493        } else {
     494            position = min_clamp0(position, Length());
     495        }
     496        _DoInsert(string, position, len);
    504497    }
    505498    return *this;
    506499}
    507500
    508501
    509 // Insert
    510502BString&
    511 BString::Insert(const char *str, int32 fromOffset, int32 length, int32 pos)
     503BString::Insert(const char* string, int32 fromOffset, int32 length,
     504                int32 position)
    512505{
    513     CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
    514     return Insert(str + fromOffset, length, pos);
     506    if (string)
     507        Insert(string + fromOffset, length, position);
     508    return *this;
    515509}
    516510
    517511
    518 // Insert
    519512BString&
    520 BString::Insert(const BString &string, int32 pos)
     513BString::Insert(const BString& string, int32 position)
    521514{
    522     if (&string != this)
    523         Insert(string.String(), pos); //TODO: Optimize
    524     return *this;                 
     515    if ((fPrivateData != string.fPrivateData) && string.Length() > 0)
     516        Insert(string.fPrivateData, position);
     517    return *this;
    525518}
    526519
    527520
    528 // Insert
    529521BString&
    530 BString::Insert(const BString &string, int32 length, int32 pos)
     522BString::Insert(const BString& string, int32 length,
     523                int32 position)
    531524{
    532     if (&string != this)
    533         Insert(string.String(), length, pos); //TODO: Optimize
     525    if ((fPrivateData != string.fPrivateData) && string.Length() > 0)
     526        Insert(string.String(), length, position);
    534527    return *this;
    535528}
    536529
    537530
    538 // Insert
    539531BString&
    540 BString::Insert(const BString &string, int32 fromOffset, int32 length, int32 pos)
     532BString::Insert(const BString& string, int32 fromOffset,
     533                int32 length, int32 position)
    541534{
    542     if (&string != this) {
    543         CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
    544         Insert(string.String() + fromOffset, length, pos);
    545     }
     535    if ((fPrivateData != string.fPrivateData) && string.Length() > 0)
     536        Insert(string.String() + fromOffset, length, position);
    546537    return *this;
    547538}
    548539
    549540
    550 // Insert
    551541BString&
    552 BString::Insert(char c, int32 count, int32 pos)
     542BString::Insert(char c, int32 count, int32 position)
    553543{
    554     CHECK_PARAM(pos <= Length(), "'pos' exceeds length!");
    555     if (pos < 0) {
    556         count = max_c(count + pos, 0);
    557         pos = 0;
     544    if (position < 0) {
     545        count = MAX(count + position, 0);
     546        position = 0;
    558547    } else
    559         pos = min_clamp0(pos, Length());
    560    
    561     if (count > 0 && _OpenAtBy(pos, count))
    562         memset(fPrivateData + pos, c, count);
    563    
     548        position = min_clamp0(position, Length());
     549
     550    if (count > 0 && _DoInsert("", position, count))
     551        memset(fPrivateData + position, c, count);
     552
    564553    return *this;
    565554}
    566555
     
    574563    if (newLength < 0)
    575564        newLength = 0;
    576565
    577     int32 curLen = Length();
     566    if (newLength < Length())
     567        // ignore lazy, since we might detach
     568        _DetachWith(fPrivateData, newLength);
    578569
    579     if (newLength < curLen) {
    580         if (lazy) {
    581             // don't free memory yet, just set new length
    582             _SetLength(newLength);
    583             fPrivateData[newLength] = '\0';
    584         } else
    585             _Alloc(newLength);
    586     }
    587 
    588570    return *this;
    589571}
    590572
    591573
    592 // Remove
    593574BString&
    594575BString::Remove(int32 from, int32 length)
    595576{
    596     int32 len = Length();
    597     if (from < 0) {
    598         int32 skipLen = min_clamp0(from, len);
    599         len -= skipLen;
    600         from = 0;
    601     } else
    602         from = min_clamp0(from, len);
    603     _ShrinkAtBy(from, min_clamp0(length, len - from));
     577    if (length > 0 && from < Length())
     578        _ShrinkAtBy(from, min_clamp0(length, (Length() - from)));
    604579    return *this;
    605580}
    606581
    607582
    608 // Remove
    609583BString&
    610 BString::RemoveFirst(const BString &string)
     584BString::RemoveFirst(const BString& string)
    611585{
    612586    if (string.Length() > 0) {
    613587        int32 pos = _ShortFindAfter(string.String(), string.Length());
     
    618592}
    619593
    620594
    621 // Remove
    622595BString&
    623 BString::RemoveLast(const BString &string)
     596BString::RemoveLast(const BString& string)
    624597{
    625598    int32 pos = _FindBefore(string.String(), Length(), string.Length());
    626599    if (pos >= 0)
     
    630603}
    631604
    632605
    633 // Remove
    634606BString&
    635 BString::RemoveAll(const BString &string)
     607BString::RemoveAll(const BString& string)
    636608{
     609    if (string.Length() == 0 || Length() == 0 || FindFirst(string) < 0)
     610        return *this;
     611
     612    if (_Detach() != B_OK)
     613        return *this;
     614
    637615    return _DoReplace(string.String(), "", REPLACE_ALL, 0, KEEP_CASE);
    638616}
    639617
    640618
    641 // Remove
    642619BString&
    643 BString::RemoveFirst(const char *string)
     620BString::RemoveFirst(const char* string)
    644621{
    645622    int32 length = string ? strlen(string) : 0;
    646623    if (length > 0) {
     
    652629}
    653630
    654631
    655 // Remove
    656632BString&
    657 BString::RemoveLast(const char *string)
     633BString::RemoveLast(const char* string)
    658634{
    659635    int32 length = string ? strlen(string) : 0;
    660636    if (length > 0) {
     
    666642}
    667643
    668644
    669 // Remove
    670645BString&
    671 BString::RemoveAll(const char *str)
     646BString::RemoveAll(const char* string)
    672647{
    673     return _DoReplace(str, "", REPLACE_ALL, 0, KEEP_CASE);
     648    if (!string || Length() == 0 || FindFirst(string) < 0)
     649        return *this;
     650
     651    if (_Detach() != B_OK)
     652        return *this;
     653
     654    return _DoReplace(string, "", REPLACE_ALL, 0, KEEP_CASE);
    674655}
    675656
    676657
    677 // Remove
    678658BString&
    679 BString::RemoveSet(const char *setOfCharsToRemove)
     659BString::RemoveSet(const char* setOfCharsToRemove)
    680660{
    681661    return ReplaceSet(setOfCharsToRemove, "");
    682662}
    683663
    684664
    685 // MoveInto
    686665BString&
    687 BString::MoveInto(BString &into, int32 from, int32 length)
     666BString::MoveInto(BString& into, int32 from, int32 length)
    688667{
    689     CHECK_PARAM_RET(from >= 0, "'from' must not be negative!", into);
    690     CHECK_PARAM_RET(from <= Length(), "'from' exceeds length!", into);
    691     int32 len = min_clamp0(length, Length() - from);
    692     if (&into == this) {
    693         /* TODO: [zooey]: to be activated later (>R1):
    694         // strings are identical, just move the data:
    695         if (from>0 && fPrivateData)
    696             memmove( fPrivateData, fPrivateData+from, len);
    697         Truncate( len);
    698         */
    699         return *this;
     668    if (length) {
     669        CopyInto(into, from, length);
     670        Remove(from, length);
    700671    }
    701     into.SetTo(String() + from, len);
    702     _ShrinkAtBy(from, len);
    703 
    704672    return into;
    705673}
    706674
    707675
    708 // MoveInto
    709676void
    710 BString::MoveInto(char *into, int32 from, int32 length)
     677BString::MoveInto(char* into, int32 from, int32 length)
    711678{
    712     if (into != NULL) {
    713         CHECK_PARAM_VOID(from >= 0, "'from' must not be negative!");
    714         CHECK_PARAM_VOID(from <= Length(), "'from' exceeds length!");
    715         int32 len = min_clamp0(length, Length() - from);
    716         memcpy(into, String() + from, len);
    717         into[len] = '\0';
    718         _ShrinkAtBy(from, len);
     679    if (into) {
     680        CopyInto(into, from, length);
     681        Remove(from, length);
    719682    }
    720683}
    721684
    722685
    723 /*---- Compare functions ---------------------------------------------------*/
     686//  #pragma mark - Compare functions
     687
     688
    724689bool
    725 BString::operator<(const char *string) const
     690BString::operator<(const char* string) const
    726691{
    727692    return strcmp(String(), safestr(string)) < 0;
    728693}
    729694
    730695
    731696bool
    732 BString::operator<=(const char *string) const
     697BString::operator<=(const char* string) const
    733698{
    734699    return strcmp(String(), safestr(string)) <= 0;
    735700}
    736701
    737702
    738703bool
    739 BString::operator==(const char *string) const
     704BString::operator==(const char* string) const
    740705{
    741706    return strcmp(String(), safestr(string)) == 0;
    742707}
    743708
    744709
    745710bool
    746 BString::operator>=(const char *string) const
     711BString::operator>=(const char* string) const
    747712{
    748713    return strcmp(String(), safestr(string)) >= 0;
    749714}
    750715
    751716
    752717bool
    753 BString::operator>(const char *string) const
     718BString::operator>(const char* string) const
    754719{
    755720    return strcmp(String(), safestr(string)) > 0;
    756721}
    757722
    758723
    759 //  #pragma mark - Comparison
     724//  #pragma mark - strcmp()-style compare functions
    760725
    761726
    762727int
    763 BString::Compare(const BString &string) const
     728BString::Compare(const BString& string) const
    764729{
    765730    return strcmp(String(), string.String());
    766731}
    767732
    768733
    769734int
    770 BString::Compare(const char *string) const
     735BString::Compare(const char* string) const
    771736{
    772737    return strcmp(String(), safestr(string));
    773738}
    774739
    775740
    776741int
    777 BString::Compare(const BString &string, int32 n) const
     742BString::Compare(const BString& string, int32 length) const
    778743{
    779     return strncmp(String(), string.String(), n);
     744    return strncmp(String(), string.String(), length);
    780745}
    781746
    782747
    783748int
    784 BString::Compare(const char *string, int32 n) const
     749BString::Compare(const char* string, int32 length) const
    785750{
    786     return strncmp(String(), safestr(string), n);
     751    return strncmp(String(), safestr(string), length);
    787752}
    788753
    789754
    790755int
    791 BString::ICompare(const BString &string) const
     756BString::ICompare(const BString& string) const
    792757{
    793758    return strcasecmp(String(), string.String());
    794759}
    795760
    796761
    797762int
    798 BString::ICompare(const char *str) const
     763BString::ICompare(const char* string) const
    799764{
    800     return strcasecmp(String(), safestr(str));
     765    return strcasecmp(String(), safestr(string));
    801766}
    802767
    803768
    804769int
    805 BString::ICompare(const BString &string, int32 n) const
     770BString::ICompare(const BString& string, int32 length) const
    806771{
    807     return strncasecmp(String(), string.String(), n);
     772    return strncasecmp(String(), string.String(), length);
    808773}
    809774
    810775
    811776int
    812 BString::ICompare(const char *str, int32 n) const
     777BString::ICompare(const char* string, int32 length) const
    813778{
    814     return strncasecmp(String(), safestr(str), n);
     779    return strncasecmp(String(), safestr(string), length);
    815780}
    816781
    817782
     
    819784
    820785
    821786int32
    822 BString::FindFirst(const BString &string) const
     787BString::FindFirst(const BString& string) const
    823788{
    824789    return _ShortFindAfter(string.String(), string.Length());
    825790}
    826791
    827792
    828 // FindFirst
    829793int32
    830 BString::FindFirst(const char *string) const
     794BString::FindFirst(const char* string) const
    831795{
    832796    if (string == NULL)
    833797        return B_BAD_VALUE;
     
    836800}
    837801
    838802
    839 // FindFirst
    840803int32
    841 BString::FindFirst(const BString &string, int32 fromOffset) const
     804BString::FindFirst(const BString& string, int32 fromOffset) const
    842805{
    843806    if (fromOffset < 0)
    844807        return B_ERROR;
     
    848811}
    849812
    850813
    851 // FindFirst
    852814int32
    853 BString::FindFirst(const char *string, int32 fromOffset) const
     815BString::FindFirst(const char* string, int32 fromOffset) const
    854816{
    855817    if (string == NULL)
    856818        return B_BAD_VALUE;
     819
    857820    if (fromOffset < 0)
    858821        return B_ERROR;
    859822
    860823    return _FindAfter(string, min_clamp0(fromOffset, Length()),
    861         strlen(string));
     824        strlen(safestr(string)));
    862825}
    863826
    864827
    865 // FindFirst
    866828int32
    867829BString::FindFirst(char c) const
    868 {   
     830{
    869831    const char *start = String();
    870832    const char *end = String() + Length();
    871833
    872     /* Scans the string until we find the character, */
    873     /* or we hit the string's end */
     834    // Scans the string until we found the
     835    // character, or we reach the string's start
    874836    while (start != end && *start != c) {
    875837        start++;
    876838    }
     
    882844}
    883845
    884846
    885 // FindFirst
    886847int32
    887848BString::FindFirst(char c, int32 fromOffset) const
    888849{
     
    892853    const char *start = String() + min_clamp0(fromOffset, Length());
    893854    const char *end = String() + Length();
    894855
    895     /* Scans the string until we found the character, */
    896     /* or we hit the string's end */
     856    // Scans the string until we found the
     857    // character, or we reach the string's start
    897858    while (start < end && *start != c) {
    898859        start++;
    899860    }
     
    905866}
    906867
    907868
    908 // FindLast
    909869int32
    910 BString::FindLast(const BString &string) const
     870BString::FindLast(const BString& string) const
    911871{
    912872    return _FindBefore(string.String(), Length(), string.Length());
    913873}
    914874
    915875
    916 // FindLast
    917876int32
    918 BString::FindLast(const char *string) const
     877BString::FindLast(const char* string) const
    919878{
    920879    if (string == NULL)
    921880        return B_BAD_VALUE;
    922881
    923     return _FindBefore(string, Length(), strlen(string));
     882    return _FindBefore(string, Length(), strlen(safestr(string)));
    924883}
    925884
    926885
    927 // FindLast
    928886int32
    929 BString::FindLast(const BString &string, int32 beforeOffset) const
     887BString::FindLast(const BString& string, int32 beforeOffset) const
    930888{
    931889    if (beforeOffset < 0)
    932890        return B_ERROR;
    933891
    934     return _FindBefore(string.String(), min_clamp0(beforeOffset, Length()), 
    935         string.Length()); 
     892    return _FindBefore(string.String(), min_clamp0(beforeOffset, Length()),
     893        string.Length());
    936894}
    937895
    938896
    939 // FindLast
    940897int32
    941 BString::FindLast(const char *string, int32 beforeOffset) const
     898BString::FindLast(const char* string, int32 beforeOffset) const
    942899{
    943900    if (string == NULL)
    944901        return B_BAD_VALUE;
     902
    945903    if (beforeOffset < 0)
    946904        return B_ERROR;
    947905
    948     return _FindBefore(string, min_clamp0(beforeOffset, Length()), strlen(string));
     906    return _FindBefore(string, min_clamp0(beforeOffset, Length()),
     907        strlen(safestr(string)));
    949908}
    950909
    951910
    952 // FindLast
    953911int32
    954912BString::FindLast(char c) const
    955913{
    956914    const char *start = String();
    957915    const char *end = String() + Length();
    958916
    959     /* Scans the string backwards until we found the character, */
    960     /* or we reach the string's start */
     917    // Scans the string backwards until we found
     918    // the character, or we reach the string's start
    961919    while (end != start && *end != c) {
    962920        end--;
    963921    }
     
    969927}
    970928
    971929
    972 // FindLast
    973930int32
    974931BString::FindLast(char c, int32 beforeOffset) const
    975932{
     
    979936    const char *start = String();
    980937    const char *end = String() + min_clamp0(beforeOffset, Length());
    981938
    982     /* Scans the string backwards until we found the character, */
    983     /* or we reach the string's start */
     939    // Scans the string backwards until we found
     940    // the character, or we reach the string's start
    984941    while (end > start && *end != c) {
    985942        end--;
    986943    }
     
    993950
    994951
    995952int32
    996 BString::IFindFirst(const BString &string) const
     953BString::IFindFirst(const BString& string) const
    997954{
    998955    return _IFindAfter(string.String(), 0, string.Length());
    999956}
    1000957
    1001958
    1002959int32
    1003 BString::IFindFirst(const char *string) const
     960BString::IFindFirst(const char* string) const
    1004961{
    1005962    if (string == NULL)
    1006963        return B_BAD_VALUE;
    1007964
    1008     return _IFindAfter(string, 0, strlen(string));
     965    return _IFindAfter(string, 0, strlen(safestr(string)));
    1009966}
    1010967
    1011968
    1012969int32
    1013 BString::IFindFirst(const BString &string, int32 fromOffset) const
     970BString::IFindFirst(const BString& string, int32 fromOffset) const
    1014971{
    1015972    if (fromOffset < 0)
    1016973        return B_ERROR;
    1017974
    1018     return _IFindAfter(string.String(), min_clamp0(fromOffset, Length()), 
     975    return _IFindAfter(string.String(), min_clamp0(fromOffset, Length()),
    1019976        string.Length());
    1020977}
    1021978
    1022979
    1023980int32
    1024 BString::IFindFirst(const char *string, int32 fromOffset) const
     981BString::IFindFirst(const char* string, int32 fromOffset) const
    1025982{
    1026983    if (string == NULL)
    1027984        return B_BAD_VALUE;
     985
    1028986    if (fromOffset < 0)
    1029987        return B_ERROR;
    1030988
    1031     return _IFindAfter(string, min_clamp0(fromOffset,Length()), strlen(string));
     989    return _IFindAfter(string, min_clamp0(fromOffset,Length()),
     990        strlen(safestr(string)));
    1032991}
    1033992
    1034993
    1035994int32
    1036 BString::IFindLast(const BString &string) const
     995BString::IFindLast(const BString& string) const
    1037996{
    1038997    return _IFindBefore(string.String(), Length(), string.Length());
    1039998}
    1040999
    10411000
    10421001int32
    1043 BString::IFindLast(const char *string) const
     1002BString::IFindLast(const char* string) const
    10441003{
    10451004    if (string == NULL)
    10461005        return B_BAD_VALUE;
    10471006
    1048     return _IFindBefore(string, Length(), strlen(string));
     1007    return _IFindBefore(string, Length(), strlen(safestr(string)));
    10491008}
    10501009
    10511010
    10521011int32
    1053 BString::IFindLast(const BString &string, int32 beforeOffset) const
     1012BString::IFindLast(const BString& string, int32 beforeOffset) const
    10541013{
    10551014    if (beforeOffset < 0)
    10561015        return B_ERROR;
    10571016
    1058     return _IFindBefore(string.String(), min_clamp0(beforeOffset, Length()), 
     1017    return _IFindBefore(string.String(), min_clamp0(beforeOffset, Length()),
    10591018        string.Length());
    10601019}
    10611020
    10621021
    10631022int32
    1064 BString::IFindLast(const char *string, int32 beforeOffset) const
     1023BString::IFindLast(const char* string, int32 beforeOffset) const
    10651024{
    10661025    if (string == NULL)
    10671026        return B_BAD_VALUE;
     1027
    10681028    if (beforeOffset < 0)
    10691029        return B_ERROR;
    10701030
    10711031    return _IFindBefore(string, min_clamp0(beforeOffset, Length()),
    1072         strlen(string));
     1032        strlen(safestr(string)));
    10731033}
    10741034
    10751035
     
    10801040BString::ReplaceFirst(char replaceThis, char withThis)
    10811041{
    10821042    int32 pos = FindFirst(replaceThis);
    1083     if (pos >= 0)
     1043    if (pos >= 0 && _Detach() == B_OK)
    10841044        fPrivateData[pos] = withThis;
    1085 
    10861045    return *this;
    10871046}
    10881047
     
    10911050BString::ReplaceLast(char replaceThis, char withThis)
    10921051{
    10931052    int32 pos = FindLast(replaceThis);
    1094     if (pos >= 0)
     1053    if (pos >= 0 && _Detach() == B_OK)
    10951054        fPrivateData[pos] = withThis;
    1096 
    10971055    return *this;
    10981056}
    10991057
     
    11011059BString&
    11021060BString::ReplaceAll(char replaceThis, char withThis, int32 fromOffset)
    11031061{
    1104     CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
    1105     for (int32 pos = min_clamp0(fromOffset, Length());;) {
    1106         pos = FindFirst(replaceThis, pos);
    1107         if (pos < 0)
    1108             break;
     1062    fromOffset = min_clamp0(fromOffset, Length());
     1063    int32 pos = FindFirst(replaceThis, fromOffset);
     1064
     1065    // detach and set first match
     1066    if (pos >= 0 && _Detach() == B_OK) {
    11091067        fPrivateData[pos] = withThis;
     1068        for (pos = pos;;) {
     1069            pos = FindFirst(replaceThis, pos);
     1070            if (pos < 0)
     1071                break;
     1072            fPrivateData[pos] = withThis;
     1073        }
    11101074    }
    1111 
    11121075    return *this;
    11131076}
    11141077
    11151078
    11161079BString&
    1117 BString::Replace(char replaceThis, char withThis, int32 maxReplaceCount, int32 fromOffset)
     1080BString::Replace(char replaceThis, char withThis, int32 maxReplaceCount,
     1081                 int32 fromOffset)
    11181082{
    1119     CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
    1120     if (maxReplaceCount > 0) {
    1121         for (int32 pos = min_clamp0(fromOffset, Length());
    1122                     maxReplaceCount > 0; maxReplaceCount--) {
     1083    fromOffset = min_clamp0(fromOffset, Length());
     1084    int32 pos = FindFirst(replaceThis, fromOffset);
     1085
     1086    if (maxReplaceCount > 0 && pos >= 0 && _Detach() == B_OK) {
     1087        maxReplaceCount--;
     1088        fPrivateData[pos] = withThis;
     1089        for (pos = pos;  maxReplaceCount > 0; maxReplaceCount--) {
    11231090            pos = FindFirst(replaceThis, pos);
    11241091            if (pos < 0)
    11251092                break;
     
    11311098
    11321099
    11331100BString&
    1134 BString::ReplaceFirst(const char *replaceThis, const char *withThis)
     1101BString::ReplaceFirst(const char* replaceThis, const char* withThis)
    11351102{
    1136     return _DoReplace( replaceThis, withThis, 1, 0, KEEP_CASE);
     1103    if (!replaceThis || !withThis || FindFirst(replaceThis) < 0)
     1104        return *this;
     1105
     1106    if (_Detach() != B_OK)
     1107        return *this;
     1108
     1109    return _DoReplace(replaceThis, withThis, 1, 0, KEEP_CASE);
    11371110}
    11381111
    11391112
    11401113BString&
    1141 BString::ReplaceLast(const char *replaceThis, const char *withThis)
     1114BString::ReplaceLast(const char* replaceThis, const char* withThis)
    11421115{
    1143     if (replaceThis == NULL)
     1116    if (!replaceThis || !withThis)
    11441117        return *this;
    1145        
    1146     int32 firstStringLength = strlen(replaceThis); 
    1147     int32 pos = _FindBefore(replaceThis, Length(), firstStringLength);
    1148    
     1118
     1119    int32 replaceThisLength = strlen(replaceThis);
     1120    int32 pos = _FindBefore(replaceThis, Length(), replaceThisLength);
     1121
    11491122    if (pos >= 0) {
    1150         int32 len = (withThis ? strlen(withThis) : 0);
    1151         int32 difference = len - firstStringLength;
    1152        
     1123        int32 withThisLength =  strlen(withThis);
     1124        int32 difference = withThisLength - replaceThisLength;
     1125
    11531126        if (difference > 0) {
    11541127            if (!_OpenAtBy(pos, difference))
    11551128                return *this;
    11561129        } else if (difference < 0) {
    11571130            if (!_ShrinkAtBy(pos, -difference))
    11581131                return *this;
     1132        } else {
     1133            if (_Detach() != B_OK)
     1134                return *this;
    11591135        }
    1160         memcpy(fPrivateData + pos, withThis, len);
     1136        memcpy(fPrivateData + pos, withThis, withThisLength);
    11611137    }
    1162        
     1138
    11631139    return *this;
    11641140}
    11651141
    11661142
    11671143BString&
    1168 BString::ReplaceAll(const char *replaceThis, const char *withThis, int32 fromOffset)
     1144BString::ReplaceAll(const char* replaceThis, const char* withThis,
     1145                    int32 fromOffset)
    11691146{
    1170     CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
     1147    if (!replaceThis || !withThis || FindFirst(replaceThis) < 0)
     1148        return *this;
     1149
     1150    if (_Detach() != B_OK)
     1151        return *this;
     1152
    11711153    return _DoReplace(replaceThis, withThis, REPLACE_ALL,
    1172         min_clamp0(fromOffset,Length()), KEEP_CASE);
     1154        min_clamp0(fromOffset, Length()), KEEP_CASE);
    11731155}
    11741156
    11751157
    11761158BString&
    1177 BString::Replace(const char *replaceThis, const char *withThis, int32 maxReplaceCount, int32 fromOffset)
     1159BString::Replace(const char* replaceThis, const char* withThis,
     1160                 int32 maxReplaceCount, int32 fromOffset)
    11781161{
    1179     CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
     1162    if (!replaceThis || !withThis || maxReplaceCount <= 0
     1163        || FindFirst(replaceThis) < 0)
     1164        return *this;
     1165
     1166    if (_Detach() != B_OK)
     1167        return *this;
     1168
    11801169    return _DoReplace(replaceThis, withThis, maxReplaceCount,
    1181         min_clamp0(fromOffset,Length()), KEEP_CASE);
     1170        min_clamp0(fromOffset, Length()), KEEP_CASE);
    11821171}
    11831172
    11841173
     
    11881177    char tmp[2] = { replaceThis, '\0' };
    11891178
    11901179    int32 pos = _IFindAfter(tmp, 0, 1);
    1191     if (pos >= 0)
     1180    if (pos >= 0 && _Detach() == B_OK)
    11921181        fPrivateData[pos] = withThis;
    1193 
    11941182    return *this;
    11951183}
    11961184
     
    12011189    char tmp[2] = { replaceThis, '\0' };
    12021190
    12031191    int32 pos = _IFindBefore(tmp, Length(), 1);
    1204     if (pos >= 0)
     1192    if (pos >= 0 && _Detach() == B_OK)
    12051193        fPrivateData[pos] = withThis;
    1206    
    12071194    return *this;
    12081195}
    12091196
     
    12111198BString&
    12121199BString::IReplaceAll(char replaceThis, char withThis, int32 fromOffset)
    12131200{
    1214     CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
    1215 
    12161201    char tmp[2] = { replaceThis, '\0' };
     1202    fromOffset = min_clamp0(fromOffset, Length());
     1203    int32 pos = _IFindAfter(tmp, fromOffset, 1);
    12171204
    1218     for (int32 pos = min_clamp0(fromOffset, Length());;) {
    1219         pos = _IFindAfter(tmp, pos, 1);
    1220         if (pos < 0)
    1221             break;
     1205    if (pos >= 0 && _Detach() == B_OK) {
    12221206        fPrivateData[pos] = withThis;
     1207        for (pos = pos;;) {
     1208            pos = _IFindAfter(tmp, pos, 1);
     1209            if (pos < 0)
     1210                break;
     1211            fPrivateData[pos] = withThis;
     1212        }
    12231213    }
    12241214    return *this;
    12251215}
    12261216
    12271217
    12281218BString&
    1229 BString::IReplace(char replaceThis, char withThis, int32 maxReplaceCount, int32 fromOffset)
     1219BString::IReplace(char replaceThis, char withThis, int32 maxReplaceCount,
     1220                  int32 fromOffset)
    12301221{
    1231     CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
     1222    char tmp[2] = { replaceThis, '\0' };
     1223    fromOffset = min_clamp0(fromOffset, Length());
     1224    int32 pos = _IFindAfter(tmp, fromOffset, 1);
    12321225
    1233     char tmp[2] = { replaceThis, '\0' };
    1234    
    1235     if (fPrivateData == NULL)
    1236         return *this;
    1237        
    1238     for (int32 pos = min_clamp0(fromOffset,Length());
    1239             maxReplaceCount > 0;   maxReplaceCount--) {
    1240         pos = _IFindAfter(tmp, pos, 1);
    1241         if (pos < 0)
    1242             break;
     1226    if (maxReplaceCount > 0 && pos >= 0 && _Detach() == B_OK) {
    12431227        fPrivateData[pos] = withThis;
     1228        maxReplaceCount--;
     1229        for (pos = pos;  maxReplaceCount > 0; maxReplaceCount--) {
     1230            pos = _IFindAfter(tmp, pos, 1);
     1231            if (pos < 0)
     1232                break;
     1233            fPrivateData[pos] = withThis;
     1234        }
    12441235    }
     1236
    12451237    return *this;
    12461238}
    12471239
    12481240
    12491241BString&
    1250 BString::IReplaceFirst(const char *replaceThis, const char *withThis)
     1242BString::IReplaceFirst(const char* replaceThis, const char* withThis)
    12511243{
     1244    if (!replaceThis || !withThis || IFindFirst(replaceThis) < 0)
     1245        return *this;
     1246
     1247    if (_Detach() != B_OK)
     1248        return *this;
    12521249    return _DoReplace(replaceThis, withThis, 1, 0, IGNORE_CASE);
    12531250}
    12541251
    12551252
    12561253BString&
    1257 BString::IReplaceLast(const char *replaceThis, const char *withThis)
     1254BString::IReplaceLast(const char* replaceThis, const char* withThis)
    12581255{
    1259     if (replaceThis == NULL)
     1256    if (!replaceThis || !withThis)
    12601257        return *this;
    12611258
    1262     int32 firstStringLength = strlen(replaceThis);     
    1263     int32 pos = _IFindBefore(replaceThis, Length(), firstStringLength);
     1259    int32 replaceThisLength = strlen(replaceThis);
     1260    int32 pos = _IFindBefore(replaceThis, Length(), replaceThisLength);
    12641261
    12651262    if (pos >= 0) {
    1266         int32 len = (withThis ? strlen(withThis) : 0);
    1267         int32 difference = len - firstStringLength;
     1263        int32 withThisLength = strlen(withThis);
     1264        int32 difference = withThisLength - replaceThisLength;
    12681265
    12691266        if (difference > 0) {
    12701267            if (!_OpenAtBy(pos, difference))
     
    12721269        } else if (difference < 0) {
    12731270            if (!_ShrinkAtBy(pos, -difference))
    12741271                return *this;
     1272        } else {
     1273            if (_Detach() != B_OK)
     1274                return *this;
    12751275        }
    1276         memcpy(fPrivateData + pos, withThis, len);
     1276        memcpy(fPrivateData + pos, withThis, withThisLength);
    12771277    }
    12781278
    12791279    return *this;
     
    12811281
    12821282
    12831283BString&
    1284 BString::IReplaceAll(const char *replaceThis, const char *withThis, int32 fromOffset)
     1284BString::IReplaceAll(const char* replaceThis, const char* withThis,
     1285                     int32 fromOffset)
    12851286{
    1286     CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
     1287    if (!replaceThis || !withThis || IFindFirst(replaceThis) < 0)
     1288        return *this;
     1289
     1290    if (_Detach() != B_OK)
     1291        return *this;
     1292
    12871293    return _DoReplace(replaceThis, withThis, REPLACE_ALL,
    12881294        min_clamp0(fromOffset, Length()), IGNORE_CASE);
    12891295}
    12901296
    12911297
    12921298BString&
    1293 BString::IReplace(const char *replaceThis, const char *withThis,
    1294     int32 maxReplaceCount, int32 fromOffset)
     1299BString::IReplace(const char* replaceThis, const char* withThis,
     1300                  int32 maxReplaceCount, int32 fromOffset)
    12951301{
    1296     CHECK_PARAM(fromOffset >= 0, "'fromOffset' must not be negative!");
     1302    if (!replaceThis || !withThis || maxReplaceCount <= 0
     1303        || FindFirst(replaceThis) < 0)
     1304        return *this;
     1305
     1306    if (_Detach() != B_OK)
     1307        return *this;
     1308
    12971309    return _DoReplace(replaceThis, withThis, maxReplaceCount,
    12981310        min_clamp0(fromOffset, Length()), IGNORE_CASE);
    12991311}
    13001312
    13011313
    13021314BString&
    1303 BString::ReplaceSet(const char *setOfChars, char with)
     1315BString::ReplaceSet(const char* setOfChars, char with)
    13041316{
    1305     if (setOfChars == NULL)
     1317    if (!setOfChars || strcspn(fPrivateData, setOfChars) >= uint32(Length()))
    13061318        return *this;
    13071319
     1320    if (_Detach() != B_OK)
     1321        return *this;
     1322
    13081323    int32 offset = 0;
    13091324    int32 length = Length();
    1310 
    13111325    for (int32 pos;;) {
    1312         pos = strcspn(String() + offset, setOfChars);
     1326        pos = strcspn(fPrivateData + offset, setOfChars);
    13131327
    13141328        offset += pos;
    13151329        if (offset >= length)
     
    13241338
    13251339
    13261340BString&
    1327 BString::ReplaceSet(const char *setOfChars, const char *with)
     1341BString::ReplaceSet(const char* setOfChars, const char* with)
    13281342{
    1329     int32 withLen = with ? strlen(with) : 0;
    1330     if (withLen == 1) {
    1331         // delegate simple case:
     1343    if (!setOfChars || !with
     1344        || strcspn(fPrivateData, setOfChars) >= uint32(Length()))
     1345        return *this;
     1346
     1347    // delegate simple case
     1348    int32 withLen = strlen(with);
     1349    if (withLen == 1)
    13321350        return ReplaceSet(setOfChars, *with);
    1333     }
    13341351
    1335     if (setOfChars == NULL || fPrivateData == NULL)
     1352    if (_Detach() != B_OK)
    13361353        return *this;
    13371354
    1338     PosVect positions;
    1339 
     1355    int32 pos = 0;
    13401356    int32 searchLen = 1;
    13411357    int32 len = Length();
    1342     int32 pos = 0;
    1343     for (int32 offset = 0; offset < len; offset += (pos+searchLen)) {
     1358
     1359    PosVect positions;
     1360    for (int32 offset = 0; offset < len; offset += (pos + searchLen)) {
    13441361        pos = strcspn(fPrivateData + offset, setOfChars);
    13451362        if (pos + offset >= len)
    13461363            break;
     
    13481365            return *this;
    13491366    }
    13501367
    1351     _ReplaceAtPositions(&positions, searchLen, with, withLen); 
     1368    _ReplaceAtPositions(&positions, searchLen, with, withLen);
    13521369    return *this;
    13531370}
    13541371
    13551372
    1356 /*---- Unchecked char access -----------------------------------------------*/
     1373//  #pragma mark - Unchecked char access
    13571374
    1358 // operator[]
    1359 char &
     1375
     1376#if __GNUC__ > 3
     1377BStringRef
    13601378BString::operator[](int32 index)
    13611379{
     1380    return BStringRef(*this, index);
     1381}
     1382#else
     1383char&
     1384BString::operator[](int32 index)
     1385{
     1386    _Detach();
     1387    _SetReferenceCount(-1);
     1388
    13621389    return fPrivateData[index];
    13631390}
     1391#endif
    13641392
    13651393
    1366 /*---- Fast low-level manipulation -----------------------------------------*/
     1394//  #pragma mark - Fast low-level manipulation
     1395
     1396
    13671397char*
    13681398BString::LockBuffer(int32 maxLength)
    13691399{
    1370     _SetUsingAsCString(true);
     1400    int32 length = Length();
     1401    if (maxLength > length)
     1402        length += maxLength - length;
    13711403
    1372     int32 len = Length();
    1373 
    1374     if (maxLength > len) {
    1375         if (!_GrowBy(maxLength - len))
    1376             return NULL;
    1377         if (!len && fPrivateData)
    1378             // if string was empty before call to LockBuffer(), we make sure the
    1379             // buffer represents an empty c-string:
    1380             *fPrivateData = '\0';
    1381     } else if (!maxLength && !len) {
    1382         // special case for unallocated string, we return an empty c-string:
    1383         return const_cast<char*>(String());
    1384     }
    1385 
     1404    _DetachWith(fPrivateData, length);
    13861405    return fPrivateData;
    13871406}
    13881407
     
    13901409BString&
    13911410BString::UnlockBuffer(int32 length)
    13921411{
    1393     _SetUsingAsCString(false);
    1394 
    1395     if (length < 0)
     1412    if (length > 0) {
     1413        if (length)
     1414            length = min_clamp0(length, Length());
     1415    } else {
    13961416        length = (fPrivateData == NULL) ? 0 : strlen(fPrivateData);
     1417    }
    13971418
    1398     if (length != Length())
    1399         _GrowBy(length - Length());
     1419    _Realloc(length);
     1420    fPrivateData[length] = '\0';
    14001421
    14011422    return *this;
    14021423}
    14031424
    14041425
    1405 /*---- Uppercase<->Lowercase ------------------------------------------------*/
    1406 // ToLower
     1426//  #pragma mark - Uppercase <-> Lowercase
     1427
     1428
    14071429BString&
    14081430BString::ToLower()
    14091431{
    14101432    int32 length = Length();
    1411     for (int32 count = 0; count < length; count++) {
    1412         fPrivateData[count] = tolower(fPrivateData[count]);
     1433    if (length > 0 && _Detach() == B_OK) {
     1434        for (int32 count = 0; count < length; count++)
     1435            fPrivateData[count] = tolower(fPrivateData[count]);
    14131436    }
    1414 
    14151437    return *this;
    14161438}
    14171439
    14181440
    1419 // ToUpper
    14201441BString&
    14211442BString::ToUpper()
    1422 {           
     1443{
    14231444    int32 length = Length();
    1424     for (int32 count = 0; count < length; count++) {
    1425         fPrivateData[count] = toupper(fPrivateData[count]);
     1445    if (length > 0 && _Detach() == B_OK) {
     1446        for (int32 count = 0; count < length; count++)
     1447            fPrivateData[count] = toupper(fPrivateData[count]);
    14261448    }
    1427 
    14281449    return *this;
    14291450}
    14301451
    14311452
    1432 // Capitalize
    14331453BString&
    14341454BString::Capitalize()
    14351455{
    1436     if (fPrivateData == NULL)
    1437         return *this;
    1438 
    1439     fPrivateData[0] = toupper(fPrivateData[0]);
    14401456    int32 length = Length();
    14411457
    1442     for (int32 count = 1; count < length; count++) {
    1443         fPrivateData[count] = tolower(fPrivateData[count]);
     1458    if (length > 0 && _Detach() == B_OK) {
     1459        fPrivateData[0] = toupper(fPrivateData[0]);
     1460        for (int32 count = 1; count < length; count++)
     1461            fPrivateData[count] = tolower(fPrivateData[count]);
    14441462    }
    1445 
    14461463    return *this;
    14471464}
    14481465
    14491466
    1450 // CapitalizeEachWord
    14511467BString&
    14521468BString::CapitalizeEachWord()
    14531469{
    1454     if (fPrivateData == NULL)
    1455         return *this;
    1456        
    1457     int32 count = 0;
    14581470    int32 length = Length();
    1459        
    1460     do {
    1461         // Find the first alphabetical character...
    1462         for (; count < length; count++) {
    1463             if (isalpha(fPrivateData[count])) {
    1464                 // ...found! Convert it to uppercase.
    1465                 fPrivateData[count] = toupper(fPrivateData[count]);
    1466                 count++;
    1467                 break;
     1471
     1472    if (length > 0 && _Detach() == B_OK) {
     1473        int32 count = 0;
     1474        do {
     1475            // Find the first alphabetical character...
     1476            for (; count < length; count++) {
     1477                if (isalpha(fPrivateData[count])) {
     1478                    // ...found! Convert it to uppercase.
     1479                    fPrivateData[count] = toupper(fPrivateData[count]);
     1480                    count++;
     1481                    break;
     1482                }
    14681483            }
    1469         }
    14701484
    1471         // Now find the first non-alphabetical character,
    1472         // and meanwhile, turn to lowercase all the alphabetical ones
    1473         for (; count < length; count++) {
    1474             if (isalpha(fPrivateData[count]))
    1475                 fPrivateData[count] = tolower(fPrivateData[count]);
    1476             else
    1477                 break;
    1478         }
    1479     } while (count < length);
    1480 
     1485            // Now find the first non-alphabetical character,
     1486            // and meanwhile, turn to lowercase all the alphabetical ones
     1487            for (; count < length; count++) {
     1488                if (isalpha(fPrivateData[count]))
     1489                    fPrivateData[count] = tolower(fPrivateData[count]);
     1490                else
     1491                    break;
     1492            }
     1493        } while (count < length);
     1494    }
    14811495    return *this;
    14821496}
    14831497
    14841498
    1485 /*----- Escaping and Deescaping --------------------------------------------*/
     1499//  #pragma mark - Escaping and De-escaping
     1500
     1501
    14861502BString&
    1487 BString::CharacterEscape(const char *original, const char *setOfCharsToEscape,
    1488     char escapeWith)
     1503BString::CharacterEscape(const char* original,
     1504                         const char* setOfCharsToEscape, char escapeWith)
    14891505{
    1490     SetTo(original);
    1491     CharacterEscape(setOfCharsToEscape, escapeWith);
    1492 
     1506    if (setOfCharsToEscape)
     1507        _DoCharacterEscape(original, setOfCharsToEscape, escapeWith);
    14931508    return *this;
    14941509}
    14951510
    14961511
    14971512BString&
    1498 BString::CharacterEscape(const char *setOfCharsToEscape, char escapeWith)
     1513BString::CharacterEscape(const char* setOfCharsToEscape, char escapeWith)
    14991514{
    1500     if (setOfCharsToEscape == NULL || fPrivateData == NULL)
    1501         return *this;
    1502 
    1503     PosVect positions;
    1504     int32 len = Length();
    1505     int32 pos = 0;
    1506     for (int32 offset = 0; offset < len; offset += pos + 1) {
    1507         if ((pos = strcspn(fPrivateData + offset, setOfCharsToEscape)) < len - offset) {
    1508             if (!positions.Add(offset + pos))
    1509                 return *this;
    1510         }
    1511     }
    1512 
    1513     uint32 count = positions.CountItems();
    1514     int32 newLength = len + count;
    1515     if (!newLength) {
    1516         _Alloc(0);
    1517         return *this;
    1518     }
    1519 
    1520     int32 lastPos = 0;
    1521     char* oldAdr = fPrivateData;
    1522     char* newData = (char*)malloc(newLength + sizeof(int32) + 1);
    1523     if (newData) {
    1524         newData += sizeof(int32);
    1525         char* newAdr = newData;
    1526         for (uint32 i = 0; i < count; ++i) {
    1527             pos = positions.ItemAt( i);
    1528             len = pos-lastPos;
    1529             if (len > 0) {
    1530                 memcpy(newAdr, oldAdr, len);
    1531                 oldAdr += len;
    1532                 newAdr += len;
    1533             }
    1534             *newAdr++ = escapeWith;
    1535             *newAdr++ = *oldAdr++;
    1536             lastPos = pos + 1;
    1537         }
    1538         len = Length() + 1 - lastPos;
    1539         if (len > 0)
    1540             memcpy(newAdr, oldAdr, len);
    1541 
    1542         free(fPrivateData - sizeof(int32));
    1543         fPrivateData = newData;
    1544         fPrivateData[newLength] = 0;
    1545         _SetLength( newLength);
    1546     }
    1547 
     1515    if (setOfCharsToEscape && Length() > 0)
     1516        _DoCharacterEscape(fPrivateData, setOfCharsToEscape, escapeWith);
    15481517    return *this;
    15491518}
    15501519
    15511520
    15521521BString&
    1553 BString::CharacterDeescape(const char *original, char escapeChar)
     1522BString::CharacterDeescape(const char* original, char escapeChar)
    15541523{
    1555     SetTo(original);   
    1556     CharacterDeescape(escapeChar);
    1557 
    1558     return *this;
     1524    return _DoCharacterDeescape(original, escapeChar);
    15591525}
    15601526
    15611527
    15621528BString&
    15631529BString::CharacterDeescape(char escapeChar)
    15641530{
    1565     const char temp[2] = {escapeChar, 0};
    1566     return _DoReplace(temp, "", REPLACE_ALL, 0, KEEP_CASE);
     1531    if (Length() > 0)
     1532        _DoCharacterDeescape(fPrivateData, escapeChar);
     1533    return *this;
    15671534}
    15681535
    15691536
    1570 /*---- Simple sprintf replacement calls ------------------------------------*/
    1571 /*---- Slower than sprintf but type and overflow safe ----------------------*/
     1537//  #pragma mark - Insert
     1538
     1539
    15721540BString&
    1573 BString::operator<<(const char *str)
     1541BString::operator<<(const char* string)
    15741542{
    1575     if (str != NULL)
    1576         _DoAppend(str, strlen(str));
    1577     return *this;   
     1543    if (string != NULL)
     1544        _DoAppend(string, strlen(string));
     1545    return *this;
    15781546}
    15791547
    15801548
    15811549BString&
    1582 BString::operator<<(const BString &string)
     1550BString::operator<<(const BString& string)
    15831551{
    1584     _DoAppend(string.String(), string.Length());
     1552    if (string.Length() > 0)
     1553        _DoAppend(string.String(), string.Length());
    15851554    return *this;
    15861555}
    15871556
     
    15891558BString&
    15901559BString::operator<<(char c)
    15911560{
    1592     _DoAppend(&c, 1);   
     1561    _DoAppend(&c, 1);
    15931562    return *this;
    15941563}
    15951564
     
    16741643//  #pragma mark - Private or reserved
    16751644
    16761645
    1677 char *
    1678 BString::_Alloc(int32 dataLength)
     1646status_t
     1647BString::_Detach()
    16791648{
    1680     char *dataPtr = fPrivateData ? fPrivateData - sizeof(int32) : NULL;
    1681     if (dataLength <= 0) {
    1682         // release buffer
    1683 #if 0
    1684         free(dataPtr);
    1685         fPrivateData = NULL;
    1686         return NULL;
    1687 #else
    1688         // TODO: think about removing this work-around again; it lets
    1689         //  BeOS R5 NetPositive run on Haiku - this is obviously ignoring
    1690         //  the fact, that fPrivateData could be NULL at one point
    1691         //  (while building the menus from resources).
    1692         dataLength = 0;
    1693 #endif
     1649    char* newData = fPrivateData;
     1650    if (atomic_get(&(*(((vint32*)fPrivateData - 2)))) > 1) {
     1651        // we share our data with someone else
     1652        if (atomic_add(&(*(((vint32*)fPrivateData) - 2)), -1) < 1) {
     1653            ; // someone else decrement, we are the last owner
     1654        } else {
     1655            // there is still someone who shares our data
     1656            newData = _Clone(fPrivateData, Length());
     1657        }
     1658    } else {
     1659        ; // we don't share our data with someone else
    16941660    }
    16951661
    1696     int32 allocLength = dataLength + sizeof(int32) + 1;
    1697     dataPtr = (char *)realloc(dataPtr, allocLength);
     1662    if (newData)
     1663        fPrivateData = newData;
     1664    return newData != NULL ? B_OK : B_NO_MEMORY;
     1665}
     1666
     1667
     1668char*
     1669BString::_Realloc(int32 length)
     1670{
     1671    if (length == Length())
     1672        return fPrivateData;
     1673
     1674    int32 offset = 2 * sizeof(int32);
     1675    char *dataPtr = fPrivateData ? fPrivateData - offset : NULL;
     1676    if (length < 0)
     1677        length = 0;
     1678
     1679    dataPtr = (char*)realloc(dataPtr, length + offset + 1);
    16981680    if (dataPtr) {
    1699         dataPtr += sizeof(int32);
     1681        dataPtr += offset;
     1682
    17001683        fPrivateData = dataPtr;
     1684        fPrivateData[length] = '\0';
    17011685
    1702         _SetLength(dataLength);
    1703         fPrivateData[dataLength] = '\0';
     1686        _SetLength(length);
     1687        _SetReferenceCount(1);
    17041688    }
    1705 
    17061689    return dataPtr;
    1707 }   
    1708 
    1709 void
    1710 BString::_Init(const char *str, int32 len)
    1711 {
    1712     if (_Alloc(len))
    1713         memcpy(fPrivateData, str, len);
    17141690}
    17151691
    17161692
    1717 #if ENABLE_INLINES
    1718 inline
    1719 #endif
    17201693void
    1721 BString::_DoAssign(const char *str, int32 len)
     1694BString::_Init(const char* src, int32 length)
    17221695{
    1723     int32 curLen = Length();
     1696    fPrivateData = _Clone(src, length);
     1697    if (!fPrivateData) {
     1698        int32 offset = 2 * sizeof(int32);
     1699        fPrivateData = (char *)realloc(fPrivateData, offset + 1);
    17241700
    1725     if (len == curLen || _GrowBy(len - curLen))
    1726         memcpy(fPrivateData, str, len);
     1701        fPrivateData += offset;
     1702        fPrivateData[0] = '\0';
     1703
     1704        _SetLength(0);
     1705        _SetReferenceCount(1);
     1706    }
    17271707}
    17281708
    17291709
    1730 #if ENABLE_INLINES
    1731 inline
    1732 #endif
    1733 void
    1734 BString::_DoAppend(const char *str, int32 len)
     1710char*
     1711BString::_Clone(const char* data, int32 length)
    17351712{
    1736     int32 length = Length();
    1737     if (_GrowBy(len))
    1738         memcpy(fPrivateData + length, str, len);
    1739 }
     1713    char* newData = NULL;
     1714    int32 offset = 2 * sizeof(int32);
     1715    newData = (char *)realloc(newData, length + offset + 1);
    17401716
     1717    if (newData) {
     1718        newData += offset;
     1719        newData[length] = '\0';
    17411720
    1742 char*
    1743 BString::_GrowBy(int32 size)
    1744 {
    1745     return _Alloc(Length() + size);
     1721        *(((vint32*)newData) - 2) = 1;
     1722        *(((int32*)newData) - 1) = length & 0x7fffffff;
     1723
     1724        if (data && length)
     1725            memcpy(newData, data, length);
     1726    }
     1727    return newData;
    17461728}
    17471729
    17481730
     
    17511733{
    17521734    int32 oldLength = Length();
    17531735
    1754     char* newData = _Alloc(oldLength + length);
    1755     if (newData != NULL) {
    1756         memmove(fPrivateData + offset + length, fPrivateData + offset,
    1757             oldLength - offset);
    1758     }
     1736    if (_Detach() != B_OK)
     1737        return NULL;
    17591738
    1760     return newData;
     1739    memmove(fPrivateData + offset + length, fPrivateData + offset,
     1740        oldLength - offset);
     1741    return _Realloc(oldLength + length);
    17611742}
    17621743
    17631744
    17641745char*
    17651746BString::_ShrinkAtBy(int32 offset, int32 length)
    1766 {   
    1767     if (!fPrivateData)
     1747{
     1748    int32 oldLength = Length();
     1749    if (_Detach() != B_OK)
    17681750        return NULL;
    17691751
    1770     int32 oldLength = Length();
    1771 
    17721752    memmove(fPrivateData + offset, fPrivateData + offset + length,
    17731753        oldLength - offset - length);
     1754    return _Realloc(oldLength - length);
     1755}
    17741756
    1775     // the following actually should never fail, since we are reducing the size...
    1776     return _Alloc(oldLength - length);
     1757
     1758status_t
     1759BString::_DetachWith(const char* string, int32 length)
     1760{
     1761    char* newData = NULL;
     1762    if (atomic_get(&(*(((vint32*)fPrivateData) - 2))) > 1) {
     1763        // we share our data with someone else
     1764        if (atomic_add(&(*(((vint32*)fPrivateData) - 2)), -1) < 1) {
     1765            // someone else decrement, we are the last owner
     1766            newData = _Realloc(length);
     1767        } else {
     1768            // there is still someone who shares our data
     1769            newData = _Clone(string, length);
     1770        }
     1771    } else {
     1772        // we don't share our data with someone else
     1773        newData = _Realloc(length);
     1774    }
     1775
     1776    if (newData)
     1777        fPrivateData = newData;
     1778    return newData != NULL ? B_OK : B_NO_MEMORY;
    17771779}
    17781780
    17791781
    1780 #if ENABLE_INLINES
    1781 inline
    1782 #endif
    17831782void
    1784 BString::_DoPrepend(const char *str, int32 count)
     1783BString::_SetLength(int32 length)
    17851784{
    1786     if (_OpenAtBy(0, count))
    1787         memcpy(fPrivateData, str, count);
     1785    *(((int32*)fPrivateData) - 1) = length & 0x7fffffff;
    17881786}
    17891787
    17901788
    1791 /* XXX: These could be inlined too, if they are too slow */
     1789void
     1790BString::_SetReferenceCount(int32 count)
     1791{
     1792    *(((vint32*)fPrivateData) - 2) = count;
     1793}
     1794
     1795
     1796bool
     1797BString::_DoAppend(const char* string, int32 length)
     1798{
     1799    int32 len = Length();
     1800    if (_DetachWith(fPrivateData, len + length) == B_OK) {
     1801        if (string && length)
     1802            memcpy(fPrivateData + len, string, length);
     1803        return true;
     1804    }
     1805    return false;
     1806}
     1807
     1808
     1809bool
     1810BString::_DoPrepend(const char* string, int32 length)
     1811{
     1812    int32 len = Length();
     1813    if (_DetachWith(fPrivateData, len + length) == B_OK) {
     1814        memmove(fPrivateData + length, fPrivateData, len);
     1815        if (string && length)
     1816            memcpy(fPrivateData, string, length);
     1817        return true;
     1818    }
     1819    return false;
     1820}
     1821
     1822
     1823bool
     1824BString::_DoInsert(const char* string, int32 offset, int32 length)
     1825{
     1826    int32 len = Length();
     1827    if (_DetachWith(fPrivateData, len + length) == B_OK) {
     1828        memmove(fPrivateData + offset + length, fPrivateData + offset, len - offset);
     1829        if (string && length)
     1830            memcpy(fPrivateData + offset, string, length);
     1831        return true;
     1832    }
     1833    return false;
     1834}
     1835
     1836
    17921837int32
    1793 BString::_FindAfter(const char *str, int32 offset, int32 strlen) const
    1794 {   
    1795     char *ptr = strstr(String() + offset, str);
     1838BString::_ShortFindAfter(const char* string, int32 len) const
     1839{
     1840    const char *ptr = strstr(String(), string);
    17961841
    17971842    if (ptr != NULL)
    17981843        return ptr - String();
    1799    
     1844
    18001845    return B_ERROR;
    18011846}
    18021847
    18031848
    18041849int32
    1805 BString::_IFindAfter(const char *str, int32 offset, int32 strlen) const
     1850BString::_FindAfter(const char* string, int32 offset, int32 strlen) const
    18061851{
    1807     char *ptr = strcasestr(String() + offset, str);
     1852    const char *ptr = strstr(String() + offset, string);
    18081853
    18091854    if (ptr != NULL)
    18101855        return ptr - String();
     
    18141859
    18151860
    18161861int32
    1817 BString::_ShortFindAfter(const char *str, int32 len) const
     1862BString::_IFindAfter(const char* string, int32 offset, int32 strlen) const
    18181863{
    1819     char *ptr = strstr(String(), str);
    1820    
     1864    const char *ptr = strcasestr(String() + offset, string);
     1865
    18211866    if (ptr != NULL)
    18221867        return ptr - String();
    1823        
     1868
    18241869    return B_ERROR;
    18251870}
    18261871
    18271872
    18281873int32
    1829 BString::_FindBefore(const char *str, int32 offset, int32 strlen) const
     1874BString::_FindBefore(const char* string, int32 offset, int32 strlen) const
    18301875{
    18311876    if (fPrivateData) {
    18321877        const char *ptr = fPrivateData + offset - strlen;
    1833        
    1834         while (ptr >= fPrivateData) {   
    1835             if (!memcmp(ptr, str, strlen))
    1836                 return ptr - fPrivateData; 
     1878
     1879        while (ptr >= fPrivateData) {
     1880            if (!memcmp(ptr, string, strlen))
     1881                return ptr - fPrivateData;
    18371882            ptr--;
    18381883        }
    18391884    }
     
    18421887
    18431888
    18441889int32
    1845 BString::_IFindBefore(const char *str, int32 offset, int32 strlen) const
     1890BString::_IFindBefore(const char* string, int32 offset, int32 strlen) const
    18461891{
    18471892    if (fPrivateData) {
    18481893        char *ptr1 = fPrivateData + offset - strlen;
    1849        
     1894
    18501895        while (ptr1 >= fPrivateData) {
    1851             if (!strncasecmp(ptr1, str, strlen))
    1852                 return ptr1 - fPrivateData; 
     1896            if (!strncasecmp(ptr1, string, strlen))
     1897                return ptr1 - fPrivateData;
    18531898            ptr1--;
    18541899        }
    18551900    }
     
    18581903
    18591904
    18601905BString&
    1861 BString::_DoReplace(const char *findThis, const char *replaceWith,
    1862     int32 maxReplaceCount, int32 fromOffset, bool ignoreCase)
     1906BString::_DoCharacterEscape(const char* string,
     1907                            const char *setOfCharsToEscape, char escapeChar)
    18631908{
    1864     if (findThis == NULL || maxReplaceCount <= 0
     1909    if (_DetachWith(string, strlen(safestr(string))) != B_OK)
     1910        return *this;
     1911
     1912    memcpy(fPrivateData, string, Length());
     1913
     1914    PosVect positions;
     1915    int32 len = Length();
     1916    int32 pos = 0;
     1917    for (int32 offset = 0; offset < len; offset += pos + 1) {
     1918        if ((pos = strcspn(fPrivateData + offset, setOfCharsToEscape)) < len - offset) {
     1919            if (!positions.Add(offset + pos))
     1920                return *this;
     1921        }
     1922    }
     1923
     1924    uint32 count = positions.CountItems();
     1925    int32 newLength = len + count;
     1926    if (!newLength) {
     1927        _Realloc(0);
     1928        return *this;
     1929    }
     1930
     1931    int32 lastPos = 0;
     1932    char* oldAdr = fPrivateData;
     1933    int32 offset = 2 * sizeof(int32);
     1934
     1935    char* newData = (char*)malloc(newLength + offset + 1);
     1936    if (newData) {
     1937        newData += offset;
     1938        char* newAdr = newData;
     1939        for (uint32 i = 0; i < count; ++i) {
     1940            pos = positions.ItemAt(i);
     1941            len = pos - lastPos;
     1942            if (len > 0) {
     1943                memcpy(newAdr, oldAdr, len);
     1944                oldAdr += len;
     1945                newAdr += len;
     1946            }
     1947            *newAdr++ = escapeChar;
     1948            *newAdr++ = *oldAdr++;
     1949            lastPos = pos + 1;
     1950        }
     1951        len = Length() + 1 - lastPos;
     1952        if (len > 0)
     1953            memcpy(newAdr, oldAdr, len);
     1954
     1955        free(fPrivateData - offset);
     1956
     1957        fPrivateData = newData;
     1958        _SetLength(newLength);
     1959        fPrivateData[newLength] = '\0';
     1960    }
     1961    return *this;
     1962}
     1963
     1964
     1965BString&
     1966BString::_DoCharacterDeescape(const char* string, char escapeChar)
     1967{
     1968    if (_DetachWith(string, strlen(safestr(string))) != B_OK)
     1969        return *this;
     1970
     1971    memcpy(fPrivateData, string, Length());
     1972    const char temp[2] = { escapeChar, '\0' };
     1973    return _DoReplace(temp, "", REPLACE_ALL, 0, KEEP_CASE);
     1974}
     1975
     1976
     1977BString&
     1978BString::_DoReplace(const char* findThis, const char* replaceWith,
     1979                    int32 maxReplaceCount, int32 fromOffset, bool ignoreCase)
     1980{
     1981    if (findThis == NULL || maxReplaceCount <= 0
    18651982        || fromOffset < 0 || fromOffset >= Length())
    18661983        return *this;
    18671984
    1868     typedef int32 (BString::*TFindMethod)(const char *, int32, int32) const;
    1869     TFindMethod findMethod = ignoreCase ? &BString::_IFindAfter : &BString::_FindAfter;
     1985    typedef int32 (BString::*TFindMethod)(const char*, int32, int32) const;
     1986    TFindMethod findMethod = ignoreCase ? &BString::_IFindAfter
     1987        : &BString::_FindAfter;
    18701988    int32 findLen = strlen(findThis);
    18711989
    18721990    if (!replaceWith)
     
    18751993    int32 replaceLen = strlen(replaceWith);
    18761994    int32 lastSrcPos = fromOffset;
    18771995    PosVect positions;
    1878     for(int32 srcPos = 0;
    1879             maxReplaceCount > 0
    1880             && (srcPos = (this->*findMethod)(findThis, lastSrcPos, findLen)) >= 0;
    1881             maxReplaceCount-- ) {
     1996    for (int32 srcPos = 0; maxReplaceCount > 0
     1997        && (srcPos = (this->*findMethod)(findThis, lastSrcPos, findLen)) >= 0;
     1998        maxReplaceCount--) {
    18821999        positions.Add(srcPos);
    18832000        lastSrcPos = srcPos + findLen;
    18842001    }
     
    18882005
    18892006
    18902007void
    1891 BString::_ReplaceAtPositions(const PosVect* positions,
    1892     int32 searchLen, const char* with, int32 withLen)
     2008BString::_ReplaceAtPositions(const PosVect* positions, int32 searchLen,
     2009                            const char* with, int32 withLen)
    18932010{
    18942011    int32 len = Length();
    18952012    uint32 count = positions->CountItems();
    18962013    int32 newLength = len + count * (withLen - searchLen);
    18972014    if (!newLength) {
    1898         _Alloc(0);
     2015        _Realloc(0);
    18992016        return;
    19002017    }
    19012018
    19022019    int32 pos;
    19032020    int32 lastPos = 0;
    19042021    char *oldAdr = fPrivateData;
    1905     char *newData = (char *)malloc(newLength + sizeof(int32) + 1);
     2022
     2023    int32 offset = 2 * sizeof(int32);
     2024    char *newData = (char *)malloc(newLength + offset + 1);
    19062025    if (newData) {
    1907         newData += sizeof(int32);
     2026        newData += offset;
    19082027        char *newAdr = newData;
    1909         for(uint32 i = 0; i < count; ++i) {
     2028        for (uint32 i = 0; i < count; ++i) {
    19102029            pos = positions->ItemAt(i);
    19112030            len = pos - lastPos;
    19122031            if (len > 0) {
     
    19232042        if (len > 0)
    19242043            memcpy(newAdr, oldAdr, len);
    19252044
    1926         free(fPrivateData - sizeof(int32));
     2045        free(fPrivateData - offset);
     2046
    19272047        fPrivateData = newData;
    1928         fPrivateData[newLength] = 0;
    1929         _SetLength( newLength);
     2048        _SetLength(newLength);
     2049        fPrivateData[newLength] = '\0';
    19302050    }
    19312051}
    19322052
    19332053
    1934 #if ENABLE_INLINES
    1935 inline
    1936 #endif
    1937 void
    1938 BString::_SetLength(int32 length)
    1939 {
    1940     *((int32*)fPrivateData - 1) = length & 0x7fffffff;
    1941 }
    1942 
    1943 
    1944 #if DEBUG
    1945 // AFAIK, these are not implemented in BeOS R5
    1946 // XXX : Test these puppies
    1947 void
    1948 BString::_SetUsingAsCString(bool state)
    1949 {   
    1950     //TODO: Implement ?     
    1951 }
    1952 
    1953 
    1954 void
    1955 BString::_AssertNotUsingAsCString() const
    1956 {
    1957     //TODO: Implement ?
    1958 }
    1959 #endif
    1960 
    1961 
    19622054//  #pragma mark - backwards compatibility
    19632055
    19642056
     
    20022094{
    20032095    return strcasecmp(string1->String(), string2->String());
    20042096}
    2005