""" 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" if self._order == ByteOrder.BIG_ENDIAN else "q" if self._order == ByteOrder.BIG_ENDIAN else "q" if self._order == ByteOrder.BIG_ENDIAN else "f" if self._order == ByteOrder.BIG_ENDIAN else "f" if self._order == ByteOrder.BIG_ENDIAN else "d" if self._order == ByteOrder.BIG_ENDIAN else "d" if self._order == ByteOrder.BIG_ENDIAN else "h" if self._order == ByteOrder.BIG_ENDIAN else "h" if self._order == ByteOrder.BIG_ENDIAN else " 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" if self._int_order == ByteOrder.BIG_ENDIAN else "i" if self._int_order == ByteOrder.BIG_ENDIAN else "q" if self._long_order == ByteOrder.BIG_ENDIAN else "q" if self._long_order == ByteOrder.BIG_ENDIAN else "q" if self._long_order == ByteOrder.BIG_ENDIAN else "f" if self._float_order == ByteOrder.BIG_ENDIAN else "f" if self._float_order == ByteOrder.BIG_ENDIAN else "f" if self._float_order == ByteOrder.BIG_ENDIAN else "d" if self._double_order == ByteOrder.BIG_ENDIAN else "d" if self._double_order == ByteOrder.BIG_ENDIAN else "d" if self._double_order == ByteOrder.BIG_ENDIAN else "h" if self._short_order == ByteOrder.BIG_ENDIAN else "h" if self._short_order == ByteOrder.BIG_ENDIAN else "h" if self._short_order == ByteOrder.BIG_ENDIAN else "h" if self._char_order == ByteOrder.BIG_ENDIAN else "h" if self._char_order == ByteOrder.BIG_ENDIAN else "h" if self._char_order == ByteOrder.BIG_ENDIAN else "