HomeForumSourceResearchGuide
Sign in to contribute to source. how it works
Component io.File:mem by barry
expand copy to clipboardexpand
const int BLOCK_SIZE = 2048

data FileBlock {
	byte content[]
	int length
	int pos
	
	FileBlock next
	}

component provides io.File:mem requires data.IntUtil iu, io.Output out {
	
	int size
	int pos
	Mutex rwLock = new Mutex()
	
	int blockCount
	FileBlock blocks
	FileBlock curBlock
	
	byte mode
	
	File:File(char path[], byte m)
		{
		pos = 0
		
		blocks = new FileBlock(new byte[BLOCK_SIZE])
		curBlock = blocks
		
		blockCount = 1
		
		mode = m
		}
	
	void copyArray(byte into[], int intoOffset, byte source[], int sourceOffset, int copyAmount)
		{
		for (int i = 0; i < copyAmount; i++)
			{
			into[intoOffset] = source[sourceOffset]
			intoOffset ++
			sourceOffset ++
			}
		}
	
	int File:write(byte content[])
		{
		mutex(rwLock)
			{
			if (mode != File.WRITE && mode != File.CREATE)
				{
				throw new Exception("File is not open for write")
				}
			
			int rlen = content.arrayLength
			int cpos = 0
			
			while (rlen > 0)
				{
				if (curBlock.pos == curBlock.content.arrayLength)
					{
					if (curBlock.next != null)
						{
						curBlock = curBlock.next
						curBlock.pos = 0
						}
						else
						{
						curBlock.next = new FileBlock(new byte[BLOCK_SIZE])
						curBlock = curBlock.next
						
						blockCount ++
						}
					}
				
				int blockRemainder = curBlock.content.arrayLength - curBlock.pos
				
				int copyAmount = content.arrayLength - cpos
				
				if (copyAmount > blockRemainder)
					{
					copyAmount = blockRemainder
					}
				
				copyArray(curBlock.content, curBlock.pos, content, cpos, copyAmount)
				curBlock.pos += copyAmount
				cpos += copyAmount
				rlen -= copyAmount
				
				pos += copyAmount
				
				if (curBlock.next == null)
					{
					int ns = (BLOCK_SIZE * (blockCount-1)) + curBlock.pos
					
					if (ns > size) size = ns
					}
				}
			
			return content.arrayLength
			}
		}
	
	byte[] File:read(int length)
		{
		mutex(rwLock)
			{
			if (length > (size - pos))
				length = size - pos
			
			byte content[] = new byte[length]
			int rlen = length
			int cpos = 0
			
			while (rlen > 0 && curBlock != null)
				{
				if (curBlock.pos == curBlock.content.arrayLength)
					{
					if (curBlock.next != null)
						{
						curBlock = curBlock.next
						curBlock.pos = 0
						}
						else
						{
						break
						}
					}
				
				int blockRemainder = curBlock.content.arrayLength - curBlock.pos
				
				int copyAmount = length - cpos
				
				if (copyAmount > blockRemainder)
					{
					copyAmount = blockRemainder
					}
				
				copyArray(content, cpos, curBlock.content, curBlock.pos, copyAmount)
				curBlock.pos += copyAmount
				cpos += copyAmount
				rlen -= copyAmount
				
				pos += copyAmount
				}
			
			return content
			}
		}
	
	bool File:flush()
		{
		return true
		}
	
	bool File:eof()
		{
		mutex(rwLock)
			{
			return pos == size
			}
		}
	
	bool File:setPos(int p)
		{
		mutex(rwLock)
			{
			if (p <= size)
				{
				pos = p
				
				FileBlock bw = blocks
				while (bw != null && p > bw.content.arrayLength)
					{
					p -= bw.content.arrayLength
					bw = bw.next
					}
				
				curBlock = bw
				curBlock.pos = p
				
				return true
				}
				else
				{
				throw new Exception("attempt to seek past end of file")
				return false
				}
			}
		}
	
	int File:getPos()
		{
		return pos
		}
	
	int File:getSize()
		{
		mutex(rwLock)
			{
			return size
			}
		}
	
	void File:close()
		{
		mutex(rwLock)
			{
			
			}
		}
	}
Revision history
To propose a new revision to this entity, use dana source put -uc your/new/version.dn -n io.File:mem -m "reason for update" -u yourUsername
Version 1 (this version) by barry
Notes for this version: Standard Library Initialisation