mirror of
https://github.com/AppleCommander/AppleCommander.git
synced 2026-10-24 23:02:27 +00:00
Adding SequentialAllocator; hopefully usefor for GameDOS, NakedOS, Apple Pascal, and likely RDOS as well.
This commit is contained in:
1 parent
bf517ee583
commit
19720bd5f3
3 files changed
+79
No files matched your search
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package org.applecommander.device;
|
||||
|
||||
import org.applecommander.device.Coordinate.TrackAndSectorCoordinate;
|
||||
import org.applecommander.util.DataBuffer;
|
||||
import org.applecommander.util.InformationGroup;
|
||||
import org.applecommander.util.InformationProvider;
|
||||
@@ -102,6 +103,12 @@ public interface TrackSectorDevice extends Device {
|
||||
public int deviceSize() {
|
||||
return sectorsPerDisk() * SECTOR_SIZE;
|
||||
}
|
||||
public int calculateSectorOffset(int track, int sector) {
|
||||
return track * sectorsPerTrack + sector;
|
||||
}
|
||||
public TrackAndSectorCoordinate sectorOffsetToCoordinate(int sectorOffset) {
|
||||
return new TrackAndSectorCoordinate(sectorOffset / sectorsPerTrack, sectorOffset % sectorsPerTrack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InformationGroup> information() {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.applecommander.os;
|
||||
|
||||
import org.applecommander.util.Range;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/// The SequentialAllocator is intended to handle what is, essentially, a
|
||||
/// single dimension allocation. That is, if the disk is allocated by sequential
|
||||
/// chunks, this allocator should support it. For images that use T/S geometry
|
||||
/// instead of block geometry, the T/S will need to be transformed.
|
||||
///
|
||||
/// For instance, GameDOS allocates by T/S but allocates all in a chunk. So once
|
||||
/// there is a starting place, the rest of the file follows in a very specific
|
||||
/// order.
|
||||
public class SequentialAllocator {
|
||||
private final int totalSize;
|
||||
private final List<Range> used = new ArrayList<>();
|
||||
|
||||
public SequentialAllocator(int totalSize) {
|
||||
this.totalSize = totalSize;
|
||||
}
|
||||
|
||||
public void addUsed(int first, int last) {
|
||||
assert first <= last;
|
||||
assert first < totalSize && last <= totalSize;
|
||||
used.add(new Range(first, last));
|
||||
}
|
||||
public void addUsedByLength(int first, int length) {
|
||||
addUsed(first, first+length-1);
|
||||
}
|
||||
|
||||
/// Look for `requestSize` spaces between the used ranges.
|
||||
/// Returns either the first placement that the request will fit
|
||||
/// or a `-1` if there is no fit.
|
||||
public int find(int requestSize) {
|
||||
used.sort(Comparator.comparingInt(Range::first));
|
||||
int start = 0;
|
||||
for (Range range : used) {
|
||||
if (range.first() - start >= requestSize) {
|
||||
return start;
|
||||
}
|
||||
start = range.last() + 1;
|
||||
}
|
||||
if (totalSize - start >= requestSize) {
|
||||
return start;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.applecommander.os;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class SequentialAllocatorTest {
|
||||
@Test
|
||||
public void test() {
|
||||
SequentialAllocator allocator = new SequentialAllocator(10);
|
||||
allocator.addUsed(2,4);
|
||||
allocator.addUsed(5,6);
|
||||
|
||||
// Allocation:
|
||||
// 0123456789
|
||||
// FFUUUUUFFF
|
||||
assertEquals(0, allocator.find(2));
|
||||
assertEquals(7, allocator.find(3));
|
||||
assertEquals(-1, allocator.find(4));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user