Files
SweepStore/dart/lib/helpers.dart

251 lines
7.1 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;
}
}
const Duration _windowsMinSleepTime = Duration(milliseconds: 16);
void preciseSleep(Duration duration) {
final stopwatch = Stopwatch()..start();
if (Platform.isWindows) {
if (duration < _windowsMinSleepTime) {
// Pure busy-wait with high-res timer
while (stopwatch.elapsed < duration) {}
} else {
// Hybrid: sleep most of it, busy-wait the remainder
final sleepDuration = duration - _windowsMinSleepTime;
sleep(sleepDuration);
while (stopwatch.elapsed < duration) {}
}
} else {
sleep(duration);
}
stopwatch.stop();
// print('preciseSleep: requested ${duration.inMicroseconds}μs, actual ${stopwatch.elapsedMicroseconds}μs, diff ${stopwatch.elapsedMicroseconds - duration.inMicroseconds}μs');
}