• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.res.android;
2 
3 import java.io.File;
4 
5 // transliterated from https://android.googlesource.com/platform/system/core/+/android-9.0.0_r12/libutils/String8.cpp
6 // and https://android.googlesource.com/platform/system/core/+/android-9.0.0_r12/include/utils/String8.h
7 public class String8 {
8 
9   private StringBuilder mString;
10 
String8()11   public String8() {
12     this("");
13   }
14 
String8(String value)15   public String8(String value) {
16     mString = new StringBuilder(value);
17   }
18 
String8(String8 path)19   public String8(String8 path) {
20     this(path.string());
21   }
22 
String8(String value, int len)23   public String8(String value, int len) {
24     this(value.substring(0, len));
25   }
26 
length()27   int length() {
28     return mString.length();
29   }
30 //String8 String8::format(const char* fmt, ...)
31 //{
32 //    va_list args;
33 //    va_start(args, fmt);
34 //    String8 result(formatV(fmt, args));
35 //    va_end(args);
36 //    return result;
37 //}
38 //String8 String8::formatV(const char* fmt, va_list args)
39 //{
40 //    String8 result;
41 //    result.appendFormatV(fmt, args);
42 //    return result;
43 //}
44 //void String8::clear() {
45 //    SharedBuffer::bufferFromData(mString)->release();
46 //    mString = getEmptyString();
47 //}
48 //void String8::setTo(const String8& other)
49 //{
50 //    SharedBuffer::bufferFromData(other.mString)->acquire();
51 //    SharedBuffer::bufferFromData(mString)->release();
52 //    mString = other.mString;
53 //}
54 //status_t String8::setTo(const char* other)
55 //{
56 //    const char *newString = allocFromUTF8(other, strlen(other));
57 //    SharedBuffer::bufferFromData(mString)->release();
58 //    mString = newString;
59 //    if (mString) return NO_ERROR;
60 //    mString = getEmptyString();
61 //    return NO_MEMORY;
62 //}
63 //status_t String8::setTo(const char* other, size_t len)
64 //{
65 //    const char *newString = allocFromUTF8(other, len);
66 //    SharedBuffer::bufferFromData(mString)->release();
67 //    mString = newString;
68 //    if (mString) return NO_ERROR;
69 //    mString = getEmptyString();
70 //    return NO_MEMORY;
71 //}
72 //status_t String8::setTo(const char16_t* other, size_t len)
73 //{
74 //    const char *newString = allocFromUTF16(other, len);
75 //    SharedBuffer::bufferFromData(mString)->release();
76 //    mString = newString;
77 //    if (mString) return NO_ERROR;
78 //    mString = getEmptyString();
79 //    return NO_MEMORY;
80 //}
81 //status_t String8::setTo(const char32_t* other, size_t len)
82 //{
83 //    const char *newString = allocFromUTF32(other, len);
84 //    SharedBuffer::bufferFromData(mString)->release();
85 //    mString = newString;
86 //    if (mString) return NO_ERROR;
87 //    mString = getEmptyString();
88 //    return NO_MEMORY;
89 //}
90 //status_t String8::append(const String8& other)
91 //{
92 //    const size_t otherLen = other.bytes();
93 //    if (bytes() == 0) {
94 //        setTo(other);
95 //        return NO_ERROR;
96 //    } else if (otherLen == 0) {
97 //        return NO_ERROR;
98 //    }
99 //    return real_append(other.string(), otherLen);
100 //}
append(final String other)101 public String8 append(final String other) {
102   mString.append(other);
103     return this;
104 }
105 //status_t String8::append(const char* other, size_t otherLen)
106 //{
107 //    if (bytes() == 0) {
108 //        return setTo(other, otherLen);
109 //    } else if (otherLen == 0) {
110 //        return NO_ERROR;
111 //    }
112 //    return real_append(other, otherLen);
113 //}
114 //status_t String8::appendFormat(const char* fmt, ...)
115 //{
116 //    va_list args;
117 //    va_start(args, fmt);
118 //    status_t result = appendFormatV(fmt, args);
119 //    va_end(args);
120 //    return result;
121 //}
122 //status_t String8::appendFormatV(const char* fmt, va_list args)
123 //{
124 //    int n, result = NO_ERROR;
125 //    va_list tmp_args;
126 //    /* args is undefined after vsnprintf.
127 //     * So we need a copy here to avoid the
128 //     * second vsnprintf access undefined args.
129 //     */
130 //    va_copy(tmp_args, args);
131 //    n = vsnprintf(NULL, 0, fmt, tmp_args);
132 //    va_end(tmp_args);
133 //    if (n != 0) {
134 //        size_t oldLength = length();
135 //        char* buf = lockBuffer(oldLength + n);
136 //        if (buf) {
137 //            vsnprintf(buf + oldLength, n + 1, fmt, args);
138 //        } else {
139 //            result = NO_MEMORY;
140 //        }
141 //    }
142 //    return result;
143 //}
144 //status_t String8::real_append(const char* other, size_t otherLen)
145 //{
146 //    const size_t myLen = bytes();
147 //
148 //    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
149 //        ->editResize(myLen+otherLen+1);
150 //    if (buf) {
151 //        char* str = (char*)buf->data();
152 //        mString = str;
153 //        str += myLen;
154 //        memcpy(str, other, otherLen);
155 //        str[otherLen] = '\0';
156 //        return NO_ERROR;
157 //    }
158 //    return NO_MEMORY;
159 //}
160 //char* String8::lockBuffer(size_t size)
161 //{
162 //    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
163 //        ->editResize(size+1);
164 //    if (buf) {
165 //        char* str = (char*)buf->data();
166 //        mString = str;
167 //        return str;
168 //    }
169 //    return NULL;
170 //}
171 //void String8::unlockBuffer()
172 //{
173 //    unlockBuffer(strlen(mString));
174 //}
175 //status_t String8::unlockBuffer(size_t size)
176 //{
177 //    if (size != this->size()) {
178 //        SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
179 //            ->editResize(size+1);
180 //        if (! buf) {
181 //            return NO_MEMORY;
182 //        }
183 //        char* str = (char*)buf->data();
184 //        str[size] = 0;
185 //        mString = str;
186 //    }
187 //    return NO_ERROR;
188 //}
189 //ssize_t String8::find(const char* other, size_t start) const
190 //{
191 //    size_t len = size();
192 //    if (start >= len) {
193 //        return -1;
194 //    }
195 //    const char* s = mString+start;
196 //    const char* p = strstr(s, other);
197 //    return p ? p-mString : -1;
198 //}
199 //bool String8::removeAll(const char* other) {
200 //    ssize_t index = find(other);
201 //    if (index < 0) return false;
202 //    char* buf = lockBuffer(size());
203 //    if (!buf) return false; // out of memory
204 //    size_t skip = strlen(other);
205 //    size_t len = size();
206 //    size_t tail = index;
207 //    while (size_t(index) < len) {
208 //        ssize_t next = find(other, index + skip);
209 //        if (next < 0) {
210 //            next = len;
211 //        }
212 //        memmove(buf + tail, buf + index + skip, next - index - skip);
213 //        tail += next - index - skip;
214 //        index = next;
215 //    }
216 //    unlockBuffer(tail);
217 //    return true;
218 //}
219 //void String8::toLower()
220 //{
221 //    toLower(0, size());
222 //}
223 //void String8::toLower(size_t start, size_t length)
224 //{
225 //    const size_t len = size();
226 //    if (start >= len) {
227 //        return;
228 //    }
229 //    if (start+length > len) {
230 //        length = len-start;
231 //    }
232 //    char* buf = lockBuffer(len);
233 //    buf += start;
234 //    while (length > 0) {
235 //        *buf = tolower(*buf);
236 //        buf++;
237 //        length--;
238 //    }
239 //    unlockBuffer(len);
240 //}
241 //void String8::toUpper()
242 //{
243 //    toUpper(0, size());
244 //}
245 //void String8::toUpper(size_t start, size_t length)
246 //{
247 //    const size_t len = size();
248 //    if (start >= len) {
249 //        return;
250 //    }
251 //    if (start+length > len) {
252 //        length = len-start;
253 //    }
254 //    char* buf = lockBuffer(len);
255 //    buf += start;
256 //    while (length > 0) {
257 //        *buf = toupper(*buf);
258 //        buf++;
259 //        length--;
260 //    }
261 //    unlockBuffer(len);
262 //}
263 //size_t String8::getUtf32Length() const
264 //{
265 //    return utf8_to_utf32_length(mString, length());
266 //}
267 //int32_t String8::getUtf32At(size_t index, size_t *next_index) const
268 //{
269 //    return utf32_from_utf8_at(mString, length(), index, next_index);
270 //}
271 //void String8::getUtf32(char32_t* dst) const
272 //{
273 //    utf8_to_utf32(mString, length(), dst);
274 //}
275 //// ---------------------------------------------------------------------------
276 //// Path functions
277 //void String8::setPathName(const char* name)
278 //{
279 //    setPathName(name, strlen(name));
280 //}
281 //void String8::setPathName(const char* name, size_t len)
282 //{
283 //    char* buf = lockBuffer(len);
284 //    memcpy(buf, name, len);
285 //    // remove trailing path separator, if present
286 //    if (len > 0 && buf[len-1] == OS_PATH_SEPARATOR)
287 //        len--;
288 //    buf[len] = '\0';
289 //    unlockBuffer(len);
290 //}
getPathLeaf()291 String8 getPathLeaf() {
292   final int cp;
293   final String buf = mString.toString();
294   cp = buf.lastIndexOf(File.separatorChar);
295   if (cp == -1) {
296     return new String8(this);
297   } else {
298     return new String8(buf.substring(cp + 1));
299   }
300 }
301 //String8 String8::getPathDir(void) const
302 //{
303 //    const char* cp;
304 //    const char*const str = mString;
305 //    cp = strrchr(str, OS_PATH_SEPARATOR);
306 //    if (cp == NULL)
307 //        return String8("");
308 //    else
309 //        return String8(str, cp - str);
310 //}
311 //String8 String8::walkPath(String8* outRemains) const
312 //{
313 //    const char* cp;
314 //    const char*const str = mString;
315 //    const char* buf = str;
316 //    cp = strchr(buf, OS_PATH_SEPARATOR);
317 //    if (cp == buf) {
318 //        // don't include a leading '/'.
319 //        buf = buf+1;
320 //        cp = strchr(buf, OS_PATH_SEPARATOR);
321 //    }
322 //    if (cp == NULL) {
323 //        String8 res = buf != str ? String8(buf) : *this;
324 //        if (outRemains) *outRemains = String8("");
325 //        return res;
326 //    }
327 //    String8 res(buf, cp-buf);
328 //    if (outRemains) *outRemains = String8(cp+1);
329 //    return res;
330 //}
331 
332 /*
333  * Helper function for finding the start of an extension in a pathname.
334  *
335  * Returns a index inside mString, or -1 if no extension was found.
336  */
find_extension()337 private int find_extension()
338 {
339     int lastSlashIndex;
340 
341     final StringBuilder str = mString;
342     // only look at the filename
343     lastSlashIndex = str.lastIndexOf(File.pathSeparator);
344     if (lastSlashIndex == -1) {
345       lastSlashIndex = 0;
346     } else {
347       lastSlashIndex++;
348     }
349     // find the last dot
350     return str.lastIndexOf(".", lastSlashIndex);
351 }
352 
getPathExtension()353 public String getPathExtension()
354 {
355     int extIndex;
356     extIndex = find_extension();
357     if (extIndex != -1) {
358       return mString.substring(extIndex);
359     }
360     else {
361       return "";
362     }
363 }
364 
getBasePath()365   String8 getBasePath() {
366     int extIndex;
367     extIndex = find_extension();
368     if (extIndex == -1) {
369       return new String8(this);
370     } else {
371       return new String8(mString.substring(extIndex));
372     }
373   }
374 
appendPath(String name)375   public String8 appendPath(String name) {
376     if (name.length() == 0) {
377       // nothing to do
378       return this;
379     }
380     if (name.charAt(0) != File.separatorChar) {
381       mString.append(File.separatorChar);
382     }
383     mString.append(name);
384     return this;
385 }
386 
387 //String8& String8::convertToResPath()
388 //{
389 //#if OS_PATH_SEPARATOR != RES_PATH_SEPARATOR
390 //    size_t len = length();
391 //    if (len > 0) {
392 //        char * buf = lockBuffer(len);
393 //        for (char * end = buf + len; buf < end; ++buf) {
394 //            if (*buf == OS_PATH_SEPARATOR)
395 //                *buf = RES_PATH_SEPARATOR;
396 //        }
397 //        unlockBuffer(len);
398 //    }
399 //#endif
400 //    return *this;
401 //}
402 //}; // namespace android
403 
string()404   public final String string() {
405     return mString.toString();
406   }
407 
408   @Override
toString()409   public String toString() {
410     return mString.toString();
411   }
412 
413   @Override
equals(Object o)414   public boolean equals(Object o) {
415     if (this == o) {
416       return true;
417     }
418     if (o == null || getClass() != o.getClass()) {
419       return false;
420     }
421 
422     String8 string8 = (String8) o;
423 
424     return mString != null ? mString.toString().equals(string8.mString.toString()) : string8.mString == null;
425   }
426 
427   @Override
hashCode()428   public int hashCode() {
429     return mString != null ? mString.hashCode() : 0;
430   }
431 
432 }
433 
434 
435