import "System"
import "BufferedFile"
-#define OFFSET(s, m) ((uint) (&((s *) 0)->m))
+#define OFFSET(s, m) ((uint)(uintptr) (&((s *) 0)->m))
#define MDWORD(a,b) ((((uint32)((uint16)(b)))<<16)+((uint16)(a)))
#define EAR_RECOGNITION { 'e', 'A', 'R', 228, 11, 12, 3, 0 }
};
static struct EARHeader
-{
- byte recognition[sizeof(earRecognition)] __attribute__((packed));
- uint version __attribute__((packed));
- FileSize totalSize __attribute__((packed));
+{
+ byte recognition[sizeof(earRecognition)];
+ uint version __attribute__((packed));
+ FileSize totalSize __attribute__((packed));
};
static enum EAREntryType { ENTRY_FILE = 1, ENTRY_FOLDER = 2 };
// null terminated file name follows
};
-static File EAROpenArchive(char * archive, EARHeader header)
+static File EAROpenArchive(const char * archive, EARHeader header)
{
File f = null;
if(archive[0] == ':')
{
char moduleName[MAX_LOCATION];
- char * name = archive + 1;
-#if defined(__ANDROID__)
+ const char * name = archive + 1;
+#if defined(__ANDROID__) || defined(__EMSCRIPTEN__)
if(!name[0])
name = ((SubModule)__thisModule.application.modules.first).next.module.name;
#endif
-
+#if defined(__EMSCRIPTEN__)
+ //sprintf(moduleName, "__%s.ear", name);
+ sprintf(moduleName, "__%s.ear", "HelloForm");
+ f = FileOpen(moduleName, read);
+#else
if(LocateModule(name, moduleName))
f = FileOpen(moduleName, read);
+#endif
}
else
f = FileOpen(archive, read);
// First attempt to treat this as an archive file
if(f.Read(header, sizeof(EARHeader), 1) == 1 &&
- !strncmp(header.recognition, earRecognition, sizeof(earRecognition)))
+ !memcmp(header.recognition, earRecognition, sizeof(earRecognition)))
return f;
// Then try to see if an archive is at the end of the file
f.Read(&archiveSize, sizeof(uint), 1);
f.Seek(-(int)archiveSize, end);
if(f.Read(header, sizeof(EARHeader), 1) == 1 &&
- !strncmp(header.recognition, earRecognition, sizeof(earRecognition)))
+ !memcmp(header.recognition, earRecognition, sizeof(earRecognition)))
return f;
delete f;
return null;
}
-static FileAttribs EARGetEntry(File f, EAREntry entry, char * name, char * path)
+static FileAttribs EARGetEntry(File f, EAREntry entry, const char * name, char * path)
{
uint first = 0, last = 0;
if(!name[0])
for(;;)
{
char fileName[MAX_FILENAME];
-
+
f.Read(entry, sizeof(EAREntry), 1);
f.Read(fileName, 1, entry.nameLen);
fileName[entry.nameLen] = '\0';
return end;
}
+ return 0;
}
~EARArchive()
// Fix the size of the archive
FileTruncate(path, archiveStart);
}*/
-
+
freeBlocks.Free(null);
}
return true;
}
- ArchiveDir OpenDirectory(char * name, FileStats stats, ArchiveAddMode addMode)
+ ArchiveDir OpenDirectory(const char * name, FileStats stats, ArchiveAddMode addMode)
{
ArchiveDir result = null;
EARArchiveDir dir { readOnly = addMode == readOnlyDir };
if(dir)
{
char namePart[MAX_LOCATION] = "", nameRest[MAX_LOCATION];
- uint position;
dir.archive = this;
rootDir = Position(2*sizeof(uint));
dir.position = rootDir;
}
-
+
result = dir;
// Open rest of directory...
if(f.Seek(dirPosition + sizeof(uint), start))
f.Write(&last, sizeof(uint), 1);
}
-
+
for(; position; position = next)
{
EAREntry entry { };
Defrag(position + sizeof(EAREntry) + entry.nameLen);
}
else
- return 0;
+ return;
}
// Move all the blocks
}
}
- uint Find(EARArchiveDir directory, char * namePart, EAREntry entry)
+ uint Find(EARArchiveDir directory, const char * namePart, EAREntry entry)
{
uint position;
for(position = directory.first; position; position = entry.next)
{
char fileName[MAX_FILENAME];
-
+
if(f.Seek(position, start) && f.Read(entry, sizeof(EAREntry), 1))
{
if(entry.nameLen > MAX_FILENAME)
void AddFreeBlock(uint position, uint size)
{
FreeBlock block, prevBlock, nextBlock = null;
-
+
// Find the previous and next free block
prevBlock = null;
for(block = freeBlocks.first; block; block = block.next)
if(block.end < position)
- prevBlock = block;
+ prevBlock = block;
else
{
nextBlock = block;
size = sizeof(EAREntry) + entry.nameLen + (entry.cSize ? entry.cSize : entry.size);
// Unlink this file
- if(entry.prev)
+ if(entry.prev)
{
f.Seek(entry.prev + OFFSET(EAREntry, next), start);
f.Write(&entry.next, sizeof(uint), 1);
}
- if(entry.next)
+ if(entry.next)
{
f.Seek(entry.next + OFFSET(EAREntry, prev), start);
f.Write(&entry.prev, sizeof(uint), 1);
// bf.handle = f;
}
- File FileOpen(char * name)
+ File FileOpen(const char * name)
{
File result = null;
EARFile file {};
if(file)
{
- char fileName[MAX_LOCATION];
EAREntry entry { };
f.Seek(archiveStart + sizeof(EARHeader), start);
if(compressed)
{
if(f.Read(compressed, 1, entry.cSize) == entry.cSize)
- uncompress(uncompressed, (uint *)&entry.size, compressed, entry.cSize);
+ {
+ unsigned long destLen = entry.size;
+ uncompress(uncompressed, &destLen, compressed, entry.cSize);
+ entry.size = (FileSize)destLen; // TODO: Support 64 bit file sizes
+ }
delete compressed;
}
if(compressed)
{
if(f.Read(compressed, 1, entry.cSize) == entry.cSize)
- uncompress(uncompressed, (uint *)&entry.size, compressed, entry.cSize);
+ {
+ unsigned long destLen = entry.size;
+ uncompress(uncompressed, &destLen, compressed, entry.cSize);
+ entry.size = (FileSize)destLen;
+ }
delete compressed;
}
return file;
}
- FileAttribs FileExists(char * fileName)
+ FileAttribs FileExists(const char * fileName)
{
FileAttribs result;
EAREntry entry { };
{
uint first, last;
if(!f.Read(&first, sizeof(uint), 1))
- return 0;
+ return;
#ifdef _DEBUG
if(first > f.GetSize())
{
}
}
- File FileOpen(char * name)
+ File FileOpen(const char * name)
{
File result = null;
EARFile file {};
if(file)
{
- char fileName[MAX_LOCATION];
EAREntry entry { };
archive.f.Seek(position, start);
if(compressed)
{
if(archive.f.Read(compressed, 1, entry.cSize) == entry.cSize)
- uncompress(uncompressed, (uint *)&entry.size, compressed, entry.cSize);
+ {
+ unsigned long destLen = entry.size;
+ uncompress(uncompressed, &destLen, compressed, entry.cSize);
+ entry.size = (FileSize)destLen;
+ }
delete compressed;
}
return result;
}
- FileAttribs FileExists(char * fileName)
+ FileAttribs FileExists(const char * fileName)
{
FileAttribs result;
EAREntry entry { };
return result;
}
- ArchiveDir OpenDirectory(char * name, FileStats stats, ArchiveAddMode addMode)
+ ArchiveDir OpenDirectory(const char * name, FileStats stats, ArchiveAddMode addMode)
{
ArchiveDir result = null;
EARArchiveDir dir { readOnly = addMode == readOnlyDir };
strcpy(namePart, DIR_SEPS);
// Search for directory
-
+
position = archive.Find(this, namePart, entry);
if(position)
{
archive.f.Read(&dir.first, sizeof(uint), 1);
archive.f.Read(&dir.last, sizeof(uint), 1);
-
+
result = dir;
- }
+ }
}
// If directory doesn't exist already
return result;
}
- bool Delete(char * name)
+ bool Delete(const char * name)
{
EAREntry entry { };
uint position;
strcpy(namePart, name);
if(!strcmp(namePart, "/") || !strcmp(namePart, "\\"))
strcpy(namePart, DIR_SEPS);
-
+
position = archive.Find(this, namePart, entry);
if(position)
{
return false;
}
- bool Move(char * name, EARArchiveDir to)
+ bool Move(const char * name, EARArchiveDir to)
{
bool result = false;
if(position != to.position)
archive.f.Seek(entry.prev + OFFSET(EAREntry, next), start);
archive.f.Write(&entry.next, sizeof(uint), 1);
}
- if(entry.next)
+ if(entry.next)
{
archive.f.Seek(entry.next + OFFSET(EAREntry, prev), start);
archive.f.Write(&entry.prev, sizeof(uint), 1);
return result;
}
- bool Rename(char * name, char * newName)
+ bool Rename(const char * name, const char * newName)
{
bool result = false;
EAREntry entry { };
dataSize = 2 * sizeof(uint);
else
dataSize = entry.cSize ? entry.cSize : entry.size;
-
+
newEntry.nameLen = strlen(newName);
if(newEntry.nameLen > entry.nameLen)
{
archive.f.Write(newName, sizeof(char), newEntry.nameLen);
// Fix the links
- if(entry.prev)
+ if(entry.prev)
{
archive.f.Seek(entry.prev + OFFSET(EAREntry, next), start);
archive.f.Write(&newPosition, sizeof(uint), 1);
}
- if(entry.next)
+ if(entry.next)
{
archive.f.Seek(entry.next + OFFSET(EAREntry, prev), start);
archive.f.Write(&newPosition, sizeof(uint), 1);
// There will be free space at the end of an entry with a shorter new name
if(newEntry.nameLen < entry.nameLen)
- archive.AddFreeBlock(position + sizeof(EAREntry) + newEntry.nameLen + dataSize, entry.nameLen - newEntry.nameLen);
+ archive.AddFreeBlock(position + sizeof(EAREntry) + newEntry.nameLen + dataSize, entry.nameLen - newEntry.nameLen);
}
if(entry.nameLen != newEntry.nameLen)
{
return result;
}
- bool AddFromFile(char * name, File input, FileStats stats, ArchiveAddMode addMode, int compression, int * ratio, uint * newPosition)
+ bool AddFromFile(const char * name, File input, FileStats stats, ArchiveAddMode addMode, int compression, int * ratio, uint * newPosition)
{
// Search for identical entry
EAREntry oldEntry;
return _AddFromFileAtPosition(oldEntry, oldPosition, name, input, stats, addMode, compression, ratio, newPosition);
}
- bool AddFromFileAtPosition(uint oldPosition, char * name, File input, FileStats stats, ArchiveAddMode addMode, int compression, int * ratio, uint * newPosition)
+ bool AddFromFileAtPosition(uint oldPosition, const char * name, File input, FileStats stats, ArchiveAddMode addMode, int compression, int * ratio, uint * newPosition)
{
EAREntry oldEntry;
if(oldPosition)
return _AddFromFileAtPosition(oldEntry, oldPosition, name, input, stats, addMode, compression, ratio, newPosition);
}
- bool _AddFromFileAtPosition(EAREntry oldEntry, uint oldPosition, char * name, File input, FileStats stats, ArchiveAddMode addMode, int compression, int * ratio, uint * newPosition)
+ bool _AddFromFileAtPosition(EAREntry oldEntry, uint oldPosition, const char * name, File input, FileStats stats, ArchiveAddMode addMode, int compression, int * ratio, uint * newPosition)
{
- bool result = false;
bool skip = false;
FileStats oldStats { };
break;
// Only updates changed files
case refresh:
- if(oldPosition &&
- (oldEntry.size != stats.size ||
- oldEntry.modified != (TimeStamp32)stats.modified ||
+ if(oldPosition &&
+ (oldEntry.size != stats.size ||
+ oldEntry.modified != (TimeStamp32)stats.modified ||
oldEntry.created != (TimeStamp32)stats.created))
archive.Delete(this, oldPosition, oldEntry);
else
case update:
if(oldPosition)
{
- if(oldEntry.size != stats.size ||
- oldEntry.modified != (TimeStamp32)stats.modified ||
+ if(oldEntry.size != stats.size ||
+ oldEntry.modified != (TimeStamp32)stats.modified ||
oldEntry.created != (TimeStamp32)stats.created)
archive.Delete(this, oldPosition, oldEntry);
else
entry.prev = last;
entry.next = 0;
entry.type = ENTRY_FILE;
-
+
entry.size = stats.size;
entry.created = (TimeStamp32)stats.created;
entry.modified = (TimeStamp32)stats.modified;
-
+
if(compression)
{
byte * uncompressed = new byte[entry.size];
{
if(input.Read(uncompressed, 1, entry.size) == entry.size)
{
- entry.cSize = entry.size + entry.size / 1000 + 12;
+ unsigned long destLen = entry.size + entry.size / 1000 + 12;
- compressed = new byte[entry.cSize];
+ compressed = new byte[destLen];
if(compressed)
- compress2(compressed, (uint *)&entry.cSize, uncompressed, entry.size, compression);
+ {
+ compress2(compressed, &destLen, uncompressed, entry.size, compression);
+ entry.cSize = (FileSize)destLen;
+ }
}
delete uncompressed;
}
last = position;
if(!first) first = position;
- if(newPosition) *newPosition = (bool)position;
+ if(newPosition) *newPosition = position;
}
else
{
if(newPosition) *newPosition = 0;
}
-
+
// archive.f.handle = archive.f;
return true;
}
};
-#endif
+#endif // !defined(ECERE_NOARCHIVE) && !defined(ECERE_VANILLA)
// Directory Description for file listing
class EARDir : struct
return read;
}
- int Write(byte * buffer, uint size, uint count)
+ int Write(const byte * buffer, uint size, uint count)
{
return 0;
}
return false;
}
- bool Puts(char * string)
+ bool Puts(const char * string)
{
return false;
}
bool result = false;
switch(mode)
{
- case start:
+ case start:
if(pos <= (int)size)
{
position = pos;
}
break;
}
- return result;
+ return result;
}
uint Tell()
return position >= size || (f && f.Eof());
}
- bool GetSize()
+ uint GetSize()
{
return size;
}
class EARFileSystem : FileSystem
{
- File ::Open(char * archive, char * name, FileOpenMode mode)
+ File ::Open(const char * archive, const char * name, FileOpenMode mode)
{
File result = null;
if(mode == read)
if(compressed)
{
if(f.Read(compressed, 1, entry.cSize) == entry.cSize)
- uncompress(uncompressed, (uint *)&entry.size, compressed, entry.cSize);
+ {
+ unsigned long destLen = entry.size;
+ uncompress(uncompressed, &destLen, compressed, entry.cSize);
+ entry.size = (FileSize)destLen;
+ }
delete compressed;
}
return result;
}
- FileAttribs ::Exists(char * archive, char * fileName)
+ FileAttribs ::Exists(const char * archive, const char * fileName)
{
uint result = 0;
EARHeader header;
return result;
}
- bool ::GetSize(char * archive, char * fileName, FileSize * size)
+ bool ::GetSize(const char * archive, const char * fileName, FileSize * size)
{
bool result = false;
EARHeader header;
return result;
}
- bool ::Stats(char * archive, char * fileName, FileStats stats)
+ bool ::Stats(const char * archive, const char * fileName, FileStats stats)
{
bool result = false;
EARHeader header;
return result;
}
- void ::FixCase(char * archive, char * name)
+ void ::FixCase(const char * archive, char * name)
{
#ifdef __WIN32__
EARHeader header;
#endif
}
- bool ::Find(FileDesc file, char * archive, char * name)
+ bool ::Find(FileDesc file, const char * archive, const char * name)
{
bool result = false;
EARDir d {};
file.stats.accessed = file.stats.modified = (TimeStamp)entry.modified;
file.stats.created = (TimeStamp)entry.created;
file.stats.size = entry.size;
-
+
strcpy(file.path, d.path);
PathCat(file.path, file.name);
d.next = entry.next;
}
#if !defined(ECERE_NOARCHIVE) && !defined(ECERE_VANILLA)
- Archive ::OpenArchive(char * fileName, ArchiveOpenFlags flags)
+ Archive ::OpenArchive(const char * fileName, ArchiveOpenFlags flags)
{
Archive result = null;
EARArchive archive { writeAccess = flags.writeAccess };
archive.archiveStart = archive.f.Tell();
if(archive.f.Read(&header, sizeof(EARHeader), 1) == 1 &&
- !strncmp(header.recognition, earRecognition, sizeof(earRecognition)))
+ !memcmp(header.recognition, earRecognition, sizeof(earRecognition)))
opened = true;
if(!opened)
archive.archiveStart = archive.f.Tell();
archiveSize = archive.f.GetSize();
if(archive.f.Read(&header, sizeof(EARHeader), 1) == 1 &&
- !strncmp(header.recognition, earRecognition, sizeof(earRecognition)))
+ !memcmp(header.recognition, earRecognition, sizeof(earRecognition)))
opened = true;
}
EAR_RECOGNITION,
MDWORD(0, 1)
};
-
+
archive.f.Seek(0, end);
-
+
archive.archiveStart = archive.f.Tell();
archive.freeBlocks.Add(FreeBlock { start = archive.archiveStart + sizeof(EARHeader), end = MAXDWORD });
}
return result;
}
-#endif
- bool ::QuerySize(char * archive, FileSize * size)
+#endif // !defined(ECERE_NOARCHIVE) && !defined(ECERE_VANILLA)
+ bool ::QuerySize(const char * archive, FileSize * size)
{
bool result = false;
EARHeader header;