mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[escher] Create class File and FileSystem
This commit is contained in:
committed by
EmilieNumworks
parent
4c796d404f
commit
c37696133d
@@ -21,6 +21,8 @@ objs += $(addprefix escher/src/,\
|
||||
expression_table_cell.o\
|
||||
expression_table_cell_with_pointer.o\
|
||||
expression_view.o\
|
||||
file.o\
|
||||
file_system.o\
|
||||
highlight_cell.o\
|
||||
gauge_view.o\
|
||||
image_view.o\
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <escher/expression_table_cell.h>
|
||||
#include <escher/expression_table_cell_with_pointer.h>
|
||||
#include <escher/expression_view.h>
|
||||
#include <escher/file.h>
|
||||
#include <escher/file_system.h>
|
||||
#include <escher/gauge_view.h>
|
||||
#include <escher/highlight_cell.h>
|
||||
#include <escher/image.h>
|
||||
|
||||
47
escher/include/escher/file.h
Normal file
47
escher/include/escher/file.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef ESCHER_FILE_H
|
||||
#define ESCHER_FILE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* File : | Total Size | Type | Name | Body | */
|
||||
|
||||
class File {
|
||||
public:
|
||||
enum class Type : uint8_t {
|
||||
Null,
|
||||
Script
|
||||
};
|
||||
enum class ErrorStatus {
|
||||
None = 0,
|
||||
NameTaken = 1,
|
||||
NameTooLong = 2,
|
||||
NoEnoughSpaceAvailable = 3
|
||||
};
|
||||
File(size_t * totalSize = nullptr, char * name = nullptr, Type type = Type::Null, char * body = nullptr);
|
||||
|
||||
bool isNull() const;
|
||||
|
||||
const char * name() const;
|
||||
ErrorStatus rename(const char * newName); // May fail if name taken or name too long
|
||||
|
||||
const char * read() const;
|
||||
ErrorStatus write(const char * data, size_t size = 0); // May fail if no more space is available
|
||||
|
||||
Type type();
|
||||
|
||||
void remove(); // Will always succeed
|
||||
constexpr static size_t k_nameSize = 50;
|
||||
constexpr static size_t k_sizeSize = sizeof(size_t);
|
||||
constexpr static size_t k_typeSize = sizeof(Type);
|
||||
protected:
|
||||
size_t bodySize() const;
|
||||
char * start();
|
||||
char * m_body;
|
||||
size_t * m_size;
|
||||
private:
|
||||
char * m_name;
|
||||
Type m_type;
|
||||
};
|
||||
|
||||
#endif
|
||||
39
escher/include/escher/file_system.h
Normal file
39
escher/include/escher/file_system.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef ESCHER_FILE_SYSTEM_H
|
||||
#define ESCHER_FILE_SYSTEM_H
|
||||
|
||||
/* FileSystem : | Magic | File1 | File2 | ... | Magic |
|
||||
* | Magic | Size1 | Type1 | Name1 | BodySize1 | Body1 | Size2 | Type2 | Name2 | BodySize2 | Body2 | ... | Magic */
|
||||
|
||||
class FileSystem {
|
||||
public:
|
||||
FileSystem();
|
||||
static FileSystem * sharedFileSystem();
|
||||
int numberOfFileOfType(File::Type type);
|
||||
File fileOfTypeAtIndex(File::Type type, int index);
|
||||
File getFile(File::Type type, const char * name);
|
||||
|
||||
File addFile(const char * name, File::Type type, const char * content);
|
||||
|
||||
// availableSize takes into account the the size of the last File must be 0.
|
||||
size_t availableSize();
|
||||
|
||||
bool isNameTaken(const char * name, File::Type type);
|
||||
bool moveNextFile(char * start, int delta);
|
||||
size_t sizeOfFileWithBody(const char * body) const;
|
||||
private:
|
||||
// lastUsedData takes into account the the size of the last File must be 0.
|
||||
char * lastUsedData();
|
||||
size_t * sizeAddressOfFileStarting(char * start) const;
|
||||
size_t sizeOfFileStarting(char * start) const;
|
||||
File::Type typeOfFileStarting(char * start) const;
|
||||
char * nameOfFileStarting(char * start);
|
||||
char * bodyOfFileStarting(char * start);
|
||||
constexpr static size_t k_totalSize = 4096;
|
||||
constexpr static uint32_t Magic = 0xDEC00DF0;
|
||||
uint32_t m_dataHeader;
|
||||
char m_data[k_totalSize];
|
||||
uint32_t m_dataFooter;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
67
escher/src/file.cpp
Normal file
67
escher/src/file.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <escher/file.h>
|
||||
#include <escher/file_system.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
File::File(size_t * size, char * name, Type type, char * body) :
|
||||
m_body(body),
|
||||
m_size(size),
|
||||
m_name(name),
|
||||
m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
bool File::isNull() const {
|
||||
if (m_type == Type::Null) {
|
||||
assert(m_size == nullptr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const char * File::name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
File::ErrorStatus File::rename(const char * newName) {
|
||||
if (FileSystem::sharedFileSystem()->isNameTaken(newName, m_type)) {
|
||||
return ErrorStatus::NameTaken;
|
||||
}
|
||||
if (strlen(newName) >= k_nameSize) {
|
||||
return ErrorStatus::NameTooLong;
|
||||
}
|
||||
strlcpy(m_name, newName, k_nameSize);
|
||||
return ErrorStatus::None;
|
||||
}
|
||||
|
||||
const char * File::read() const {
|
||||
return m_body;
|
||||
}
|
||||
|
||||
File::ErrorStatus File::write(const char * data, size_t size) {
|
||||
int deltaSize = (int)size - (int)bodySize();
|
||||
// TODO: if this fails because deltaSize is too big, return an error?
|
||||
if (FileSystem::sharedFileSystem()->moveNextFile(start(), deltaSize)) {
|
||||
*m_size += deltaSize;
|
||||
strlcpy(m_body, data, size);
|
||||
return ErrorStatus::None;
|
||||
}
|
||||
return ErrorStatus::NoEnoughSpaceAvailable;
|
||||
}
|
||||
|
||||
File::Type File::type() {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
void File::remove() {
|
||||
FileSystem::sharedFileSystem()->moveNextFile(start(), -*(m_size));
|
||||
}
|
||||
|
||||
char * File::start() {
|
||||
return m_name - k_typeSize - k_sizeSize;
|
||||
}
|
||||
|
||||
size_t File::bodySize() const {
|
||||
return *m_size - k_nameSize - k_typeSize - k_sizeSize;
|
||||
}
|
||||
152
escher/src/file_system.cpp
Normal file
152
escher/src/file_system.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
#include <escher/file.h>
|
||||
#include <escher/file_system.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
FileSystem::FileSystem() :
|
||||
m_dataHeader(Magic),
|
||||
m_data(),
|
||||
m_dataFooter(Magic)
|
||||
{
|
||||
size_t * p = (size_t *)m_data;
|
||||
p[0] = 0;
|
||||
}
|
||||
|
||||
FileSystem * FileSystem::sharedFileSystem() {
|
||||
static FileSystem f;
|
||||
return &f;
|
||||
}
|
||||
|
||||
int FileSystem::numberOfFileOfType(File::Type type) {
|
||||
assert(m_dataHeader == Magic);
|
||||
assert(m_dataFooter == Magic);
|
||||
int count = 0;
|
||||
char * currentPointer = m_data;
|
||||
size_t size = sizeOfFileStarting(currentPointer);
|
||||
while (size != 0 && currentPointer < m_data + k_totalSize) {
|
||||
if (typeOfFileStarting(currentPointer) == type) {
|
||||
count++;
|
||||
}
|
||||
currentPointer += size;
|
||||
size = sizeOfFileStarting(currentPointer);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
File FileSystem::fileOfTypeAtIndex(File::Type type, int index) {
|
||||
int currentIndex = -1;
|
||||
char * currentPointer = m_data;
|
||||
size_t size = sizeOfFileStarting(currentPointer);
|
||||
while (size != 0 && currentPointer < m_data + k_totalSize) {
|
||||
if (typeOfFileStarting(currentPointer) == type) {
|
||||
currentIndex++;
|
||||
if (currentIndex == index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentPointer += size;
|
||||
size = sizeOfFileStarting(currentPointer);
|
||||
}
|
||||
return File(sizeAddressOfFileStarting(currentPointer), nameOfFileStarting(currentPointer), type, bodyOfFileStarting(currentPointer));
|
||||
}
|
||||
|
||||
File FileSystem::getFile(File::Type type, const char * name) {
|
||||
for (int i = 0; i < numberOfFileOfType(type); i++) {
|
||||
File currentFile = fileOfTypeAtIndex(type, i);
|
||||
if (strcmp(currentFile.name(), name) == 0) {
|
||||
return currentFile;
|
||||
}
|
||||
}
|
||||
return File();
|
||||
}
|
||||
|
||||
File FileSystem::addFile(const char * name, File::Type type, const char * body) {
|
||||
// assert name is short enough and there is enough space to add the file
|
||||
assert(strlen(name) < File::k_nameSize);
|
||||
assert(availableSize() >= sizeOfFileWithBody(body));
|
||||
// Find the end of data
|
||||
char * currentPointer = m_data;
|
||||
size_t size = sizeOfFileStarting(currentPointer);
|
||||
while (size != 0 && currentPointer < m_data + k_totalSize) {
|
||||
currentPointer += size;
|
||||
size = sizeOfFileStarting(currentPointer);
|
||||
}
|
||||
size_t fileSize = sizeOfFileWithBody(body);
|
||||
// Fill totalSize
|
||||
*((size_t *)currentPointer) = fileSize;
|
||||
// Fill type
|
||||
*(currentPointer+File::k_sizeSize) = (uint8_t)type;
|
||||
// Fill name
|
||||
strlcpy(currentPointer+File::k_sizeSize+File::k_typeSize, name, File::k_nameSize);
|
||||
// Fill body
|
||||
strlcpy(currentPointer+File::k_sizeSize+File::k_typeSize+File::k_nameSize, body, strlen(body)+1);
|
||||
char * nextPointer = currentPointer + fileSize;
|
||||
*((size_t *)nextPointer) = 0;
|
||||
return File(sizeAddressOfFileStarting(currentPointer), nameOfFileStarting(currentPointer), type, bodyOfFileStarting(currentPointer));
|
||||
}
|
||||
|
||||
char * FileSystem::lastUsedData() {
|
||||
size_t usedSize = 0;
|
||||
char * currentPointer = m_data;
|
||||
size_t size = sizeOfFileStarting(currentPointer);
|
||||
while (size != 0 && currentPointer < m_data + k_totalSize) {
|
||||
usedSize += size;
|
||||
currentPointer += size;
|
||||
size = sizeOfFileStarting(currentPointer);
|
||||
}
|
||||
return currentPointer + File::k_sizeSize;
|
||||
}
|
||||
|
||||
|
||||
size_t FileSystem::availableSize() {
|
||||
return k_totalSize-(lastUsedData()-m_data);
|
||||
}
|
||||
|
||||
bool FileSystem::isNameTaken(const char * name, File::Type type) {
|
||||
char * currentPointer = m_data;
|
||||
size_t size = sizeOfFileStarting(currentPointer);
|
||||
while (size != 0 && currentPointer < m_data + k_totalSize) {
|
||||
if (typeOfFileStarting(currentPointer) == type && strcmp(nameOfFileStarting(currentPointer), name) == 0) {
|
||||
return true;
|
||||
}
|
||||
currentPointer += size;
|
||||
size = sizeOfFileStarting(currentPointer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileSystem::moveNextFile(char * start, int delta) {
|
||||
if (delta > (int)availableSize()) {
|
||||
return false;
|
||||
}
|
||||
char * nextFile = start + sizeOfFileStarting(start);
|
||||
memmove(nextFile+delta, nextFile, lastUsedData()-nextFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t * FileSystem::sizeAddressOfFileStarting(char * start) const {
|
||||
return (size_t *)start;
|
||||
}
|
||||
|
||||
size_t FileSystem::sizeOfFileStarting(char * start) const {
|
||||
if (start >= m_data + k_totalSize) {
|
||||
return 0;
|
||||
}
|
||||
return *(sizeAddressOfFileStarting(start));
|
||||
}
|
||||
|
||||
File::Type FileSystem::typeOfFileStarting(char * start) const {
|
||||
return (File::Type)*((uint8_t *)start+File::k_sizeSize);
|
||||
}
|
||||
|
||||
char * FileSystem::nameOfFileStarting(char * start) {
|
||||
return start+File::k_sizeSize+File::k_typeSize;
|
||||
}
|
||||
|
||||
char * FileSystem::bodyOfFileStarting(char * start) {
|
||||
return start+File::k_sizeSize+File::k_typeSize+File::k_nameSize;
|
||||
}
|
||||
|
||||
size_t FileSystem::sizeOfFileWithBody(const char * body) const {
|
||||
return File::k_sizeSize+File::k_typeSize+File::k_nameSize+strlen(body)+1;
|
||||
}
|
||||
Reference in New Issue
Block a user