import 'dart:io'; import 'dart:math'; import 'dart:typed_data'; import 'package:sweepstore/structures.dart'; class RandomAccessMemory { List _buffer; int _position = 0; RandomAccessMemory([List? initialData]) : _buffer = initialData != null ? List.from(initialData) : []; // Position management int positionSync() => _position; void setPositionSync(int position) { _position = position; } int length() => _buffer.length; // Read bytes List readSync(int count) { if (_position + count > _buffer.length) { throw RangeError('Not enough bytes to read'); } List result = _buffer.sublist(_position, _position + count); _position += count; return result; } // Write bytes void writeFromSync(List bytes) { for (int i = 0; i < bytes.length; i++) { if (_position + i >= _buffer.length) { _buffer.add(bytes[i]); } else { _buffer[_position + i] = bytes[i]; } } _position += bytes.length; } // Read/Write Int Dynamic int readIntSync([int size = 4, Endian endianness = Endian.little]) { if (size < 1 || size > 8) { throw ArgumentError('Size must be between 1 and 8 bytes'); } List bytes = readSync(size); // Build integer from bytes with proper endianness int result = 0; if (endianness == Endian.little) { for (int i = size - 1; i >= 0; i--) { result = (result << 8) | bytes[i]; } } else { for (int i = 0; i < size; i++) { result = (result << 8) | bytes[i]; } } // Sign extend if MSB is set int signBit = 1 << (size * 8 - 1); if (result & signBit != 0) { result -= 1 << (size * 8); } return result; } void writeIntSync(int value, [int size = 4, Endian endianness = Endian.little]) { if (size < 1 || size > 8) { throw ArgumentError('Size must be between 1 and 8 bytes'); } List bytes = List.filled(size, 0); // Extract bytes with proper endianness if (endianness == Endian.little) { for (int i = 0; i < size; i++) { bytes[i] = (value >> (i * 8)) & 0xFF; } } else { for (int i = 0; i < size; i++) { bytes[size - 1 - i] = (value >> (i * 8)) & 0xFF; } } writeFromSync(bytes); } // Read/Write Pointers SweepstorePointer readPointerSync() { int offset = readIntSync(SweepstorePrimitives.POINTER.size); return SweepstorePointer(offset); } void writePointerSync(SweepstorePointer pointer) { writeIntSync(pointer.address, SweepstorePrimitives.POINTER.size); } // Read/Write Float32 double readFloat32Sync([Endian endianness = Endian.little]) { List bytes = readSync(4); return ByteData.sublistView(Uint8List.fromList(bytes)).getFloat32(0, endianness); } void writeFloat32Sync(double value, [Endian endianness = Endian.little]) { ByteData byteData = ByteData(4); byteData.setFloat32(0, value, endianness); writeFromSync(byteData.buffer.asUint8List()); } // Read/Write Float64 (Double) double readFloat64Sync([Endian endianness = Endian.little]) { List bytes = readSync(8); return ByteData.sublistView(Uint8List.fromList(bytes)).getFloat64(0, endianness); } void writeFloat64Sync(double value, [Endian endianness = Endian.little]) { ByteData byteData = ByteData(8); byteData.setFloat64(0, value, endianness); writeFromSync(byteData.buffer.asUint8List()); } // Conversion methods List toList() => List.from(_buffer); Uint8List toUint8List() => Uint8List.fromList(_buffer); } extension SweepstoreRandomAccessFileHelper on RandomAccessFile { // Read/Write Int Dynamic - Can specify size in bytes, does not have to align to 1, 2, 4, or 8 bytes. Default is 4 bytes (Int32) int readIntSync([int size = 4, Endian endianness = Endian.little]) { if (size < 1 || size > 8) { throw ArgumentError('Size must be between 1 and 8 bytes'); } List bytes = readSync(size); // Build integer from bytes with proper endianness int result = 0; if (endianness == Endian.little) { for (int i = size - 1; i >= 0; i--) { result = (result << 8) | bytes[i]; } } else { for (int i = 0; i < size; i++) { result = (result << 8) | bytes[i]; } } // Sign extend if MSB is set int signBit = 1 << (size * 8 - 1); if (result & signBit != 0) { result -= 1 << (size * 8); } return result; } void writeIntSync(int value, [int size = 4, Endian endianness = Endian.little]) { if (size < 1 || size > 8) { throw ArgumentError('Size must be between 1 and 8 bytes'); } List bytes = List.filled(size, 0); // Extract bytes with proper endianness if (endianness == Endian.little) { for (int i = 0; i < size; i++) { bytes[i] = (value >> (i * 8)) & 0xFF; } } else { for (int i = 0; i < size; i++) { bytes[size - 1 - i] = (value >> (i * 8)) & 0xFF; } } writeFromSync(bytes); } // Read/Write Pointers SweepstorePointer readPointerSync() { int offset = readIntSync(SweepstorePrimitives.POINTER.size); return SweepstorePointer(offset); } void writePointerSync(SweepstorePointer pointer) { writeIntSync(pointer.address, SweepstorePrimitives.POINTER.size); } // Read/Write Float32 double readFloat32Sync([Endian endianness = Endian.little]) { List bytes = readSync(4); return ByteData.sublistView(Uint8List.fromList(bytes)).getFloat32(0, endianness); } void writeFloat32Sync(double value, [Endian endianness = Endian.little]) { ByteData byteData = ByteData(4); byteData.setFloat32(0, value, endianness); writeFromSync(byteData.buffer.asUint8List()); } // Read/Write Float64 (Double) double readFloat64Sync([Endian endianness = Endian.little]) { List bytes = readSync(8); return ByteData.sublistView(Uint8List.fromList(bytes)).getFloat64(0, endianness); } void writeFloat64Sync(double value, [Endian endianness = Endian.little]) { ByteData byteData = ByteData(8); byteData.setFloat64(0, value, endianness); writeFromSync(byteData.buffer.asUint8List()); } } extension SweepstoreDateTimeHelper on DateTime { int millisecondsSinceEpoch32() { return (millisecondsSinceEpoch ~/ 1000) & 0xFFFFFFFF; } int millisecondsSinceEpoch64() { return millisecondsSinceEpoch; } } const Duration _windowsMinSleepTime = Duration(milliseconds: 16); void preciseSleep(Duration duration) { if (Platform.isWindows && duration < _windowsMinSleepTime) { // Busy-wait for short durations on Windows final end = DateTime.now().add(duration); while (DateTime.now().isBefore(end)) {} } else { // Use normal sleep for longer durations or on Unix sleep(duration); } }