<commit_before>package androidbinary

import (
	"encoding/binary"
	"fmt"
	"io"
	"strconv"
	"strings"
	"unsafe"
)

// ResID is ID for resources.
type ResID uint32

// TableFile is a resrouce table file.
type TableFile struct {
	stringPool    *ResStringPool
	tablePackages map[uint32]*TablePackage
}

// ResTableHeader is a header of TableFile.
type ResTableHeader struct {
	Header       ResChunkHeader
	PackageCount uint32
}

// ResTablePackage is a header of table packages.
type ResTablePackage struct {
	Header         ResChunkHeader
	ID             uint32
	Name           [128]uint16
	TypeStrings    uint32
	LastPublicType uint32
	KeyStrings     uint32
	LastPublicKey  uint32
}

// TablePackage is a table package.
type TablePackage struct {
	Header      ResTablePackage
	TypeStrings *ResStringPool
	KeyStrings  *ResStringPool
	TableTypes  []*TableType
}

// ResTableType is a type of a table.
type ResTableType struct {
	Header       ResChunkHeader
	ID           uint8
	Res0         uint8
	Res1         uint16
	EntryCount   uint32
	EntriesStart uint32
	Config       ResTableConfig
}

// ScreenLayout describes screen layout.
type ScreenLayout uint8

// ScreenLayout bits
const (
	MaskScreenSize   ScreenLayout = 0x0f
	ScreenSizeAny    ScreenLayout = 0x01
	ScreenSizeSmall  ScreenLayout = 0x02
	ScreenSizeNormal ScreenLayout = 0x03
	ScreenSizeLarge  ScreenLayout = 0x04
	ScreenSizeXLarge ScreenLayout = 0x05

	MaskScreenLong  ScreenLayout = 0x30
	ShiftScreenLong              = 4
	ScreenLongAny   ScreenLayout = 0x00
	ScreenLongNo    ScreenLayout = 0x10
	ScreenLongYes   ScreenLayout = 0x20

	MaskLayoutDir  ScreenLayout = 0xC0
	ShiftLayoutDir              = 6
	LayoutDirAny   ScreenLayout = 0x00
	LayoutDirLTR   ScreenLayout = 0x40
	LayoutDirRTL   ScreenLayout = 0x80
)

// UIMode describes UI mode.
type UIMode uint8

// UIMode bits
const (
	MaskUIModeType   UIMode = 0x0f
	UIModeTypeAny    UIMode = 0x01
	UIModeTypeNormal UIMode = 0x02
	UIModeTypeDesk   UIMode = 0x03
	UIModeTypeCar    UIMode = 0x04

	MaskUIModeNight  UIMode = 0x30
	ShiftUIModeNight        = 4
	UIModeNightAny   UIMode = 0x00
	UIModeNightNo    UIMode = 0x10
	UIModeNightYes   UIMode = 0x20
)

// InputFlags are input flags.
type InputFlags uint8

// input flags
const (
	MaskKeysHidden InputFlags = 0x03
	KeysHiddenAny  InputFlags = 0x00
	KeysHiddenNo   InputFlags = 0x01
	KeysHiddenYes  InputFlags = 0x02
	KeysHiddenSoft InputFlags = 0x03

	MaskNavHidden InputFlags = 0x0c
	NavHiddenAny  InputFlags = 0x00
	NavHiddenNo   InputFlags = 0x04
	NavHiddenYes  InputFlags = 0x08
)

// ResTableConfig is a configuration of a table.
type ResTableConfig struct {
	Size uint32
	// imsi
	Mcc uint16
	Mnc uint16

	// locale
	Language [2]uint8
	Country  [2]uint8

	// screen type
	Orientation uint8
	Touchscreen uint8
	Density     uint16

	// inout
	Keyboard   uint8
	Navigation uint8
	InputFlags InputFlags
	InputPad0  uint8

	// screen size
	ScreenWidth  uint16
	ScreenHeight uint16

	// version
	SDKVersion   uint16
	MinorVersion uint16

	// screen config
	ScreenLayout          ScreenLayout
	UIMode                UIMode
	SmallestScreenWidthDp uint16

	// screen size dp
	ScreenWidthDp  uint16
	ScreenHeightDp uint16
}

// TableType is a collection of resource entries for a particular resource data type.
type TableType struct {
	Header  *ResTableType
	Entries []TableEntry
}

// ResTableEntry is the beginning of information about an entry in the resource table.
type ResTableEntry struct {
	Size  uint16
	Flags uint16
	Key   ResStringPoolRef
}

// TableEntry is a entry in a recource table.
type TableEntry struct {
	Key   *ResTableEntry
	Value *ResValue
	Flags uint32
}

// ResTableTypeSpec is specification of the resources defined by a particular type.
type ResTableTypeSpec struct {
	Header     ResChunkHeader
	ID         uint8
	Res0       uint8
	Res1       uint16
	EntryCount uint32
}

// IsResID returns whether s is ResId.
func IsResID(s string) bool {
	return strings.HasPrefix(s, "@0x")
}

// ParseResID parses ResId.
func ParseResID(s string) (ResID, error) {
	if !IsResID(s) {
		return 0, fmt.Errorf("androidbinary: %s is not ResID", s)
	}
	id, err := strconv.ParseUint(s[3:], 16, 32)
	if err != nil {
		return 0, err
	}
	return ResID(id), nil
}

func (id ResID) String() string {
	return fmt.Sprintf("@0x%08X", uint32(id))
}

// Package returns the package index of id.
func (id ResID) Package() int {
	return int(id) >> 24
}

// Type returns the type index of id.
func (id ResID) Type() int {
	return (int(id) >> 16) & 0xFF
}

// Entry returns the entry index of id.
func (id ResID) Entry() int {
	return int(id) & 0xFFFF
}

// NewTableFile returns new TableFile.
func NewTableFile(r io.ReaderAt) (*TableFile, error) {
	f := new(TableFile)
	sr := io.NewSectionReader(r, 0, 1<<63-1)

	header := new(ResTableHeader)
	binary.Read(sr, binary.LittleEndian, header)
	f.tablePackages = make(map[uint32]*TablePackage)

	offset := int64(header.Header.HeaderSize)
	for offset < int64(header.Header.Size) {
		chunkHeader, err := f.readChunk(sr, offset)
		if err != nil {
			return nil, err
		}
		offset += int64(chunkHeader.Size)
	}
	return f, nil
}

func (f *TableFile) findPackage(id int) *TablePackage {
	return f.tablePackages[uint32(id)]
}

func (p *TablePackage) findEntry(typeIndex, entryIndex int, config *ResTableConfig) TableEntry {
	var best *TableType
	for _, t := range p.TableTypes {
		switch {
		case int(t.Header.ID) != typeIndex:
			// nothing to do
		case !t.Header.Config.Match(config):
			// nothing to do
		case entryIndex >= len(t.Entries):
			// nothing to do
		case t.Entries[entryIndex].Value == nil:
			// nothing to do
		case best == nil || t.Header.Config.IsBetterThan(&best.Header.Config, config):
			best = t
		}
	}
	if best == nil || entryIndex >= len(best.Entries) {
		return TableEntry{}
	}
	return best.Entries[entryIndex]
}

// GetResource returns a resrouce referenced by id.
func (f *TableFile) GetResource(id ResID, config *ResTableConfig) (interface{}, error) {
	p := f.findPackage(id.Package())
	if p == nil {<commit_msg>Use uint32 everywhere and fix null deref in resource parser<commit_after>package androidbinary

import (
	"encoding/binary"
	"fmt"
	"io"
	"strconv"
	"strings"
	"unsafe"
)

// ResID is ID for resources.
type ResID uint32

// TableFile is a resrouce table file.
type TableFile struct {
	stringPool    *ResStringPool
	tablePackages map[uint32]*TablePackage
}

// ResTableHeader is a header of TableFile.
type ResTableHeader struct {
	Header       ResChunkHeader
	PackageCount uint32
}

// ResTablePackage is a header of table packages.
type ResTablePackage struct {
	Header         ResChunkHeader
	ID             uint32
	Name           [128]uint16
	TypeStrings    uint32
	LastPublicType uint32
	KeyStrings     uint32
	LastPublicKey  uint32
}

// TablePackage is a table package.
type TablePackage struct {
	Header      ResTablePackage
	TypeStrings *ResStringPool
	KeyStrings  *ResStringPool
	TableTypes  []*TableType
}

// ResTableType is a type of a table.
type ResTableType struct {
	Header       ResChunkHeader
	ID           uint8
	Res0         uint8
	Res1         uint16
	EntryCount   uint32
	EntriesStart uint32
	Config       ResTableConfig
}

// ScreenLayout describes screen layout.
type ScreenLayout uint8

// ScreenLayout bits
const (
	MaskScreenSize   ScreenLayout = 0x0f
	ScreenSizeAny    ScreenLayout = 0x01
	ScreenSizeSmall  ScreenLayout = 0x02
	ScreenSizeNormal ScreenLayout = 0x03
	ScreenSizeLarge  ScreenLayout = 0x04
	ScreenSizeXLarge ScreenLayout = 0x05

	MaskScreenLong  ScreenLayout = 0x30
	ShiftScreenLong              = 4
	ScreenLongAny   ScreenLayout = 0x00
	ScreenLongNo    ScreenLayout = 0x10
	ScreenLongYes   ScreenLayout = 0x20

	MaskLayoutDir  ScreenLayout = 0xC0
	ShiftLayoutDir              = 6
	LayoutDirAny   ScreenLayout = 0x00
	LayoutDirLTR   ScreenLayout = 0x40
	LayoutDirRTL   ScreenLayout = 0x80
)

// UIMode describes UI mode.
type UIMode uint8

// UIMode bits
const (
	MaskUIModeType   UIMode = 0x0f
	UIModeTypeAny    UIMode = 0x01
	UIModeTypeNormal UIMode = 0x02
	UIModeTypeDesk   UIMode = 0x03
	UIModeTypeCar    UIMode = 0x04

	MaskUIModeNight  UIMode = 0x30
	ShiftUIModeNight        = 4
	UIModeNightAny   UIMode = 0x00
	UIModeNightNo    UIMode = 0x10
	UIModeNightYes   UIMode = 0x20
)

// InputFlags are input flags.
type InputFlags uint8

// input flags
const (
	MaskKeysHidden InputFlags = 0x03
	KeysHiddenAny  InputFlags = 0x00
	KeysHiddenNo   InputFlags = 0x01
	KeysHiddenYes  InputFlags = 0x02
	KeysHiddenSoft InputFlags = 0x03

	MaskNavHidden InputFlags = 0x0c
	NavHiddenAny  InputFlags = 0x00
	NavHiddenNo   InputFlags = 0x04
	NavHiddenYes  InputFlags = 0x08
)

// ResTableConfig is a configuration of a table.
type ResTableConfig struct {
	Size uint32
	// imsi
	Mcc uint16
	Mnc uint16

	// locale
	Language [2]uint8
	Country  [2]uint8

	// screen type
	Orientation uint8
	Touchscreen uint8
	Density     uint16

	// inout
	Keyboard   uint8
	Navigation uint8
	InputFlags InputFlags
	InputPad0  uint8

	// screen size
	ScreenWidth  uint16
	ScreenHeight uint16

	// version
	SDKVersion   uint16
	MinorVersion uint16

	// screen config
	ScreenLayout          ScreenLayout
	UIMode                UIMode
	SmallestScreenWidthDp uint16

	// screen size dp
	ScreenWidthDp  uint16
	ScreenHeightDp uint16
}

// TableType is a collection of resource entries for a particular resource data type.
type TableType struct {
	Header  *ResTableType
	Entries []TableEntry
}

// ResTableEntry is the beginning of information about an entry in the resource table.
type ResTableEntry struct {
	Size  uint16
	Flags uint16
	Key   ResStringPoolRef
}

// TableEntry is a entry in a recource table.
type TableEntry struct {
	Key   *ResTableEntry
	Value *ResValue
	Flags uint32
}

// ResTableTypeSpec is specification of the resources defined by a particular type.
type ResTableTypeSpec struct {
	Header     ResChunkHeader
	ID         uint8
	Res0       uint8
	Res1       uint16
	EntryCount uint32
}

// IsResID returns whether s is ResId.
func IsResID(s string) bool {
	return strings.HasPrefix(s, "@0x")
}

// ParseResID parses ResId.
func ParseResID(s string) (ResID, error) {
	if !IsResID(s) {
		return 0, fmt.Errorf("androidbinary: %s is not ResID", s)
	}
	id, err := strconv.ParseUint(s[3:], 16, 32)
	if err != nil {
		return 0, err
	}
	return ResID(id), nil
}

func (id ResID) String() string {
	return fmt.Sprintf("@0x%08X", uint32(id))
}

// Package returns the package index of id.
func (id ResID) Package() uint32 {
	return uint32(id) >> 24
}

// Type returns the type index of id.
func (id ResID) Type() int {
	return (int(id) >> 16) & 0xFF
}

// Entry returns the entry index of id.
func (id ResID) Entry() int {
	return int(id) & 0xFFFF
}

// NewTableFile returns new TableFile.
func NewTableFile(r io.ReaderAt) (*TableFile, error) {
	f := new(TableFile)
	sr := io.NewSectionReader(r, 0, 1<<63-1)

	header := new(ResTableHeader)
	binary.Read(sr, binary.LittleEndian, header)
	f.tablePackages = make(map[uint32]*TablePackage)

	offset := int64(header.Header.HeaderSize)
	for offset < int64(header.Header.Size) {
		chunkHeader, err := f.readChunk(sr, offset)
		if err != nil {
			return nil, err
		}
		offset += int64(chunkHeader.Size)
	}
	return f, nil
}

func (f *TableFile) findPackage(id uint32) *TablePackage {
	if f == nil {
		return nil
	}
	return f.tablePackages[id]
}

func (p *TablePackage) findEntry(typeIndex, entryIndex int, config *ResTableConfig) TableEntry {
	var best *TableType
	for _, t := range p.TableTypes {
		switch {
		case int(t.Header.ID) != typeIndex:
			// nothing to do
		case !t.Header.Config.Match(config):
			// nothing to do
		case entryIndex >= len(t.Entries):
			// nothing to do
		case t.Entries[entryIndex].Value == nil:
			// nothing to do
		case best == nil || t.Header.Config.IsBetterThan(&best.Header.Config, config):
			best = t
		}
	}
	if best == nil || entryIndex >= len(best.Entries) {
		return TableEntry{}
	}
	return best.Entries[entryIndex]
}

// GetResource returns a resrouce referenced by id.
func (f *TableFile) GetResource(id ResID, config *ResTableConfig) (interface{}, error) {
	p := f.findPackage(id.Package())
	if p == nil {
{'fraction_non_alphanumeric': 0.0785831960461285, 'fraction_numerical': 0.034925864909390446, 'mean_word_length': 3.414909090909091, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3445910', 'n_tokens_mistral': 4418, 'n_tokens_neox': 4081, 'n_words': 1240}