Reland "libutils: Introduce StaticString16""
This reverts commit 1270e4fbf17402fb01dbfa7928a654d41d8553ee.
Bug: 138856262
Test: Run unit tests.
Change-Id: I37be01d7d4f98a83078870cb0917275336fa2bbd
Merged-In: I8da93f2c9b95183e32d4a2ea895f90c449abbe4d
diff --git a/libutils/String16.cpp b/libutils/String16.cpp
index 818b171..5c3cf32 100644
--- a/libutils/String16.cpp
+++ b/libutils/String16.cpp
@@ -24,21 +24,21 @@
namespace android {
+static const StaticString16 emptyString(u"");
static inline char16_t* getEmptyString() {
- static SharedBuffer* gEmptyStringBuf = [] {
- SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t));
- char16_t* str = static_cast<char16_t*>(buf->data());
- *str = 0;
- return buf;
- }();
-
- gEmptyStringBuf->acquire();
- return static_cast<char16_t*>(gEmptyStringBuf->data());
+ return const_cast<char16_t*>(emptyString.string());
}
// ---------------------------------------------------------------------------
-static char16_t* allocFromUTF8(const char* u8str, size_t u8len)
+void* String16::alloc(size_t size)
+{
+ SharedBuffer* buf = SharedBuffer::alloc(size);
+ buf->mClientMetadata = kIsSharedBufferAllocated;
+ return buf;
+}
+
+char16_t* String16::allocFromUTF8(const char* u8str, size_t u8len)
{
if (u8len == 0) return getEmptyString();
@@ -49,7 +49,7 @@
return getEmptyString();
}
- SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t)*(u16len+1));
+ SharedBuffer* buf = static_cast<SharedBuffer*>(alloc(sizeof(char16_t) * (u16len + 1)));
if (buf) {
u8cur = (const uint8_t*) u8str;
char16_t* u16str = (char16_t*)buf->data();
@@ -66,13 +66,13 @@
return getEmptyString();
}
-static char16_t* allocFromUTF16(const char16_t* u16str, size_t u16len) {
+char16_t* String16::allocFromUTF16(const char16_t* u16str, size_t u16len) {
if (u16len >= SIZE_MAX / sizeof(char16_t)) {
android_errorWriteLog(0x534e4554, "73826242");
abort();
}
- SharedBuffer* buf = SharedBuffer::alloc((u16len + 1) * sizeof(char16_t));
+ SharedBuffer* buf = static_cast<SharedBuffer*>(alloc((u16len + 1) * sizeof(char16_t)));
ALOG_ASSERT(buf, "Unable to allocate shared buffer");
if (buf) {
char16_t* str = (char16_t*)buf->data();
@@ -97,8 +97,8 @@
// having run. In this case we always allocate an empty string. It's less
// efficient than using getEmptyString(), but we assume it's uncommon.
- char16_t* data = static_cast<char16_t*>(
- SharedBuffer::alloc(sizeof(char16_t))->data());
+ SharedBuffer* buf = static_cast<SharedBuffer*>(alloc(sizeof(char16_t)));
+ char16_t* data = static_cast<char16_t*>(buf->data());
data[0] = 0;
mString = data;
}
@@ -106,7 +106,7 @@
String16::String16(const String16& o)
: mString(o.mString)
{
- SharedBuffer::bufferFromData(mString)->acquire();
+ acquire();
}
String16::String16(const String16& o, size_t len, size_t begin)
@@ -136,26 +136,30 @@
String16::~String16()
{
- SharedBuffer::bufferFromData(mString)->release();
+ release();
}
size_t String16::size() const
{
- return SharedBuffer::sizeFromData(mString)/sizeof(char16_t)-1;
+ if (isStaticString()) {
+ return staticStringSize();
+ } else {
+ return SharedBuffer::sizeFromData(mString) / sizeof(char16_t) - 1;
+ }
}
void String16::setTo(const String16& other)
{
- SharedBuffer::bufferFromData(other.mString)->acquire();
- SharedBuffer::bufferFromData(mString)->release();
+ release();
mString = other.mString;
+ acquire();
}
status_t String16::setTo(const String16& other, size_t len, size_t begin)
{
const size_t N = other.size();
if (begin >= N) {
- SharedBuffer::bufferFromData(mString)->release();
+ release();
mString = getEmptyString();
return OK;
}
@@ -184,8 +188,7 @@
abort();
}
- SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
- ->editResize((len+1)*sizeof(char16_t));
+ SharedBuffer* buf = static_cast<SharedBuffer*>(editResize((len + 1) * sizeof(char16_t)));
if (buf) {
char16_t* str = (char16_t*)buf->data();
memmove(str, other, len*sizeof(char16_t));
@@ -212,8 +215,8 @@
abort();
}
- SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
- ->editResize((myLen+otherLen+1)*sizeof(char16_t));
+ SharedBuffer* buf =
+ static_cast<SharedBuffer*>(editResize((myLen + otherLen + 1) * sizeof(char16_t)));
if (buf) {
char16_t* str = (char16_t*)buf->data();
memcpy(str+myLen, other, (otherLen+1)*sizeof(char16_t));
@@ -238,8 +241,8 @@
abort();
}
- SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
- ->editResize((myLen+otherLen+1)*sizeof(char16_t));
+ SharedBuffer* buf =
+ static_cast<SharedBuffer*>(editResize((myLen + otherLen + 1) * sizeof(char16_t)));
if (buf) {
char16_t* str = (char16_t*)buf->data();
memcpy(str+myLen, chrs, otherLen*sizeof(char16_t));
@@ -273,8 +276,8 @@
len, myLen, String8(chrs, len).string());
#endif
- SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
- ->editResize((myLen+len+1)*sizeof(char16_t));
+ SharedBuffer* buf =
+ static_cast<SharedBuffer*>(editResize((myLen + len + 1) * sizeof(char16_t)));
if (buf) {
char16_t* str = (char16_t*)buf->data();
if (pos < myLen) {
@@ -338,23 +341,87 @@
return strstr16(mString, chrs) != nullptr;
}
+void* String16::edit() {
+ SharedBuffer* buf;
+ if (isStaticString()) {
+ buf = static_cast<SharedBuffer*>(alloc((size() + 1) * sizeof(char16_t)));
+ if (buf) {
+ buf->acquire();
+ memcpy(buf->data(), mString, (size() + 1) * sizeof(char16_t));
+ }
+ } else {
+ buf = SharedBuffer::bufferFromData(mString)->edit();
+ buf->mClientMetadata = kIsSharedBufferAllocated;
+ }
+ return buf;
+}
+
+void* String16::editResize(size_t newSize) {
+ SharedBuffer* buf;
+ if (isStaticString()) {
+ size_t copySize = (size() + 1) * sizeof(char16_t);
+ if (newSize < copySize) {
+ copySize = newSize;
+ }
+ buf = static_cast<SharedBuffer*>(alloc(newSize));
+ if (buf) {
+ buf->acquire();
+ memcpy(buf->data(), mString, copySize);
+ }
+ } else {
+ buf = SharedBuffer::bufferFromData(mString)->editResize(newSize);
+ buf->mClientMetadata = kIsSharedBufferAllocated;
+ }
+ return buf;
+}
+
+void String16::acquire()
+{
+ if (!isStaticString()) {
+ SharedBuffer::bufferFromData(mString)->acquire();
+ }
+}
+
+void String16::release()
+{
+ if (!isStaticString()) {
+ SharedBuffer::bufferFromData(mString)->release();
+ }
+}
+
+bool String16::isStaticString() const {
+ // See String16.h for notes on the memory layout of String16::StaticData and
+ // SharedBuffer.
+ static_assert(sizeof(SharedBuffer) - offsetof(SharedBuffer, mClientMetadata) == 4);
+ const uint32_t* p = reinterpret_cast<const uint32_t*>(mString);
+ return (*(p - 1) & kIsSharedBufferAllocated) == 0;
+}
+
+size_t String16::staticStringSize() const {
+ // See String16.h for notes on the memory layout of String16::StaticData and
+ // SharedBuffer.
+ static_assert(sizeof(SharedBuffer) - offsetof(SharedBuffer, mClientMetadata) == 4);
+ const uint32_t* p = reinterpret_cast<const uint32_t*>(mString);
+ return static_cast<size_t>(*(p - 1));
+}
+
status_t String16::makeLower()
{
const size_t N = size();
const char16_t* str = string();
- char16_t* edit = nullptr;
+ char16_t* edited = nullptr;
for (size_t i=0; i<N; i++) {
const char16_t v = str[i];
if (v >= 'A' && v <= 'Z') {
- if (!edit) {
- SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit();
+ if (!edited) {
+ SharedBuffer* buf = static_cast<SharedBuffer*>(edit());
if (!buf) {
return NO_MEMORY;
}
- edit = (char16_t*)buf->data();
- mString = str = edit;
+ edited = (char16_t*)buf->data();
+ mString = str = edited;
}
- edit[i] = tolower((char)v);
+ edited[i] = tolower((char)v);
}
}
return OK;
@@ -364,18 +431,18 @@
{
const size_t N = size();
const char16_t* str = string();
- char16_t* edit = nullptr;
+ char16_t* edited = nullptr;
for (size_t i=0; i<N; i++) {
if (str[i] == replaceThis) {
- if (!edit) {
- SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit();
+ if (!edited) {
+ SharedBuffer* buf = static_cast<SharedBuffer*>(edit());
if (!buf) {
return NO_MEMORY;
}
- edit = (char16_t*)buf->data();
- mString = str = edit;
+ edited = (char16_t*)buf->data();
+ mString = str = edited;
}
- edit[i] = withThis;
+ edited[i] = withThis;
}
}
return OK;
@@ -385,7 +452,7 @@
{
const size_t N = size();
if (begin >= N) {
- SharedBuffer::bufferFromData(mString)->release();
+ release();
mString = getEmptyString();
return OK;
}
@@ -395,8 +462,7 @@
}
if (begin > 0) {
- SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
- ->editResize((N+1)*sizeof(char16_t));
+ SharedBuffer* buf = static_cast<SharedBuffer*>(editResize((N + 1) * sizeof(char16_t)));
if (!buf) {
return NO_MEMORY;
}
@@ -404,8 +470,7 @@
memmove(str, str+begin, (N-begin+1)*sizeof(char16_t));
mString = str;
}
- SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
- ->editResize((len+1)*sizeof(char16_t));
+ SharedBuffer* buf = static_cast<SharedBuffer*>(editResize((len + 1) * sizeof(char16_t)));
if (buf) {
char16_t* str = (char16_t*)buf->data();
str[len] = 0;