blob: 96d8f9818d27b202fe634ac763112fd40e9c0255 [file] [log] [blame]
package org.robolectric.res.android;
import java.io.File;
// transliterated from https://android.googlesource.com/platform/system/core/+/android-8.1.0_r22/libutils/String8.cpp
// and https://android.googlesource.com/platform/system/core/+/android-8.1.0_r22/include/utils/String8.h
public class String8 {
private StringBuilder mString;
public String8() {
this("");
}
public String8(String value) {
mString = new StringBuilder(value);
}
public String8(String8 path) {
this(path.string());
}
public String8(String value, int len) {
this(value.substring(0, len));
}
int length() {
return mString.length();
}
//String8 String8::format(const char* fmt, ...)
//{
// va_list args;
// va_start(args, fmt);
// String8 result(formatV(fmt, args));
// va_end(args);
// return result;
//}
//String8 String8::formatV(const char* fmt, va_list args)
//{
// String8 result;
// result.appendFormatV(fmt, args);
// return result;
//}
//void String8::clear() {
// SharedBuffer::bufferFromData(mString)->release();
// mString = getEmptyString();
//}
//void String8::setTo(const String8& other)
//{
// SharedBuffer::bufferFromData(other.mString)->acquire();
// SharedBuffer::bufferFromData(mString)->release();
// mString = other.mString;
//}
//status_t String8::setTo(const char* other)
//{
// const char *newString = allocFromUTF8(other, strlen(other));
// SharedBuffer::bufferFromData(mString)->release();
// mString = newString;
// if (mString) return NO_ERROR;
// mString = getEmptyString();
// return NO_MEMORY;
//}
//status_t String8::setTo(const char* other, size_t len)
//{
// const char *newString = allocFromUTF8(other, len);
// SharedBuffer::bufferFromData(mString)->release();
// mString = newString;
// if (mString) return NO_ERROR;
// mString = getEmptyString();
// return NO_MEMORY;
//}
//status_t String8::setTo(const char16_t* other, size_t len)
//{
// const char *newString = allocFromUTF16(other, len);
// SharedBuffer::bufferFromData(mString)->release();
// mString = newString;
// if (mString) return NO_ERROR;
// mString = getEmptyString();
// return NO_MEMORY;
//}
//status_t String8::setTo(const char32_t* other, size_t len)
//{
// const char *newString = allocFromUTF32(other, len);
// SharedBuffer::bufferFromData(mString)->release();
// mString = newString;
// if (mString) return NO_ERROR;
// mString = getEmptyString();
// return NO_MEMORY;
//}
//status_t String8::append(const String8& other)
//{
// const size_t otherLen = other.bytes();
// if (bytes() == 0) {
// setTo(other);
// return NO_ERROR;
// } else if (otherLen == 0) {
// return NO_ERROR;
// }
// return real_append(other.string(), otherLen);
//}
public String8 append(final String other) {
mString.append(other);
return this;
}
//status_t String8::append(const char* other, size_t otherLen)
//{
// if (bytes() == 0) {
// return setTo(other, otherLen);
// } else if (otherLen == 0) {
// return NO_ERROR;
// }
// return real_append(other, otherLen);
//}
//status_t String8::appendFormat(const char* fmt, ...)
//{
// va_list args;
// va_start(args, fmt);
// status_t result = appendFormatV(fmt, args);
// va_end(args);
// return result;
//}
//status_t String8::appendFormatV(const char* fmt, va_list args)
//{
// int n, result = NO_ERROR;
// va_list tmp_args;
// /* args is undefined after vsnprintf.
// * So we need a copy here to avoid the
// * second vsnprintf access undefined args.
// */
// va_copy(tmp_args, args);
// n = vsnprintf(NULL, 0, fmt, tmp_args);
// va_end(tmp_args);
// if (n != 0) {
// size_t oldLength = length();
// char* buf = lockBuffer(oldLength + n);
// if (buf) {
// vsnprintf(buf + oldLength, n + 1, fmt, args);
// } else {
// result = NO_MEMORY;
// }
// }
// return result;
//}
//status_t String8::real_append(const char* other, size_t otherLen)
//{
// const size_t myLen = bytes();
//
// SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
// ->editResize(myLen+otherLen+1);
// if (buf) {
// char* str = (char*)buf->data();
// mString = str;
// str += myLen;
// memcpy(str, other, otherLen);
// str[otherLen] = '\0';
// return NO_ERROR;
// }
// return NO_MEMORY;
//}
//char* String8::lockBuffer(size_t size)
//{
// SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
// ->editResize(size+1);
// if (buf) {
// char* str = (char*)buf->data();
// mString = str;
// return str;
// }
// return NULL;
//}
//void String8::unlockBuffer()
//{
// unlockBuffer(strlen(mString));
//}
//status_t String8::unlockBuffer(size_t size)
//{
// if (size != this->size()) {
// SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
// ->editResize(size+1);
// if (! buf) {
// return NO_MEMORY;
// }
// char* str = (char*)buf->data();
// str[size] = 0;
// mString = str;
// }
// return NO_ERROR;
//}
//ssize_t String8::find(const char* other, size_t start) const
//{
// size_t len = size();
// if (start >= len) {
// return -1;
// }
// const char* s = mString+start;
// const char* p = strstr(s, other);
// return p ? p-mString : -1;
//}
//bool String8::removeAll(const char* other) {
// ssize_t index = find(other);
// if (index < 0) return false;
// char* buf = lockBuffer(size());
// if (!buf) return false; // out of memory
// size_t skip = strlen(other);
// size_t len = size();
// size_t tail = index;
// while (size_t(index) < len) {
// ssize_t next = find(other, index + skip);
// if (next < 0) {
// next = len;
// }
// memmove(buf + tail, buf + index + skip, next - index - skip);
// tail += next - index - skip;
// index = next;
// }
// unlockBuffer(tail);
// return true;
//}
//void String8::toLower()
//{
// toLower(0, size());
//}
//void String8::toLower(size_t start, size_t length)
//{
// const size_t len = size();
// if (start >= len) {
// return;
// }
// if (start+length > len) {
// length = len-start;
// }
// char* buf = lockBuffer(len);
// buf += start;
// while (length > 0) {
// *buf = tolower(*buf);
// buf++;
// length--;
// }
// unlockBuffer(len);
//}
//void String8::toUpper()
//{
// toUpper(0, size());
//}
//void String8::toUpper(size_t start, size_t length)
//{
// const size_t len = size();
// if (start >= len) {
// return;
// }
// if (start+length > len) {
// length = len-start;
// }
// char* buf = lockBuffer(len);
// buf += start;
// while (length > 0) {
// *buf = toupper(*buf);
// buf++;
// length--;
// }
// unlockBuffer(len);
//}
//size_t String8::getUtf32Length() const
//{
// return utf8_to_utf32_length(mString, length());
//}
//int32_t String8::getUtf32At(size_t index, size_t *next_index) const
//{
// return utf32_from_utf8_at(mString, length(), index, next_index);
//}
//void String8::getUtf32(char32_t* dst) const
//{
// utf8_to_utf32(mString, length(), dst);
//}
//// ---------------------------------------------------------------------------
//// Path functions
//void String8::setPathName(const char* name)
//{
// setPathName(name, strlen(name));
//}
//void String8::setPathName(const char* name, size_t len)
//{
// char* buf = lockBuffer(len);
// memcpy(buf, name, len);
// // remove trailing path separator, if present
// if (len > 0 && buf[len-1] == OS_PATH_SEPARATOR)
// len--;
// buf[len] = '\0';
// unlockBuffer(len);
//}
String8 getPathLeaf() {
final int cp;
final String buf = mString.toString();
cp = buf.lastIndexOf(File.separatorChar);
if (cp == -1) {
return new String8(this);
} else {
return new String8(buf.substring(cp + 1));
}
}
//String8 String8::getPathDir(void) const
//{
// const char* cp;
// const char*const str = mString;
// cp = strrchr(str, OS_PATH_SEPARATOR);
// if (cp == NULL)
// return String8("");
// else
// return String8(str, cp - str);
//}
//String8 String8::walkPath(String8* outRemains) const
//{
// const char* cp;
// const char*const str = mString;
// const char* buf = str;
// cp = strchr(buf, OS_PATH_SEPARATOR);
// if (cp == buf) {
// // don't include a leading '/'.
// buf = buf+1;
// cp = strchr(buf, OS_PATH_SEPARATOR);
// }
// if (cp == NULL) {
// String8 res = buf != str ? String8(buf) : *this;
// if (outRemains) *outRemains = String8("");
// return res;
// }
// String8 res(buf, cp-buf);
// if (outRemains) *outRemains = String8(cp+1);
// return res;
//}
/*
* Helper function for finding the start of an extension in a pathname.
*
* Returns a index inside mString, or -1 if no extension was found.
*/
private int find_extension()
{
int lastSlashIndex;
final StringBuilder str = mString;
// only look at the filename
lastSlashIndex = str.lastIndexOf(File.pathSeparator);
if (lastSlashIndex == -1) {
lastSlashIndex = 0;
} else {
lastSlashIndex++;
}
// find the last dot
return str.lastIndexOf(".", lastSlashIndex);
}
public String getPathExtension()
{
int extIndex;
extIndex = find_extension();
if (extIndex != -1) {
return mString.substring(extIndex);
}
else {
return "";
}
}
String8 getBasePath() {
int extIndex;
extIndex = find_extension();
if (extIndex == -1) {
return new String8(this);
} else {
return new String8(mString.substring(extIndex));
}
}
public String8 appendPath(String name) {
if (name.length() == 0) {
// nothing to do
return this;
}
if (name.charAt(0) != File.separatorChar) {
mString.append(File.separatorChar);
}
mString.append(name);
return this;
}
//String8& String8::convertToResPath()
//{
//#if OS_PATH_SEPARATOR != RES_PATH_SEPARATOR
// size_t len = length();
// if (len > 0) {
// char * buf = lockBuffer(len);
// for (char * end = buf + len; buf < end; ++buf) {
// if (*buf == OS_PATH_SEPARATOR)
// *buf = RES_PATH_SEPARATOR;
// }
// unlockBuffer(len);
// }
//#endif
// return *this;
//}
//}; // namespace android
public final String string() {
return mString.toString();
}
@Override
public String toString() {
return mString.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
String8 string8 = (String8) o;
return mString != null ? mString.toString().equals(string8.mString.toString()) : string8.mString == null;
}
@Override
public int hashCode() {
return mString != null ? mString.hashCode() : 0;
}
}