228 lines
6.3 KiB
Dart
228 lines
6.3 KiB
Dart
|
|
import 'dart:io';
|
|
import 'dart:math';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:sweepstore/structures.dart';
|
|
|
|
|
|
class RandomAccessMemory {
|
|
List<int> _buffer;
|
|
int _position = 0;
|
|
|
|
RandomAccessMemory([List<int>? initialData]) : _buffer = initialData != null ? List<int>.from(initialData) : [];
|
|
|
|
// Position management
|
|
int positionSync() => _position;
|
|
|
|
void setPositionSync(int position) {
|
|
_position = position;
|
|
}
|
|
|
|
int length() => _buffer.length;
|
|
|
|
// Read bytes
|
|
List<int> readSync(int count) {
|
|
if (_position + count > _buffer.length) {
|
|
throw RangeError('Not enough bytes to read');
|
|
}
|
|
List<int> result = _buffer.sublist(_position, _position + count);
|
|
_position += count;
|
|
return result;
|
|
}
|
|
|
|
// Write bytes
|
|
void writeFromSync(List<int> 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<int> 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<int> 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<int> 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<int> 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<int> toList() => List<int>.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<int> 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<int> 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<int> 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<int> 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;
|
|
}
|
|
} |