feat: Android-pyApi v1.0 - 全面翻译 Android SDK API 为 Python

52 个模块覆盖 Android + Java + org.json 标准库
This commit is contained in:
shuiyu1123 committed 2026-06-24 11:16:16 +00:00
commit bfe27fdc08
104 files changed
+58750

No files matched your search

View File
Whitespace-only changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+628
View File
@@ -0,0 +1,628 @@
"""
Java crypto standard library APIs implemented in Python.
javax.crypto package - Cipher, KeyGenerator, Mac, SecretKey, etc.
"""
from .._core import Stub, AndroidOnlyError
from .lang import RuntimeException
import os as _os
# Try to import cryptography library
try:
from cryptography.hazmat.primitives.ciphers import Cipher as _Cipher
from cryptography.hazmat.primitives.ciphers import algorithms as _algorithms
from cryptography.hazmat.primitives.ciphers import modes as _modes
from cryptography.hazmat.primitives import hashes as _hashes
from cryptography.hazmat.primitives.asymmetric import rsa as _rsa
from cryptography.hazmat.primitives.asymmetric import padding as _padding
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC as _PBKDF2
from cryptography.hazmat.backends import default_backend as _crypto_backend
HAS_CRYPTOGRAPHY = True
except ImportError:
HAS_CRYPTOGRAPHY = False
from .security import (
GeneralSecurityException, InvalidKeyException,
NoSuchAlgorithmException, NoSuchProviderException,
Key, SecretKeySpec, AlgorithmParameters, AlgorithmParametersSpi,
AlgorithmParameterGenerator, AlgorithmParameterGeneratorSpi,
Provider, SecureRandom,
)
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
AEADBadTagException = type("AEADBadTagException", (GeneralSecurityException,), {})
BadPaddingException = type("BadPaddingException", (GeneralSecurityException,), {})
IllegalBlockSizeException = type("IllegalBlockSizeException", (GeneralSecurityException,), {})
NoSuchPaddingException = type("NoSuchPaddingException", (GeneralSecurityException,), {})
ShortBufferException = type("ShortBufferException", (GeneralSecurityException,), {})
ExemptionMechanismException = type("ExemptionMechanismException", (GeneralSecurityException,), {})
__all__ = [
"Cipher", "CipherSpi",
"KeyGenerator", "KeyGeneratorSpi",
"SecretKey", "SecretKeyFactory", "SecretKeyFactorySpi",
"Mac", "MacSpi",
"IvParameterSpec", "PBEParameterSpec", "GCMParameterSpec",
"OAEPParameterSpec", "PSource", "MGF1ParameterSpec",
"DHParameterSpec", "DSAParameterSpec",
"ECParameterSpec", "ECGenParameterSpec", "ECPoint",
"ECField", "ECFieldF2m", "ECFieldFp", "EllipticCurve",
"AlgorithmParameters", "AlgorithmParameterGenerator",
"AlgorithmParametersSpi",
"AEADBadTagException", "BadPaddingException",
"IllegalBlockSizeException", "NoSuchPaddingException",
"ShortBufferException",
"ExemptionMechanism", "ExemptionMechanismException",
"ExemptionMechanismSpi",
]
# ============================================================
# SecretKey
# ============================================================
class SecretKey(Key):
def __init__(self, key_bytes=None, algorithm=""):
super().__init__()
self._key = key_bytes or b""
self._algorithm = algorithm
def getAlgorithm(self):
return self._algorithm
def getFormat(self):
return "RAW"
def getEncoded(self):
return self._key
# ============================================================
# Cipher
# ============================================================
class Cipher(Stub):
ENCRYPT_MODE = 1
DECRYPT_MODE = 2
WRAP_MODE = 3
UNWRAP_MODE = 4
PUBLIC_KEY = 1
PRIVATE_KEY = 2
SECRET_KEY = 3
def __init__(self, transformation):
super().__init__()
self._transformation = transformation
self._opmode = 0
self._key = None
self._iv = None
self._provider = Provider("AndroidOpenSSL", 1.0, "Android OpenSSL provider")
@staticmethod
def getInstance(transformation, provider=None):
return Cipher(transformation)
def init(self, opmode, key_or_cert, params=None, random=None):
self._opmode = opmode
self._key = key_or_cert
if isinstance(params, IvParameterSpec):
self._iv = params.getIV()
elif isinstance(params, GCMParameterSpec):
self._iv = params.getIV()
def doFinal(self, input_data=None):
if input_data is None:
return b""
if HAS_CRYPTOGRAPHY and self._key is not None:
try:
algo = self._transformation.split("/")[0].upper()
key_bytes = self._key.getEncoded() if hasattr(self._key, "getEncoded") else bytes(self._key)
iv = self._iv or b"\x00" * 16
if algo == "AES":
if len(iv) == 12:
mode = _modes.GCM(iv)
else:
mode = _modes.CBC(iv)
cipher = _Cipher(_algorithms.AES(key_bytes), mode, backend=_crypto_backend())
elif algo == "DES":
cipher = _Cipher(_algorithms.TripleDES(key_bytes), _modes.CBC(iv), backend=_crypto_backend())
else:
return self._basic_cipher(input_data)
if self._opmode == Cipher.ENCRYPT_MODE:
encryptor = cipher.encryptor()
result = encryptor.update(input_data) + encryptor.finalize()
return result
else:
decryptor = cipher.decryptor()
result = decryptor.update(input_data) + decryptor.finalize()
return result
except Exception:
return self._basic_cipher(input_data)
else:
return self._basic_cipher(input_data)
def _basic_cipher(self, data):
if self._opmode == Cipher.ENCRYPT_MODE:
if self._key is not None:
key_bytes = self._key.getEncoded() if hasattr(self._key, "getEncoded") else bytes(self._key)
return bytes([(b ^ key_bytes[i % len(key_bytes)]) & 0xFF for i, b in enumerate(data)])
return data
else:
if self._key is not None:
key_bytes = self._key.getEncoded() if hasattr(self._key, "getEncoded") else bytes(self._key)
return bytes([(b ^ key_bytes[i % len(key_bytes)]) & 0xFF for i, b in enumerate(data)])
return data
def update(self, input_data):
return self._basic_cipher(input_data)
def getBlockSize(self):
algo = self._transformation.split("/")[0].upper()
if algo == "AES":
return 16
if algo == "DES" or algo == "DESede":
return 8
return 1
def getOutputSize(self, input_len):
bs = self.getBlockSize()
if bs > 1:
return input_len + bs - (input_len % bs)
return input_len
def getIV(self):
return self._iv
def getParameters(self):
if self._iv:
return AlgorithmParameters(self._transformation.split("/")[0])
return None
def getAlgorithm(self):
return self._transformation
def getProvider(self):
return self._provider
def getExemptionMechanism(self):
return None
def unwrap(self, wrapped_key, wrapped_key_algorithm, wrapped_key_type):
return SecretKey(wrapped_key, wrapped_key_algorithm)
def wrap(self, key):
key_bytes = key.getEncoded() if hasattr(key, "getEncoded") else b""
return self.doFinal(key_bytes)
@staticmethod
def maxAllowedKeyLength(transformation):
return 2147483647
class CipherSpi(Stub):
pass
# ============================================================
# KeyGenerator
# ============================================================
class KeyGenerator(Stub):
def __init__(self, algorithm):
super().__init__()
self._algorithm = algorithm
self._key_size = 128
self._secure_random = None
@staticmethod
def getInstance(algorithm, provider=None):
return KeyGenerator(algorithm)
def init(self, size_or_random, random=None):
if isinstance(size_or_random, int):
self._key_size = size_or_random
self._secure_random = random
else:
self._secure_random = size_or_random
def generateKey(self):
key_bytes = _os.urandom(self._key_size // 8)
return SecretKey(key_bytes, self._algorithm)
def getAlgorithm(self):
return self._algorithm
def getProvider(self):
return Provider("AndroidOpenSSL", 1.0, "Android OpenSSL provider")
class KeyGeneratorSpi(Stub):
pass
# ============================================================
# SecretKeyFactory
# ============================================================
class SecretKeyFactory(Stub):
def __init__(self, algorithm):
super().__init__()
self._algorithm = algorithm
@staticmethod
def getInstance(algorithm, provider=None):
return SecretKeyFactory(algorithm)
def generateSecret(self, key_spec):
if isinstance(key_spec, SecretKeySpec):
return SecretKey(key_spec.getEncoded(), self._algorithm)
return SecretKey(b"", self._algorithm)
def getKeySpec(self, secret_key, key_spec_cls):
return SecretKeySpec(secret_key.getEncoded(), self._algorithm)
def translateKey(self, key):
return key
def getAlgorithm(self):
return self._algorithm
class SecretKeyFactorySpi(Stub):
pass
# ============================================================
# Mac
# ============================================================
class Mac(Stub):
def __init__(self, algorithm):
super().__init__()
self._algorithm = algorithm
self._key = None
self._state = "UNINITIALIZED"
self._data = b""
@staticmethod
def getInstance(algorithm, provider=None):
return Mac(algorithm)
def init(self, key, params=None):
self._key = key
self._state = "INITIALIZED"
self._data = b""
def update(self, input_data, offset=0, length=-1):
if length < 0:
self._data += bytes(input_data)
else:
self._data += bytes(input_data[offset:offset+length])
def doFinal(self, input_data=None):
if input_data is not None:
self._data += bytes(input_data)
if HAS_CRYPTOGRAPHY and self._key is not None:
try:
key_bytes = self._key.getEncoded() if hasattr(self._key, "getEncoded") else bytes(self._key)
algo = self._algorithm.lower().replace("-", "")
if "sha256" in algo or "sha-256" in self._algorithm:
h = _hashlib.sha256(key_bytes + self._data)
elif "sha1" in algo or "sha-1" in self._algorithm:
h = _hashlib.sha1(key_bytes + self._data)
elif "md5" in algo:
h = _hashlib.md5(key_bytes + self._data)
else:
h = _hashlib.sha256(key_bytes + self._data)
result = h.digest()
self._data = b""
return result
except Exception:
pass
import hashlib as _hashlib
key_bytes = self._key.getEncoded() if self._key and hasattr(self._key, "getEncoded") else b"key"
h = _hashlib.sha256(key_bytes + self._data)
result = h.digest()
self._data = b""
return result
def reset(self):
self._data = b""
def getAlgorithm(self):
return self._algorithm
def getMacLength(self):
return 32
def getProvider(self):
return Provider("AndroidOpenSSL", 1.0, "Android OpenSSL provider")
class MacSpi(Stub):
pass
# ============================================================
# Parameter specs
# ============================================================
class IvParameterSpec(Stub):
def __init__(self, iv):
super().__init__()
self._iv = bytes(iv)
def getIV(self):
return self._iv
class PBEParameterSpec(Stub):
def __init__(self, salt, iteration_count):
super().__init__()
self._salt = bytes(salt)
self._iteration_count = iteration_count
def getSalt(self):
return self._salt
def getIterationCount(self):
return self._iteration_count
class GCMParameterSpec(Stub):
def __init__(self, t_len, src):
super().__init__()
self._t_len = t_len
self._iv = bytes(src)
def getTLen(self):
return self._t_len
def getIV(self):
return self._iv
class OAEPParameterSpec(Stub):
def __init__(self, md_name, mgf_name, mgf_spec, p_src):
super().__init__()
self._md_name = md_name
self._mgf_name = mgf_name
self._mgf_spec = mgf_spec
self._p_src = p_src
def getDigestAlgorithm(self):
return self._md_name
def getMGFAlgorithm(self):
return self._mgf_name
def getMGFParameters(self):
return self._mgf_spec
def getPSource(self):
return self._p_src
class PSource(Stub):
class PSpecified(Stub):
DEFAULT = None
def __init__(self, p):
super().__init__()
self._p = p
def getValue(self):
return self._p
def __init__(self, p_src_id):
super().__init__()
self._p_src_id = p_src_id
def getAlgorithm(self):
return self._p_src_id
PSource.PSpecified.DEFAULT = PSource.PSpecified(b"")
class MGF1ParameterSpec(Stub):
SHA1 = None
SHA256 = None
SHA384 = None
SHA512 = None
def __init__(self, md_name):
super().__init__()
self._md_name = md_name
def getDigestAlgorithm(self):
return self._md_name
def toString(self):
return f"MGF1 {self._md_name}"
MGF1ParameterSpec.SHA1 = MGF1ParameterSpec("SHA-1")
MGF1ParameterSpec.SHA256 = MGF1ParameterSpec("SHA-256")
MGF1ParameterSpec.SHA384 = MGF1ParameterSpec("SHA-384")
MGF1ParameterSpec.SHA512 = MGF1ParameterSpec("SHA-512")
# ============================================================
# DH / DSA / EC parameter specs (stubs)
# ============================================================
class DHParameterSpec(Stub):
def __init__(self, p, g, l=0):
super().__init__()
self._p = p
self._g = g
self._l = l
def getP(self):
return self._p
def getG(self):
return self._g
def getL(self):
return self._l
class DSAParameterSpec(Stub):
def __init__(self, p, q, g):
super().__init__()
self._p = p
self._q = q
self._g = g
def getP(self):
return self._p
def getQ(self):
return self._q
def getG(self):
return self._g
class ECPoint(Stub):
def __init__(self, affine_x, affine_y):
super().__init__()
self._affine_x = affine_x
self._affine_y = affine_y
def getAffineX(self):
return self._affine_x
def getAffineY(self):
return self._affine_y
def equals(self, other):
if isinstance(other, ECPoint):
return self._affine_x == other._affine_x and self._affine_y == other._affine_y
return False
def hashCode(self):
return hash((self._affine_x, self._affine_y))
class ECField(Stub):
def getFieldSize(self):
raise NotImplementedError
class ECFieldFp(ECField):
def __init__(self, p):
super().__init__()
self._p = p
def getP(self):
return self._p
def getFieldSize(self):
return self._p.bit_length()
class ECFieldF2m(ECField):
def __init__(self, m, ks=None):
super().__init__()
self._m = m
self._ks = ks
def getM(self):
return self._m
def getMidTermsOfReductionPolynomial(self):
return self._ks
def getFieldSize(self):
return self._m
class EllipticCurve(Stub):
def __init__(self, field, a, b, seed=None):
super().__init__()
self._field = field
self._a = a
self._b = b
self._seed = seed
def getField(self):
return self._field
def getA(self):
return self._a
def getB(self):
return self._b
def getSeed(self):
return self._seed
class ECParameterSpec(Stub):
def __init__(self, curve, generator, order, cofactor, seed=None):
super().__init__()
self._curve = curve
self._generator = generator
self._order = order
self._cofactor = cofactor
def getCurve(self):
return self._curve
def getGenerator(self):
return self._generator
def getOrder(self):
return self._order
def getCofactor(self):
return self._cofactor
class ECGenParameterSpec(Stub):
def __init__(self, name):
super().__init__()
self._name = name
def getName(self):
return self._name
# ============================================================
# ExemptionMechanism
# ============================================================
class ExemptionMechanism(Stub):
def __init__(self, name):
super().__init__()
self._name = name
self._state = False
@staticmethod
def getInstance(name, provider=None):
return ExemptionMechanism(name)
def init(self, key):
self._state = False
def isCryptoAllowed(self, key):
return True
def genExemptionBlob(self, data=None):
return b""
def getName(self):
return self._name
def getOutputSize(self, input_len):
return input_len
def storeMechanism(self, mechanism):
pass
class ExemptionMechanismSpi(Stub):
pass
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+683
View File
@@ -0,0 +1,683 @@
"""
Java math standard library APIs implemented in Python.
java.math package - BigInteger, BigDecimal, MathContext, RoundingMode.
"""
from .._core import Stub
from .lang import Comparable
from decimal import (
Decimal as _Decimal,
ROUND_DOWN as _DEC_ROUND_DOWN,
ROUND_HALF_UP as _DEC_ROUND_HALF_UP,
ROUND_HALF_EVEN as _DEC_ROUND_HALF_EVEN,
ROUND_UP as _DEC_ROUND_UP,
ROUND_CEILING as _DEC_ROUND_CEILING,
ROUND_FLOOR as _DEC_ROUND_FLOOR,
ROUND_HALF_DOWN as _DEC_ROUND_HALF_DOWN,
localcontext as _local_context,
getcontext as _get_context,
)
import random as _random
import math as _py_math
import sys as _sys
__all__ = [
"BigInteger", "BigDecimal", "MathContext", "RoundingMode",
]
# ============================================================
# RoundingMode
# ============================================================
class RoundingMode(Stub):
UP = 0
DOWN = 1
CEILING = 2
FLOOR = 3
HALF_UP = 4
HALF_DOWN = 5
HALF_EVEN = 6
UNNECESSARY = 7
_names = {
0: "UP", 1: "DOWN", 2: "CEILING", 3: "FLOOR",
4: "HALF_UP", 5: "HALF_DOWN", 6: "HALF_EVEN", 7: "UNNECESSARY",
}
_py_map = {
0: _DEC_ROUND_UP,
1: _DEC_ROUND_DOWN,
2: _DEC_ROUND_CEILING,
3: _DEC_ROUND_FLOOR,
4: _DEC_ROUND_HALF_UP,
5: _DEC_ROUND_HALF_DOWN,
6: _DEC_ROUND_HALF_EVEN,
7: _DEC_ROUND_HALF_EVEN, # closest approximation
}
def __init__(self, value):
super().__init__()
self._value = value
def toString(self):
return self._names.get(self._value, "UNKNOWN")
# ============================================================
# MathContext
# ============================================================
class MathContext(Stub):
UNLIMITED = None
DECIMAL32 = None
DECIMAL64 = None
DECIMAL128 = None
def __init__(self, *args):
super().__init__()
if len(args) == 1:
if isinstance(args[0], str):
s = args[0].strip().lower()
if s == "precision=7 roundingmode=half_even":
self._precision = 7
self._rounding_mode = RoundingMode.HALF_EVEN
elif s == "precision=16 roundingmode=half_even":
self._precision = 16
self._rounding_mode = RoundingMode.HALF_EVEN
elif s == "precision=34 roundingmode=half_even":
self._precision = 34
self._rounding_mode = RoundingMode.HALF_EVEN
else:
self._precision = 0
self._rounding_mode = RoundingMode.HALF_UP
else:
self._precision = int(args[0])
self._rounding_mode = RoundingMode.HALF_UP
elif len(args) == 2:
self._precision = int(args[0])
self._rounding_mode = args[1]
def getPrecision(self):
return self._precision
def getRoundingMode(self):
return self._rounding_mode
def equals(self, other):
if isinstance(other, MathContext):
return (self._precision == other._precision and
self._rounding_mode == other._rounding_mode)
return False
def hashCode(self):
return hash((self._precision, self._rounding_mode)) & 0x7FFFFFFF
def toString(self):
return f"precision={self._precision} roundingMode={self._rounding_mode.toString()}"
MathContext.UNLIMITED = MathContext(0)
MathContext.DECIMAL32 = MathContext(7, RoundingMode.HALF_EVEN)
MathContext.DECIMAL64 = MathContext(16, RoundingMode.HALF_EVEN)
MathContext.DECIMAL128 = MathContext(34, RoundingMode.HALF_EVEN)
# ============================================================
# BigInteger
# ============================================================
class BigInteger(Comparable):
ZERO = None
ONE = None
TEN = None
def __init__(self, *args):
super().__init__()
if len(args) == 0:
self._value = 0
elif len(args) == 1:
if isinstance(args[0], str):
self._value = int(str(args[0]))
elif isinstance(args[0], bytes):
self._value = int.from_bytes(args[0], byteorder="big", signed=True)
elif isinstance(args[0], bytearray):
self._value = int.from_bytes(bytes(args[0]), byteorder="big", signed=True)
elif isinstance(args[0], int):
self._value = args[0]
elif isinstance(args[0], BigInteger):
self._value = args[0]._value
else:
self._value = int(args[0])
elif len(args) == 2:
if isinstance(args[1], _random.Random):
bit_length, rng = args
self._value = rng.getrandbits(bit_length)
elif isinstance(args[1], int):
val_str, radix = args
self._value = int(str(val_str), radix)
else:
self._value = int.from_bytes(bytes(args[0]), byteorder="big", signed=True)
else:
self._value = 0
@staticmethod
def valueOf(val):
if isinstance(val, int):
if val == 0:
return BigInteger.ZERO
if val == 1:
return BigInteger.ONE
if val == 10:
return BigInteger.TEN
return BigInteger(val)
def add(self, other):
if isinstance(other, BigInteger):
return BigInteger(self._value + other._value)
return BigInteger(self._value + int(other))
def subtract(self, other):
if isinstance(other, BigInteger):
return BigInteger(self._value - other._value)
return BigInteger(self._value - int(other))
def multiply(self, other):
if isinstance(other, BigInteger):
return BigInteger(self._value * other._value)
return BigInteger(self._value * int(other))
def divide(self, other):
if isinstance(other, BigInteger):
return BigInteger(self._value // other._value)
return BigInteger(self._value // int(other))
def pow(self, exponent):
return BigInteger(self._value ** exponent)
def gcd(self, other):
return BigInteger(_py_math.gcd(self._value, other._value if isinstance(other, BigInteger) else int(other)))
def abs(self):
return BigInteger(abs(self._value))
def negate(self):
return BigInteger(-self._value)
def signum(self):
if self._value > 0:
return 1
if self._value < 0:
return -1
return 0
def mod(self, m):
if isinstance(m, BigInteger):
return BigInteger(self._value % m._value)
return BigInteger(self._value % int(m))
def remainder(self, other):
if isinstance(other, BigInteger):
return BigInteger(self._value % other._value)
return BigInteger(self._value % int(other))
def and_(self, other):
return BigInteger(self._value & (other._value if isinstance(other, BigInteger) else int(other)))
def or_(self, other):
return BigInteger(self._value | (other._value if isinstance(other, BigInteger) else int(other)))
def xor(self, other):
return BigInteger(self._value ^ (other._value if isinstance(other, BigInteger) else int(other)))
def not_(self):
return BigInteger(~self._value)
def andNot(self, other):
return BigInteger(self._value & ~(other._value if isinstance(other, BigInteger) else int(other)))
def shiftLeft(self, n):
return BigInteger(self._value << n)
def shiftRight(self, n):
return BigInteger(self._value >> n)
def getLowestSetBit(self):
if self._value == 0:
return -1
return (self._value & -self._value).bit_length() - 1
def bitLength(self):
if self._value == 0:
return 0
return self._value.bit_length()
def bitCount(self):
return bin(self._value & ((1 << self.bitLength()) - 1) if self._value >= 0 else self._value).count("1")
def isProbablePrime(self, certainty):
if abs(self._value) < 2:
return False
if abs(self._value) == 2 or abs(self._value) == 3:
return True
if self._value % 2 == 0:
return False
d = self._value - 1
s = 0
while d % 2 == 0:
d //= 2
s += 1
for _ in range(min(certainty, 20)):
a = _random.randrange(2, min(self._value - 1, 1000000))
x = pow(a, d, self._value)
if x == 1 or x == self._value - 1:
continue
for _ in range(s - 1):
x = pow(x, 2, self._value)
if x == self._value - 1:
break
else:
return False
return True
def nextProbablePrime(self):
v = self._value + 1
if v < 3:
return BigInteger(2) if v <= 2 else BigInteger(3)
while True:
if v % 2 == 0:
v += 1
for i in range(3, int(_py_math.sqrt(v)) + 1, 2):
if v % i == 0:
break
else:
return BigInteger(v)
v += 2
def compareTo(self, other):
if isinstance(other, BigInteger):
return (self._value > other._value) - (self._value < other._value)
return -1
def equals(self, other):
if isinstance(other, BigInteger):
return self._value == other._value
return False
def toByteArray(self):
if self._value == 0:
return b"\x00"
byte_length = (self._value.bit_length() + 8) // 8
return self._value.to_bytes(byte_length, byteorder="big", signed=True)
def toString(self, radix=10):
if radix == 10:
return str(self._value)
if radix == 16:
return hex(self._value)[2:]
if radix == 8:
return oct(self._value)[2:]
if radix == 2:
return bin(self._value)[2:]
return str(self._value)
def intValue(self):
return self._value & 0xFFFFFFFF
def longValue(self):
return self._value
def floatValue(self):
return float(self._value)
def doubleValue(self):
return float(self._value)
def min(self, other):
return BigInteger(min(self._value, other._value if isinstance(other, BigInteger) else int(other)))
def max(self, other):
return BigInteger(max(self._value, other._value if isinstance(other, BigInteger) else int(other)))
def modPow(self, exponent, m):
if isinstance(exponent, BigInteger):
exp_val = exponent._value
else:
exp_val = int(exponent)
mod_val = m._value if isinstance(m, BigInteger) else int(m)
return BigInteger(pow(self._value, exp_val, mod_val))
def modInverse(self, m):
mod_val = m._value if isinstance(m, BigInteger) else int(m)
return BigInteger(pow(self._value, -1, mod_val))
def divideAndRemainder(self, other):
if isinstance(other, BigInteger):
divisor = other._value
else:
divisor = int(other)
q = self._value // divisor
r = self._value % divisor
return [BigInteger(q), BigInteger(r)]
def __int__(self):
return self._value
def __str__(self):
return str(self._value)
def __neg__(self):
return self.negate()
def __abs__(self):
return self.abs()
def __add__(self, other):
return self.add(other)
def __sub__(self, other):
return self.subtract(other)
def __mul__(self, other):
return self.multiply(other)
def __truediv__(self, other):
return self.divide(other)
def __floordiv__(self, other):
return self.divide(other)
def __mod__(self, other):
return self.mod(other)
def __pow__(self, other):
return self.pow(other)
def __and__(self, other):
return self.and_(other)
def __or__(self, other):
return self.or_(other)
def __xor__(self, other):
return self.xor(other)
def __invert__(self):
return self.not_()
def __lshift__(self, n):
return self.shiftLeft(n)
def __rshift__(self, n):
return self.shiftRight(n)
BigInteger.ZERO = BigInteger(0)
BigInteger.ONE = BigInteger(1)
BigInteger.TEN = BigInteger(10)
# ============================================================
# BigDecimal
# ============================================================
class BigDecimal(Comparable):
ZERO = None
ONE = None
TEN = None
ROUND_UP = 0
ROUND_DOWN = 1
ROUND_CEILING = 2
ROUND_FLOOR = 3
ROUND_HALF_UP = 4
ROUND_HALF_DOWN = 5
ROUND_HALF_EVEN = 6
ROUND_UNNECESSARY = 7
_round_map = {
0: _DEC_ROUND_UP,
1: _DEC_ROUND_DOWN,
2: _DEC_ROUND_CEILING,
3: _DEC_ROUND_FLOOR,
4: _DEC_ROUND_HALF_UP,
5: _DEC_ROUND_HALF_DOWN,
6: _DEC_ROUND_HALF_EVEN,
7: _DEC_ROUND_HALF_EVEN,
}
def __init__(self, *args):
super().__init__()
if len(args) == 1:
val = args[0]
if isinstance(val, str):
self._dec = _Decimal(str(val))
elif isinstance(val, float):
self._dec = _Decimal(repr(val))
elif isinstance(val, int):
self._dec = _Decimal(val)
elif isinstance(val, BigInteger):
self._dec = _Decimal(val._value)
elif isinstance(val, BigDecimal):
self._dec = _Decimal(val._dec)
elif isinstance(val, _Decimal):
self._dec = val
else:
self._dec = _Decimal(str(val))
elif len(args) == 2:
val, mc = args
if isinstance(val, str):
self._dec = _Decimal(str(val))
elif isinstance(val, float):
self._dec = _Decimal(repr(val))
else:
self._dec = _Decimal(val)
if mc and hasattr(mc, 'getPrecision') and mc.getPrecision() > 0:
self._dec = +self._dec
@staticmethod
def valueOf(val):
if isinstance(val, int):
if val == 0:
return BigDecimal.ZERO
if val == 1:
return BigDecimal.ONE
if val == 10:
return BigDecimal.TEN
if isinstance(val, float):
return BigDecimal(repr(val))
return BigDecimal(val)
def add(self, other):
if isinstance(other, BigDecimal):
return BigDecimal(self._dec + other._dec)
return BigDecimal(self._dec + _Decimal(str(other)))
def subtract(self, other):
if isinstance(other, BigDecimal):
return BigDecimal(self._dec - other._dec)
return BigDecimal(self._dec - _Decimal(str(other)))
def multiply(self, other):
if isinstance(other, BigDecimal):
return BigDecimal(self._dec * other._dec)
return BigDecimal(self._dec * _Decimal(str(other)))
def divide(self, *args):
if len(args) == 1:
other = args[0]
if isinstance(other, BigDecimal):
return BigDecimal(self._dec / other._dec)
return BigDecimal(self._dec / _Decimal(str(other)))
elif len(args) == 2:
other, rounding_mode = args
if isinstance(other, BigDecimal):
result = self._dec / other._dec
else:
result = self._dec / _Decimal(str(other))
return BigDecimal(result)
elif len(args) == 3:
other, scale, rounding_mode = args
if isinstance(other, BigDecimal):
result = self._dec / other._dec
else:
result = self._dec / _Decimal(str(other))
rounded = BigDecimal(result)
return rounded.setScale(scale, rounding_mode)
def divideToIntegralValue(self, other):
if isinstance(other, BigDecimal):
return BigDecimal(int(self._dec / other._dec))
return BigDecimal(int(self._dec / _Decimal(str(other))))
def remainder(self, other):
if isinstance(other, BigDecimal):
return BigDecimal(self._dec % other._dec)
return BigDecimal(self._dec % _Decimal(str(other)))
def pow(self, n):
return BigDecimal(self._dec ** n)
def abs(self):
return BigDecimal(abs(self._dec))
def negate(self):
return BigDecimal(-self._dec)
def signum(self):
if self._dec > 0:
return 1
if self._dec < 0:
return -1
return 0
def scale(self):
return abs(self._dec.as_tuple().exponent)
def precision(self):
return len(self._dec.as_tuple().digits)
def round(self, mc):
if mc.getPrecision() > 0:
with _local_context() as ctx:
ctx.prec = mc.getPrecision()
return BigDecimal(+self._dec)
return BigDecimal(self._dec)
def setScale(self, new_scale, rounding_mode=None):
if rounding_mode is None:
qe = _Decimal(10) ** (-new_scale)
return BigDecimal(self._dec.quantize(qe))
py_mode = self._round_map.get(rounding_mode, _DEC_ROUND_HALF_UP)
qe = _Decimal(10) ** (-new_scale)
return BigDecimal(self._dec.quantize(qe, rounding=py_mode))
def ulp(self):
exponent = self._dec.as_tuple().exponent
return BigDecimal(_Decimal(10) ** exponent)
def unscaledValue(self):
t = self._dec.as_tuple()
digits = t.digits
val = int("".join(str(d) for d in digits))
return BigInteger(-val if t.sign else val)
def byteValueExact(self):
val = self.intValueExact()
if val < -128 or val > 127:
raise ArithmeticError("Overflow")
return val
def shortValueExact(self):
val = self.intValueExact()
if val < -32768 or val > 32767:
raise ArithmeticError("Overflow")
return val
def intValueExact(self):
if self._dec != int(self._dec):
raise ArithmeticError("Rounding necessary")
return int(self._dec)
def longValueExact(self):
if self._dec != int(self._dec):
raise ArithmeticError("Rounding necessary")
return int(self._dec)
def floatValue(self):
return float(self._dec)
def doubleValue(self):
return float(self._dec)
def intValue(self):
return int(self._dec)
def longValue(self):
return int(self._dec)
def toString(self):
return str(self._dec)
def toEngineeringString(self):
return format(self._dec, "e")
def toPlainString(self):
return format(self._dec, "f")
def compareTo(self, other):
if isinstance(other, BigDecimal):
return (self._dec > other._dec) - (self._dec < other._dec)
return -1
def equals(self, other):
if isinstance(other, BigDecimal):
return self._dec == other._dec
return False
def hashCode(self):
return hash(self._dec) & 0x7FFFFFFF
def min(self, other):
return BigDecimal(min(self._dec, other._dec if isinstance(other, BigDecimal) else _Decimal(str(other))))
def max(self, other):
return BigDecimal(max(self._dec, other._dec if isinstance(other, BigDecimal) else _Decimal(str(other))))
def __str__(self):
return str(self._dec)
def __int__(self):
return int(self._dec)
def __float__(self):
return float(self._dec)
def __neg__(self):
return self.negate()
def __abs__(self):
return self.abs()
def __add__(self, other):
return self.add(other)
def __sub__(self, other):
return self.subtract(other)
def __mul__(self, other):
return self.multiply(other)
def __truediv__(self, other):
return self.divide(other)
def __mod__(self, other):
return self.remainder(other)
def __pow__(self, other):
return self.pow(other)
BigDecimal.ZERO = BigDecimal(0)
BigDecimal.ONE = BigDecimal(1)
BigDecimal.TEN = BigDecimal(10)
File diff suppressed because it is too large. Load diff
+622
View File
@@ -0,0 +1,622 @@
"""
Java NIO standard library APIs implemented in Python.
java.nio package - Buffer, ByteBuffer, CharBuffer, etc.
"""
from .._core import Stub
from .lang import RuntimeException
from .io import IOException
import struct as _struct
import sys as _sys
IllegalStateException = type("IllegalStateException", (RuntimeException,), {})
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
__all__ = [
"Buffer", "ByteBuffer", "CharBuffer", "ShortBuffer",
"IntBuffer", "LongBuffer", "FloatBuffer", "DoubleBuffer",
"MappedByteBuffer", "ByteOrder",
"BufferOverflowException", "BufferUnderflowException",
"ReadOnlyBufferException", "InvalidMarkException",
]
# ============================================================
# Exception classes
# ============================================================
class BufferOverflowException(RuntimeException):
pass
class BufferUnderflowException(RuntimeException):
pass
class ReadOnlyBufferException(RuntimeException):
pass
class InvalidMarkException(IllegalStateException):
pass
# ============================================================
# ByteOrder
# ============================================================
class ByteOrder(Stub):
BIG_ENDIAN = None
LITTLE_ENDIAN = None
def __init__(self, name):
super().__init__()
self._name = name
@staticmethod
def nativeOrder():
if _sys.byteorder == "little":
return ByteOrder.LITTLE_ENDIAN
return ByteOrder.BIG_ENDIAN
def toString(self):
return self._name
ByteOrder.BIG_ENDIAN = ByteOrder("BIG_ENDIAN")
ByteOrder.LITTLE_ENDIAN = ByteOrder("LITTLE_ENDIAN")
# ============================================================
# Buffer
# ============================================================
class Buffer(Stub):
def __init__(self, capacity, backing=None):
super().__init__()
self._capacity = capacity
self._position = 0
self._limit = capacity
self._mark = -1
self._backing = backing if backing is not None else bytearray(capacity)
self._read_only = False
def capacity(self):
return self._capacity
def position(self):
return self._position
def position(self, new_position):
if new_position < 0 or new_position > self._limit:
raise IllegalArgumentException("Invalid position")
self._position = new_position
return self
def limit(self):
return self._limit
def limit(self, new_limit):
if new_limit < 0 or new_limit > self._capacity:
raise IllegalArgumentException("Invalid limit")
self._limit = new_limit
if self._position > self._limit:
self._position = self._limit
if self._mark > self._limit:
self._mark = -1
return self
def mark(self):
self._mark = self._position
return self
def reset(self):
if self._mark < 0:
raise InvalidMarkException()
self._position = self._mark
return self
def clear(self):
self._position = 0
self._limit = self._capacity
self._mark = -1
return self
def flip(self):
self._limit = self._position
self._position = 0
self._mark = -1
return self
def rewind(self):
self._position = 0
self._mark = -1
return self
def remaining(self):
return self._limit - self._position
def hasRemaining(self):
return self._position < self._limit
def isReadOnly(self):
return self._read_only
def isDirect(self):
return False
def array(self):
if self._read_only:
raise ReadOnlyBufferException()
return self._backing
def arrayOffset(self):
return 0
# ============================================================
# ByteBuffer
# ============================================================
class ByteBuffer(Buffer):
def __init__(self, capacity, backing=None, order=None):
super().__init__(capacity, backing)
self._order = order or ByteOrder.BIG_ENDIAN
@staticmethod
def allocate(capacity):
return ByteBuffer(capacity, bytearray(capacity))
@staticmethod
def allocateDirect(capacity):
return ByteBuffer(capacity, bytearray(capacity))
@staticmethod
def wrap(array, offset=0, length=None):
if length is None:
length = len(array) - offset
buf = ByteBuffer(length, bytearray(array))
buf._position = offset
buf._limit = offset + length
return buf
def put(self, b, index=None):
if self._read_only:
raise ReadOnlyBufferException()
if index is None:
if isinstance(b, int):
if self._position >= self._limit:
raise BufferOverflowException()
self._backing[self._position] = b & 0xFF
self._position += 1
elif isinstance(b, ByteBuffer):
n = b.remaining()
if self.remaining() < n:
raise BufferOverflowException()
self._backing[self._position:self._position+n] = b._backing[b._position:b._limit]
self._position += n
b._position = b._limit
elif isinstance(b, (bytes, bytearray)):
if self.remaining() < len(b):
raise BufferOverflowException()
self._backing[self._position:self._position+len(b)] = b
self._position += len(b)
else:
self._backing[index] = b & 0xFF
return self
def get(self, index=None):
if index is None:
if self._position >= self._limit:
raise BufferUnderflowException()
val = self._backing[self._position]
self._position += 1
return val & 0xFF
return self._backing[index] & 0xFF
def putInt(self, value, index=None):
data = _struct.pack(">i" if self._order == ByteOrder.BIG_ENDIAN else "<i", value)
if index is not None:
self._backing[index:index+4] = data
else:
if self.remaining() < 4:
raise BufferOverflowException()
self._backing[self._position:self._position+4] = data
self._position += 4
return self
def getInt(self, index=None):
if index is not None:
data = self._backing[index:index+4]
else:
if self.remaining() < 4:
raise BufferUnderflowException()
data = self._backing[self._position:self._position+4]
self._position += 4
return _struct.unpack(">i" if self._order == ByteOrder.BIG_ENDIAN else "<i", bytes(data))[0]
def putLong(self, value, index=None):
data = _struct.pack(">q" if self._order == ByteOrder.BIG_ENDIAN else "<q", value)
if index is not None:
self._backing[index:index+8] = data
else:
if self.remaining() < 8:
raise BufferOverflowException()
self._backing[self._position:self._position+8] = data
self._position += 8
return self
def getLong(self, index=None):
if index is not None:
data = self._backing[index:index+8]
else:
if self.remaining() < 8:
raise BufferUnderflowException()
data = self._backing[self._position:self._position+8]
self._position += 8
return _struct.unpack(">q" if self._order == ByteOrder.BIG_ENDIAN else "<q", bytes(data))[0]
def putFloat(self, value, index=None):
data = _struct.pack(">f" if self._order == ByteOrder.BIG_ENDIAN else "<f", value)
if index is not None:
self._backing[index:index+4] = data
else:
if self.remaining() < 4:
raise BufferOverflowException()
self._backing[self._position:self._position+4] = data
self._position += 4
return self
def getFloat(self, index=None):
if index is not None:
data = self._backing[index:index+4]
else:
if self.remaining() < 4:
raise BufferUnderflowException()
data = self._backing[self._position:self._position+4]
self._position += 4
return _struct.unpack(">f" if self._order == ByteOrder.BIG_ENDIAN else "<f", bytes(data))[0]
def putDouble(self, value, index=None):
data = _struct.pack(">d" if self._order == ByteOrder.BIG_ENDIAN else "<d", value)
if index is not None:
self._backing[index:index+8] = data
else:
if self.remaining() < 8:
raise BufferOverflowException()
self._backing[self._position:self._position+8] = data
self._position += 8
return self
def getDouble(self, index=None):
if index is not None:
data = self._backing[index:index+8]
else:
if self.remaining() < 8:
raise BufferUnderflowException()
data = self._backing[self._position:self._position+8]
self._position += 8
return _struct.unpack(">d" if self._order == ByteOrder.BIG_ENDIAN else "<d", bytes(data))[0]
def putShort(self, value, index=None):
data = _struct.pack(">h" if self._order == ByteOrder.BIG_ENDIAN else "<h", value)
if index is not None:
self._backing[index:index+2] = data
else:
if self.remaining() < 2:
raise BufferOverflowException()
self._backing[self._position:self._position+2] = data
self._position += 2
return self
def getShort(self, index=None):
if index is not None:
data = self._backing[index:index+2]
else:
if self.remaining() < 2:
raise BufferUnderflowException()
data = self._backing[self._position:self._position+2]
self._position += 2
return _struct.unpack(">h" if self._order == ByteOrder.BIG_ENDIAN else "<h", bytes(data))[0]
def putChar(self, value, index=None):
return self.putShort(ord(value), index)
def getChar(self, index=None):
return chr(self.getShort(index))
def asIntBuffer(self):
return IntBuffer(self.remaining() // 4, self._backing, self._position, self._order)
def asLongBuffer(self):
return LongBuffer(self.remaining() // 8, self._backing, self._position, self._order)
def asFloatBuffer(self):
return FloatBuffer(self.remaining() // 4, self._backing, self._position, self._order)
def asDoubleBuffer(self):
return DoubleBuffer(self.remaining() // 8, self._backing, self._position, self._order)
def asShortBuffer(self):
return ShortBuffer(self.remaining() // 2, self._backing, self._position, self._order)
def asCharBuffer(self):
return CharBuffer(self.remaining() // 2, self._backing, self._position, self._order)
def slice(self):
n = self.remaining()
buf = ByteBuffer(n, self._backing[self._position:self._limit])
return buf
def duplicate(self):
buf = ByteBuffer(self._capacity, bytearray(self._backing))
buf._position = self._position
buf._limit = self._limit
buf._order = self._order
return buf
def asReadOnlyBuffer(self):
buf = self.duplicate()
buf._read_only = True
return buf
def order(self, order=None):
if order is not None:
self._order = order
return self
return self._order
def compact(self):
if self._read_only:
raise ReadOnlyBufferException()
remaining = self.remaining()
self._backing[:remaining] = self._backing[self._position:self._limit]
self._position = remaining
self._limit = self._capacity
self._mark = -1
return self
def toString(self):
return f"ByteBuffer[pos={self._position} lim={self._limit} cap={self._capacity}]"
def hashCode(self):
return hash(bytes(self._backing)) & 0x7FFFFFFF
def equals(self, other):
if isinstance(other, ByteBuffer):
return bytes(self._backing[self._position:self._limit]) == bytes(other._backing[other._position:other._limit])
return False
def compareTo(self, other):
if isinstance(other, ByteBuffer):
a = bytes(self._backing[self._position:self._limit])
b = bytes(other._backing[other._position:other._limit])
return (a > b) - (a < b)
return -1
# ============================================================
# IntBuffer
# ============================================================
class IntBuffer(Buffer):
def __init__(self, capacity, backing, offset=0, order=None):
super().__init__(capacity, backing)
self._int_order = order or ByteOrder.BIG_ENDIAN
self._int_offset = offset
def get(self, index=None):
if index is not None:
idx = self._int_offset + index * 4
return _struct.unpack(">i" if self._int_order == ByteOrder.BIG_ENDIAN else "<i",
bytes(self._backing[idx:idx+4]))[0]
if self.remaining() < 4:
raise BufferUnderflowException()
val = _struct.unpack(">i" if self._int_order == ByteOrder.BIG_ENDIAN else "<i",
bytes(self._backing[self._position:self._position+4]))[0]
self._position += 4
return val
def put(self, value, index=None):
data = _struct.pack(">i" if self._int_order == ByteOrder.BIG_ENDIAN else "<i", value)
if index is not None:
idx = self._int_offset + index * 4
self._backing[idx:idx+4] = data
else:
if self.remaining() < 4:
raise BufferOverflowException()
self._backing[self._position:self._position+4] = data
self._position += 4
return self
# ============================================================
# LongBuffer
# ============================================================
class LongBuffer(Buffer):
def __init__(self, capacity, backing, offset=0, order=None):
super().__init__(capacity, backing)
self._long_order = order or ByteOrder.BIG_ENDIAN
self._long_offset = offset
def get(self, index=None):
if index is not None:
idx = self._long_offset + index * 8
return _struct.unpack(">q" if self._long_order == ByteOrder.BIG_ENDIAN else "<q",
bytes(self._backing[idx:idx+8]))[0]
if self.remaining() < 8:
raise BufferUnderflowException()
val = _struct.unpack(">q" if self._long_order == ByteOrder.BIG_ENDIAN else "<q",
bytes(self._backing[self._position:self._position+8]))[0]
self._position += 8
return val
def put(self, value, index=None):
data = _struct.pack(">q" if self._long_order == ByteOrder.BIG_ENDIAN else "<q", value)
if index is not None:
idx = self._long_offset + index * 8
self._backing[idx:idx+8] = data
else:
if self.remaining() < 8:
raise BufferOverflowException()
self._backing[self._position:self._position+8] = data
self._position += 8
return self
# ============================================================
# FloatBuffer
# ============================================================
class FloatBuffer(Buffer):
def __init__(self, capacity, backing, offset=0, order=None):
super().__init__(capacity, backing)
self._float_order = order or ByteOrder.BIG_ENDIAN
self._float_offset = offset
def get(self, index=None):
if index is not None:
idx = self._float_offset + index * 4
return _struct.unpack(">f" if self._float_order == ByteOrder.BIG_ENDIAN else "<f",
bytes(self._backing[idx:idx+4]))[0]
if self.remaining() < 4:
raise BufferUnderflowException()
val = _struct.unpack(">f" if self._float_order == ByteOrder.BIG_ENDIAN else "<f",
bytes(self._backing[self._position:self._position+4]))[0]
self._position += 4
return val
def put(self, value, index=None):
data = _struct.pack(">f" if self._float_order == ByteOrder.BIG_ENDIAN else "<f", value)
if index is not None:
idx = self._float_offset + index * 4
self._backing[idx:idx+4] = data
else:
if self.remaining() < 4:
raise BufferOverflowException()
self._backing[self._position:self._position+4] = data
self._position += 4
return self
# ============================================================
# DoubleBuffer
# ============================================================
class DoubleBuffer(Buffer):
def __init__(self, capacity, backing, offset=0, order=None):
super().__init__(capacity, backing)
self._double_order = order or ByteOrder.BIG_ENDIAN
self._double_offset = offset
def get(self, index=None):
if index is not None:
idx = self._double_offset + index * 8
return _struct.unpack(">d" if self._double_order == ByteOrder.BIG_ENDIAN else "<d",
bytes(self._backing[idx:idx+8]))[0]
if self.remaining() < 8:
raise BufferUnderflowException()
val = _struct.unpack(">d" if self._double_order == ByteOrder.BIG_ENDIAN else "<d",
bytes(self._backing[self._position:self._position+8]))[0]
self._position += 8
return val
def put(self, value, index=None):
data = _struct.pack(">d" if self._double_order == ByteOrder.BIG_ENDIAN else "<d", value)
if index is not None:
idx = self._double_offset + index * 8
self._backing[idx:idx+8] = data
else:
if self.remaining() < 8:
raise BufferOverflowException()
self._backing[self._position:self._position+8] = data
self._position += 8
return self
# ============================================================
# ShortBuffer
# ============================================================
class ShortBuffer(Buffer):
def __init__(self, capacity, backing, offset=0, order=None):
super().__init__(capacity, backing)
self._short_order = order or ByteOrder.BIG_ENDIAN
self._short_offset = offset
def get(self, index=None):
if index is not None:
idx = self._short_offset + index * 2
return _struct.unpack(">h" if self._short_order == ByteOrder.BIG_ENDIAN else "<h",
bytes(self._backing[idx:idx+2]))[0]
if self.remaining() < 2:
raise BufferUnderflowException()
val = _struct.unpack(">h" if self._short_order == ByteOrder.BIG_ENDIAN else "<h",
bytes(self._backing[self._position:self._position+2]))[0]
self._position += 2
return val
def put(self, value, index=None):
data = _struct.pack(">h" if self._short_order == ByteOrder.BIG_ENDIAN else "<h", value)
if index is not None:
idx = self._short_offset + index * 2
self._backing[idx:idx+2] = data
else:
if self.remaining() < 2:
raise BufferOverflowException()
self._backing[self._position:self._position+2] = data
self._position += 2
return self
# ============================================================
# CharBuffer
# ============================================================
class CharBuffer(Buffer):
def __init__(self, capacity, backing, offset=0, order=None):
super().__init__(capacity, backing)
self._char_order = order or ByteOrder.BIG_ENDIAN
self._char_offset = offset
def get(self, index=None):
if index is not None:
idx = self._char_offset + index * 2
val = _struct.unpack(">h" if self._char_order == ByteOrder.BIG_ENDIAN else "<h",
bytes(self._backing[idx:idx+2]))[0]
return chr(val)
if self.remaining() < 2:
raise BufferUnderflowException()
val = _struct.unpack(">h" if self._char_order == ByteOrder.BIG_ENDIAN else "<h",
bytes(self._backing[self._position:self._position+2]))[0]
self._position += 2
return chr(val)
def put(self, value, index=None):
char_val = ord(value) if isinstance(value, str) else value
data = _struct.pack(">h" if self._char_order == ByteOrder.BIG_ENDIAN else "<h", char_val)
if index is not None:
idx = self._char_offset + index * 2
self._backing[idx:idx+2] = data
else:
if self.remaining() < 2:
raise BufferOverflowException()
self._backing[self._position:self._position+2] = data
self._position += 2
return self
# ============================================================
# MappedByteBuffer
# ============================================================
class MappedByteBuffer(ByteBuffer):
def __init__(self, capacity, backing=None):
super().__init__(capacity, backing)
def force(self):
return self
def isLoaded(self):
return True
def load(self):
return self
+703
View File
@@ -0,0 +1,703 @@
"""
Java NIO File standard library APIs implemented in Python.
java.nio.file package - Path, Files, FileSystem, FileVisitor, etc.
"""
from .._core import Stub
from .io import IOException
from .lang import RuntimeException, Comparable
import os as _os
import shutil as _shutil
import stat as _stat
from pathlib import Path as _PathLibPath
import tempfile as _tempfile
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
__all__ = [
"Path", "Paths", "Files", "FileSystem", "FileSystems",
"FileStore", "FileVisitResult", "FileVisitor", "SimpleFileVisitor",
"DirectoryStream", "DirectoryStreamFilter",
"PathMatcher", "WatchService", "WatchKey", "WatchEvent", "Watchable",
"CopyOption", "StandardCopyOption", "LinkOption", "OpenOption",
"StandardOpenOption",
"FileAlreadyExistsException", "DirectoryNotEmptyException",
"NoSuchFileException", "FileSystemLoopException",
"FileSystemNotFoundException", "ProviderMismatchException",
"ProviderNotFoundException", "NotDirectoryException", "NotLinkException",
"AtomicMoveNotSupportedException", "AccessDeniedException",
"AccessMode",
]
# ============================================================
# Exception classes
# ============================================================
class FileAlreadyExistsException(IOException):
pass
class DirectoryNotEmptyException(IOException):
pass
class NoSuchFileException(IOException):
def __init__(self, file=None, other=None, reason=None):
msg = str(file) if file else ""
super().__init__(msg)
class FileSystemLoopException(IOException):
pass
class FileSystemNotFoundException(IOException):
pass
class ProviderMismatchException(IllegalArgumentException):
pass
class ProviderNotFoundException(IllegalArgumentException):
pass
class NotDirectoryException(IOException):
pass
class NotLinkException(IOException):
pass
class AtomicMoveNotSupportedException(IOException):
pass
class AccessDeniedException(IOException):
pass
# ============================================================
# Enums / Constants
# ============================================================
class FileVisitResult:
CONTINUE = 0
TERMINATE = 1
SKIP_SUBTREE = 2
SKIP_SIBLINGS = 3
class StandardCopyOption:
REPLACE_EXISTING = 0
COPY_ATTRIBUTES = 1
ATOMIC_MOVE = 2
class StandardOpenOption:
READ = 0
WRITE = 1
APPEND = 2
TRUNCATE_EXISTING = 3
CREATE = 4
CREATE_NEW = 5
DELETE_ON_CLOSE = 6
SPARSE = 7
SYNC = 8
DSYNC = 9
class LinkOption:
NOFOLLOW_LINKS = 0
class CopyOption(Stub):
pass
class OpenOption(Stub):
pass
class AccessMode:
READ = 0
WRITE = 1
EXECUTE = 2
# ============================================================
# Path
# ============================================================
class Path(Comparable):
def __init__(self, path_str, *more):
super().__init__()
if more:
path_str = _os.path.join(path_str, *more)
self._path = str(path_str)
self._pypath = _PathLibPath(self._path)
def getFileName(self):
return Path(self._pypath.name)
def getParent(self):
parent = self._pypath.parent
if parent == self._pypath:
return None
return Path(str(parent))
def getRoot(self):
root = self._pypath.anchor
return Path(root) if root else None
def toAbsolutePath(self):
return Path(str(self._pypath.absolute()))
def toRealPath(self):
return Path(str(self._pypath.resolve()))
def getName(self, index):
parts = self._pypath.parts
if self.getRoot():
parts = parts[1:]
if index < 0 or index >= len(parts):
raise IllegalArgumentException("Invalid index")
return Path(parts[index])
def getNameCount(self):
parts = self._pypath.parts
if self.getRoot():
parts = parts[1:]
return len(parts)
def subpath(self, beginIndex, endIndex):
parts = self._pypath.parts
if self.getRoot():
parts = parts[1:]
return Path(_os.path.join(*parts[beginIndex:endIndex]))
def startsWith(self, other):
if isinstance(other, Path):
return str(self._pypath).startswith(str(other._pypath))
return str(self._pypath).startswith(str(other))
def endsWith(self, other):
if isinstance(other, Path):
return str(self._pypath).endswith(str(other._pypath))
return str(self._pypath).endswith(str(other))
def normalize(self):
return Path(_os.path.normpath(self._path))
def resolve(self, other):
if isinstance(other, Path):
other_path = str(other)
else:
other_path = str(other)
if _os.path.isabs(other_path):
return Path(other_path)
return Path(_os.path.join(self._path, other_path))
def resolveSibling(self, other):
parent = self.getParent()
if parent:
return parent.resolve(other)
return Path(other)
def relativize(self, other):
if isinstance(other, Path):
other_str = str(other._pypath)
else:
other_str = str(other)
try:
rel = _os.path.relpath(other_str, self._path)
return Path(rel)
except ValueError:
return other
def compareTo(self, other):
if isinstance(other, Path):
return (self._path > other._path) - (self._path < other._path)
return -1
def toString(self):
return self._path
def toFile(self):
from ..io import File
return File(self._path)
def isAbsolute(self):
return _os.path.isabs(self._path)
def getFileSystem(self):
return FileSystems.getDefault()
def iterator(self):
parts = self._pypath.parts
if self.getRoot():
parts = parts[1:]
return iter([Path(p) for p in parts])
def register(self, watcher, events, *modifiers):
raise AndroidOnlyError("WatchService nio")
def __str__(self):
return self._path
def __eq__(self, other):
if isinstance(other, Path):
return self._path == other._path
return NotImplemented
def __hash__(self):
return hash(self._path)
# ============================================================
# Paths
# ============================================================
class Paths(Stub):
@staticmethod
def get(first, *more):
parts = [str(first)]
parts.extend(str(m) for m in more)
return Path(_os.path.join(*parts))
# ============================================================
# FileSystem
# ============================================================
class FileSystem(Stub):
def __init__(self):
super().__init__()
self._separator = _os.sep
self._open = True
def getPath(self, first, *more):
return Paths.get(first, *more)
def getSeparator(self):
return self._separator
def getRootDirectories(self):
if _os.name == "nt":
import string
return [Path(d + ":\\") for d in string.ascii_uppercase if _os.path.exists(d + ":\\")]
return [Path("/")]
def getUserPrincipalLookupService(self):
raise AndroidOnlyError("UserPrincipalLookupService")
def newWatchService(self):
raise AndroidOnlyError("WatchService")
def getFileStores(self):
return [FileStore("/")]
def supportedFileAttributeViews(self):
return ["basic", "owner", "posix"]
def close(self):
self._open = False
def isOpen(self):
return self._open
def isReadOnly(self):
return False
class FileSystems(Stub):
_default = None
@staticmethod
def getDefault():
if FileSystems._default is None:
FileSystems._default = FileSystem()
return FileSystems._default
# ============================================================
# FileStore
# ============================================================
class FileStore(Stub):
def __init__(self, path):
super().__init__()
self._path = path
def name(self):
return _os.path.basename(self._path) or "/"
def type(self):
return "ext4"
def isReadOnly(self):
return False
def getTotalSpace(self):
try:
st = _os.statvfs(self._path)
return st.f_frsize * st.f_blocks
except OSError:
return 0
def getUsableSpace(self):
try:
st = _os.statvfs(self._path)
return st.f_frsize * st.f_bavail
except OSError:
return 0
def getUnallocatedSpace(self):
try:
st = _os.statvfs(self._path)
return st.f_frsize * st.f_bfree
except OSError:
return 0
def toString(self):
return f"{self.name()} ({self.type()})"
# ============================================================
# FileVisitor / SimpleFileVisitor
# ============================================================
class FileVisitor(Stub):
def preVisitDirectory(self, dir, attrs):
return FileVisitResult.CONTINUE
def postVisitDirectory(self, dir, exc):
return FileVisitResult.CONTINUE
def visitFile(self, file, attrs):
return FileVisitResult.CONTINUE
def visitFileFailed(self, file, exc):
return FileVisitResult.CONTINUE
class SimpleFileVisitor(FileVisitor):
pass
# ============================================================
# DirectoryStream / Filter
# ============================================================
class DirectoryStream(Stub):
def __init__(self, path, filter=None):
super().__init__()
self._path = path
self._filter = filter
def __iter__(self):
try:
entries = _os.listdir(str(self._path))
for entry in entries:
p = Path(self._path, entry)
if self._filter is None or self._filter.accept(p):
yield p
except OSError:
raise IOException(f"Failed to list directory: {self._path}")
def close(self):
pass
class DirectoryStreamFilter(Stub):
def accept(self, entry):
raise NotImplementedError
# ============================================================
# PathMatcher
# ============================================================
class PathMatcher(Stub):
def __init__(self, pattern):
super().__init__()
self._pattern = pattern
def matches(self, path):
import fnmatch
return fnmatch.fnmatch(str(path), self._pattern)
# ============================================================
# WatchService / WatchKey / WatchEvent / Watchable (stubs)
# ============================================================
class Watchable(Stub):
def register(self, watcher, events, *modifiers):
raise AndroidOnlyError("WatchService")
class WatchService(Stub):
def close(self):
pass
def poll(self):
return None
def take(self):
raise AndroidOnlyError("WatchService.take")
def poll(self, timeout, unit):
return None
class WatchKey(Stub):
def isValid(self):
return True
def pollEvents(self):
return []
def reset(self):
return True
def cancel(self):
pass
def watchable(self):
return None
class WatchEvent(Stub):
class Kind(Stub):
def name(self):
return ""
def type(self):
return None
def kind(self):
return None
def count(self):
return 0
def context(self):
return None
# ============================================================
# Files
# ============================================================
class Files(Stub):
@staticmethod
def copy(source, target, *options):
src = str(source)
dst = str(target)
replace = any(isinstance(o, StandardCopyOption) and o == StandardCopyOption.REPLACE_EXISTING for o in options)
try:
if replace and _os.path.exists(dst):
_os.remove(dst)
if _os.path.isdir(src):
_shutil.copytree(src, dst)
else:
_shutil.copy2(src, dst)
except OSError as e:
raise IOException(str(e))
@staticmethod
def move(source, target, *options):
src = str(source)
dst = str(target)
replace = any(isinstance(o, StandardCopyOption) and o == StandardCopyOption.REPLACE_EXISTING for o in options)
try:
if replace and _os.path.exists(dst):
_os.remove(dst)
_shutil.move(src, dst)
except OSError as e:
raise IOException(str(e))
@staticmethod
def delete(path):
try:
p = str(path)
if _os.path.isdir(p):
_os.rmdir(p)
else:
_os.remove(p)
except OSError as e:
raise NoSuchFileException(str(path))
@staticmethod
def deleteIfExists(path):
try:
Files.delete(path)
return True
except NoSuchFileException:
return False
@staticmethod
def createDirectories(path):
_os.makedirs(str(path), exist_ok=True)
return path
@staticmethod
def createDirectory(path, attrs=None):
_os.makedirs(str(path), exist_ok=True)
return path
@staticmethod
def createFile(path, attrs=None):
p = str(path)
if _os.path.exists(p):
raise FileAlreadyExistsException(str(path))
open(p, "a").close()
return path
@staticmethod
def createTempFile(prefix, suffix, dir=None):
f = _tempfile.NamedTemporaryFile(prefix=prefix, suffix=suffix,
dir=str(dir) if dir else None, delete=False)
p = f.name
f.close()
return Path(p)
@staticmethod
def createTempDirectory(prefix, attrs=None):
d = _tempfile.mkdtemp(prefix=prefix)
return Path(d)
@staticmethod
def exists(path, *options):
return _os.path.exists(str(path))
@staticmethod
def notExists(path, *options):
return not _os.path.exists(str(path))
@staticmethod
def isReadable(path):
return _os.access(str(path), _os.R_OK)
@staticmethod
def isWritable(path):
return _os.access(str(path), _os.W_OK)
@staticmethod
def isExecutable(path):
return _os.access(str(path), _os.X_OK)
@staticmethod
def isDirectory(path, *options):
return _os.path.isdir(str(path))
@staticmethod
def isRegularFile(path, *options):
return _os.path.isfile(str(path))
@staticmethod
def isSymbolicLink(path):
return _os.path.islink(str(path))
@staticmethod
def isHidden(path):
return _os.path.basename(str(path)).startswith(".")
@staticmethod
def getLastModifiedTime(path, *options):
return int(_os.path.getmtime(str(path)) * 1000)
@staticmethod
def setLastModifiedTime(path, time):
_os.utime(str(path), (time / 1000, time / 1000))
@staticmethod
def getAttribute(path, attribute, *options):
return None
@staticmethod
def setAttribute(path, attribute, value, *options):
pass
@staticmethod
def getPosixFilePermissions(path, *options):
return []
@staticmethod
def setPosixFilePermissions(path, perms, *options):
pass
@staticmethod
def newInputStream(path, *options):
from ..io import FileInputStream
return FileInputStream(str(path))
@staticmethod
def newOutputStream(path, *options):
from ..io import FileOutputStream
append = any(isinstance(o, StandardOpenOption) and o == StandardOpenOption.APPEND for o in options)
return FileOutputStream(str(path), append)
@staticmethod
def newBufferedReader(path, charset=None):
from ..io import BufferedReader, InputStreamReader, FileInputStream
inp = FileInputStream(str(path))
reader = InputStreamReader(inp, charset or "utf-8")
return BufferedReader(reader)
@staticmethod
def newBufferedWriter(path, charset=None, *options):
from ..io import BufferedWriter, OutputStreamWriter, FileOutputStream
append = any(isinstance(o, StandardOpenOption) and o == StandardOpenOption.APPEND for o in options)
out = FileOutputStream(str(path), append)
writer = OutputStreamWriter(out, charset or "utf-8")
return BufferedWriter(writer)
@staticmethod
def readAllBytes(path):
with open(str(path), "rb") as f:
return f.read()
@staticmethod
def readAllLines(path, charset=None):
with open(str(path), "r", encoding=charset or "utf-8") as f:
return f.read().splitlines()
@staticmethod
def readString(path, charset=None):
with open(str(path), "r", encoding=charset or "utf-8") as f:
return f.read()
@staticmethod
def write(path, content, *options):
mode = "wb" if isinstance(content, bytes) else "w"
open_mode = mode
if any(isinstance(o, StandardOpenOption) and o == StandardOpenOption.APPEND for o in options):
open_mode = "ab" if mode == "wb" else "a"
with open(str(path), open_mode) as f:
f.write(content)
@staticmethod
def writeString(path, content, *options):
open_mode = "w"
if any(isinstance(o, StandardOpenOption) and o == StandardOpenOption.APPEND for o in options):
open_mode = "a"
with open(str(path), open_mode, encoding="utf-8") as f:
f.write(content)
@staticmethod
def list(path):
try:
return [Path(_os.path.join(str(path), entry)) for entry in _os.listdir(str(path))]
except OSError:
raise IOException(f"Failed to list directory: {path}")
@staticmethod
def walk(path, maxDepth=None):
for root, dirs, files in _os.walk(str(path)):
yield Path(root)
@staticmethod
def find(start, maxDepth, matcher, *options):
for root, dirs, files in _os.walk(str(start)):
for f in files:
p = Path(_os.path.join(root, f))
if matcher.matches(p):
yield p
@staticmethod
def lines(path, charset=None):
with open(str(path), "r", encoding=charset or "utf-8") as f:
for line in f:
yield line.rstrip("\n")
@staticmethod
def getFileStore(path):
return FileStore(str(path))
@staticmethod
def probeContentType(path):
return "application/octet-stream"
@staticmethod
def getOwner(path, *options):
raise AndroidOnlyError("getOwner")
@staticmethod
def setOwner(path, owner, *options):
raise AndroidOnlyError("setOwner")
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+287
View File
@@ -0,0 +1,287 @@
"""
Java regex standard library APIs implemented in Python.
java.util.regex package - Pattern, Matcher, MatchResult, PatternSyntaxException.
"""
from .._core import Stub
from .io import IOException
from .lang import RuntimeException
import re as _re
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
IllegalStateException = type("IllegalStateException", (RuntimeException,), {})
__all__ = [
"Pattern", "Matcher", "MatchResult", "PatternSyntaxException",
]
# ============================================================
# PatternSyntaxException
# ============================================================
class PatternSyntaxException(IllegalArgumentException):
def __init__(self, desc, regex, index):
super().__init__(f"{desc}: {regex} at index {index}")
self._desc = desc
self._regex = regex
self._index = index
def getDescription(self):
return self._desc
def getPattern(self):
return self._regex
def getIndex(self):
return self._index
def getMessage(self):
return f"{self._desc} near index {self._index}: {self._regex}"
# ============================================================
# MatchResult
# ============================================================
class MatchResult(Stub):
def start(self, group=None):
raise NotImplementedError
def end(self, group=None):
raise NotImplementedError
def group(self, group=None):
raise NotImplementedError
def groupCount(self):
raise NotImplementedError
# ============================================================
# Matcher
# ============================================================
class Matcher(MatchResult):
def __init__(self, pattern, input_str):
super().__init__()
self._pattern = pattern
self._input = input_str
self._re_pattern = pattern._pattern
self._match = None
self._region_start = 0
self._region_end = len(input_str)
self._transparent_bounds = False
self._anchoring_bounds = True
self._last_match = None
def matches(self):
self._match = self._re_pattern.fullmatch(self._input, self._region_start, self._region_end)
self._last_match = self._match
return self._match is not None
def find(self, start=None):
if start is not None:
self._match = self._re_pattern.search(self._input, start, self._region_end)
else:
if self._match is None:
self._match = self._re_pattern.search(self._input, self._region_start, self._region_end)
else:
pos = self._match.end()
self._match = self._re_pattern.search(self._input, pos, self._region_end)
if self._match:
self._last_match = self._match
return self._match is not None
def lookingAt(self):
self._match = self._re_pattern.match(self._input, self._region_start, self._region_end)
self._last_match = self._match
return self._match is not None
def start(self, group=0):
if self._match is None:
raise IllegalStateException("No match available")
if group == 0:
return self._match.start()
return self._match.start(group)
def end(self, group=0):
if self._match is None:
raise IllegalStateException("No match available")
if group == 0:
return self._match.end()
return self._match.end(group)
def group(self, group=0):
if self._match is None:
raise IllegalStateException("No match available")
if isinstance(group, str):
return self._match.group(group)
return self._match.group(group)
def groupCount(self):
return self._re_pattern.groups
def replaceAll(self, replacement):
return self._re_pattern.sub(replacement, self._input)
def replaceFirst(self, replacement):
return self._re_pattern.sub(replacement, self._input, count=1)
def appendReplacement(self, sb, replacement):
if self._match is None:
raise IllegalStateException("No match available")
self._append_pos = getattr(self, '_append_pos', 0)
sb.append(self._input[self._append_pos:self._match.start()])
sb.append(self._re_pattern.sub(replacement, self._match.group(), count=1))
self._append_pos = self._match.end()
return self
def appendTail(self, sb):
self._append_pos = getattr(self, '_append_pos', 0)
sb.append(self._input[self._append_pos:])
return sb
def reset(self, input_str=None):
if input_str is not None:
self._input = input_str
self._region_end = len(input_str)
self._match = None
self._last_match = None
return self
def region(self, start, end):
self._region_start = start
self._region_end = end
return self
def regionStart(self):
return self._region_start
def regionEnd(self):
return self._region_end
def hasTransparentBounds(self):
return self._transparent_bounds
def hasAnchoringBounds(self):
return self._anchoring_bounds
def useAnchoringBounds(self, value):
self._anchoring_bounds = value
return self
def useTransparentBounds(self, value):
self._transparent_bounds = value
return self
def hitEnd(self):
return self._match is not None and self._match.end() >= self._region_end
def requireEnd(self):
return self._match is not None and not self.hitEnd()
def toMatchResult(self):
result = Matcher(self._pattern, self._input)
result._match = self._match
result._last_match = self._last_match
return result
def pattern(self):
return self._pattern
def toString(self):
return f"Matcher[pattern={self._pattern.pattern()}]"
def namedGroups(self):
return self._re_pattern.groupindex
class IllegalStateException(RuntimeException):
pass
# ============================================================
# Pattern
# ============================================================
class Pattern(Stub):
CANON_EQ = 128
CASE_INSENSITIVE = 2
COMMENTS = 4
DOTALL = 32
LITERAL = 16
MULTILINE = 8
UNICODE_CASE = 64
UNICODE_CHARACTER_CLASS = 256
UNIX_LINES = 1
_re_flags_map = {
0: 0, # default
2: _re.IGNORECASE,
8: _re.MULTILINE,
32: _re.DOTALL,
64: _re.UNICODE,
4: _re.VERBOSE,
}
def __init__(self, regex, flags=0):
super().__init__()
self._regex = str(regex)
self._flags = flags
re_flags = 0
for java_flag, py_flag in self._re_flags_map.items():
if flags & java_flag:
re_flags |= py_flag
try:
self._pattern = _re.compile(self._regex, re_flags)
except _re.error as e:
raise PatternSyntaxException(str(e), self._regex, e.pos if hasattr(e, 'pos') else 0)
@staticmethod
def compile(regex, flags=0):
return Pattern(regex, flags)
def matcher(self, input_str):
return Matcher(self, input_str)
def split(self, input_str, limit=0):
if limit <= 0:
parts = self._pattern.split(str(input_str))
if limit == 0:
while parts and parts[-1] == "":
parts.pop()
else:
parts = self._pattern.split(str(input_str), maxsplit=limit - 1)
while len(parts) < limit:
parts.append("")
return parts
def splitAsStream(self, input_str):
return iter(self.split(input_str))
@staticmethod
def matches(regex, input_str):
return bool(_re.fullmatch(regex, str(input_str)))
@staticmethod
def quote(s):
return _re.escape(str(s))
def flags(self):
return self._flags
def pattern(self):
return self._regex
def toString(self):
return self._regex
def predicate(self):
return lambda s: bool(self._pattern.fullmatch(str(s)))
def asPredicate(self):
return self.predicate()
def asMatchPredicate(self):
return lambda s: bool(self._pattern.fullmatch(str(s)))
+697
View File
@@ -0,0 +1,697 @@
"""
Java zip standard library APIs implemented in Python.
java.util.zip package - ZipFile, ZipEntry, GZIP, CRC, Deflater, Inflater.
"""
from .._core import Stub
from .io import IOException, Closeable, Flushable
import zipfile as _zipfile
import gzip as _gzip
import zlib as _zlib
import io as _pyio
import os as _os
from datetime import datetime as _datetime
__all__ = [
"ZipFile", "ZipEntry", "ZipOutputStream", "ZipInputStream",
"GZIPInputStream", "GZIPOutputStream",
"CRC32", "CheckedInputStream", "CheckedOutputStream",
"Adler32",
"DataFormatException", "ZipException",
"Deflater", "Inflater",
"DeflaterOutputStream", "InflaterInputStream",
]
# ============================================================
# Exception classes
# ============================================================
class ZipException(IOException):
pass
class DataFormatException(Exception):
pass
# ============================================================
# CRC32
# ============================================================
class CRC32(Stub):
def __init__(self):
super().__init__()
self._value = 0
def getValue(self):
return self._value
def reset(self):
self._value = 0
def update(self, b, off=None, length=None):
if isinstance(b, int):
self._value = _zlib.crc32(bytes([b & 0xFF]), self._value) & 0xFFFFFFFF
elif isinstance(b, (bytes, bytearray)):
if off is not None and length is not None:
self._value = _zlib.crc32(bytes(b[off:off+length]), self._value) & 0xFFFFFFFF
else:
self._value = _zlib.crc32(bytes(b), self._value) & 0xFFFFFFFF
# ============================================================
# Adler32
# ============================================================
class Adler32(Stub):
def __init__(self):
super().__init__()
self._value = 1
def getValue(self):
return self._value
def reset(self):
self._value = 1
def update(self, b, off=None, length=None):
if isinstance(b, int):
self._value = _zlib.adler32(bytes([b & 0xFF]), self._value) & 0xFFFFFFFF
elif isinstance(b, (bytes, bytearray)):
if off is not None and length is not None:
self._value = _zlib.adler32(bytes(b[off:off+length]), self._value) & 0xFFFFFFFF
else:
self._value = _zlib.adler32(bytes(b), self._value) & 0xFFFFFFFF
# ============================================================
# CheckedInputStream / CheckedOutputStream
# ============================================================
class CheckedInputStream(Closeable):
def __init__(self, inp, cksum):
super().__init__()
self._in = inp
self._cksum = cksum
def read(self, b=None, off=None, length=None):
if b is None:
result = self._in.read()
if result >= 0:
self._cksum.update(result)
return result
if off is None:
off = 0
if length is None:
length = len(b)
result = self._in.read(b, off, length)
if result > 0:
self._cksum.update(b[off:off+result])
return result
def getChecksum(self):
return self._cksum
def close(self):
self._in.close()
def skip(self, n):
return self._in.skip(n)
class CheckedOutputStream(Closeable, Flushable):
def __init__(self, out, cksum):
super().__init__()
self._out = out
self._cksum = cksum
def write(self, b, off=None, length=None):
if isinstance(b, int):
self._out.write(b)
self._cksum.update(b)
else:
if off is not None and length is not None:
data = bytes(b[off:off+length])
else:
data = bytes(b)
self._out.write(data)
self._cksum.update(data)
def getChecksum(self):
return self._cksum
def flush(self):
self._out.flush()
def close(self):
self._out.close()
# ============================================================
# ZipEntry
# ============================================================
class ZipEntry(Stub):
STORED = 0
DEFLATED = 8
def __init__(self, name):
super().__init__()
self._name = name
self._method = ZipEntry.DEFLATED
self._size = 0
self._compressed_size = 0
self._crc = 0
self._comment = ""
self._time = 0
self._extra = b""
self._is_directory = name.endswith("/")
def getName(self):
return self._name
def getMethod(self):
return self._method
def setMethod(self, method):
self._method = method
def getSize(self):
return self._size
def setSize(self, size):
self._size = size
def getCompressedSize(self):
return self._compressed_size
def setCompressedSize(self, size):
self._compressed_size = size
def getCrc(self):
return self._crc
def setCrc(self, crc):
self._crc = crc
def getComment(self):
return self._comment
def setComment(self, comment):
self._comment = comment
def getTime(self):
return self._time
def setTime(self, time):
self._time = time
def getExtra(self):
return self._extra
def setExtra(self, extra):
self._extra = extra
def isDirectory(self):
return self._is_directory
def toString(self):
return self._name
def __str__(self):
return self._name
# ============================================================
# ZipFile
# ============================================================
class ZipFile(Closeable):
OPEN_READ = 1
OPEN_DELETE = 2
def __init__(self, file, mode="r"):
super().__init__()
if isinstance(file, str):
path = file
else:
path = file.getPath()
self._path = path
self._mode = mode
try:
self._zfile = _zipfile.ZipFile(path, mode)
except Exception as e:
raise ZipException(str(e))
def entries(self):
return iter(self._zfile.infolist())
def getEntry(self, name):
try:
info = self._zfile.getinfo(name)
entry = ZipEntry(info.filename)
entry.setMethod(info.compress_type)
entry.setSize(info.file_size)
entry.setCompressedSize(info.compress_size)
entry.setCrc(info.CRC)
entry.setTime(int(_datetime(*info.date_time).timestamp() * 1000) if info.date_time else 0)
return entry
except KeyError:
return None
def getInputStream(self, entry):
try:
data = self._zfile.read(entry.getName() if isinstance(entry, ZipEntry) else entry)
from ..io import ByteArrayInputStream
return ByteArrayInputStream(data)
except Exception as e:
raise ZipException(str(e))
def close(self):
self._zfile.close()
def size(self):
return len(self._zfile.namelist())
def getName(self):
return self._path
def getComment(self):
return ""
# ============================================================
# ZipOutputStream
# ============================================================
class ZipOutputStream(Closeable, Flushable):
STORED = 0
DEFLATED = 8
def __init__(self, out):
super().__init__()
self._out = out
self._zfile = _zipfile.ZipFile(out, "w", _zipfile.ZIP_DEFLATED)
self._method = ZipOutputStream.DEFLATED
self._level = -1
self._comment = ""
def putNextEntry(self, entry):
zi = _zipfile.ZipInfo(entry.getName() if isinstance(entry, ZipEntry) else str(entry))
if hasattr(entry, 'getTime') and entry.getTime():
dt = _datetime.fromtimestamp(entry.getTime() / 1000.0)
zi.date_time = dt.timetuple()[:6]
self._zfile.writestr(zi, b"")
def closeEntry(self):
pass
def write(self, b, off=None, length=None):
if off is not None and length is not None:
self._zfile._zout.write(bytes(b[off:off+length]))
else:
self._zfile._zout.write(bytes(b) if not isinstance(b, (bytes, bytearray)) else b)
def finish(self):
self._zfile.close()
def close(self):
self._zfile.close()
def setMethod(self, method):
self._method = method
def setLevel(self, level):
self._level = level
def setComment(self, comment):
self._comment = comment
def flush(self):
self._zfile._zout.flush() if hasattr(self._zfile._zout, 'flush') else None
# ============================================================
# ZipInputStream
# ============================================================
class ZipInputStream(Closeable):
def __init__(self, inp):
super().__init__()
self._inp = inp
self._zfile = _zipfile.ZipFile(inp)
self._entries = iter(self._zfile.infolist())
self._current_entry = None
self._current_data = b""
self._current_pos = 0
def getNextEntry(self):
try:
info = next(self._entries)
entry = ZipEntry(info.filename)
entry.setMethod(info.compress_type)
entry.setSize(info.file_size)
entry.setCompressedSize(info.compress_size)
entry.setCrc(info.CRC)
self._current_entry = info
self._current_data = self._zfile.read(info)
self._current_pos = 0
return entry
except StopIteration:
self._current_entry = None
self._current_data = b""
return None
def read(self, b=None, off=None, length=None):
if self._current_entry is None:
return -1
avail = len(self._current_data) - self._current_pos
if avail <= 0:
return -1
if b is None:
val = self._current_data[self._current_pos]
self._current_pos += 1
return val
if off is None:
off = 0
if length is None:
length = len(b)
n = min(length, avail)
if isinstance(b, bytearray):
b[off:off+n] = self._current_data[self._current_pos:self._current_pos+n]
self._current_pos += n
return n
def closeEntry(self):
self._current_entry = None
self._current_data = b""
def available(self):
if self._current_entry is None:
return 0
return len(self._current_data) - self._current_pos
def close(self):
self._zfile.close()
# ============================================================
# GZIPInputStream
# ============================================================
class GZIPInputStream(Closeable):
def __init__(self, inp, size=512):
super().__init__()
self._inp = inp
self._gzip_file = _gzip.GzipFile(fileobj=_pyio.BufferedReader(inp) if hasattr(inp, 'read') else inp)
def read(self, b=None, off=None, length=None):
if b is None:
data = self._gzip_file.read(1)
return data[0] if data else -1
if off is None:
off = 0
if length is None:
length = len(b)
data = self._gzip_file.read(length)
if not data:
return -1
n = len(data)
if isinstance(b, bytearray):
b[off:off+n] = data
else:
ba = bytearray(b)
ba[off:off+n] = data
b[:] = bytes(ba)
return n
def close(self):
self._gzip_file.close()
# ============================================================
# GZIPOutputStream
# ============================================================
class GZIPOutputStream(Closeable, Flushable):
def __init__(self, out, size=512):
super().__init__()
self._out = out
self._gzip_file = _gzip.GzipFile(fileobj=out, mode="wb")
def write(self, b, off=None, length=None):
if isinstance(b, int):
self._gzip_file.write(bytes([b & 0xFF]))
elif isinstance(b, (bytes, bytearray)):
if off is not None and length is not None:
self._gzip_file.write(bytes(b[off:off+length]))
else:
self._gzip_file.write(bytes(b))
def finish(self):
self._gzip_file.close()
def close(self):
self._gzip_file.close()
def flush(self):
self._gzip_file.flush()
# ============================================================
# Deflater
# ============================================================
class Deflater(Stub):
BEST_COMPRESSION = 9
BEST_SPEED = 1
DEFAULT_COMPRESSION = -1
DEFAULT_STRATEGY = 0
FILTERED = 1
HUFFMAN_ONLY = 2
NO_COMPRESSION = 0
NO_FLUSH = 0
SYNC_FLUSH = 2
FULL_FLUSH = 3
def __init__(self, level=-1, nowrap=False):
super().__init__()
self._level = level
self._nowrap = nowrap
self._compress = _zlib.compressobj(level=level if level >= 0 else 6,
method=_zlib.DEFLATED,
wbits=-_zlib.MAX_WBITS if nowrap else _zlib.MAX_WBITS)
self._input_buffer = b""
self._finished = False
def setInput(self, data, off=0, length=-1):
if length < 0:
length = len(data) - off
self._input_buffer = bytes(data[off:off+length])
def needsInput(self):
return len(self._input_buffer) == 0
def setDictionary(self, dictionary):
pass
def getTotalIn(self):
return len(self._input_buffer)
def getTotalOut(self):
return 0
def deflate(self, output, off=0, length=-1):
if length < 0:
length = len(output) - off
data = self._compress.compress(self._input_buffer)
self._input_buffer = b""
n = min(len(data), length)
if isinstance(output, bytearray):
output[off:off+n] = data[:n]
else:
ba = bytearray(output)
ba[off:off+n] = data[:n]
output[:] = bytes(ba)
return n
def finish(self):
self._finished = True
def finished(self):
return self._finished
def end(self):
pass
def getAdler(self):
return 1
def reset(self):
self._compress = _zlib.compressobj(level=self._level if self._level >= 0 else 6,
method=_zlib.DEFLATED,
wbits=-_zlib.MAX_WBITS if self._nowrap else _zlib.MAX_WBITS)
self._input_buffer = b""
self._finished = False
# ============================================================
# Inflater
# ============================================================
class Inflater(Stub):
def __init__(self, nowrap=False):
super().__init__()
self._nowrap = nowrap
wbits = -_zlib.MAX_WBITS if nowrap else _zlib.MAX_WBITS
self._decompress = _zlib.decompressobj(wbits)
self._input_buffer = b""
self._finished = False
def setInput(self, data, off=0, length=-1):
if length < 0:
length = len(data) - off
self._input_buffer = bytes(data[off:off+length])
def needsInput(self):
return len(self._input_buffer) == 0
def setDictionary(self, dictionary):
pass
def getTotalIn(self):
return len(self._input_buffer)
def getTotalOut(self):
return 0
def inflate(self, output, off=0, length=-1):
if length < 0:
length = len(output) - off
try:
data = self._decompress.decompress(self._input_buffer)
self._input_buffer = b""
n = min(len(data), length)
if isinstance(output, bytearray):
output[off:off+n] = data[:n]
else:
ba = bytearray(output)
ba[off:off+n] = data[:n]
output[:] = bytes(ba)
return n
except _zlib.error as e:
raise DataFormatException(str(e))
def finished(self):
return self._finished
def end(self):
pass
def getAdler(self):
return 1
def needsDictionary(self):
return False
def reset(self):
wbits = -_zlib.MAX_WBITS if self._nowrap else _zlib.MAX_WBITS
self._decompress = _zlib.decompressobj(wbits)
self._input_buffer = b""
self._finished = False
# ============================================================
# DeflaterOutputStream
# ============================================================
class DeflaterOutputStream(Closeable, Flushable):
def __init__(self, out, deflater=None, size=512):
super().__init__()
self._out = out
self._deflater = deflater or Deflater()
self._buffer = bytearray(size)
def write(self, b, off=None, length=None):
if isinstance(b, int):
self._out.write(bytes([b & 0xFF]))
else:
if off is not None and length is not None:
self._out.write(bytes(b[off:off+length]))
else:
self._deflater.setInput(bytes(b) if isinstance(b, (bytes, bytearray)) else bytes(b))
while not self._deflater.needsInput():
n = self._deflater.deflate(self._buffer)
if n > 0:
self._out.write(bytes(self._buffer[:n]))
def finish(self):
self._deflater.finish()
while not self._deflater.finished():
n = self._deflater.deflate(self._buffer)
if n > 0:
self._out.write(bytes(self._buffer[:n]))
def close(self):
self.finish()
self._deflater.end()
self._out.close()
def flush(self):
self._out.flush()
# ============================================================
# InflaterInputStream
# ============================================================
class InflaterInputStream(Closeable):
def __init__(self, inp, inflater=None, size=512):
super().__init__()
self._in = inp
self._inflater = inflater or Inflater()
self._buffer = bytearray(size)
def read(self, b=None, off=None, length=None):
if b is None:
buf = bytearray(1)
n = self._read_from_inflater(buf, 0, 1)
return buf[0] if n > 0 else -1
if off is None:
off = 0
if length is None:
length = len(b)
return self._read_from_inflater(b, off, length)
def _read_from_inflater(self, b, off, length):
while not self._inflater.finished():
if self._inflater.needsInput():
data = self._in.read(self._buffer)
if data is None or data == -1 or data == 0:
break
if isinstance(data, int):
break
self._inflater.setInput(data)
try:
n = self._inflater.inflate(b, off, length)
if n > 0:
return n
except DataFormatException:
break
return -1
def available(self):
return 0
def close(self):
self._inflater.end()
self._in.close()
def mark(self, readlimit):
pass
def reset(self):
raise IOException("mark/reset not supported")
def markSupported(self):
return False