/*
FileLikeDirectoryInfo.java
(c) 2010-2013 Edward Swartz
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
*/
package v9t9.common.files;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import v9t9.common.memory.ByteMemoryAccess;
public class FileLikeDirectoryInfo extends DirectoryInfo {
private int index;
private long totalSectors;
private long freeSectors;
private int lastEntry;
private DiskDirectory disk;
public FileLikeDirectoryInfo(DiskDirectory disk, File file, IFilesInDirectoryMapper mapper) {
super(file, mapper);
this.disk = disk;
lastEntry = Math.min(128, entries.length);
totalSectors = (file.getTotalSpace() + 255) / 256;
freeSectors = (file.getFreeSpace() + 255) / 256;
}
public void setIndex(int index) {
this.index = index;
}
protected CatalogEntry decodeFile(int index) throws DsrException {
File file = entries[index];
IEmulatedFile nativefile;
try {
nativefile = disk.getFile(file.getName());
} catch (IOException e) {
throw new DsrException(PabConstants.es_hardware, e);
}
// first field is the string representing the
// file or volume name
String name = mapper.getDsrFileName(file.getName());
// // second field is file type
// int flags = nativefile instanceof EmulatedBaseFDRFile ? ((NativeFDRFile) nativefile).getFlags() : FDR.ff_variable;
//
// // third field is file size, one sector for fdr
// int size = 1 + (nativefile.getFileSize() + 255) / 256;
//
// // fourth field is record size
// int reclen = nativefile instanceof EmulatedBaseFDRFile ? ((EmulatedBaseFDRFile) nativefile).getFDR().getRecordLength() : 80;
return new CatalogEntry(index + 2, name, nativefile);
}
/**
* Read the full catalog, even if the client can only process 128 entries.
* @return
*/
public List<CatalogEntry> readCatalog() {
List<CatalogEntry> list = new ArrayList<CatalogEntry>();
for (int index = 1; index <= entries.length; index++) {
try {
list.add(decodeFile(index - 1));
} catch (IOException e) {
// ignore
}
}
return list;
}
public int readRecord(ByteMemoryAccess access) throws DsrException {
int offset = access.offset;
// volume record?
if (index == 0) {
/* Get volume name from path. */
offset = writeName(access, offset, mapper.getDsrFileName(dir.getName()));
// zero field
offset = writeFloat(access, offset, 0);
// total space
offset = writeFloat(access, offset, totalSectors);
// free space
offset = writeFloat(access, offset, freeSectors);
index++;
return offset - access.offset;
}
// read file record; restrict it to 127 entries
// in case naive programs will die...
if (index < 0 || index > 128)
throw new DsrException(PabConstants.e_endoffile, "End of directory");
if (index > lastEntry) {
// make an empty record
access.memory[offset++] = (byte) 0;
offset = writeFloat(access, offset, 0);
offset = writeFloat(access, offset, 0);
offset = writeFloat(access, offset, 0);
index++;
return offset - access.offset;
}
// Get file info
CatalogEntry entry = decodeFile(index - 1);
// first field is the string representing the
// file or volume name
offset = writeName(access, offset, entry.fileName);
offset = writeFloat(access, offset, entry.typeCode);
// third field is file size, one sector for fdr
offset = writeFloat(access, offset, entry.secs);
// fourth field is record size
offset = writeFloat(access, offset, entry.recordLength);
index++;
return offset - access.offset;
}
/**
* @param access
* @param offset
* @param dskName2
* @return
*/
private int writeName(ByteMemoryAccess access, int offset,
String name) {
int len = name.length();
if (len > 10)
len = 10;
access.memory[offset++] = (byte) len;
for (int i = 0; i < len; i++)
access.memory[offset++] = (byte) name.charAt(i);
return offset;
}
/** Convert and push an integer into a TI floating point record:
[8 bytes] [0x40+log num] 9*[sig figs, 0-99]
Return pointer past end of float.
*/
private int writeFloat(ByteMemoryAccess access, int offset, long x) {
access.memory[offset++] = (byte) 8; // bytes in length
Arrays.fill(access.memory, offset, offset + 8, (byte) 0);
if (x == 0)
return offset + 8;
long y = x;
int places = 0;
while (y > 0) {
y /= 100;
places++;
}
access.memory[offset] = (byte) (0x3F + places);
while (places > 0) {
if (places <= 9)
access.memory[offset + places] = (byte) (x % 100);
x /= 100;
places--;
}
return offset + 8;
}
}