Home | History | Annotate | Download | only in android
      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 
     11   public String8() {
     12     this("");
     13   }
     14 
     15   public String8(String value) {
     16     mString = new StringBuilder(value);
     17   }
     18 
     19   public String8(String8 path) {
     20     this(path.string());
     21   }
     22 
     23   public String8(String value, int len) {
     24     this(value.substring(0, len));
     25   }
     26 
     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 //}
    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 //}
    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  */
    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 
    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 
    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 
    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 
    404   public final String string() {
    405     return mString.toString();
    406   }
    407 
    408   @Override
    409   public String toString() {
    410     return mString.toString();
    411   }
    412 
    413   @Override
    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
    428   public int hashCode() {
    429     return mString != null ? mString.hashCode() : 0;
    430   }
    431 
    432 }
    433 
    434 
    435