From 17473539554434c1bccc7d00697a6f885d5c6951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Wi=C5=9Bniewski?= Date: Thu, 3 Jun 2010 14:44:50 +0200 Subject: [PATCH] StringBlock: added support for UTF8 strings (Froyo compatibility). --- .../androlib/res/decoder/StringBlock.java | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/brut/androlib/res/decoder/StringBlock.java b/src/brut/androlib/res/decoder/StringBlock.java index 7d87384e..5a2ff0bf 100644 --- a/src/brut/androlib/res/decoder/StringBlock.java +++ b/src/brut/androlib/res/decoder/StringBlock.java @@ -44,11 +44,12 @@ public class StringBlock { int chunkSize = reader.readInt(); int stringCount = reader.readInt(); int styleOffsetCount = reader.readInt(); - /*?*/ reader.readInt(); + int flags = reader.readInt(); int stringsOffset = reader.readInt(); int stylesOffset = reader.readInt(); StringBlock block = new StringBlock(); + block.m_isUTF8 = (flags & UTF8_FLAG) != 0; block.m_stringOffsets = reader.readIntArray(stringCount); if (styleOffsetCount != 0) { block.m_styleOffsets = reader.readIntArray(styleOffsetCount); @@ -91,8 +92,18 @@ public class StringBlock { return null; } int offset = m_stringOffsets[index]; - int length = getShort(m_strings, offset); - return decodeString(offset + 2, length * 2); + int length; + + if (! m_isUTF8) { + length = getShort(m_strings, offset) * 2; + offset += 2; + } else { + offset += getVarint(m_strings, offset)[1]; + int[] varint = getVarint(m_strings, offset); + offset += varint[1]; + length = varint[0]; + } + return decodeString(offset, length); } /** @@ -229,7 +240,7 @@ public class StringBlock { private String decodeString(int offset, int length) { try { - return UTF16LE_DECODER.decode( + return (m_isUTF8 ? UTF8_DECODER : UTF16LE_DECODER).decode( ByteBuffer.wrap(m_strings, offset, length)).toString(); } catch (CharacterCodingException ex) { LOGGER.log(Level.WARNING, null, ex); @@ -249,13 +260,30 @@ public class StringBlock { return (value >>> 16); } } + + private static final int[] getVarint(byte[] array, int offset) { + int val = array[offset]; + boolean more = (val & 0x80) != 0; + val &= 0x7f; + + if (! more) { + return new int[]{val, 1}; + } else { + return new int[]{val << 8 | array[offset + 1] & 0xff, 2}; + } + } + private int[] m_stringOffsets; private byte[] m_strings; private int[] m_styleOffsets; private int[] m_styles; + private boolean m_isUTF8; private static final CharsetDecoder UTF16LE_DECODER = Charset.forName("UTF-16LE").newDecoder(); + private static final CharsetDecoder UTF8_DECODER = + Charset.forName("UTF-8").newDecoder(); private static final Logger LOGGER = Logger.getLogger(StringBlock.class.getName()); private static final int CHUNK_TYPE = 0x001C0001; + private static final int UTF8_FLAG = 0x00000100; }