Coverage Report

Created: 2023-06-07 07:17

/src/icu/source/common/charstr.cpp
Line
Count
Source (jump to first uncovered line)
1
// © 2016 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
/*
4
*******************************************************************************
5
*   Copyright (C) 2010-2015, International Business Machines
6
*   Corporation and others.  All Rights Reserved.
7
*******************************************************************************
8
*   file name:  charstr.cpp
9
*   encoding:   UTF-8
10
*   tab size:   8 (not used)
11
*   indentation:4
12
*
13
*   created on: 2010may19
14
*   created by: Markus W. Scherer
15
*/
16
17
#include "unicode/utypes.h"
18
#include "unicode/putil.h"
19
#include "charstr.h"
20
#include "cmemory.h"
21
#include "cstring.h"
22
#include "uinvchar.h"
23
24
U_NAMESPACE_BEGIN
25
26
0
CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) {
27
0
    if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) {
28
0
        len=s.len;
29
0
        uprv_memcpy(buffer.getAlias(), s.buffer.getAlias(), len+1);
30
0
    }
31
0
    return *this;
32
0
}
33
34
0
int32_t CharString::lastIndexOf(char c) const {
35
0
    for(int32_t i=len; i>0;) {
36
0
        if(buffer[--i]==c) {
37
0
            return i;
38
0
        }
39
0
    }
40
0
    return -1;
41
0
}
42
43
0
CharString &CharString::truncate(int32_t newLength) {
44
0
    if(newLength<0) {
45
0
        newLength=0;
46
0
    }
47
0
    if(newLength<len) {
48
0
        buffer[len=newLength]=0;
49
0
    }
50
0
    return *this;
51
0
}
52
53
2.38k
CharString &CharString::append(char c, UErrorCode &errorCode) {
54
2.38k
    if(ensureCapacity(len+2, 0, errorCode)) {
55
2.38k
        buffer[len++]=c;
56
2.38k
        buffer[len]=0;
57
2.38k
    }
58
2.38k
    return *this;
59
2.38k
}
60
61
10.7k
CharString &CharString::append(const char *s, int32_t sLength, UErrorCode &errorCode) {
62
10.7k
    if(U_FAILURE(errorCode)) {
63
0
        return *this;
64
0
    }
65
10.7k
    if(sLength<-1 || (s==NULL && sLength!=0)) {
66
0
        errorCode=U_ILLEGAL_ARGUMENT_ERROR;
67
0
        return *this;
68
0
    }
69
10.7k
    if(sLength<0) {
70
0
        sLength=uprv_strlen(s);
71
0
    }
72
10.7k
    if(sLength>0) {
73
10.7k
        if(s==(buffer.getAlias()+len)) {
74
            // The caller wrote into the getAppendBuffer().
75
0
            if(sLength>=(buffer.getCapacity()-len)) {
76
                // The caller wrote too much.
77
0
                errorCode=U_INTERNAL_PROGRAM_ERROR;
78
0
            } else {
79
0
                buffer[len+=sLength]=0;
80
0
            }
81
10.7k
        } else if(buffer.getAlias()<=s && s<(buffer.getAlias()+len) &&
82
10.7k
                  sLength>=(buffer.getCapacity()-len)
83
10.7k
        ) {
84
            // (Part of) this string is appended to itself which requires reallocation,
85
            // so we have to make a copy of the substring and append that.
86
0
            return append(CharString(s, sLength, errorCode), errorCode);
87
10.7k
        } else if(ensureCapacity(len+sLength+1, 0, errorCode)) {
88
10.7k
            uprv_memcpy(buffer.getAlias()+len, s, sLength);
89
10.7k
            buffer[len+=sLength]=0;
90
10.7k
        }
91
10.7k
    }
92
10.7k
    return *this;
93
10.7k
}
94
95
char *CharString::getAppendBuffer(int32_t minCapacity,
96
                                  int32_t desiredCapacityHint,
97
                                  int32_t &resultCapacity,
98
0
                                  UErrorCode &errorCode) {
99
0
    if(U_FAILURE(errorCode)) {
100
0
        resultCapacity=0;
101
0
        return NULL;
102
0
    }
103
0
    int32_t appendCapacity=buffer.getCapacity()-len-1;  // -1 for NUL
104
0
    if(appendCapacity>=minCapacity) {
105
0
        resultCapacity=appendCapacity;
106
0
        return buffer.getAlias()+len;
107
0
    }
108
0
    if(ensureCapacity(len+minCapacity+1, len+desiredCapacityHint+1, errorCode)) {
109
0
        resultCapacity=buffer.getCapacity()-len-1;
110
0
        return buffer.getAlias()+len;
111
0
    }
112
0
    resultCapacity=0;
113
0
    return NULL;
114
0
}
115
116
0
CharString &CharString::appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode) {
117
0
    if(U_FAILURE(errorCode)) {
118
0
        return *this;
119
0
    }
120
0
    if (!uprv_isInvariantUnicodeString(s)) {
121
0
        errorCode = U_INVARIANT_CONVERSION_ERROR;
122
0
        return *this;
123
0
    }
124
0
    if(ensureCapacity(len+s.length()+1, 0, errorCode)) {
125
0
        len+=s.extract(0, 0x7fffffff, buffer.getAlias()+len, buffer.getCapacity()-len, US_INV);
126
0
    }
127
0
    return *this;
128
0
}
129
130
UBool CharString::ensureCapacity(int32_t capacity,
131
                                 int32_t desiredCapacityHint,
132
13.1k
                                 UErrorCode &errorCode) {
133
13.1k
    if(U_FAILURE(errorCode)) {
134
0
        return FALSE;
135
0
    }
136
13.1k
    if(capacity>buffer.getCapacity()) {
137
0
        if(desiredCapacityHint==0) {
138
0
            desiredCapacityHint=capacity+buffer.getCapacity();
139
0
        }
140
0
        if( (desiredCapacityHint<=capacity || buffer.resize(desiredCapacityHint, len+1)==NULL) &&
141
0
            buffer.resize(capacity, len+1)==NULL
142
0
        ) {
143
0
            errorCode=U_MEMORY_ALLOCATION_ERROR;
144
0
            return FALSE;
145
0
        }
146
0
    }
147
13.1k
    return TRUE;
148
13.1k
}
149
150
0
CharString &CharString::appendPathPart(StringPiece s, UErrorCode &errorCode) {
151
0
    if(U_FAILURE(errorCode)) {
152
0
        return *this;
153
0
    }
154
0
    if(s.length()==0) {
155
0
        return *this;
156
0
    }
157
0
    char c;
158
0
    if(len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
159
0
        append(U_FILE_SEP_CHAR, errorCode);
160
0
    }
161
0
    append(s, errorCode);
162
0
    return *this;
163
0
}
164
165
0
CharString &CharString::ensureEndsWithFileSeparator(UErrorCode &errorCode) {
166
0
    char c;
167
0
    if(U_SUCCESS(errorCode) && len>0 &&
168
0
            (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
169
0
        append(U_FILE_SEP_CHAR, errorCode);
170
0
    }
171
0
    return *this;
172
0
}
173
174
U_NAMESPACE_END