summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--includes/cdutils.h1
-rw-r--r--lib/cdutils.cpp51
-rw-r--r--lib/luacd.cpp73
3 files changed, 125 insertions, 0 deletions
diff --git a/includes/cdutils.h b/includes/cdutils.h
index 3666491..bf38473 100644
--- a/includes/cdutils.h
+++ b/includes/cdutils.h
@@ -114,6 +114,7 @@ class cdutils : public Base {
int show_dir(struct DirEntry * dir);
struct DirEntry find_dir_entry(struct DirEntry * dir, const String & name);
struct DirEntry * find_dir_entry(Byte ** buffer, struct DirEntry * dir, const String & name);
+ struct DirEntry get_next_dir_entry(struct DirEntry * dir, int * cursor, String & name);
static Uint8 from_BCD(Uint8 x);
static Uint8 to_BCD(Uint8 x);
static bool is_valid_BCD(Uint8 x);
diff --git a/lib/cdutils.cpp b/lib/cdutils.cpp
index d863927..607d42b 100644
--- a/lib/cdutils.cpp
+++ b/lib/cdutils.cpp
@@ -541,6 +541,57 @@ struct cdutils::DirEntry cdutils::find_dir_entry(struct DirEntry * dir, const St
return r;
}
+struct cdutils::DirEntry cdutils::get_next_dir_entry(struct DirEntry * dir, int * cursor, String & name) {
+ unsigned int ptr, size;
+ Uint8 * buffer;
+ struct DirEntry r = {0, 0, 0, 0, 0};
+ Uint32 Sector;
+
+ if (!(dir->Flags & 2)) {
+ return r;
+ }
+
+ size = from_LE32(dir->Size);
+ Sector = from_LE32(dir->Sector);
+
+ buffer = (Uint8 *) malloc(size);
+ read_data(buffer, size, GUESS, Sector);
+
+ dir = 0;
+
+ ptr = 0;
+ if (*cursor < size) {
+ dir = (struct DirEntry *) &(buffer[*cursor]);
+ if (!dir->R) {
+ (*cursor)++;
+ if (*cursor < size) {
+ dir = (struct DirEntry *) &(buffer[*cursor]);
+ } else {
+ dir = 0;
+ }
+ }
+ if (dir)
+ *cursor += dir->R;
+ }
+
+ if (dir && dir->R) {
+ if ((dir->N == 1) && (dir->id[0] == 0)) {
+ name = ".";
+ } else if ((dir->N == 1) && (dir->id[0] == 1)) {
+ name = "..";
+ } else {
+ name = String(dir->id, dir->N);
+ }
+
+ r = *dir;
+ } else {
+ name = "";
+ }
+
+ free(buffer);
+ return r;
+}
+
struct cdutils::DirEntry * cdutils::find_dir_entry(Byte ** bufout, struct cdutils::DirEntry * dir, const String & name) {
unsigned int ptr, size;
Byte * buffer;
diff --git a/lib/luacd.cpp b/lib/luacd.cpp
index 97dbbaf..a32ecaf 100644
--- a/lib/luacd.cpp
+++ b/lib/luacd.cpp
@@ -598,6 +598,11 @@ enum direntry_methods_t {
DIRENTRY_ISXASTR,
DIRENTRY_ISXAXA,
DIRENTRY_ISXAFORM1,
+ DIRENTRY_ITERATE,
+};
+
+enum direntry_functions_t {
+ DIRENTRY_ITERATOR = 0,
};
struct lua_functypes_t direntry_methods[] = {
@@ -610,6 +615,11 @@ struct lua_functypes_t direntry_methods[] = {
{ DIRENTRY_ISXASTR, "isxastr", 0, 0, 0 },
{ DIRENTRY_ISXAXA, "isxaxa", 0, 0, 0 },
{ DIRENTRY_ISXAFORM1, "isxaform1", 0, 0, 0 },
+ { DIRENTRY_ITERATE, "iterate", 1, 1, { BLUA_OBJECT } },
+};
+
+struct lua_functypes_t direntry_functions[] = {
+ { DIRENTRY_ITERATOR, "iterator", 2, 2, { BLUA_TABLE, BLUA_ANY } },
{ -1, 0, 0, 0, 0 }
};
@@ -624,8 +634,11 @@ class sLua_direntry : public Base {
DECLARE_METHOD(direntry, DIRENTRY_ISXASTR);
DECLARE_METHOD(direntry, DIRENTRY_ISXAXA);
DECLARE_METHOD(direntry, DIRENTRY_ISXAFORM1);
+ DECLARE_METHOD(direntry, DIRENTRY_ITERATE);
+ DECLARE_FUNCTION(direntry, DIRENTRY_ITERATOR);
private:
static int direntry_proceed(Lua * L, int n, direntry * obj, int caller);
+ static int direntry_proceed_statics(Lua * L, int n, int caller);
};
void Luadirentry::pushmembers(Lua * L) {
@@ -640,6 +653,7 @@ void Luadirentry::pushmembers(Lua * L) {
PUSH_METHOD(direntry, DIRENTRY_ISXASTR);
PUSH_METHOD(direntry, DIRENTRY_ISXAXA);
PUSH_METHOD(direntry, DIRENTRY_ISXAFORM1);
+ PUSH_METHOD(direntry, DIRENTRY_ITERATE);
}
int sLua_direntry::direntry_proceed(Lua * L, int n, direntry * dir, int caller) {
@@ -647,6 +661,7 @@ int sLua_direntry::direntry_proceed(Lua * L, int n, direntry * dir, int caller)
String index;
bool has_xa = false;
Byte * p;
+ int cursor;
s = 33 + dir->N;
if (s & 1) {
@@ -740,11 +755,69 @@ int sLua_direntry::direntry_proceed(Lua * L, int n, direntry * dir, int caller)
} else {
L->push();
}
+ break;
+ case DIRENTRY_ITERATE:
+ L->push(function_DIRENTRY_ITERATOR);
+ L->newtable();
+ L->push("direntry");
+ L->copy(1);
+ L->settable();
+ L->push("cdutil");
+ L->copy(2);
+ L->settable();
+ L->push("cursor");
+ {
+ int * cursor = (int *) L->newuser(sizeof(int));
+ *cursor = 0;
+ }
+ L->settable();
+ L->push();
+ r = 3;
+ break;
}
return r;
}
+int sLua_direntry::direntry_proceed_statics(Lua * L, int n, int caller) {
+ int r = 0;
+ cdutils::DirEntry * dir = 0, rdir;
+ cdutils * cdutil = 0;
+ int * cursor = 0;
+ String name;
+
+ switch (caller) {
+ case DIRENTRY_ITERATOR:
+ L->push("cursor");
+ L->gettable(1);
+ cursor = (int *) L->touserdata();
+ L->pop();
+ L->push("cdutil");
+ L->gettable(1);
+ cdutil = L->recast<cdutils>(3);
+ L->pop();
+ L->push("direntry");
+ L->gettable(1);
+ dir = (cdutils::DirEntry *) LuaObject::getme(L, 3);
+ L->pop();
+ rdir = cdutil->get_next_dir_entry(dir, cursor, name);
+
+ if ((rdir.R == 0) && (rdir.NExt == 0) && (rdir.Sector == 0) && (rdir.BESector == 0) && (rdir.Size == 0)) {
+ L->push();
+ L->push();
+ } else {
+ L->push(name);
+ dir = (cdutils::DirEntry *) malloc(rdir.R);
+ memcpy(dir, &rdir, rdir.R);
+ Luadirentry ldir(dir);
+ ldir.pushdestruct(L);
+ }
+ r = 2;
+ break;
+ }
+
+ return r;
+}
/***************************\
|** class direntry exports **|