This commit is contained in:
relikd
2025-11-25 22:46:14 +01:00
commit a28636a7ca
28 changed files with 2380 additions and 0 deletions

View 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
//}