⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filenode.c

📁 老外写的一个文件系统
💻 C
字号:
#include "Platform.h"
#include "Debug/Debug.h"
#include "StdC.h"
#include "Hardware/DRAM.h"
#include "PageStack/PageStack.h"
#include "FileSystem/Fat32/FileTree/NameNode.h"
#include "FileSystem/Fat32/FileTree/FileNode.h"
#include "FileSystem/Fat32/FileTree/Node.h"


//#define SHOW_CREATION	// uncomment to see FileNode's get created.
//#define SHOW_VISITS		// uncomment to see FileNode's get visited.


struct FileNode
{
	ClusterNumber firstClusterOfFile;
	NameNodeHandle nameOfFile;
	unsigned long sizeInBytes;
	FileNodeHandle nextFileSibbling;		// next file, ignoring folders
	FileNodeHandle prevFileSibbling;		// prev file, ignoring folders
	FileNodeHandle firstFileOfNextFolder;	// first file in the next folder
	FileNodeHandle lastFileOfPrevFolder;	// last file in the previous folder
	char unused[4];	// structure MUST pad to 32 bytes, or any power of 2.
};


XDATA_AT(PAGE_STACK_ADDRESS) struct FileNode _FILENODE_fileNodeTablePort[BYTES_PER_PORT/sizeof(struct FileNode)];

XDATA DramPageIndex _FILENODE_nextNewFilePage;
XDATA unsigned char _FILENODE_nextNewFileIndex;

XDATA FileNodeHandle _FILENODE_lastFileOfPrevFolder;	// remember what was the last file of the previous folder.
XDATA FileNodeHandle _FILENODE_prevFile;				// remember what was the first file to be created

// these 3 variables are used to keep track of the state 
// between calls to FILENODE_DoneAddingFilesToFolder(),
// and are initialzied on each call to FILENODE_DoneAddingFilesToFolder()
XDATA static struct FileNode *_FILENODE_ReLink_scan;
XDATA static FileNodeHandle _FILENODE_ReLink_scanHandle;
XDATA static FileNodeHandle _FILENODE_ReLink_firstFileOfThisFolder;

void FILENODE_Initialize(void)
{
	_FILENODE_nextNewFilePage = DRAM_AllocatePage(_STRING_CreateStringInCODE("FILENODE Array"));
	_FILENODE_nextNewFileIndex = 0;
	_FILENODE_lastFileOfPrevFolder = NO_FILE_NODE;
	_FILENODE_prevFile = NO_FILE_NODE;
}


// This routine is adding a new file to a folder.
// It does so, by inserting itself as the first file in that folder, 
// and linking what used to be the first file, as its' sibbling instead.
FileNodeHandle FILENODE_AddFile(
	ClusterNumber startingClusterNumber,
	unsigned long sizeInBytes,
	NameNodeHandle nameOfFile)
{
	XDATA static FileNodeHandle thisHandle;	// the new file being created.
	XDATA static FileNodeHandle prevFileHandle;

	// figure out the file-handle of the new entry being created.
	thisHandle = MakeHandle(_FILENODE_nextNewFilePage, _FILENODE_nextNewFileIndex);

	// populate 'self'
	{
		XDATA static struct FileNode *self;
		self = &_FILENODE_fileNodeTablePort[GetIndexChar(thisHandle)];
		PAGESTACK_Push(GetPage(thisHandle));
		
		self->firstClusterOfFile = startingClusterNumber;
		self->nameOfFile = nameOfFile;
		self->sizeInBytes = sizeInBytes;
		
		self->nextFileSibbling = NO_FILE_NODE;
		self->prevFileSibbling = _FILENODE_prevFile;
		
		self->firstFileOfNextFolder = NO_FILE_NODE;	// this will be filled in when FILENODE_DoneAddingFilesToFolder() is called at the correct time.
		self->lastFileOfPrevFolder = _FILENODE_lastFileOfPrevFolder;
		
#ifdef SHOW_CREATION
		DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [new]..."));
		DbgMessageHex32(DC_FILENODE, MakeHandle(_FILENODE_nextNewFilePage, _FILENODE_nextNewFileIndex));
		DbgMessageNewLine(DC_FILENODE);
		DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
		PAGESTACK_Pop();
	}

	// fix the 'nextSibbling' pointer of the previous file...
	if(_FILENODE_prevFile != NO_FILE_NODE)
	{
		XDATA static struct FileNode *prevFile;
		prevFile = &_FILENODE_fileNodeTablePort[GetIndexChar(_FILENODE_prevFile)];
		PAGESTACK_Push(GetPage(_FILENODE_prevFile));

		prevFile->nextFileSibbling = thisHandle;
		
		PAGESTACK_Pop();
	}

	// remember this file as our new "previous file"...
	_FILENODE_prevFile = thisHandle;

	// advance pointer for next available object	
	_FILENODE_nextNewFileIndex++;
	if(_FILENODE_nextNewFileIndex == ENTRIES(_FILENODE_fileNodeTablePort))
	{
		_FILENODE_nextNewFilePage = DRAM_AllocatePage(_STRING_CreateStringInCODE("FILENODE Array"));
		_FILENODE_nextNewFileIndex = 0;
	}

	// return our new file.
	return thisHandle;
}

// this is called after the last file has been added to a folder, but before
// any files have been added for the next folder.
void FILENODE_DoneAddingFilesToFolder(void)
{
	// go back and fix-up nextFileSibbling's and firstFileOfNextFolder's...
	// only if there has been a previous folder...
	if(_FILENODE_lastFileOfPrevFolder != NO_FILE_NODE)
	{
		// get the last file of the previous folder...
		_FILENODE_ReLink_scanHandle = _FILENODE_lastFileOfPrevFolder;	// start with last file in prev folder

		// get the first file of this folder...
		_FILENODE_ReLink_scan = &_FILENODE_fileNodeTablePort[GetIndexChar(_FILENODE_ReLink_scanHandle)];
		PAGESTACK_Push(GetPage(_FILENODE_ReLink_scanHandle));
		_FILENODE_ReLink_firstFileOfThisFolder = _FILENODE_ReLink_scan->nextFileSibbling;
		PAGESTACK_Pop();
		
		// only if there are files in the current folder...
		if(_FILENODE_ReLink_firstFileOfThisFolder == NO_FILE_NODE)
		{
			// nothing to do... this will short-circuit the 
			// FILENODE_LinkFileTreeSomeMore() routine.
			_FILENODE_ReLink_scanHandle = NO_FILE_NODE;
		}
	}
	else
	{
		// nothing to do... this will short-circuit the 
		// FILENODE_LinkFileTreeSomeMore() routine.
		_FILENODE_ReLink_scanHandle = NO_FILE_NODE;	
	}
	
	// remember new "last file of prev folder"...
	_FILENODE_lastFileOfPrevFolder = _FILENODE_prevFile;
}


char FILENODE_LinkFileTreeSomeMore(void)
{
	XDATA static char togo;
	
	// NOTE:  If the music skips or pauses while the file-tree is being built 
	// after power-up, then this number can be lowered at the cost of increased 
	// load-times for the directory tree.
	togo = 32;	// do this many files each call...
	while(_FILENODE_ReLink_scanHandle != NO_FILE_NODE)
	{
		// decrement the counter which limits the length of time 
		// this function can execute, per call.
		togo--;
		if(togo > 0)
		{
			_FILENODE_ReLink_scan = &_FILENODE_fileNodeTablePort[GetIndexChar(_FILENODE_ReLink_scanHandle)];
			PAGESTACK_Push(GetPage(_FILENODE_ReLink_scanHandle));

			if(_FILENODE_ReLink_scan->firstFileOfNextFolder == NO_FILE_NODE)
				_FILENODE_ReLink_scan->firstFileOfNextFolder = _FILENODE_ReLink_firstFileOfThisFolder;

			_FILENODE_ReLink_scanHandle = _FILENODE_ReLink_scan->prevFileSibbling;
			PAGESTACK_Pop();
		}
		else
		{
			return 0;	// not done yet!!
		}
	}

	// DONE!!
	return 1;	
}


ClusterNumber FILENODE_DiscoverFirstCluster(FileNodeHandle fileNodeHandle)
{
	XDATA static struct FileNode *self;
	XDATA static ClusterNumber startingClusterNumber;
	self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
	PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
	DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit FirstCluster]..."));
	DbgMessageHex32(DC_FILENODE, fileNodeHandle);
	DbgMessageNewLine(DC_FILENODE);
	DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
	startingClusterNumber = self->firstClusterOfFile;
	PAGESTACK_Pop();
	return startingClusterNumber;
}


FileNodeHandle FILENODE_GetNextFileNodeSibbling(FileNodeHandle fileNodeHandle)
{
	XDATA static struct FileNode *self;
	XDATA static FileNodeHandle nextFileNode;
	self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
	PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
	DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit NextFileSib]..."));
	DbgMessageHex32(DC_FILENODE, fileNodeHandle);
	DbgMessageNewLine(DC_FILENODE);
	DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
	nextFileNode = self->nextFileSibbling;
	PAGESTACK_Pop();
	return nextFileNode;
}


FileNodeHandle FILENODE_GetPrevFileNodeSibbling(FileNodeHandle fileNodeHandle)
{
	XDATA static struct FileNode *self;
	XDATA static FileNodeHandle nextFileNode;
	self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
	PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
	DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit PrevFileSib]..."));
	DbgMessageHex32(DC_FILENODE, fileNodeHandle);
	DbgMessageNewLine(DC_FILENODE);
	DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
	nextFileNode = self->prevFileSibbling;
	PAGESTACK_Pop();
	return nextFileNode;
}

FileNodeHandle FILENODE_GetFirstFileNodeOfNextFolder(FileNodeHandle fileNodeHandle)
{
	XDATA static struct FileNode *self;
	XDATA static FileNodeHandle nextFileNode;
	self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
	PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
	DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit NextFolder]..."));
	DbgMessageHex32(DC_FILENODE, fileNodeHandle);
	DbgMessageNewLine(DC_FILENODE);
	DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
	nextFileNode = self->firstFileOfNextFolder;
	PAGESTACK_Pop();
	return nextFileNode;
}

FileNodeHandle FILENODE_GetLastFileNodeOfPrevFolder(FileNodeHandle fileNodeHandle)
{
	XDATA static struct FileNode *self;
	XDATA static FileNodeHandle nextFileNode;
	self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
	PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
	DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit PrevFolder]..."));
	DbgMessageHex32(DC_FILENODE, fileNodeHandle);
	DbgMessageNewLine(DC_FILENODE);
	DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
	nextFileNode = self->lastFileOfPrevFolder;
	PAGESTACK_Pop();
	return nextFileNode;
}


unsigned long FILENODE_DiscoverFileSizeInBytes(FileNodeHandle fileNodeHandle)
{
	XDATA static struct FileNode *self;
	XDATA static unsigned long sizeInBytes;
	self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
	PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
	DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit FileSize]..."));
	DbgMessageHex32(DC_FILENODE, fileNodeHandle);
	DbgMessageNewLine(DC_FILENODE);
	DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
	sizeInBytes = self->sizeInBytes;
	PAGESTACK_Pop();
	return sizeInBytes;
}

NameNodeHandle FILENODE_GetFilename(FileNodeHandle fileNodeHandle)
{
	XDATA static struct FileNode *self;
	XDATA static NameNodeHandle filename;
	self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
	PAGESTACK_Push(GetPage(fileNodeHandle));
#ifdef SHOW_VISITS
	DbgMessage(DC_FILENODE, _STRING_CreateStringInCODE("FileNode [visit GetName]..."));
	DbgMessageHex32(DC_FILENODE, fileNodeHandle);
	DbgMessageNewLine(DC_FILENODE);
	DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
#endif
	filename = self->nameOfFile;
	PAGESTACK_Pop();
	return filename;
}

void FILENODE_Dump(FileNodeHandle fileNodeHandle)
{
	XDATA static struct FileNode *self;
	self = &_FILENODE_fileNodeTablePort[GetIndexChar(fileNodeHandle)];
	PAGESTACK_Push(GetPage(fileNodeHandle));
	DbgHexDumpXDATA(DC_FILENODE, (XDATA char *)self, sizeof(*self));
	PAGESTACK_Pop();
}


_CONSTANT_DATA(FILENODE)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -