Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/intl/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
CharString::CharString(CharString&& src) U_NOEXCEPT
27
0
        : buffer(std::move(src.buffer)), len(src.len) {
28
0
    src.len = 0;  // not strictly necessary because we make no guarantees on the source string
29
0
}
30
31
0
CharString& CharString::operator=(CharString&& src) U_NOEXCEPT {
32
0
    buffer = std::move(src.buffer);
33
0
    len = src.len;
34
0
    src.len = 0;  // not strictly necessary because we make no guarantees on the source string
35
0
    return *this;
36
0
}
37
38
0
CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) {
39
0
    if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) {
40
0
        len=s.len;
41
0
        uprv_memcpy(buffer.getAlias(), s.buffer.getAlias(), len+1);
42
0
    }
43
0
    return *this;
44
0
}
45
46
0
int32_t CharString::lastIndexOf(char c) const {
47
0
    for(int32_t i=len; i>0;) {
48
0
        if(buffer[--i]==c) {
49
0
            return i;
50
0
        }
51
0
    }
52
0
    return -1;
53
0
}
54
55
0
CharString &CharString::truncate(int32_t newLength) {
56
0
    if(newLength<0) {
57
0
        newLength=0;
58
0
    }
59
0
    if(newLength<len) {
60
0
        buffer[len=newLength]=0;
61
0
    }
62
0
    return *this;
63
0
}
64
65
18
CharString &CharString::append(char c, UErrorCode &errorCode) {
66
18
    if(ensureCapacity(len+2, 0, errorCode)) {
67
18
        buffer[len++]=c;
68
18
        buffer[len]=0;
69
18
    }
70
18
    return *this;
71
18
}
72
73
81
CharString &CharString::append(const char *s, int32_t sLength, UErrorCode &errorCode) {
74
81
    if(U_FAILURE(errorCode)) {
75
0
        return *this;
76
0
    }
77
81
    if(sLength<-1 || (s==NULL && sLength!=0)) {
78
0
        errorCode=U_ILLEGAL_ARGUMENT_ERROR;
79
0
        return *this;
80
0
    }
81
81
    if(sLength<0) {
82
0
        sLength=uprv_strlen(s);
83
0
    }
84
81
    if(sLength>0) {
85
81
        if(s==(buffer.getAlias()+len)) {
86
0
            // The caller wrote into the getAppendBuffer().
87
0
            if(sLength>=(buffer.getCapacity()-len)) {
88
0
                // The caller wrote too much.
89
0
                errorCode=U_INTERNAL_PROGRAM_ERROR;
90
0
            } else {
91
0
                buffer[len+=sLength]=0;
92
0
            }
93
81
        } else if(buffer.getAlias()<=s && s<(buffer.getAlias()+len) &&
94
81
                  sLength>=(buffer.getCapacity()-len)
95
0
        ) {
96
0
            // (Part of) this string is appended to itself which requires reallocation,
97
0
            // so we have to make a copy of the substring and append that.
98
0
            return append(CharString(s, sLength, errorCode), errorCode);
99
81
        } else if(ensureCapacity(len+sLength+1, 0, errorCode)) {
100
81
            uprv_memcpy(buffer.getAlias()+len, s, sLength);
101
81
            buffer[len+=sLength]=0;
102
81
        }
103
81
    }
104
81
    return *this;
105
81
}
106
107
char *CharString::getAppendBuffer(int32_t minCapacity,
108
                                  int32_t desiredCapacityHint,
109
                                  int32_t &resultCapacity,
110
0
                                  UErrorCode &errorCode) {
111
0
    if(U_FAILURE(errorCode)) {
112
0
        resultCapacity=0;
113
0
        return NULL;
114
0
    }
115
0
    int32_t appendCapacity=buffer.getCapacity()-len-1;  // -1 for NUL
116
0
    if(appendCapacity>=minCapacity) {
117
0
        resultCapacity=appendCapacity;
118
0
        return buffer.getAlias()+len;
119
0
    }
120
0
    if(ensureCapacity(len+minCapacity+1, len+desiredCapacityHint+1, errorCode)) {
121
0
        resultCapacity=buffer.getCapacity()-len-1;
122
0
        return buffer.getAlias()+len;
123
0
    }
124
0
    resultCapacity=0;
125
0
    return NULL;
126
0
}
127
128
0
CharString &CharString::appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode) {
129
0
    if(U_FAILURE(errorCode)) {
130
0
        return *this;
131
0
    }
132
0
    if (!uprv_isInvariantUnicodeString(s)) {
133
0
        errorCode = U_INVARIANT_CONVERSION_ERROR;
134
0
        return *this;
135
0
    }
136
0
    if(ensureCapacity(len+s.length()+1, 0, errorCode)) {
137
0
        len+=s.extract(0, 0x7fffffff, buffer.getAlias()+len, buffer.getCapacity()-len, US_INV);
138
0
    }
139
0
    return *this;
140
0
}
141
142
UBool CharString::ensureCapacity(int32_t capacity,
143
                                 int32_t desiredCapacityHint,
144
99
                                 UErrorCode &errorCode) {
145
99
    if(U_FAILURE(errorCode)) {
146
0
        return FALSE;
147
0
    }
148
99
    if(capacity>buffer.getCapacity()) {
149
0
        if(desiredCapacityHint==0) {
150
0
            desiredCapacityHint=capacity+buffer.getCapacity();
151
0
        }
152
0
        if( (desiredCapacityHint<=capacity || buffer.resize(desiredCapacityHint, len+1)==NULL) &&
153
0
            buffer.resize(capacity, len+1)==NULL
154
0
        ) {
155
0
            errorCode=U_MEMORY_ALLOCATION_ERROR;
156
0
            return FALSE;
157
0
        }
158
99
    }
159
99
    return TRUE;
160
99
}
161
162
0
CharString &CharString::appendPathPart(StringPiece s, UErrorCode &errorCode) {
163
0
    if(U_FAILURE(errorCode)) {
164
0
        return *this;
165
0
    }
166
0
    if(s.length()==0) {
167
0
        return *this;
168
0
    }
169
0
    char c;
170
0
    if(len>0 && (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
171
0
        append(U_FILE_SEP_CHAR, errorCode);
172
0
    }
173
0
    append(s, errorCode);
174
0
    return *this;
175
0
}
176
177
0
CharString &CharString::ensureEndsWithFileSeparator(UErrorCode &errorCode) {
178
0
    char c;
179
0
    if(U_SUCCESS(errorCode) && len>0 &&
180
0
            (c=buffer[len-1])!=U_FILE_SEP_CHAR && c!=U_FILE_ALT_SEP_CHAR) {
181
0
        append(U_FILE_SEP_CHAR, errorCode);
182
0
    }
183
0
    return *this;
184
0
}
185
186
U_NAMESPACE_END