Initial
This commit is contained in:
91
Sources/AndroidXML/TblEntry.swift
Normal file
91
Sources/AndroidXML/TblEntry.swift
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* This is the beginning of information about an entry in the resource table.
|
||||
*
|
||||
* It holds the reference to the name of this entry, and is immediately followed by one of:
|
||||
* * A `ResValue` structure, if `Flags.Complex` is -not- set.
|
||||
* * An array of `ResTable_map` structures, if `Flags.Complex` is set.
|
||||
* These supply a set of name/value mappings of data.
|
||||
* * If `Flags.Compact` is set, this entry is a compact entry for simple values only
|
||||
*/
|
||||
/// Size: `8 Bytes`
|
||||
public struct TblEntry {
|
||||
// Note: `_size` and `_key` are private because `Flags` determine their meaning
|
||||
|
||||
/// Number of bytes in this structure.
|
||||
var size: UInt16 { flags.contains(.Compact) ? 8 : _size }
|
||||
/// Reference into `TblPackage::keyStrings` identifying this entry.
|
||||
public var key: StringPoolRef { flags.contains(.Compact) ? StringPoolRef(_size) : _key }
|
||||
|
||||
// ACTUAL data entry:
|
||||
|
||||
/// Number of bytes in this structure.
|
||||
private let _size: UInt16 // used as `key` if Flags.Compact
|
||||
/// Flags.
|
||||
let flags: Flags // UInt16
|
||||
struct Flags: OptionSet {
|
||||
let rawValue: UInt16
|
||||
/// If set, this is a complex entry, holding a set of name/value mappings.
|
||||
/// It is followed by an array of `ResTable_map` structures.
|
||||
static let Complex = Flags(rawValue: 0x0001)
|
||||
/// If set, this resource has been declared public, so libraries are allowed to reference it.
|
||||
static let Public = Flags(rawValue: 0x0002)
|
||||
/// If set, this is a weak resource and may be overriden by strong resources of the same name/type.
|
||||
/// This is only useful during linking with other resource tables.
|
||||
static let Weak = Flags(rawValue: 0x0004)
|
||||
/// If set, this is a compact entry with data type and value directly encoded in the this entry.
|
||||
/// See `ResTable_entry::compact`
|
||||
static let Compact = Flags(rawValue: 0x0008)
|
||||
}
|
||||
/// Reference into `TblPackage::keyStrings` identifying this entry.
|
||||
private let _key: StringPoolRef // UInt32 // used as `data` if Flags.Compact
|
||||
|
||||
// Interpreted data value
|
||||
|
||||
/// Only set if `Flags.Complex` is `false`
|
||||
public let value: ResValue? // 8 Bytes
|
||||
/// Only set if `Flags.Complex` is `true`
|
||||
public let valueMap: TblEntryMap?
|
||||
/// `true` if `Flags.Complex` is set
|
||||
public var isComplex: Bool { flags.contains(.Complex) }
|
||||
|
||||
init(_ br: inout RawBytes.Reader) throws {
|
||||
_size = br.read16()
|
||||
flags = Flags(rawValue: br.read16())
|
||||
_key = br.read32()
|
||||
assert(!flags.contains(.Compact), "TODO: TblEntry with Flags.Compact")
|
||||
/*
|
||||
* Always verify the memory associated with this entry and its value
|
||||
* before calling `value()` or `map_entry()`
|
||||
*/
|
||||
if flags.contains(.Compact) {
|
||||
let rawType = UInt8((flags.rawValue & 0xFF00) >> 8)
|
||||
guard let typ = DataType(rawValue: rawType) else {
|
||||
throw AXMLError("Unknown ResValue data-type \(rawType)")
|
||||
}
|
||||
value = ResValue(type: typ, data: _key)
|
||||
valueMap = nil
|
||||
} else if flags.contains(.Complex) {
|
||||
value = nil
|
||||
valueMap = try TblEntryMap(&br)
|
||||
} else {
|
||||
value = try ResValue(&br)
|
||||
valueMap = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A compact entry is indicated by `Flags.Compact`, with flags at the same offset as a normal entry.
|
||||
* This is only for simple data values where
|
||||
*
|
||||
* - size for entry or value can be inferred (both being 8 bytes).
|
||||
* - key index is encoded in 16-bit
|
||||
* - dataType is encoded as the higher 8-bit of flags
|
||||
* - data is encoded directly in this entry
|
||||
*/
|
||||
// UNUSED because case handled directly in `TblEntry`
|
||||
//struct TblEntryCompact {
|
||||
// let key: UInt16
|
||||
// let flags: UInt16
|
||||
// let data: UInt32
|
||||
//}
|
||||
Reference in New Issue
Block a user