- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等) - java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等) - javax/ 4个模块 (net/crypto/security/sql) - org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http) - dalvik/ 1个模块 (system) - ~3053个类/接口,方法签名完全对齐Android SDK - 桌面跨平台运行 (Windows/macOS/Linux) - 修复所有导入错误和Python关键字冲突
1414 lines
39 KiB
Python
1414 lines
39 KiB
Python
"""
|
|
Java java.io extended standard library APIs implemented in Python.
|
|
Extends java.io with ObjectStreamField, ObjectStreamConstants, ObjectInput, etc.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from .._core import Stub
|
|
from ..java.io import (
|
|
Serializable, Externalizable, IOException,
|
|
ObjectStreamConstants as _BaseObjectStreamConstants,
|
|
File as _File, PrintWriter,
|
|
)
|
|
from ..java.lang import RuntimeException, String, Exception as _JavaException
|
|
import io as _pyio
|
|
import os as _os
|
|
import sys as _sys
|
|
import struct as _struct
|
|
import pickle as _pickle
|
|
import threading as _threading
|
|
import traceback as _traceback
|
|
import types as _py_types
|
|
|
|
__all__ = [
|
|
"ObjectStreamField", "ObjectStreamConstants",
|
|
"ObjectInput", "ObjectOutput", "ObjectInputStream", "ObjectOutputStream",
|
|
"ObjectStreamClass", "ObjectInputValidation",
|
|
"SerialCallbackContext",
|
|
"Externalizable", "Serializable",
|
|
"FileFilter", "FileNameFilter", "FilePermission",
|
|
"SerializablePermission",
|
|
"Console", "PrintStream",
|
|
"DataInput", "DataOutput",
|
|
"SequenceInputStream", "StringBufferInputStream",
|
|
"LineNumberReader", "CharArrayReader", "CharArrayWriter",
|
|
"FilterReader", "FilterWriter", "PushbackReader",
|
|
"PushbackInputStream", "StreamTokenizer",
|
|
"StreamCorruptedException", "WriteAbortedException",
|
|
]
|
|
|
|
|
|
# ============================================================
|
|
# ObjectStreamConstants
|
|
# ============================================================
|
|
|
|
class ObjectStreamConstants(Stub):
|
|
"""java.io.ObjectStreamConstants"""
|
|
STREAM_MAGIC = 0xACED
|
|
STREAM_VERSION = 5
|
|
TC_BASE = 0x70
|
|
TC_NULL = 0x70
|
|
TC_REFERENCE = 0x71
|
|
TC_CLASS = 0x72
|
|
TC_OBJECT = 0x73
|
|
TC_STRING = 0x74
|
|
TC_ARRAY = 0x75
|
|
TC_ENUM = 0x7E
|
|
TC_CLASSDESC = 0x72
|
|
TC_PROXYCLASSDESC = 0x7D
|
|
TC_BLOCKDATA = 0x77
|
|
TC_ENDBLOCKDATA = 0x78
|
|
TC_RESET = 0x79
|
|
TC_EXCEPTION = 0x7A
|
|
TC_LONGSTRING = 0x7C
|
|
baseWireHandle = 0x7E0000
|
|
PROTOCOL_VERSION_1 = 1
|
|
PROTOCOL_VERSION_2 = 2
|
|
SC_WRITE_METHOD = 0x01
|
|
SC_BLOCK_DATA = 0x08
|
|
SC_SERIALIZABLE = 0x02
|
|
SC_EXTERNALIZABLE = 0x04
|
|
SC_ENUM = 0x10
|
|
SUBSTITUTION_PERMISSION = "enableSubstitution"
|
|
|
|
|
|
# ============================================================
|
|
# ObjectStreamField
|
|
# ============================================================
|
|
|
|
class ObjectStreamField(Stub):
|
|
"""java.io.ObjectStreamField"""
|
|
def __init__(self, name, field_type, unshared=False):
|
|
super().__init__()
|
|
self._name = name
|
|
self._type = field_type
|
|
self._unshared = unshared
|
|
|
|
def getName(self):
|
|
return self._name
|
|
|
|
def getType(self):
|
|
return self._type
|
|
|
|
def getTypeString(self):
|
|
return self._type.__name__ if hasattr(self._type, '__name__') else str(self._type)
|
|
|
|
def getTypeCode(self):
|
|
return self.getTypeString()[0].upper()
|
|
|
|
def isUnshared(self):
|
|
return self._unshared
|
|
|
|
def isPrimitive(self):
|
|
return self._type in (int, float, bool, bytes, str, bytearray)
|
|
|
|
def toString(self):
|
|
return f"{self.getTypeString()} {self._name}"
|
|
|
|
|
|
# ============================================================
|
|
# ObjectStreamClass
|
|
# ============================================================
|
|
|
|
class ObjectStreamClass(Stub):
|
|
"""java.io.ObjectStreamClass"""
|
|
_descriptors = {}
|
|
|
|
def __init__(self, cls=None):
|
|
super().__init__()
|
|
self._cls = cls
|
|
self._name = cls.__name__ if cls else ""
|
|
self._serial_version_uid = hash(cls) if cls else 0
|
|
self._fields = []
|
|
self._serializable = hasattr(cls, '__getstate__') or hasattr(cls, '__setstate__') if cls else False
|
|
|
|
if cls:
|
|
for attr_name in dir(cls):
|
|
if not attr_name.startswith('_'):
|
|
attr_type = type(getattr(cls, attr_name, None))
|
|
self._fields.append(ObjectStreamField(attr_name, attr_type))
|
|
|
|
@staticmethod
|
|
def lookup(cls):
|
|
if cls is None:
|
|
return None
|
|
if cls not in ObjectStreamClass._descriptors:
|
|
ObjectStreamClass._descriptors[cls] = ObjectStreamClass(cls)
|
|
return ObjectStreamClass._descriptors[cls]
|
|
|
|
@staticmethod
|
|
def lookupAny(cls):
|
|
return ObjectStreamClass.lookup(cls)
|
|
|
|
def getName(self):
|
|
return self._name
|
|
|
|
def getSerialVersionUID(self):
|
|
return self._serial_version_uid
|
|
|
|
def getFields(self):
|
|
return self._fields
|
|
|
|
def getField(self, name):
|
|
for f in self._fields:
|
|
if f.getName() == name:
|
|
return f
|
|
return None
|
|
|
|
def forClass(self):
|
|
return self._cls
|
|
|
|
def isSerializable(self):
|
|
return self._serializable
|
|
|
|
def isEnum(self):
|
|
return False
|
|
|
|
def toString(self):
|
|
return f"ObjectStreamClass[{self._name}]"
|
|
|
|
|
|
# ============================================================
|
|
# ObjectInputValidation
|
|
# ============================================================
|
|
|
|
class ObjectInputValidation(Stub):
|
|
"""java.io.ObjectInputValidation"""
|
|
def validateObject(self):
|
|
raise NotImplementedError
|
|
|
|
|
|
# ============================================================
|
|
# SerialCallbackContext
|
|
# ============================================================
|
|
|
|
class SerialCallbackContext(Stub):
|
|
"""java.io.SerialCallbackContext"""
|
|
def __init__(self, obj, desc):
|
|
super().__init__()
|
|
self._obj = obj
|
|
self._desc = desc
|
|
self._used = False
|
|
|
|
def getObj(self):
|
|
return self._obj
|
|
|
|
def getDesc(self):
|
|
return self._desc
|
|
|
|
def setUsed(self):
|
|
self._used = True
|
|
|
|
def isUsed(self):
|
|
return self._used
|
|
|
|
|
|
# ============================================================
|
|
# ObjectInput / ObjectOutput interfaces
|
|
# ============================================================
|
|
|
|
class DataInput(Stub):
|
|
"""java.io.DataInput"""
|
|
def readByte(self):
|
|
raise NotImplementedError
|
|
|
|
def readShort(self):
|
|
raise NotImplementedError
|
|
|
|
def readInt(self):
|
|
raise NotImplementedError
|
|
|
|
def readLong(self):
|
|
raise NotImplementedError
|
|
|
|
def readFloat(self):
|
|
raise NotImplementedError
|
|
|
|
def readDouble(self):
|
|
raise NotImplementedError
|
|
|
|
def readBoolean(self):
|
|
raise NotImplementedError
|
|
|
|
def readChar(self):
|
|
raise NotImplementedError
|
|
|
|
def readUnsignedByte(self):
|
|
raise NotImplementedError
|
|
|
|
def readUnsignedShort(self):
|
|
raise NotImplementedError
|
|
|
|
def readUTF(self):
|
|
raise NotImplementedError
|
|
|
|
def readFully(self, b, off=0, length=-1):
|
|
raise NotImplementedError
|
|
|
|
def skipBytes(self, n):
|
|
raise NotImplementedError
|
|
|
|
def readLine(self):
|
|
raise NotImplementedError
|
|
|
|
|
|
class DataOutput(Stub):
|
|
"""java.io.DataOutput"""
|
|
def writeByte(self, v):
|
|
raise NotImplementedError
|
|
|
|
def writeShort(self, v):
|
|
raise NotImplementedError
|
|
|
|
def writeInt(self, v):
|
|
raise NotImplementedError
|
|
|
|
def writeLong(self, v):
|
|
raise NotImplementedError
|
|
|
|
def writeFloat(self, v):
|
|
raise NotImplementedError
|
|
|
|
def writeDouble(self, v):
|
|
raise NotImplementedError
|
|
|
|
def writeBoolean(self, v):
|
|
raise NotImplementedError
|
|
|
|
def writeChar(self, v):
|
|
raise NotImplementedError
|
|
|
|
def writeBytes(self, s):
|
|
raise NotImplementedError
|
|
|
|
def writeChars(self, s):
|
|
raise NotImplementedError
|
|
|
|
def writeUTF(self, s):
|
|
raise NotImplementedError
|
|
|
|
def write(self, b, off=0, length=-1):
|
|
raise NotImplementedError
|
|
|
|
|
|
class ObjectInput(DataInput):
|
|
"""java.io.ObjectInput"""
|
|
def readObject(self):
|
|
raise NotImplementedError
|
|
|
|
def available(self):
|
|
return 0
|
|
|
|
def close(self):
|
|
pass
|
|
|
|
|
|
class ObjectOutput(DataOutput):
|
|
"""java.io.ObjectOutput"""
|
|
def writeObject(self, obj):
|
|
raise NotImplementedError
|
|
|
|
def flush(self):
|
|
pass
|
|
|
|
def close(self):
|
|
pass
|
|
|
|
|
|
# ============================================================
|
|
# ObjectInputStream
|
|
# ============================================================
|
|
|
|
class ObjectInputStream(ObjectInput):
|
|
"""java.io.ObjectInputStream"""
|
|
def __init__(self, inp):
|
|
super().__init__()
|
|
self._input = inp
|
|
self._data = inp.read() if hasattr(inp, 'read') else b""
|
|
self._pos = 0
|
|
self._handles = {}
|
|
self._next_handle = ObjectStreamConstants.baseWireHandle
|
|
self._validation_list = []
|
|
self._resolved = {}
|
|
|
|
def readObject(self):
|
|
if self._pos >= len(self._data):
|
|
raise StreamCorruptedException("No data")
|
|
try:
|
|
obj = _pickle.loads(self._data[self._pos:])
|
|
return obj
|
|
except Exception:
|
|
return None
|
|
|
|
def readByte(self):
|
|
val = self._data[self._pos] if self._pos < len(self._data) else 0
|
|
self._pos += 1
|
|
return val
|
|
|
|
def readInt(self):
|
|
if self._pos + 4 > len(self._data):
|
|
raise StreamCorruptedException()
|
|
val = _struct.unpack_from(">i", self._data, self._pos)[0]
|
|
self._pos += 4
|
|
return val
|
|
|
|
def readShort(self):
|
|
if self._pos + 2 > len(self._data):
|
|
raise StreamCorruptedException()
|
|
val = _struct.unpack_from(">h", self._data, self._pos)[0]
|
|
self._pos += 2
|
|
return val
|
|
|
|
def readLong(self):
|
|
if self._pos + 8 > len(self._data):
|
|
raise StreamCorruptedException()
|
|
val = _struct.unpack_from(">q", self._data, self._pos)[0]
|
|
self._pos += 8
|
|
return val
|
|
|
|
def readFloat(self):
|
|
if self._pos + 4 > len(self._data):
|
|
raise StreamCorruptedException()
|
|
val = _struct.unpack_from(">f", self._data, self._pos)[0]
|
|
self._pos += 4
|
|
return val
|
|
|
|
def readDouble(self):
|
|
if self._pos + 8 > len(self._data):
|
|
raise StreamCorruptedException()
|
|
val = _struct.unpack_from(">d", self._data, self._pos)[0]
|
|
self._pos += 8
|
|
return val
|
|
|
|
def readBoolean(self):
|
|
return self.readByte() != 0
|
|
|
|
def readChar(self):
|
|
if self._pos + 2 > len(self._data):
|
|
raise StreamCorruptedException()
|
|
val = _struct.unpack_from(">H", self._data, self._pos)[0]
|
|
self._pos += 2
|
|
return chr(val)
|
|
|
|
def readUnsignedByte(self):
|
|
return self.readByte() & 0xFF
|
|
|
|
def readUnsignedShort(self):
|
|
return self.readShort() & 0xFFFF
|
|
|
|
def readUTF(self):
|
|
length = self.readUnsignedShort()
|
|
if self._pos + length > len(self._data):
|
|
raise StreamCorruptedException()
|
|
val = self._data[self._pos:self._pos + length].decode("utf-8")
|
|
self._pos += length
|
|
return val
|
|
|
|
def readFully(self, b, off=0, length=-1):
|
|
if length < 0:
|
|
length = len(b) - off
|
|
if self._pos + length > len(self._data):
|
|
raise StreamCorruptedException()
|
|
for i in range(length):
|
|
b[off + i] = self._data[self._pos + i]
|
|
self._pos += length
|
|
|
|
def skipBytes(self, n):
|
|
actual = min(n, len(self._data) - self._pos)
|
|
self._pos += actual
|
|
return actual
|
|
|
|
def readLine(self):
|
|
result = []
|
|
while self._pos < len(self._data):
|
|
c = chr(self._data[self._pos])
|
|
self._pos += 1
|
|
if c == "\n":
|
|
break
|
|
if c == "\r":
|
|
if self._pos < len(self._data) and chr(self._data[self._pos]) == "\n":
|
|
self._pos += 1
|
|
break
|
|
result.append(c)
|
|
return "".join(result)
|
|
|
|
def available(self):
|
|
return len(self._data) - self._pos
|
|
|
|
def close(self):
|
|
self._input = None
|
|
self._data = b""
|
|
self._pos = 0
|
|
|
|
def defaultReadObject(self):
|
|
return self.readObject()
|
|
|
|
def readFields(self):
|
|
return self.readObject()
|
|
|
|
def registerValidation(self, obj, prio):
|
|
self._validation_list.append((obj, prio))
|
|
|
|
def resolveClass(self, desc):
|
|
return desc.forClass()
|
|
|
|
def resolveObject(self, obj):
|
|
return obj
|
|
|
|
def enableResolveObject(self, enable):
|
|
return False
|
|
|
|
def readUnshared(self):
|
|
return self.readObject()
|
|
|
|
|
|
# ============================================================
|
|
# ObjectOutputStream
|
|
# ============================================================
|
|
|
|
class ObjectOutputStream(ObjectOutput):
|
|
"""java.io.ObjectOutputStream"""
|
|
def __init__(self, out):
|
|
super().__init__()
|
|
self._output = out
|
|
self._buffer = bytearray()
|
|
self._handles = {}
|
|
self._next_handle = ObjectStreamConstants.baseWireHandle
|
|
self._block_data_mode = False
|
|
self._extended_block_data_mode = False
|
|
|
|
def writeObject(self, obj):
|
|
data = _pickle.dumps(obj)
|
|
self._buffer.extend(data)
|
|
self._flush_buffer()
|
|
|
|
def writeByte(self, v):
|
|
self._buffer.extend(_struct.pack(">b", v if isinstance(v, int) else ord(v)))
|
|
|
|
def writeInt(self, v):
|
|
self._buffer.extend(_struct.pack(">i", int(v)))
|
|
|
|
def writeShort(self, v):
|
|
self._buffer.extend(_struct.pack(">h", int(v)))
|
|
|
|
def writeLong(self, v):
|
|
self._buffer.extend(_struct.pack(">q", int(v)))
|
|
|
|
def writeFloat(self, v):
|
|
self._buffer.extend(_struct.pack(">f", float(v)))
|
|
|
|
def writeDouble(self, v):
|
|
self._buffer.extend(_struct.pack(">d", float(v)))
|
|
|
|
def writeBoolean(self, v):
|
|
self._buffer.extend(_struct.pack(">?", bool(v)))
|
|
|
|
def writeChar(self, v):
|
|
if isinstance(v, str):
|
|
v = ord(v)
|
|
self._buffer.extend(_struct.pack(">H", int(v)))
|
|
|
|
def writeBytes(self, s):
|
|
if isinstance(s, str):
|
|
self._buffer.extend(s.encode())
|
|
elif isinstance(s, bytes):
|
|
self._buffer.extend(s)
|
|
elif isinstance(s, bytearray):
|
|
self._buffer.extend(s)
|
|
|
|
def writeChars(self, s):
|
|
for c in s:
|
|
self._buffer.extend(_struct.pack(">H", ord(c)))
|
|
|
|
def writeUTF(self, s):
|
|
encoded = s.encode("utf-8")
|
|
self.writeShort(len(encoded))
|
|
self._buffer.extend(encoded)
|
|
|
|
def write(self, b, off=0, length=-1):
|
|
if isinstance(b, int):
|
|
self._buffer.append(b & 0xFF)
|
|
elif isinstance(b, bytes):
|
|
if length < 0:
|
|
length = len(b) - off
|
|
self._buffer.extend(b[off:off + length])
|
|
elif isinstance(b, bytearray):
|
|
if length < 0:
|
|
length = len(b) - off
|
|
self._buffer.extend(b[off:off + length])
|
|
|
|
def flush(self):
|
|
self._flush_buffer()
|
|
if hasattr(self._output, 'flush'):
|
|
self._output.flush()
|
|
|
|
def close(self):
|
|
self.flush()
|
|
if hasattr(self._output, 'close'):
|
|
self._output.close()
|
|
|
|
def defaultWriteObject(self):
|
|
pass
|
|
|
|
def putFields(self):
|
|
return self
|
|
|
|
def writeFields(self):
|
|
pass
|
|
|
|
def reset(self):
|
|
self._handles = {}
|
|
self._next_handle = ObjectStreamConstants.baseWireHandle
|
|
self._buffer = bytearray()
|
|
|
|
def useProtocolVersion(self, version):
|
|
pass
|
|
|
|
def writeUnshared(self, obj):
|
|
self.writeObject(obj)
|
|
|
|
def annotateClass(self, cls):
|
|
pass
|
|
|
|
def annotateProxyClass(self, cls):
|
|
pass
|
|
|
|
def replaceObject(self, obj):
|
|
return obj
|
|
|
|
def enableReplaceObject(self, enable):
|
|
return False
|
|
|
|
def writeStreamHeader(self):
|
|
self._buffer.extend(_struct.pack(">HH",
|
|
ObjectStreamConstants.STREAM_MAGIC,
|
|
ObjectStreamConstants.STREAM_VERSION))
|
|
|
|
def _flush_buffer(self):
|
|
if self._buffer:
|
|
data = bytes(self._buffer)
|
|
if hasattr(self._output, 'write'):
|
|
self._output.write(data)
|
|
self._buffer = bytearray()
|
|
|
|
|
|
# ============================================================
|
|
# StreamCorruptedException / WriteAbortedException
|
|
# ============================================================
|
|
|
|
class StreamCorruptedException(IOException):
|
|
"""java.io.StreamCorruptedException"""
|
|
def __init__(self, message=None):
|
|
super().__init__(message or "Stream corrupted")
|
|
|
|
|
|
class WriteAbortedException(IOException):
|
|
"""java.io.WriteAbortedException"""
|
|
def __init__(self, message, exception):
|
|
super().__init__(message)
|
|
self._exception = exception
|
|
|
|
def getException(self):
|
|
return self._exception
|
|
|
|
|
|
# ============================================================
|
|
# FileFilter / FileNameFilter
|
|
# ============================================================
|
|
|
|
class FileFilter(Stub):
|
|
"""java.io.FileFilter"""
|
|
def accept(self, pathname):
|
|
return True
|
|
|
|
|
|
class FileNameFilter(Stub):
|
|
"""java.io.FilenameFilter"""
|
|
def accept(self, dir, name):
|
|
return True
|
|
|
|
|
|
# ============================================================
|
|
# FilePermission / SerializablePermission
|
|
# ============================================================
|
|
|
|
class FilePermission(Stub):
|
|
"""java.io.FilePermission"""
|
|
def __init__(self, path, actions):
|
|
super().__init__()
|
|
self._path = path
|
|
self._actions = actions
|
|
|
|
def getName(self):
|
|
return self._path
|
|
|
|
def getActions(self):
|
|
return self._actions
|
|
|
|
def implies(self, permission):
|
|
return True
|
|
|
|
def equals(self, other):
|
|
if not isinstance(other, FilePermission):
|
|
return False
|
|
return self._path == other._path and self._actions == other._actions
|
|
|
|
def hashCode(self):
|
|
return hash((self._path, self._actions))
|
|
|
|
|
|
class SerializablePermission(Stub):
|
|
"""java.io.SerializablePermission"""
|
|
def __init__(self, name, actions=None):
|
|
super().__init__()
|
|
self._name = name
|
|
self._actions = actions or ""
|
|
|
|
def getName(self):
|
|
return self._name
|
|
|
|
def getActions(self):
|
|
return self._actions
|
|
|
|
def implies(self, permission):
|
|
return True
|
|
|
|
|
|
# ============================================================
|
|
# Console
|
|
# ============================================================
|
|
|
|
class Console(Stub):
|
|
"""java.io.Console"""
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
@staticmethod
|
|
def console():
|
|
return Console()
|
|
|
|
def readLine(self, fmt=None, *args):
|
|
if fmt:
|
|
print(fmt % args, end="")
|
|
return input()
|
|
|
|
def readPassword(self, fmt=None, *args):
|
|
import getpass
|
|
if fmt:
|
|
print(fmt % args, end="")
|
|
return getpass.getpass("")
|
|
|
|
def format(self, fmt, *args):
|
|
_sys.stdout.write(fmt % args)
|
|
_sys.stdout.flush()
|
|
return self
|
|
|
|
def printf(self, format, *args):
|
|
return self.format(format, *args)
|
|
|
|
def flush(self):
|
|
_sys.stdout.flush()
|
|
|
|
def reader(self):
|
|
return _pyio.BufferedReader(_pyio.FileIO(_sys.stdin.fileno()))
|
|
|
|
def writer(self):
|
|
return _pyio.TextIOWrapper(_pyio.BufferedWriter(
|
|
_pyio.FileIO(_sys.stdout.fileno(), "w")
|
|
))
|
|
|
|
|
|
# ============================================================
|
|
# PrintStream
|
|
# ============================================================
|
|
|
|
class PrintStream(Stub):
|
|
"""java.io.PrintStream"""
|
|
def __init__(self, out=None, auto_flush=False, encoding=None):
|
|
super().__init__()
|
|
self._out = out or _sys.stdout
|
|
self._auto_flush = auto_flush
|
|
self._encoding = encoding or "utf-8"
|
|
self._error = False
|
|
|
|
def print(self, obj=""):
|
|
_sys.stdout.write(str(obj))
|
|
|
|
def println(self, obj=""):
|
|
print(str(obj))
|
|
|
|
def printf(self, format, *args):
|
|
_sys.stdout.write(format % args)
|
|
if self._auto_flush:
|
|
_sys.stdout.flush()
|
|
return self
|
|
|
|
def format(self, format_, *args):
|
|
return self.printf(format_, *args)
|
|
|
|
def write(self, b, off=0, length=-1):
|
|
if isinstance(b, int):
|
|
self._out.write(bytes([b]))
|
|
elif isinstance(b, bytes):
|
|
if length < 0:
|
|
self._out.write(b[off:])
|
|
else:
|
|
self._out.write(b[off:off + length])
|
|
elif isinstance(b, str):
|
|
self._out.write(b)
|
|
if self._auto_flush:
|
|
self._out.flush()
|
|
|
|
def flush(self):
|
|
self._out.flush()
|
|
|
|
def close(self):
|
|
self.flush()
|
|
|
|
def checkError(self):
|
|
return self._error
|
|
|
|
def setError(self):
|
|
self._error = True
|
|
|
|
def clearError(self):
|
|
self._error = False
|
|
|
|
def append(self, c):
|
|
if isinstance(c, str):
|
|
self._out.write(c)
|
|
else:
|
|
self._out.write(str(c))
|
|
return self
|
|
|
|
|
|
# ============================================================
|
|
# SequenceInputStream
|
|
# ============================================================
|
|
|
|
class SequenceInputStream(Stub):
|
|
"""java.io.SequenceInputStream"""
|
|
def __init__(self, *args):
|
|
super().__init__()
|
|
if len(args) == 1:
|
|
self._enumerator = iter(args[0])
|
|
self._current = next(self._enumerator, None)
|
|
elif len(args) == 2:
|
|
self._enumerator = iter(args)
|
|
self._current = args[0]
|
|
else:
|
|
self._enumerator = iter([])
|
|
self._current = None
|
|
|
|
def read(self, b=None, off=0, length=-1):
|
|
while self._current is not None:
|
|
if hasattr(self._current, 'read'):
|
|
if b is None:
|
|
data = self._current.read()
|
|
else:
|
|
if length < 0:
|
|
data = self._current.read(len(b) - off)
|
|
else:
|
|
data = self._current.read(min(length, len(b) - off))
|
|
if data:
|
|
if b is not None:
|
|
for i, byte in enumerate(data):
|
|
b[off + i] = byte
|
|
return len(data)
|
|
self._current = next(self._enumerator, None)
|
|
else:
|
|
self._current = next(self._enumerator, None)
|
|
return -1
|
|
|
|
def close(self):
|
|
self._current = None
|
|
|
|
|
|
# ============================================================
|
|
# StringBufferInputStream
|
|
# ============================================================
|
|
|
|
class StringBufferInputStream(Stub):
|
|
"""java.io.StringBufferInputStream"""
|
|
def __init__(self, s):
|
|
super().__init__()
|
|
self._string = s
|
|
self._pos = 0
|
|
self._count = len(s)
|
|
|
|
def read(self, b=None, off=0, length=-1):
|
|
if self._pos >= self._count:
|
|
return -1
|
|
if b is None:
|
|
val = ord(self._string[self._pos]) if self._pos < self._count else -1
|
|
self._pos += 1
|
|
return val
|
|
if length < 0:
|
|
length = len(b) - off
|
|
available = self._count - self._pos
|
|
to_read = min(available, length)
|
|
for i in range(to_read):
|
|
b[off + i] = ord(self._string[self._pos + i])
|
|
self._pos += to_read
|
|
return to_read
|
|
|
|
def available(self):
|
|
return self._count - self._pos
|
|
|
|
def reset(self):
|
|
self._pos = 0
|
|
|
|
|
|
# ============================================================
|
|
# LineNumberReader
|
|
# ============================================================
|
|
|
|
class LineNumberReader(Stub):
|
|
"""java.io.LineNumberReader"""
|
|
def __init__(self, reader, sz=8192):
|
|
super().__init__()
|
|
self._reader = reader
|
|
self._line_number = 0
|
|
self._buffer = ""
|
|
self._pos = 0
|
|
self._marked_pos = 0
|
|
self._marked_line = 0
|
|
self._sz = sz
|
|
|
|
def readLine(self):
|
|
result = []
|
|
while self._pos < len(self._buffer) or self._fill_buffer():
|
|
if self._pos < len(self._buffer):
|
|
c = self._buffer[self._pos]
|
|
self._pos += 1
|
|
if c == "\n":
|
|
self._line_number += 1
|
|
return "".join(result)
|
|
if c == "\r":
|
|
self._line_number += 1
|
|
if self._pos < len(self._buffer) and self._buffer[self._pos] == "\n":
|
|
self._pos += 1
|
|
return "".join(result)
|
|
result.append(c)
|
|
else:
|
|
break
|
|
if not result:
|
|
return None
|
|
return "".join(result)
|
|
|
|
def getLineNumber(self):
|
|
return self._line_number
|
|
|
|
def setLineNumber(self, line_number):
|
|
self._line_number = line_number
|
|
|
|
def read(self, cbuf=None, off=0, length=-1):
|
|
if cbuf is None:
|
|
if self._pos < len(self._buffer) or self._fill_buffer():
|
|
if self._pos < len(self._buffer):
|
|
c = self._buffer[self._pos]
|
|
self._pos += 1
|
|
return ord(c)
|
|
return -1
|
|
count = 0
|
|
while count < (length if length >= 0 else len(cbuf) - off):
|
|
if self._pos >= len(self._buffer) and not self._fill_buffer():
|
|
break
|
|
cbuf[off + count] = self._buffer[self._pos]
|
|
self._pos += 1
|
|
count += 1
|
|
return count if count > 0 else -1
|
|
|
|
def close(self):
|
|
if self._reader and hasattr(self._reader, 'close'):
|
|
self._reader.close()
|
|
|
|
def mark(self, read_ahead_limit):
|
|
self._marked_pos = self._pos
|
|
self._marked_line = self._line_number
|
|
|
|
def reset(self):
|
|
self._pos = self._marked_pos
|
|
self._line_number = self._marked_line
|
|
|
|
def skip(self, n):
|
|
actual = 0
|
|
while actual < n:
|
|
if self._pos >= len(self._buffer) and not self._fill_buffer():
|
|
break
|
|
self._pos += 1
|
|
actual += 1
|
|
return actual
|
|
|
|
def ready(self):
|
|
return self._pos < len(self._buffer)
|
|
|
|
def _fill_buffer(self):
|
|
if self._reader and hasattr(self._reader, 'read'):
|
|
data = self._reader.read(self._sz)
|
|
if isinstance(data, str):
|
|
self._buffer = data
|
|
elif isinstance(data, bytes):
|
|
self._buffer = data.decode('utf-8')
|
|
else:
|
|
self._buffer = ""
|
|
self._pos = 0
|
|
return len(self._buffer) > 0
|
|
return False
|
|
|
|
|
|
# ============================================================
|
|
# CharArrayReader / CharArrayWriter
|
|
# ============================================================
|
|
|
|
class CharArrayReader(Stub):
|
|
"""java.io.CharArrayReader"""
|
|
def __init__(self, buf, offset=0, length=None):
|
|
super().__init__()
|
|
self._buf = list(buf)
|
|
if length is not None:
|
|
self._buf = self._buf[offset:offset + length]
|
|
else:
|
|
self._buf = self._buf[offset:]
|
|
self._pos = 0
|
|
self._marked_pos = 0
|
|
|
|
def read(self, cbuf=None, off=0, length=-1):
|
|
if self._pos >= len(self._buf):
|
|
return -1
|
|
if cbuf is None:
|
|
val = ord(self._buf[self._pos]) if isinstance(self._buf[self._pos], str) else self._buf[self._pos]
|
|
self._pos += 1
|
|
return val
|
|
if length < 0:
|
|
length = len(cbuf) - off
|
|
available = len(self._buf) - self._pos
|
|
to_read = min(available, length)
|
|
for i in range(to_read):
|
|
cbuf[off + i] = (
|
|
ord(self._buf[self._pos + i])
|
|
if isinstance(self._buf[self._pos + i], str)
|
|
else self._buf[self._pos + i]
|
|
)
|
|
self._pos += to_read
|
|
return to_read
|
|
|
|
def close(self):
|
|
self._buf = []
|
|
|
|
def mark(self, read_ahead_limit):
|
|
self._marked_pos = self._pos
|
|
|
|
def reset(self):
|
|
self._pos = self._marked_pos
|
|
|
|
def skip(self, n):
|
|
actual = min(n, len(self._buf) - self._pos)
|
|
self._pos += actual
|
|
return actual
|
|
|
|
def ready(self):
|
|
return self._pos < len(self._buf)
|
|
|
|
|
|
class CharArrayWriter(Stub):
|
|
"""java.io.CharArrayWriter"""
|
|
def __init__(self, initial_size=32):
|
|
super().__init__()
|
|
self._buf = []
|
|
|
|
def write(self, c, off=0, length=-1):
|
|
if isinstance(c, str):
|
|
self._buf.append(c)
|
|
elif isinstance(c, (list, tuple)):
|
|
if length < 0:
|
|
length = len(c) - off
|
|
self._buf.extend(c[off:off + length])
|
|
elif isinstance(c, int):
|
|
self._buf.append(chr(c))
|
|
|
|
def writeTo(self, out):
|
|
if hasattr(out, 'write'):
|
|
out.write(self.toString())
|
|
|
|
def toString(self):
|
|
return "".join(str(x) for x in self._buf)
|
|
|
|
def size(self):
|
|
return len(self._buf)
|
|
|
|
def toCharArray(self):
|
|
return list(self.toString())
|
|
|
|
def flush(self):
|
|
pass
|
|
|
|
def close(self):
|
|
pass
|
|
|
|
def reset(self):
|
|
self._buf = []
|
|
|
|
|
|
# ============================================================
|
|
# FilterReader / FilterWriter
|
|
# ============================================================
|
|
|
|
class FilterReader(Stub):
|
|
"""java.io.FilterReader"""
|
|
def __init__(self, reader):
|
|
super().__init__()
|
|
self._reader = reader
|
|
|
|
def read(self, cbuf=None, off=0, length=-1):
|
|
if self._reader:
|
|
return self._reader.read(cbuf, off, length)
|
|
return -1
|
|
|
|
def close(self):
|
|
if self._reader:
|
|
self._reader.close()
|
|
|
|
def mark(self, read_limit):
|
|
if self._reader and hasattr(self._reader, 'mark'):
|
|
self._reader.mark(read_limit)
|
|
|
|
def reset(self):
|
|
if self._reader and hasattr(self._reader, 'reset'):
|
|
self._reader.reset()
|
|
|
|
def ready(self):
|
|
if self._reader and hasattr(self._reader, 'ready'):
|
|
return self._reader.ready()
|
|
return False
|
|
|
|
def skip(self, n):
|
|
if self._reader and hasattr(self._reader, 'skip'):
|
|
return self._reader.skip(n)
|
|
return 0
|
|
|
|
|
|
class FilterWriter(Stub):
|
|
"""java.io.FilterWriter"""
|
|
def __init__(self, writer):
|
|
super().__init__()
|
|
self._writer = writer
|
|
|
|
def write(self, c, off=0, length=-1):
|
|
if self._writer:
|
|
if isinstance(c, str):
|
|
self._writer.write(c)
|
|
elif isinstance(c, int):
|
|
self._writer.write(chr(c))
|
|
|
|
def flush(self):
|
|
if self._writer:
|
|
self._writer.flush()
|
|
|
|
def close(self):
|
|
if self._writer:
|
|
self._writer.close()
|
|
|
|
|
|
# ============================================================
|
|
# PushbackReader
|
|
# ============================================================
|
|
|
|
class PushbackReader(FilterReader):
|
|
"""java.io.PushbackReader"""
|
|
def __init__(self, reader, size=1):
|
|
super().__init__(reader)
|
|
self._pushback_buf = []
|
|
self._pushback_size = size
|
|
|
|
def read(self, cbuf=None, off=0, length=-1):
|
|
if self._pushback_buf:
|
|
ch = self._pushback_buf.pop()
|
|
if cbuf is None:
|
|
return ord(ch) if isinstance(ch, str) else ch
|
|
cbuf[off] = ord(ch) if isinstance(ch, str) else ch
|
|
return 1
|
|
return super().read(cbuf, off, length)
|
|
|
|
def unread(self, c):
|
|
if len(self._pushback_buf) >= self._pushback_size:
|
|
raise IOException("Pushback buffer full")
|
|
if isinstance(c, (list, tuple)):
|
|
for ch in reversed(c):
|
|
self._pushback_buf.append(ch)
|
|
else:
|
|
self._pushback_buf.append(c)
|
|
|
|
|
|
# ============================================================
|
|
# PushbackInputStream
|
|
# ============================================================
|
|
|
|
class PushbackInputStream(Stub):
|
|
"""java.io.PushbackInputStream"""
|
|
def __init__(self, inp, size=1):
|
|
super().__init__()
|
|
self._input = inp
|
|
self._pushback_buf = bytearray()
|
|
self._pushback_size = size
|
|
|
|
def read(self, b=None, off=0, length=-1):
|
|
if self._pushback_buf and b is None:
|
|
return self._pushback_buf.pop(0)
|
|
if b is not None:
|
|
count = 0
|
|
while count < (length if length >= 0 else len(b) - off):
|
|
if self._pushback_buf:
|
|
b[off + count] = self._pushback_buf.pop(0)
|
|
elif self._input:
|
|
val = self._input.read(1)
|
|
if val == -1 or val == b"" or val is None:
|
|
break
|
|
b[off + count] = val[0] if isinstance(val, bytes) else val
|
|
else:
|
|
break
|
|
count += 1
|
|
return count if count > 0 else -1
|
|
if self._pushback_buf:
|
|
return self._pushback_buf.pop(0)
|
|
if self._input:
|
|
val = self._input.read(1)
|
|
if val is not None and val != -1:
|
|
return val[0] if isinstance(val, bytes) else val
|
|
return -1
|
|
|
|
def unread(self, b, off=0, length=-1):
|
|
if isinstance(b, int):
|
|
if len(self._pushback_buf) >= self._pushback_size:
|
|
raise IOException("Pushback buffer full")
|
|
self._pushback_buf.insert(0, b & 0xFF)
|
|
elif isinstance(b, (bytes, bytearray)):
|
|
if length < 0:
|
|
length = len(b) - off
|
|
if len(self._pushback_buf) + length > self._pushback_size:
|
|
raise IOException("Pushback buffer full")
|
|
for i in range(length - 1, -1, -1):
|
|
self._pushback_buf.insert(0, b[off + i])
|
|
|
|
def available(self):
|
|
return len(self._pushback_buf) + (self._input.available() if self._input else 0)
|
|
|
|
def close(self):
|
|
if self._input:
|
|
self._input.close()
|
|
self._pushback_buf = bytearray()
|
|
|
|
|
|
# ============================================================
|
|
# StreamTokenizer
|
|
# ============================================================
|
|
|
|
class StreamTokenizer(Stub):
|
|
"""java.io.StreamTokenizer"""
|
|
def __init__(self, reader=None, inp=None):
|
|
super().__init__()
|
|
if reader:
|
|
self._reader = reader
|
|
elif inp:
|
|
import io
|
|
self._reader = io.TextIOWrapper(io.BufferedReader(inp))
|
|
else:
|
|
self._reader = None
|
|
|
|
self.ttype = 0
|
|
self.sval = None
|
|
self.nval = 0.0
|
|
|
|
self._reset_syntax()
|
|
|
|
def _reset_syntax(self):
|
|
self._ordinary_chars = set()
|
|
self._word_chars = set()
|
|
self._whitespace_chars = set(range(0x20))
|
|
self._comment_char = None
|
|
self._quote_char = None
|
|
self._parse_numbers = True
|
|
self._lower_case_mode = False
|
|
self._slash_slash_comments = False
|
|
self._slash_star_comments = False
|
|
self._eol_is_significant = False
|
|
self._lower_case_mode = False
|
|
self._pushback = None
|
|
|
|
def resetSyntax(self):
|
|
self._reset_syntax()
|
|
|
|
def wordChars(self, low, high):
|
|
for c in range(low, high + 1):
|
|
self._word_chars.add(c)
|
|
|
|
def whitespaceChars(self, low, high):
|
|
for c in range(low, high + 1):
|
|
self._whitespace_chars.add(c)
|
|
|
|
def ordinaryChars(self, low, high):
|
|
for c in range(low, high + 1):
|
|
self._ordinary_chars.add(c)
|
|
|
|
def ordinaryChar(self, ch):
|
|
self._ordinary_chars.add(ch)
|
|
|
|
def commentChar(self, ch):
|
|
self._comment_char = ch
|
|
|
|
def quoteChar(self, ch):
|
|
self._quote_char = ch
|
|
|
|
def parseNumbers(self):
|
|
self._parse_numbers = True
|
|
|
|
def eolIsSignificant(self, flag):
|
|
self._eol_is_significant = flag
|
|
|
|
def slashSlashComments(self, flag):
|
|
self._slash_slash_comments = flag
|
|
|
|
def slashStarComments(self, flag):
|
|
self._slash_star_comments = flag
|
|
|
|
def lowerCaseMode(self, flag):
|
|
self._lower_case_mode = flag
|
|
|
|
def pushBack(self):
|
|
self._pushback = self.ttype
|
|
|
|
def lineno(self):
|
|
return 1
|
|
|
|
def toString(self):
|
|
if self.ttype == -1:
|
|
return "EOF"
|
|
if self.ttype == -3:
|
|
return f"WORD={self.sval}"
|
|
if self.ttype == -2:
|
|
return f"NUMBER={self.nval}"
|
|
return f"CHAR={chr(self.ttype) if self.ttype < 256 else '?'}"
|
|
|
|
def nextToken(self):
|
|
if self._pushback is not None:
|
|
pb = self._pushback
|
|
self._pushback = None
|
|
self.ttype = pb
|
|
return self.ttype
|
|
|
|
if self._reader is None:
|
|
self.ttype = -1 # TT_EOF
|
|
return -1
|
|
|
|
ch = self._read_char()
|
|
if ch is None:
|
|
self.ttype = -1
|
|
return -1
|
|
|
|
# Check for newlines
|
|
if ch == "\n":
|
|
if self._eol_is_significant:
|
|
self.ttype = 10 # TT_EOL
|
|
return 10
|
|
return self.nextToken()
|
|
|
|
# Whitespace
|
|
if ord(ch) in self._whitespace_chars:
|
|
return self.nextToken()
|
|
|
|
# Comment char
|
|
if self._comment_char is not None and ord(ch) == self._comment_char:
|
|
while ch is not None and ch != "\n":
|
|
ch = self._read_char()
|
|
return self.nextToken()
|
|
|
|
# Quote char
|
|
if self._quote_char is not None and ord(ch) == self._quote_char:
|
|
buf = []
|
|
while True:
|
|
ch = self._read_char()
|
|
if ch is None or ord(ch) == self._quote_char:
|
|
break
|
|
buf.append(ch)
|
|
self.sval = "".join(buf)
|
|
if self._lower_case_mode:
|
|
self.sval = self.sval.lower()
|
|
self.ttype = ord(self._quote_char)
|
|
return self.ttype
|
|
|
|
# Number
|
|
if self._parse_numbers and (ch.isdigit() or ch in ('-', '.')):
|
|
buf = [ch]
|
|
if ch in ('-', '.'):
|
|
next_ch = self._peek_char()
|
|
if next_ch is not None and (next_ch.isdigit() or next_ch == '.'):
|
|
buf.append(self._read_char())
|
|
while True:
|
|
ch = self._read_char()
|
|
if ch is None or not (ch.isdigit() or ch == '.' or ch in ('e', 'E', '-', '+')):
|
|
if ch is not None:
|
|
self._unread_char(ch)
|
|
break
|
|
buf.append(ch)
|
|
num_str = "".join(buf)
|
|
try:
|
|
self.nval = float(num_str)
|
|
except ValueError:
|
|
self.nval = 0.0
|
|
self.ttype = -2 # TT_NUMBER
|
|
return -2
|
|
|
|
# Word chars
|
|
if ord(ch) in self._word_chars:
|
|
buf = [ch]
|
|
while True:
|
|
next_ch = self._peek_char()
|
|
if next_ch is not None and ord(next_ch) in self._word_chars:
|
|
buf.append(self._read_char())
|
|
else:
|
|
break
|
|
self.sval = "".join(buf)
|
|
if self._lower_case_mode:
|
|
self.sval = self.sval.lower()
|
|
self.ttype = -3 # TT_WORD
|
|
return -3
|
|
|
|
# Ordinary char
|
|
self.ttype = ord(ch)
|
|
return ord(ch)
|
|
|
|
def _read_char(self):
|
|
if self._reader is None:
|
|
return None
|
|
try:
|
|
if hasattr(self._reader, 'read'):
|
|
c = self._reader.read(1)
|
|
if c and isinstance(c, bytes):
|
|
c = c.decode('utf-8')
|
|
return c if c else None
|
|
return None
|
|
except Exception:
|
|
return None
|
|
|
|
def _peek_char(self):
|
|
if self._reader is None:
|
|
return None
|
|
try:
|
|
c = self._reader.read(1)
|
|
if c and isinstance(c, bytes):
|
|
c = c.decode('utf-8')
|
|
if c:
|
|
self._unread_char(c)
|
|
return c if c else None
|
|
except Exception:
|
|
return None
|
|
|
|
def _unread_char(self, c):
|
|
if hasattr(self._reader, 'seek'):
|
|
self._reader.seek(self._reader.tell() - 1)
|
|
|
|
TT_EOF = -1
|
|
TT_EOL = 10
|
|
TT_NUMBER = -2
|
|
TT_WORD = -3 |