git-svn-id: https://profuse.googlecode.com/svn/branches/v2@140 aa027e90-d47c-11dd-86d7-074df07e0730

This commit is contained in:
ksherlock 2009-12-11 02:04:27 +00:00
parent 922494caa6
commit e3b89b2201
5 changed files with 91 additions and 35 deletions

View File

@ -16,8 +16,8 @@ public:
virtual void write() = 0; virtual void write() = 0;
virtual void *load(unsigned block); virtual void *load(unsigned block) = 0;
virtual void unload(unsigned block, bool dirty); virtual void unload(unsigned block, bool dirty) = 0;
void unload(unsigned block) { unload(block, false); } void unload(unsigned block) { unload(block, false); }
}; };

View File

@ -167,7 +167,7 @@ public:
enum { enum {
OffsetLastMod = 0x12, OffsetLastMod = 0x12,
OffsetFileNameCaseFlag = 0x16 OffsetFileNameCaseFlag = 0x16,
OffsetBitmapPointer = 0x23, OffsetBitmapPointer = 0x23,
OffsetTotalBlocks = 0x25 OffsetTotalBlocks = 0x25

View File

@ -5,6 +5,7 @@ newfs_prodos: \
newfs_prodos.o \ newfs_prodos.o \
Exception.o \ Exception.o \
BlockDevice.o \ BlockDevice.o \
BlockCache.o \
UniversalDiskImage.o \ UniversalDiskImage.o \
DiskCopy42Image.o \ DiskCopy42Image.o \
DavexDiskImage.o \ DavexDiskImage.o \

View File

@ -2,6 +2,7 @@
#include "../auto.h" #include "../auto.h"
#include "../Endian.h" #include "../Endian.h"
#include "../BlockDevice.h" #include "../BlockDevice.h"
#include "../BlockCache.h"
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
@ -19,6 +20,7 @@ Entry::Entry()
_lastBlock = 0; _lastBlock = 0;
_fileKind = 0; _fileKind = 0;
_inode = 0; _inode = 0;
_parent = NULL;
} }
Entry::Entry(void *vp) Entry::Entry(void *vp)
@ -53,7 +55,10 @@ VolumeEntry::VolumeEntry()
_accessTime = 0; _accessTime = 0;
setInode(1); setInode(1);
_inodeGenerator = 1; _inodeGenerator = 1;
_cache = NULL;
_device = NULL;
} }
VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device) VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device)
@ -64,6 +69,9 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device)
// read the header block, then load up all the header // read the header block, then load up all the header
// blocks. // blocks.
_device = device;
_cache = device->blockCache();
device->read(2, buffer.get()); device->read(2, buffer.get());
init(buffer.get()); init(buffer.get());
@ -83,8 +91,10 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device)
// now load up all the children. // now load up all the children.
// if this throws, memory could be lost... // if this throws, memory could be lost...
try try
{ {
for (unsigned i = 1; i < _fileCount; ++i) for (unsigned i = 1; i < _fileCount; ++i)
{ {
std::auto_ptr<FileEntry> child; std::auto_ptr<FileEntry> child;
@ -92,6 +102,7 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device)
child.reset(new FileEntry(buffer.get() + i * 0x1a)); child.reset(new FileEntry(buffer.get() + i * 0x1a));
child->setInode(++_inodeGenerator); child->setInode(++_inodeGenerator);
child->_parent = this;
_files.push_back(child.release()); _files.push_back(child.release());
} }
} }
@ -106,6 +117,7 @@ VolumeEntry::VolumeEntry(ProFUSE::BlockDevice *device)
throw; throw;
} }
} }
VolumeEntry::~VolumeEntry() VolumeEntry::~VolumeEntry()
@ -115,6 +127,9 @@ VolumeEntry::~VolumeEntry()
{ {
if (*iter) delete *iter; if (*iter) delete *iter;
} }
// _blockCache does not need deleting.
delete _device;
} }
@ -145,6 +160,25 @@ FileEntry *VolumeEntry::fileAtIndex(unsigned i) const
void *VolumeEntry::loadBlock(unsigned block)
{
return _cache->load(block);
}
void VolumeEntry::unloadBlock(unsigned block, bool dirty)
{
return _cache->unload(block, dirty);
}
void VolumeEntry::readBlock(unsigned block, void *buffer)
{
_device->read(block, buffer);
}
void VolumeEntry::writeBlock(unsigned block, void *buffer)
{
_device->write(block, buffer);
}
#pragma mark - #pragma mark -
#pragma mark FileEntry #pragma mark FileEntry
@ -159,12 +193,12 @@ FileEntry::FileEntry(void *vp) :
_modification = DateRec(Read16(vp, 0x18)); _modification = DateRec(Read16(vp, 0x18));
_fileSize = 0; _fileSize = 0;
_pageLength = NULL; _pageSize = NULL;
} }
FileEntry::~FileEntry() FileEntry::~FileEntry()
{ {
delete _pageLength; delete _pageSize;
} }
@ -208,13 +242,12 @@ unsigned FileEntry::dataFileSize()
unsigned FileEntry::textFileSize() unsigned FileEntry::textFileSize()
{ {
if (!_pageLength) textInit(); if (!_pageSize) textInit();
return _fileSize; return _fileSize;
} }
#if 0
@ -225,7 +258,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset)
unsigned count = 0; unsigned count = 0;
unsigned block = 0; unsigned block = 0;
block = _startBlock + (offset / 512); block = _firstBlock + (offset / 512);
// returned value (count) is equal to size at this point. // returned value (count) is equal to size at this point.
// (no partial reads). // (no partial reads).
@ -238,7 +271,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset)
{ {
unsigned bytes = std::min(offset % 512, size); unsigned bytes = std::min(offset % 512, size);
_device->read(block++, tmp); parent()->readBlock(block++, tmp);
std::memcpy(buffer, tmp + 512 - bytes, bytes); std::memcpy(buffer, tmp + 512 - bytes, bytes);
@ -253,7 +286,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset)
while (size >= 512) while (size >= 512)
{ {
_device->read(block++, buffer); parent()->readBlock(block++, buffer);
buffer += 512; buffer += 512;
count += 512; count += 512;
@ -265,7 +298,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset)
*/ */
if (size) if (size)
{ {
_device->read(block, tmp); parent()->readBlock(block, tmp);
std::memcpy(buffer, tmp, size); std::memcpy(buffer, tmp, size);
count += size; count += size;
@ -282,30 +315,33 @@ int FileEntry::textRead(uint8_t *buffer, unsigned size, unsigned offset)
{ {
unsigned page = 0; unsigned page = 0;
unsigned to = 0; unsigned to = 0;
unsigned l = _pageSize.length();
unsigned block; unsigned block;
unsigned l;
unsigned count = 0; unsigned count = 0;
auto_array<uint8_t> tmp; auto_array<uint8_t> tmp;
unsigned tmpSize = 0; unsigned tmpSize = 0;
if (!_pageLength) textInit(); if (!_pageSize) textInit();
l = _pageSize->size();
// find the first page. // find the first page.
for (page = 1; page < l; ++page) for (page = 1; page < l; ++page)
{ {
if (to + _pageSize[page] > offset) unsigned pageSize = (*_pageSize)[page];
if (to + pageSize > offset)
{ {
break; break;
} }
to += _pageSize[i]; to += pageSize;
} }
--page; --page;
block = _startBlock + 2 + (page * 2); block = _firstBlock + 2 + (page * 2);
// offset not needed anymore, // offset not needed anymore,
@ -314,16 +350,18 @@ int FileEntry::textRead(uint8_t *buffer, unsigned size, unsigned offset)
while (size) while (size)
{ {
unsigned pageSize = _pageSize[page]; unsigned pageSize = (*_pageSize)[page];
if (pageSize > tmp) unsigned bytes = std::min(size, pageSize - offset);
if (pageSize > tmpSize)
{ {
tmp.reset(new uint8_t[pageSize]); tmp.reset(new uint8_t[pageSize]);
tmpSize = pageSize; tmpSize = pageSize;
} }
bytes = std::min(size, pageSize - offset);
decodePage(block, tmp.get()); // can decode straight to buffer if size >= bytes && offset = 0.
textDecodePage(block, tmp.get());
std::memcpy(buffer, tmp.get() + offset, bytes); std::memcpy(buffer, tmp.get() + offset, bytes);
@ -348,7 +386,7 @@ unsigned FileEntry::textDecodePage(unsigned block, uint8_t *out)
{ {
uint8_t buffer[1024]; uint8_t buffer[1024];
unsigned size = 0; unsigned size = 0;
unsigned bytes = readPage(block, buffer); unsigned bytes = textReadPage(block, buffer);
for (unsigned i = 0; i < bytes; ++i) for (unsigned i = 0; i < bytes; ++i)
{ {
@ -361,7 +399,7 @@ unsigned FileEntry::textDecodePage(unsigned block, uint8_t *out)
// 16, n -> n-32 spaces. // 16, n -> n-32 spaces.
unsigned x = buffer[++i] - 32; unsigned x = buffer[++i] - 32;
if (out) for(unsigned i = 0; i < x; ++i) *out++ = ' '; if (out) for (unsigned i = 0; i < x; ++i) *out++ = ' ';
size += x; size += x;
} }
else else
@ -377,17 +415,16 @@ unsigned FileEntry::textDecodePage(unsigned block, uint8_t *out)
unsigned FileEntry::textReadPage(unsigned block, uint8_t *in) unsigned FileEntry::textReadPage(unsigned block, uint8_t *in)
{ {
// reads up to 2 blocks. // reads up to 2 blocks.
// assumes block within _startBlock ... _endBlock - 1 // assumes block within _startBlock ... _lastBlock - 1
unsigned size = 0;
_device->read(block, in); parent()->readBlock(block, in);
if (block + 1 == _endBlock) if (block + 1 == _lastBlock)
{ {
return _lastByte; return _lastByte;
} }
_device->read(block + 1, in + 512); parent()->readBlock(block + 1, in + 512);
if (block +2 == _endBlock) if (block +2 == _lastBlock)
{ {
return 512 + _lastByte; return 512 + _lastByte;
} }
@ -401,15 +438,14 @@ void FileEntry::textInit()
{ {
// calculate the file size and page offsets. // calculate the file size and page offsets.
_pageSize.reserve((_endBlock - _startBlock - 2) / 2); _pageSize->reserve((_lastBlock - _firstBlock + 1 - 2) / 2);
_fileSize = 0; _fileSize = 0;
for (unsigned block = _startBlock + 2; block < _endBlock; block += 2) for (unsigned block = _firstBlock + 2; block < _lastBlock; block += 2)
{ {
unsigned size = decodePage(block, NULL); unsigned size = textDecodePage(block, NULL);
_fileSize += size; _fileSize += size;
_pageSize.push_back(size); _pageSize->push_back(size);
} }
} }
#endif

View File

@ -7,6 +7,7 @@
namespace ProFUSE { namespace ProFUSE {
class BlockDevice; class BlockDevice;
class AbstractBlockCache;
} }
namespace Pascal { namespace Pascal {
@ -25,6 +26,7 @@ enum {
}; };
class FileEntry; class FileEntry;
class VolumeEntry;
class Entry { class Entry {
@ -42,6 +44,9 @@ public:
unsigned inode() const { return _inode; } unsigned inode() const { return _inode; }
void setInode(unsigned inode) { _inode = inode; } void setInode(unsigned inode) { _inode = inode; }
VolumeEntry *parent() { return _parent; }
protected: protected:
Entry(); Entry();
@ -53,6 +58,11 @@ protected:
unsigned _fileKind; unsigned _fileKind;
unsigned _inode; unsigned _inode;
private:
friend class VolumeEntry;
VolumeEntry *_parent;
}; };
@ -70,6 +80,13 @@ public:
FileEntry *fileAtIndex(unsigned i) const; FileEntry *fileAtIndex(unsigned i) const;
void *loadBlock(unsigned block);
void unloadBlock(unsigned block, bool dirty = false);
void readBlock(unsigned block, void *);
void writeBlock(unsigned block, void *);
private: private:
VolumeEntry(); VolumeEntry();
@ -84,7 +101,9 @@ private:
std::vector<FileEntry *> _files; std::vector<FileEntry *> _files;
unsigned _inodeGenerator; unsigned _inodeGenerator;
ProFUSE::BlockDevice *_device;
ProFUSE::AbstractBlockCache *_cache;
}; };
@ -122,7 +141,7 @@ class FileEntry : public Entry {
unsigned textReadPage(unsigned block, uint8_t *in); unsigned textReadPage(unsigned block, uint8_t *in);
unsigned textDecodePage(unsigned block, uint8_t *out); unsigned textDecodePage(unsigned block, uint8_t *out);
std::vector<unsigned> *_pageLength; std::vector<unsigned> *_pageSize;
unsigned _fileSize; unsigned _fileSize;
}; };