diff options
author | Adam Lesinski <adamlesinski@google.com> | 2015-04-24 19:19:30 -0700 |
---|---|---|
committer | Adam Lesinski <adamlesinski@google.com> | 2015-05-04 16:43:24 -0700 |
commit | 24aad163bc88cb10d2275385e9afc3de7f342d65 (patch) | |
tree | 361fc0b3fbef5f68a16f357ae9d2bed5e93efbf5 /tools/aapt2/StringPool.cpp | |
parent | ab2581398c812917145088590bd18eb83f3a2ea6 (diff) | |
download | frameworks_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.cpp | 71 |
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 |