//magic header of a Dana object matching the below format
const byte danaMagic[] = new int[](0x44, 0x41, 0x4E, 0x41, 0x0, 0x1)
//a Dana object header
data SourceHeader{
//basic identification; this part is always the same total size
byte magic[6]
byte checksum[4]
byte objectType[2]
byte hostType[2]
byte vpuType[2]
//the below fields are each the size of the target host machine's native address width
//machine code
int textOffset
int textSize
//local relocations; a list of addresses to add the start address of this object to
int lrTableOffset
int lrTableSize
int lrTableCount
//info sections (if one of these is hardlinks then this object file is not fit to be loaded)
int infoSectionsOffset
int infoSectionsSize
int infoSectionsCount
}
//an info section header
data DanaInfoSection{
byte sectionType[4] //type code identifying the section's purpose (0.x.x.x, D.N.x.x, F.R.x.x are reserved)
byte contentType[4] //type code identifying the kind of content (json, xml, jpeg, etc.)
int size //size of the section's content, excluding this header
}
component provides ObjectReader requires io.File, System system {
char objectPath[]
ObjectInfo info
int lastInfoIndex
int infoSectionsOffset
ObjectReader:ObjectReader(char path[])
{
File fd = new File(path, File.READ)
if (fd == null)
throw new Exception("File not found")
SourceHeader hdr = new SourceHeader()
byte serialHDR[] = dana.serial(hdr)
byte buf[]
if ((buf = fd.read(serialHDR.arrayLength)).arrayLength != serialHDR.arrayLength)
{
throw new Exception("Error: File is not a Dana object")
}
serialHDR =[] buf
if (hdr.magic != danaMagic)
{
throw new Exception("Error: File is not a Dana object")
}
if (hdr.hostType != system.getHostType())
{
throw new Exception("Error: File was compiled for a different architecture")
}
if (hdr.vpuType != system.getVMType())
{
throw new Exception("Error: File was compiled for a different VPU version")
}
info = new ObjectInfo(hdr.textSize, hdr.infoSectionsCount, hdr.lrTableCount)
infoSectionsOffset = hdr.infoSectionsOffset
fd.close()
objectPath = path
}
ObjectInfo ObjectReader:getInfo()
{
return info
}
InfoSection ObjectReader:getNextSection()
{
File fd = new File(objectPath, File.READ)
if (fd == null)
{
throw new Exception("Object file $objectPath is no longer readable")
}
if (lastInfoIndex >= info.infoSectionCount)
{
lastInfoIndex = 0
return null
}
fd.setPos(infoSectionsOffset)
for (int i = 0; i < lastInfoIndex; i++)
{
byte serialData[]
DanaInfoSection is = new DanaInfoSection()
serialData = dana.serial(is)
serialData =[] fd.read(serialData.arrayLength)
byte contents[] = fd.read(is.size)
}
//read the actual one we want
InfoSection section = new InfoSection()
byte serialData[]
DanaInfoSection is
serialData = dana.serial(is)
serialData =[] fd.read(serialData.arrayLength)
section.sectionType = is.sectionType
section.contentType = is.contentType
section.content = fd.read(is.size)
fd.close()
lastInfoIndex ++
return section
}
InfoSection ObjectReader:getInfoSection(char type[])
{
File fd = new File(objectPath, File.READ)
if (fd == null)
{
throw new Exception("Object file $objectPath is no longer readable")
}
fd.setPos(infoSectionsOffset)
for (int i = 0; i < info.infoSectionCount; i++)
{
byte serialData[]
DanaInfoSection is = new DanaInfoSection()
serialData = dana.serial(is)
serialData =[] fd.read(serialData.arrayLength)
byte contents[] = fd.read(is.size)
if (is.sectionType == type)
{
InfoSection section = new InfoSection(is.sectionType, is.contentType, contents)
fd.close()
return section
}
}
fd.close()
return null
}
char[] ObjectReader:getPath()
{
return objectPath
}
int ObjectReader:getCurrentInfoSectionIndex()
{
if (lastInfoIndex > 0)
return lastInfoIndex - 1
else
return lastInfoIndex
}
}To propose a new revision to this entity, use dana source put -uc your/new/version.dn -n composition.ObjectReader -m "reason for update" -u yourUsername
Version 1 (this version) by barry
Notes for this version: Standard Library Initialisation