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