92 lines
3.4 KiB
Swift
92 lines
3.4 KiB
Swift
/**
|
|
* 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
|
|
//}
|