summaryrefslogtreecommitdiffstats
path: root/tools/aapt2/StringPool.cpp
diff options
context:
space:
mode:
authorAdam Lesinski <adamlesinski@google.com>2015-04-24 19:19:30 -0700
committerAdam Lesinski <adamlesinski@google.com>2015-05-04 16:43:24 -0700
commit24aad163bc88cb10d2275385e9afc3de7f342d65 (patch)
tree361fc0b3fbef5f68a16f357ae9d2bed5e93efbf5 /tools/aapt2/StringPool.cpp
parentab2581398c812917145088590bd18eb83f3a2ea6 (diff)
downloadframeworks_base-24aad163bc88cb10d2275385e9afc3de7f342d65.zip
frameworks_base-24aad163bc88cb10d2275385e9afc3de7f342d65.tar.gz
frameworks_base-24aad163bc88cb10d2275385e9afc3de7f342d65.tar.bz2
Add namespace handling in attribute values
Previously, you could only reference namespace prefixes in attribute names: <View xmlns:appcompat="http://schemas.android.com/apk/res/android.support.v7.appcompat" appcompat:name="hey" ... Now you can also reference them in resource names within an attribute value: ... android:text="@appcompat:string/confirm" ... Which will be treated as "@android.support.v7.appcompat:string/confirm". Change-Id: Ib076e867a990c80cf877a704eb77cd1ef0b23b52
Diffstat (limited to 'tools/aapt2/StringPool.cpp')
-rw-r--r--tools/aapt2/StringPool.cpp71
1 files changed, 49 insertions, 22 deletions
diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp
index b983a53..c19aa98 100644
--- a/tools/aapt2/StringPool.cpp
+++ b/tools/aapt2/StringPool.cpp
@@ -265,25 +265,38 @@ void StringPool::sort(const std::function<bool(const Entry&, const Entry&)>& cmp
);
}
-static uint8_t* encodeLength(uint8_t* data, size_t length) {
- if (length > 0x7fu) {
- *data++ = 0x80u | (0x000000ffu & (length >> 8));
+template <typename T>
+static T* encodeLength(T* data, size_t length) {
+ static_assert(std::is_integral<T>::value, "wat.");
+
+ constexpr size_t kMask = 1 << ((sizeof(T) * 8) - 1);
+ constexpr size_t kMaxSize = kMask - 1;
+ if (length > kMaxSize) {
+ *data++ = kMask | (kMaxSize & (length >> (sizeof(T) * 8)));
}
- *data++ = 0x000000ffu & length;
+ *data++ = length;
return data;
}
-static size_t encodedLengthByteCount(size_t length) {
- return length > 0x7fu ? 2 : 1;
+template <typename T>
+static size_t encodedLengthUnits(size_t length) {
+ static_assert(std::is_integral<T>::value, "wat.");
+
+ constexpr size_t kMask = 1 << ((sizeof(T) * 8) - 1);
+ constexpr size_t kMaxSize = kMask - 1;
+ return length > kMaxSize ? 2 : 1;
}
-bool StringPool::flattenUtf8(BigBuffer* out, const StringPool& pool) {
+
+bool StringPool::flatten(BigBuffer* out, const StringPool& pool, bool utf8) {
const size_t startIndex = out->size();
android::ResStringPool_header* header = out->nextBlock<android::ResStringPool_header>();
header->header.type = android::RES_STRING_POOL_TYPE;
header->header.headerSize = sizeof(*header);
header->stringCount = pool.size();
- header->flags |= android::ResStringPool_header::UTF8_FLAG;
+ if (utf8) {
+ header->flags |= android::ResStringPool_header::UTF8_FLAG;
+ }
uint32_t* indices = pool.size() != 0 ? out->nextBlock<uint32_t>(pool.size()) : nullptr;
@@ -300,25 +313,31 @@ bool StringPool::flattenUtf8(BigBuffer* out, const StringPool& pool) {
*indices = out->size() - beforeStringsIndex;
indices++;
- std::string encoded = util::utf16ToUtf8(entry->value);
+ if (utf8) {
+ std::string encoded = util::utf16ToUtf8(entry->value);
+
+ const size_t totalSize = encodedLengthUnits<char>(entry->value.size())
+ + encodedLengthUnits<char>(encoded.length())
+ + encoded.size() + 1;
- const size_t stringByteLength = sizeof(char) * encoded.length();
- const size_t totalSize = encodedLengthByteCount(entry->value.size())
- + encodedLengthByteCount(encoded.length())
- + stringByteLength
- + sizeof(char);
+ char* data = out->nextBlock<char>(totalSize);
- uint8_t* data = out->nextBlock<uint8_t>(totalSize);
+ // First encode the actual UTF16 string length.
+ data = encodeLength(data, entry->value.size());
- // First encode the actual UTF16 string length.
- data = encodeLength(data, entry->value.size());
+ // Now encode the size of the converted UTF8 string.
+ data = encodeLength(data, encoded.length());
+ strncpy(data, encoded.data(), encoded.size());
+ } else {
+ const size_t totalSize = encodedLengthUnits<char16_t>(entry->value.size())
+ + entry->value.size() + 1;
- // Now encode the size of the converted UTF8 string.
- data = encodeLength(data, encoded.length());
+ char16_t* data = out->nextBlock<char16_t>(totalSize);
- memcpy(data, encoded.data(), stringByteLength);
- data += stringByteLength;
- *data = 0;
+ // Encode the actual UTF16 string length.
+ data = encodeLength(data, entry->value.size());
+ strncpy16(data, entry->value.data(), entry->value.size());
+ }
}
out->align4();
@@ -364,4 +383,12 @@ bool StringPool::flattenUtf8(BigBuffer* out, const StringPool& pool) {
return true;
}
+bool StringPool::flattenUtf8(BigBuffer* out, const StringPool& pool) {
+ return flatten(out, pool, true);
+}
+
+bool StringPool::flattenUtf16(BigBuffer* out, const StringPool& pool) {
+ return flatten(out, pool, false);
+}
+
} // namespace aapt