Source code for caterpillar.byteorder
# Copyright (C) MatrixEditor 2023-2025
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from sys import maxsize
from platform import machine
from dataclasses import dataclass
from enum import Enum
from caterpillar.shared import ATTR_BYTEORDER
[docs]
@dataclass(frozen=True)
class ByteOrder:
"""
Represents byte order information, including alignment and size.
:param name: A string representing the name of the byte order.
:param ch: A string representing the character used to specify the byte
order in struct format strings.
:param alignment: An enumeration representing the alignment (default
is `Alignment.NONE`).
:param size: An enumeration representing the size (default is
`Size.STANDARD`).
"""
name: str
ch: str
[docs]
class Alignment(Enum):
NONE = 0
NATIVE = 1
alignment: Alignment = Alignment.NONE
[docs]
class Size(Enum):
STANDARD = 0
NATIVE = 1
size: Size = Size.STANDARD
[docs]
def apply(self, other):
"""
Applies the byte order information to another object.
:param other: The object to which the byte order information should be applied.
"""
setattr(other, ATTR_BYTEORDER, self)
def __add__(self, other):
"""
Adds the byte order information to another object using the
`__set_byteorder__` method.
:param other: The object to which the byte order information should be added.
:return: The modified object.
"""
return other.__set_byteorder__(self)
def __or__(self, other):
"""
Applies the byte order information to another object using the `apply` method.
:param other: The object to which the byte order information should be applied.
:return: The modified object.
"""
self.apply(other)
return other
LITTLE_ENDIAN_FMT = "<"
# Instances representing commonly used byte orders
Native = ByteOrder("Native", "=")
BigEndian = ByteOrder("Big Endian", ">")
LittleEndian = ByteOrder("Little Endian", LITTLE_ENDIAN_FMT)
NetEndian = ByteOrder("Network", "!")
SysNative = ByteOrder(
"SysNative", "@", ByteOrder.Alignment.NATIVE, ByteOrder.Size.NATIVE
)
[docs]
def byteorder(obj, default=None):
"""
Get the byte order of an object, defaulting to SysNative if not explicitly set.
:param obj: The object to retrieve the byte order from.
:return: The byte order of the object.
"""
return getattr(obj, ATTR_BYTEORDER, default or SysNative)
[docs]
@dataclass(frozen=True)
class Arch:
"""
Represents a system architecture with a name and an indication of whether it is 64-bit.
:param name: The name of the architecture.
:param ptr_size: the amount of bits one pointer takes
"""
name: str
ptr_size: int
system_arch: Arch = Arch(machine(), 64 if maxsize > 2**32 else 32)
# common architectures
x86 = Arch("x86", 32)
x86_64 = Arch("x86-64", 64)
ARM = Arch("ARM", 32)
ARM64 = Arch("ARM64", 64)
AARCH64 = ARM64
PowerPC = Arch("PowerPC", 32)
PowerPC64 = Arch("PowerPC64", 64)
MIPS = Arch("MIPS", 32)
MIPS64 = Arch("MIPS64", 64)
SPARC = Arch("SPARC", 32)
SPARC64 = Arch("SPARC64", 64)
RISC_V64 = Arch("RISK-V64", 64)
RISC_V = Arch("RISK-V", 32)
AMD = Arch("AMD", 32)
AMD64 = Arch("AMD64", 64)