class Android::Resource::ResStringPool
Constants
- SORTED_FLAG
- UTF8_FLAG
Attributes
strings[R]
Private Class Methods
utf16_len(data)
click to toggle source
@note refer to /frameworks/base/libs/androidfw/ResourceTypes.cpp
static inline size_t decodeLength(const char16_t** str)
@param [String] data parse target @return[Integer, Integer] string length and parsed length
# File lib/android/resource.rb, line 186 def self.utf16_len(data) first, second = data.unpack('vv') if (first & 0x8000) != 0 return (((first & 0x7FFF) << 16) + second), 4 else return first, 2 end end
utf16_str_len(str)
click to toggle source
# File lib/android/resource.rb, line 195 def self.utf16_str_len(str) [str.size].pack('v') end
utf8_len(data)
click to toggle source
@note refer to /frameworks/base/libs/androidfw/ResourceTypes.cpp
static inline size_t decodeLength(const uint8_t** str)
@param [String] data parse target @return[Integer, Integer] string length and parsed length
# File lib/android/resource.rb, line 174 def self.utf8_len(data) first, second = data.unpack('CC') if (first & 0x80) != 0 return (((first & 0x7F) << 8) + second), 2 else return first, 1 end end
Public Instance Methods
add_string(str)
click to toggle source
# File lib/android/resource.rb, line 62 def add_string(str) raise UnsupportedStringFormatError, 'Adding strings in UTF-8 format is not supported yet' if utf8_string_format? @data_io = StringIO.new(@data, 'r+b') increment_string_count bytes_added = insert_string(str) increment_string_start_offset update_chunk_size(bytes_added) @data_io.close [@string_count - 1, bytes_added] end
utf8_string_format?()
click to toggle source
# File lib/android/resource.rb, line 76 def utf8_string_format? (@flags & UTF8_FLAG != 0) end
Private Instance Methods
increment_string_count()
click to toggle source
# File lib/android/resource.rb, line 107 def increment_string_count string_count_offset = @offset + 8 @string_count = @data[string_count_offset, 4].unpack1('V') + 1 @data_io.pos = string_count_offset @data_io.write([@string_count].pack('V')) end
increment_string_start_offset()
click to toggle source
# File lib/android/resource.rb, line 154 def increment_string_start_offset string_start_offset = @offset + 20 @string_start = @data[string_start_offset, 4].unpack1('V') + 4 @data_io.pos = string_start_offset @data_io.write([@string_start].pack('V')) end
insert_string(str)
click to toggle source
Inserts the string into the string data section and updates the string index. @return [Integer] number of bytes added to the string pool chunk
# File lib/android/resource.rb, line 116 def insert_string(str) bytes = str.codepoints << 0 # To keep the alignment we need to pad the new string we're inserting. # In total, we're adding the string bytes + 2 bytes string length + 4 bytes string index. padding = (4 - (bytes.size * 2 + 2 + 4) % 4) % 4 padding_bytes = [0] * padding next_string_offset = new_string_offset string_bytes = ResStringPool.utf16_str_len(str.codepoints) + bytes.pack('v*') + padding_bytes.pack('C*') # Write string data into the string data section. @data.insert(next_string_offset, string_bytes) # Insert new string index entry. The offset needs to be relative to the start of the string data section. @data.insert(last_string_index_offset + 4, [next_string_offset - (@offset + @string_start)].pack('V')) # We added the bytes of the string itself + a new string index entry string_bytes.size + 4 end
last_string_index_offset()
click to toggle source
# File lib/android/resource.rb, line 135 def last_string_index_offset # The last entry in the string index section is the 4 bytes right before the start # of the string-data section (string_start). @offset + @string_start - 4 end
new_string_offset()
click to toggle source
Calculates the offset at which to insert new string data. @return [Integer] offset of the end of the current string data section
# File lib/android/resource.rb, line 143 def new_string_offset last_string_index = @data[last_string_index_offset, 4].unpack1('V') offset = @offset + @string_start + last_string_index u16len, o16 = ResStringPool.utf16_len(@data[offset, 4]) # To insert a new string at the end of the string section, we need to start at the current # last string entry, and add o16 (number of length bytes), u16len * 2(number of string bytes), # and 2 bytes for the terminating null-bytes. offset + o16 + u16len * 2 + 2 end
parse()
click to toggle source
Calls superclass method
Android::Resource::ChunkHeader#parse
# File lib/android/resource.rb, line 81 def parse super @string_count = read_int32 @style_count = read_int32 @flags = read_int32 @string_start = read_int32 @style_start = read_int32 @strings = [] @string_count.times do offset = @offset + @string_start + read_int32 if utf8_string_format? # read length twice(utf16 length and utf8 length) # const uint16_t* ResStringPool::stringAt(size_t idx, size_t* u16len) const u16len, o16 = ResStringPool.utf8_len(@data[offset, 2]) u8len, o8 = ResStringPool.utf8_len(@data[offset+o16, 2]) str = @data[offset+o16+o8, u8len] @strings << str.force_encoding(Encoding::UTF_8) else u16len, o16 = ResStringPool.utf16_len(@data[offset, 4]) str = @data[offset+o16, u16len*2] str.force_encoding(Encoding::UTF_16LE) @strings << str.encode(Encoding::UTF_8) end end end
update_chunk_size(bytes_added)
click to toggle source
# File lib/android/resource.rb, line 162 def update_chunk_size(bytes_added) size_offset = @offset + 4 @size = @data[size_offset, 4].unpack1('V') + bytes_added @data_io.pos = size_offset @data_io.write([@size].pack('V')) end