Class: Android::AXMLParser
- Inherits:
-
Object
- Object
- Android::AXMLParser
- Defined in:
- lib/android/axml_parser.rb
Overview
Note:
refer to Android OS framework code:
/frameworks/base/include/androidfw/ResourceTypes.h,
/frameworks/base/libs/androidfw/ResourceTypes.cpp
binary AXML parser
Defined Under Namespace
Classes: ReadError
Constant Summary collapse
- TAG_START_DOC =
0x00100100
- TAG_END_DOC =
0x00100101
- TAG_START =
0x00100102
- TAG_END =
0x00100103
- TAG_TEXT =
0x00100104
- TAG_CDSECT =
0x00100105
- TAG_ENTITY_REF =
0x00100106
- VAL_TYPE_NULL =
0
- VAL_TYPE_REFERENCE =
1
- VAL_TYPE_ATTRIBUTE =
2
- VAL_TYPE_STRING =
3
- VAL_TYPE_FLOAT =
4
- VAL_TYPE_DIMENSION =
5
- VAL_TYPE_FRACTION =
6
- VAL_TYPE_INT_DEC =
16
- VAL_TYPE_INT_HEX =
17
- VAL_TYPE_INT_BOOLEAN =
18
- VAL_TYPE_INT_COLOR_ARGB8 =
28
- VAL_TYPE_INT_COLOR_RGB8 =
29
- VAL_TYPE_INT_COLOR_ARGB4 =
30
- VAL_TYPE_INT_COLOR_RGB4 =
31
Instance Attribute Summary collapse
-
#strings ⇒ Array<String>
readonly
Strings defined in axml.
Class Method Summary collapse
Instance Method Summary collapse
- #convert_value(val_str_id, flags, val) ⇒ Object
-
#initialize(axml) ⇒ AXMLParser
constructor
A new instance of AXMLParser.
-
#parse ⇒ REXML::Document
parse binary xml.
-
#parse_attribute ⇒ Object
parse attribute of a element.
-
#parse_strings ⇒ Object
relace string table parser.
-
#parse_tags ⇒ Object
parse tag.
-
#short(offset) ⇒ Integer
read 2byte as short integer.
-
#word(offset = nil) ⇒ Integer
read one word(4byte) as integer.
Constructor Details
#initialize(axml) ⇒ AXMLParser
Returns a new instance of AXMLParser.
49 50 51 52 |
# File 'lib/android/axml_parser.rb', line 49 def initialize(axml) @io = StringIO.new(axml, "rb") @strings = [] end |
Instance Attribute Details
#strings ⇒ Array<String> (readonly)
Returns strings defined in axml.
46 47 48 |
# File 'lib/android/axml_parser.rb', line 46 def strings @strings end |
Class Method Details
.axml?(data) ⇒ Boolean
15 16 17 |
# File 'lib/android/axml_parser.rb', line 15 def self.axml?(data) (data[0..3] == "\x03\x00\x08\x00") end |
Instance Method Details
#convert_value(val_str_id, flags, val) ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/android/axml_parser.rb', line 150 def convert_value(val_str_id, flags, val) unless val_str_id == 0xFFFFFFFF value = @strings[val_str_id] else type = flags >> 24 case type when VAL_TYPE_NULL value = nil when VAL_TYPE_REFERENCE value = "@%#x" % val # refered resource id. when VAL_TYPE_INT_DEC value = val when VAL_TYPE_INT_HEX value = "%#x" % val when VAL_TYPE_INT_BOOLEAN value = ((val == 0xFFFFFFFF) || (val==1)) ? true : false else value = "[%#x, flag=%#x]" % [val, flags] end end end |
#parse ⇒ REXML::Document
parse binary xml
56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/android/axml_parser.rb', line 56 def parse @doc = REXML::Document.new @doc << REXML::XMLDecl.new @num_str = word(4*4) @xml_offset = word(3*4) @parents = [@doc] @ns = [] parse_strings @doc end |
#parse_attribute ⇒ Object
parse attribute of a element
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/android/axml_parser.rb', line 133 def parse_attribute ns_id, name_id, val_str_id, flags, val = @io.read(4*5).unpack("V*") key = @strings[name_id] unless ns_id == 0xFFFFFFFF ns = @strings[ns_id] prefix = ns.sub(/.*\//,'') unless @ns.include? ns @ns << ns @doc.root.add_namespace(prefix, ns) end key = "#{prefix}:#{key}" end value = convert_value(val_str_id, flags, val) return key, value end |
#parse_strings ⇒ Object
relace string table parser
88 89 90 91 |
# File 'lib/android/axml_parser.rb', line 88 def parse_strings strpool = Resource::ResStringPool.new(@io.string, 8) # ugh! @strings = strpool.strings end |
#parse_tags ⇒ Object
parse tag
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/android/axml_parser.rb', line 94 def # skip until START_TAG pos = @xml_offset pos += 4 until (word(pos) == TAG_START) #ugh! @io.pos -= 4 # read tags #puts "start tag parse: %d(%#x)" % [@io.pos, @io.pos] until @io.eof? last_pos = @io.pos tag, tag1, line, tag3, ns_id, name_id = @io.read(4*6).unpack("V*") case tag when TAG_START tag6, num_attrs, tag8 = @io.read(4*3).unpack("V*") elem = REXML::Element.new(@strings[name_id]) #puts "start tag %d(%#x): #{@strings[name_id]} attrs:#{num_attrs}" % [last_pos, last_pos] @parents.last.add_element elem num_attrs.times do key, val = parse_attribute elem.add_attribute(key, val) end @parents.push elem when TAG_END @parents.pop when TAG_END_DOC break when TAG_TEXT text = REXML::Text.new(@strings[ns_id]) @parents.last.text = text dummy = @io.read(4*1).unpack("V*") # skip 4bytes when TAG_START_DOC, TAG_CDSECT, TAG_ENTITY_REF # not implemented yet. else raise ReadError, "pos=%d(%#x)[tag:%#x]" % [last_pos, last_pos, tag] end end end |
#short(offset) ⇒ Integer
read 2byte as short integer
82 83 84 85 |
# File 'lib/android/axml_parser.rb', line 82 def short(offset) @io.pos = offset unless offset.nil? @io.read(2).unpack("v")[0] end |
#word(offset = nil) ⇒ Integer
read one word(4byte) as integer
74 75 76 77 |
# File 'lib/android/axml_parser.rb', line 74 def word(offset=nil) @io.pos = offset unless offset.nil? @io.read(4).unpack("V")[0] end |