2026-01-26 22:52:56 +08:00
|
|
|
import json
|
|
|
|
|
import typing
|
|
|
|
|
import utils
|
2026-02-15 10:58:58 +08:00
|
|
|
import enum
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BEnumEntryFlagKind(enum.StrEnum):
|
|
|
|
|
"""
|
|
|
|
|
The kind of enum entry value.
|
|
|
|
|
This kind indicates whether this enum entry belong to a flag enum.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
NotFlag = "not-flag"
|
|
|
|
|
"""
|
|
|
|
|
This enum entry can not belong to a flag enum.
|
|
|
|
|
Because its value is ordinary.
|
|
|
|
|
"""
|
|
|
|
|
MayFlag = "may-flag"
|
|
|
|
|
"""
|
|
|
|
|
This enum entry may belong to a flag enum.
|
|
|
|
|
Because its value is in HEX format, and refering other members.
|
|
|
|
|
"""
|
|
|
|
|
MustFlag = "must-flag"
|
|
|
|
|
"""
|
|
|
|
|
This enum entry must belong to a flag enum.
|
|
|
|
|
Because its value use bitwise operation.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BEnumEntrySignKind(enum.StrEnum):
|
|
|
|
|
"""
|
|
|
|
|
The kind of enum entry value.
|
|
|
|
|
This kind indicates the sign of this enum entry value.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
Positive = "positive"
|
|
|
|
|
"""The value of this enum entry is positive number or zero."""
|
|
|
|
|
Negative = "negative"
|
|
|
|
|
"""he value of this enum entry is negative number."""
|
|
|
|
|
Unknown = "unknown"
|
|
|
|
|
"""
|
|
|
|
|
The value of this enum entry is unknown.
|
|
|
|
|
This is may be caused by that it refer other memeber.
|
|
|
|
|
"""
|
2026-01-26 22:52:56 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class BEnumEntry:
|
|
|
|
|
"""The struct to describe the entry of an enum."""
|
|
|
|
|
|
|
|
|
|
__entry_name: str
|
|
|
|
|
"""The name of this entry."""
|
|
|
|
|
__entry_value: str | None
|
|
|
|
|
"""The value of this entry. None if this entry do not have explicit value."""
|
2026-02-15 10:58:58 +08:00
|
|
|
__entry_flag_kind: BEnumEntryFlagKind
|
|
|
|
|
"""The flag kind of this entry value."""
|
|
|
|
|
__entry_sign_kind: BEnumEntrySignKind
|
|
|
|
|
"""The sign kind of this entry value."""
|
2026-01-26 22:52:56 +08:00
|
|
|
__entry_comment: str | None
|
|
|
|
|
"""The comment of this entry. None if no comment."""
|
|
|
|
|
|
|
|
|
|
def __init__(
|
2026-02-15 10:58:58 +08:00
|
|
|
self,
|
|
|
|
|
entry_name: str,
|
|
|
|
|
entry_value: str | None,
|
|
|
|
|
entry_flag_kind: BEnumEntryFlagKind,
|
|
|
|
|
entry_sign_kind: BEnumEntrySignKind,
|
|
|
|
|
entry_comment: str | None,
|
2026-01-26 22:52:56 +08:00
|
|
|
):
|
|
|
|
|
self.__entry_name = entry_name
|
|
|
|
|
self.__entry_value = entry_value
|
2026-02-15 10:58:58 +08:00
|
|
|
self.__entry_flag_kind = entry_flag_kind
|
|
|
|
|
self.__entry_sign_kind = entry_sign_kind
|
2026-01-26 22:52:56 +08:00
|
|
|
self.__entry_comment = entry_comment
|
|
|
|
|
|
|
|
|
|
def get_entry_name(self) -> str:
|
|
|
|
|
"""Get the name of this entry."""
|
|
|
|
|
return self.__entry_name
|
|
|
|
|
|
|
|
|
|
def get_entry_value(self) -> str | None:
|
|
|
|
|
"""Get the value of this entry. None if this entry do not have explicit value."""
|
|
|
|
|
return self.__entry_value
|
|
|
|
|
|
|
|
|
|
def get_entry_comment(self) -> str | None:
|
|
|
|
|
"""Get the comment of this entry. None if no comment."""
|
|
|
|
|
return self.__entry_comment
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def from_json(data: dict[str, typing.Any]) -> "BEnumEntry":
|
|
|
|
|
return BEnumEntry(
|
|
|
|
|
data["name"],
|
|
|
|
|
data.get("value", None),
|
2026-02-15 10:58:58 +08:00
|
|
|
BEnumEntryFlagKind(data.get("flag_kind")),
|
|
|
|
|
BEnumEntrySignKind(data.get("sign_kind")),
|
2026-01-26 22:52:56 +08:00
|
|
|
data.get("comment", None),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BHierarchyEnumEntry(BEnumEntry):
|
|
|
|
|
"""
|
|
|
|
|
The specialized EnumEntry type which can store extra hierarchy info.
|
|
|
|
|
Used in CK_CLASSID parsing.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
__hierarchy: list[str]
|
|
|
|
|
"""
|
|
|
|
|
The list to store this CK_CLASSID inheritance relationship.
|
|
|
|
|
The first item is the oldest parent in inheritance.
|
|
|
|
|
The last item is self.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
|
self,
|
|
|
|
|
entry_name: str,
|
|
|
|
|
entry_value: str | None,
|
2026-02-15 10:58:58 +08:00
|
|
|
entry_flag_kind: BEnumEntryFlagKind,
|
|
|
|
|
entry_sign_kind: BEnumEntrySignKind,
|
2026-01-26 22:52:56 +08:00
|
|
|
entry_comment: str | None,
|
|
|
|
|
hierarchy: list[str],
|
|
|
|
|
):
|
2026-02-15 10:58:58 +08:00
|
|
|
super().__init__(entry_name, entry_value, entry_flag_kind, entry_sign_kind, entry_comment)
|
2026-01-26 22:52:56 +08:00
|
|
|
self.__hierarchy = hierarchy
|
|
|
|
|
|
|
|
|
|
def iter_hierarchy(self, benum: "BEnum") -> typing.Iterator["BHierarchyEnumEntry"]:
|
|
|
|
|
return map(
|
|
|
|
|
lambda e: typing.cast(BHierarchyEnumEntry, benum.get_entry_by_name(e)),
|
|
|
|
|
self.__hierarchy,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def from_json(data: dict[str, typing.Any]) -> "BHierarchyEnumEntry":
|
|
|
|
|
return BHierarchyEnumEntry(
|
|
|
|
|
data["name"],
|
|
|
|
|
data.get("value", None),
|
2026-02-15 10:58:58 +08:00
|
|
|
BEnumEntryFlagKind(data.get("flag_kind")),
|
|
|
|
|
BEnumEntrySignKind(data.get("sign_kind")),
|
2026-01-26 22:52:56 +08:00
|
|
|
data.get("comment", None),
|
|
|
|
|
data["hierarchy"],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BEnum:
|
|
|
|
|
"""The struct to describe an enum."""
|
|
|
|
|
|
|
|
|
|
__enum_name: str
|
|
|
|
|
"""The name of this enum."""
|
|
|
|
|
__enum_comment: str | None
|
|
|
|
|
"""The comment of this enum. None if no comment."""
|
2026-02-11 22:49:54 +08:00
|
|
|
__is_unsigned: bool
|
2026-01-26 22:52:56 +08:00
|
|
|
"""True if this enum can use unsigned integer as its underlying type."""
|
2026-02-11 22:49:54 +08:00
|
|
|
__is_flag: bool
|
2026-01-26 22:52:56 +08:00
|
|
|
"""True if this enum will use flags feature (supporting OR, AND, operators)."""
|
|
|
|
|
__entries: list[BEnumEntry]
|
|
|
|
|
"""The list to store entries of this enum."""
|
|
|
|
|
|
|
|
|
|
__entries_map: dict[str, BEnumEntry]
|
|
|
|
|
"""The name map for `entries`."""
|
|
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
|
self,
|
|
|
|
|
enum_name: str,
|
|
|
|
|
enum_comment: str | None,
|
2026-02-11 22:49:54 +08:00
|
|
|
is_unsigned: bool,
|
|
|
|
|
is_flag: bool,
|
2026-01-26 22:52:56 +08:00
|
|
|
entries: list[BEnumEntry],
|
|
|
|
|
):
|
|
|
|
|
self.__enum_name = enum_name
|
|
|
|
|
self.__enum_comment = enum_comment
|
2026-02-11 22:49:54 +08:00
|
|
|
self.__is_unsigned = is_unsigned
|
|
|
|
|
self.__is_flag = is_flag
|
2026-01-26 22:52:56 +08:00
|
|
|
self.__entries = entries
|
|
|
|
|
self.__entries_map = {e.get_entry_name(): e for e in entries}
|
|
|
|
|
|
|
|
|
|
def get_enum_name(self) -> str:
|
|
|
|
|
"""Get the name of this enum."""
|
|
|
|
|
return self.__enum_name
|
|
|
|
|
|
|
|
|
|
def get_enum_comment(self) -> str | None:
|
|
|
|
|
"""Get the comment of this enum. None if no comment."""
|
|
|
|
|
return self.__enum_comment
|
|
|
|
|
|
2026-02-11 22:49:54 +08:00
|
|
|
def is_unsigned(self) -> bool:
|
2026-01-26 22:52:56 +08:00
|
|
|
"""True if this enum can use unsigned integer as its underlying type."""
|
2026-02-11 22:49:54 +08:00
|
|
|
return self.__is_unsigned
|
2026-01-26 22:52:56 +08:00
|
|
|
|
2026-02-11 22:49:54 +08:00
|
|
|
def is_flag(self) -> bool:
|
2026-01-26 22:52:56 +08:00
|
|
|
"""True if this enum will use flags feature (supporting OR, AND, operators)."""
|
2026-02-11 22:49:54 +08:00
|
|
|
return self.__is_flag
|
2026-01-26 22:52:56 +08:00
|
|
|
|
|
|
|
|
def iter_entries(self) -> typing.Iterator[BEnumEntry]:
|
|
|
|
|
"""Get the iterator of entries of this enum."""
|
|
|
|
|
return iter(self.__entries)
|
|
|
|
|
|
|
|
|
|
def get_entry_by_name(self, name: str) -> BEnumEntry:
|
|
|
|
|
return self.__entries_map[name]
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def from_json(data: dict[str, typing.Any]) -> "BEnum":
|
|
|
|
|
return BEnum(
|
|
|
|
|
data["name"],
|
|
|
|
|
data.get("comment", None),
|
2026-02-11 22:49:54 +08:00
|
|
|
data["is_unsigned"],
|
|
|
|
|
data["is_flag"],
|
2026-01-26 22:52:56 +08:00
|
|
|
list(map(lambda i: BEnum.__create_entry_by_content(i), data["entries"])),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def __create_entry_by_content(data: dict[str, typing.Any]) -> "BEnumEntry":
|
|
|
|
|
if "hierarchy" in data:
|
|
|
|
|
return BHierarchyEnumEntry.from_json(data)
|
|
|
|
|
else:
|
|
|
|
|
return BEnumEntry.from_json(data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BEnumCollection:
|
|
|
|
|
"""The struct to describe a collection of enums."""
|
|
|
|
|
|
|
|
|
|
__enums: list[BEnum]
|
|
|
|
|
"""The list to store enums."""
|
|
|
|
|
|
|
|
|
|
def __init__(self, enums: list[BEnum]):
|
|
|
|
|
self.__enums = enums
|
|
|
|
|
|
|
|
|
|
def iter_enums(self) -> typing.Iterator[BEnum]:
|
|
|
|
|
"""Get the iterator of enums."""
|
|
|
|
|
return iter(self.__enums)
|
|
|
|
|
|
|
|
|
|
def get_enums_count(self) -> int:
|
|
|
|
|
"""Get the count of enums."""
|
|
|
|
|
return len(self.__enums)
|
|
|
|
|
|
|
|
|
|
def get_enum_by_index(self, index: int) -> BEnum:
|
|
|
|
|
"""Get the enum by index."""
|
|
|
|
|
return self.__enums[index]
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def from_json(data: list[typing.Any]) -> "BEnumCollection":
|
|
|
|
|
return BEnumCollection(list(map(lambda i: BEnum.from_json(i), data)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_enums(filename: str) -> BEnumCollection:
|
|
|
|
|
with open(utils.get_input_file_path(filename), "r", encoding="utf-8") as f:
|
|
|
|
|
return BEnumCollection.from_json(json.load(f))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def load_enum(filename: str) -> BEnum:
|
|
|
|
|
collection = load_enums(filename)
|
|
|
|
|
assert collection.get_enums_count() == 1
|
|
|
|
|
return collection.get_enum_by_index(0)
|