Re: [AD] path and fshooks

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


Thomas Fjellstrom wrote:
This is the kind of thing I really wanted to do, but I thought people would frown on the OO Qt like interface I was starting to build, so I left some of the nicer things out.


That's the wrong mindset - the nicer the A5 API the better for everyone :)


I vote a resounding yes for all of those changes.


I also added a new function:

al_path_create_dir

Maybe it should be internal instead, but I needed it a few times to make the other changes so it seemed quite useful.

I also included a quick example program which re-implements the "ls" command from bash.

It doesn't matter whether this is included in 4.9.9 or not - in current SVN the affected functions don't seem to be used by any examples/tests, so they are untested either way :P

--
Elias Pschernig <elias@xxxxxxxxxx>
diff --git a/docs/src/refman/fshook.txt b/docs/src/refman/fshook.txt
index f968ba8..189f006 100644
--- a/docs/src/refman/fshook.txt
+++ b/docs/src/refman/fshook.txt
@@ -179,12 +179,9 @@ Returns NULL on error.
 
 ## API: al_readdir
 
-Reads the next dir item name into 'name' buffer, up to 'size' chars.
+Reads the next dir item and returns a filesystem entry for it.
 
-Warning: this may leave the filename truncated.
-XXX and how do users know if that's the case?
-
-Returns non zero on error.
+Returns NULL on error.
 
 ## API: al_unlink_entry
 
@@ -307,14 +304,13 @@ See Also:
 
 ## API: al_get_entry_name
 
-Fills in buf up to size bytes including trailing NULL char with the entry's name
+Returns the entry's filename path. Note that the path will not be an
+absolute path if the entry wasn't created from an absolute path.
 
-Returns true on success, and false on error.
+Returns NULL on error.
 
 errno is set to indicate the error.
 
-If buf isn't large enough, errno will be set to ERANGE
-
 ## API: al_get_entry_size
 
 Returns the size, in bytes, of the given entry.
@@ -512,9 +508,9 @@ See also: [al_get_errno]
 
 ## API: al_getcwd
 
-Fill in 'buf' up to 'len' characters with the current working directory.
+Returns the path to the current working directory.
 
-Returns true on success, false on failure.
+Returns NULL on failure.
 
 errno is filled in to indicate the error.
 
diff --git a/docs/src/refman/path.txt b/docs/src/refman/path.txt
index 6a71091..78e172b 100644
--- a/docs/src/refman/path.txt
+++ b/docs/src/refman/path.txt
@@ -63,6 +63,12 @@ otherwise returns false.
 Create a path structure from a string.
 The string may be NULL for an empty path.
 
+## API: al_path_create_dir
+
+This is the same as [al_path_create], but interprets the passed string
+as a directory path. The filename component of the returned path will
+always be empty.
+
 ## API: al_path_drop_tail
 
 Drop the last directory component.
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 08b55f0..d3c84b6 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -101,6 +101,7 @@ example(ex_user_events)
 example(ex_multisample ${PRIMITIVES_LINK_WITH})
 example(ex_vsync)
 example(ex_blend_test ${PRIMITIVES_LINK_WITH})
+example(ex_dir)
 
 if(SUPPORT_D3D)
     example(ex_d3d ex_d3d.cpp d3dx9)
diff --git a/examples/ex_path_test.c b/examples/ex_path_test.c
index 84c1202..fdb9bc4 100644
--- a/examples/ex_path_test.c
+++ b/examples/ex_path_test.c
@@ -476,18 +476,18 @@ void t15(void)
 /* Test al_path_make_absolute. */
 void t16(void)
 {
-   ALLEGRO_PATH *path;
-   char cwd[PATH_MAX];
-   const char *buf;
+   ALLEGRO_PATH *path, *cwd;
+   const char *buf, *buf2;
 
    path = al_path_create("abc/def");
    CHECK(al_path_make_absolute(path));
 
-   al_getcwd(PATH_MAX, cwd);
+   cwd = al_getcwd();
    buf = al_path_to_string(path, ALLEGRO_NATIVE_PATH_SEP);
-   CHECK(0 == strncmp(buf, cwd, strlen(cwd)));
-   CHECK(0 == strcmp(buf + strlen(cwd), "abc/def") ||
-         0 == strcmp(buf + strlen(cwd), "abc\\def"));
+   buf2 = al_path_to_string(cwd, ALLEGRO_NATIVE_PATH_SEP);
+   CHECK(0 == strncmp(buf, buf2, strlen(buf2)));
+   CHECK(0 == strcmp(buf + strlen(buf2), "abc/def") ||
+         0 == strcmp(buf + strlen(buf2), "abc\\def"));
 
    al_path_free(path);
 }
diff --git a/include/allegro5/fshook.h b/include/allegro5/fshook.h
index babcb83..fd53401 100644
--- a/include/allegro5/fshook.h
+++ b/include/allegro5/fshook.h
@@ -19,7 +19,8 @@
 #ifndef ALLEGRO_FSHOOK_H
 #define ALLEGRO_FSHOOK_H
 
-#include "base.h"
+#include "allegro5/base.h"
+#include "allegro5/path.h"
 
 #ifdef ALLEGRO_HAVE_SYS_TYPES_H
    #include <sys/types.h>
@@ -156,7 +157,7 @@ AL_FUNC(ALLEGRO_FS_ENTRY*, al_mktemp, (const char *tmpl, uint32_t ulink));
 
 AL_FUNC(ALLEGRO_FS_ENTRY*, al_fopen, (const char *path, const char *mode));
 AL_FUNC(void, al_fclose, (ALLEGRO_FS_ENTRY *fp));
-AL_FUNC(bool, al_get_entry_name, (ALLEGRO_FS_ENTRY *fp, size_t, char *fn));
+AL_FUNC(ALLEGRO_PATH *, al_get_entry_name, (ALLEGRO_FS_ENTRY *fp));
 
 AL_FUNC(size_t, al_fread, (ALLEGRO_FS_ENTRY *fp, size_t size, void *ptr));
 AL_FUNC(size_t, al_fwrite, (ALLEGRO_FS_ENTRY *fp, size_t size, const void *ptr));
@@ -184,7 +185,7 @@ AL_FUNC(bool, al_is_file, (ALLEGRO_FS_ENTRY *));
 
 AL_FUNC(ALLEGRO_FS_ENTRY *, al_opendir, (const char *path));
 AL_FUNC(bool, al_closedir, (ALLEGRO_FS_ENTRY *dir));
-AL_FUNC(int32_t, al_readdir, (ALLEGRO_FS_ENTRY *dir, size_t size, char *name));
+AL_FUNC(ALLEGRO_FS_ENTRY *, al_readdir, (ALLEGRO_FS_ENTRY *dir));
 
 
 AL_FUNC(uint32_t, al_get_entry_mode_str,  (AL_CONST char *));
@@ -201,7 +202,7 @@ AL_FUNC(bool, al_is_present_str, (AL_CONST char *));
 
 AL_FUNC(bool, al_mkdir, (AL_CONST char *));
 
-AL_FUNC(bool, al_getcwd, (size_t len, char *buf));
+AL_FUNC(ALLEGRO_PATH *, al_getcwd, (void));
 AL_FUNC(bool, al_chdir, (const char *path));
 
 AL_FUNC(bool, al_add_search_path, (const char *path));
diff --git a/include/allegro5/internal/aintern_fshook.h b/include/allegro5/internal/aintern_fshook.h
index e5b3aa8..8ab72cc 100644
--- a/include/allegro5/internal/aintern_fshook.h
+++ b/include/allegro5/internal/aintern_fshook.h
@@ -34,7 +34,7 @@ struct ALLEGRO_FS_HOOK_SYS_INTERFACE {
    AL_METHOD(ALLEGRO_FS_ENTRY *, fopen,         (AL_CONST char *path, AL_CONST char *mode) );
    AL_METHOD(ALLEGRO_FS_ENTRY *, mktemp,        (AL_CONST char *t, uint32_t ulink) );
 
-   AL_METHOD(bool, getcwd, (size_t len, char *buf) );
+   AL_METHOD(ALLEGRO_PATH *, getcwd, (void) );
    AL_METHOD(bool, chdir,  (AL_CONST char *path) );
 
    AL_METHOD(bool, add_search_path,   (AL_CONST char *path) );
@@ -64,7 +64,7 @@ struct ALLEGRO_FS_HOOK_ENTRY_INTERFACE {
    AL_METHOD(bool,  open,    (ALLEGRO_FS_ENTRY *handle, AL_CONST char *mode) );
    AL_METHOD(void,  close,   (ALLEGRO_FS_ENTRY *handle) );
 
-   AL_METHOD(bool,     fname,  (ALLEGRO_FS_ENTRY *fh, size_t s, char *name) );
+   AL_METHOD(ALLEGRO_PATH *, fname,  (ALLEGRO_FS_ENTRY *fh) );
 
    AL_METHOD(void,  fclose, (ALLEGRO_FS_ENTRY *fp) );
    AL_METHOD(size_t,   fread,  (ALLEGRO_FS_ENTRY *fp, size_t size, void *ptr) );
@@ -86,7 +86,7 @@ struct ALLEGRO_FS_HOOK_ENTRY_INTERFACE {
    AL_METHOD(bool,  exists,  (ALLEGRO_FS_ENTRY *) );
    AL_METHOD(bool,  unlink,  (ALLEGRO_FS_ENTRY *) );
 
-   AL_METHOD(int32_t,  readdir,  (ALLEGRO_FS_ENTRY *dir, size_t size, char *name) );
+   AL_METHOD(ALLEGRO_FS_ENTRY *,  readdir,  (ALLEGRO_FS_ENTRY *dir) );
    AL_METHOD(bool,  closedir, (ALLEGRO_FS_ENTRY *dir) );
 };
 
@@ -101,7 +101,7 @@ extern struct ALLEGRO_FS_HOOK_SYS_INTERFACE _al_stdio_sys_fshooks;
 #define _al_fs_hook_open(handle, mode) (handle)->vtable->open(handle, mode)
 #define _al_fs_hook_close(handle)      (handle)->vtable->close(handle)
 
-#define _al_fs_hook_entry_name(fp, s, b)           (fp)->vtable->fname(fp, s, b)
+#define _al_fs_hook_entry_name(fp)                 (fp)->vtable->fname(fp)
 #define _al_fs_hook_entry_open(path, mode)         _al_sys_fshooks->fopen(path, mode)
 #define _al_fs_hook_entry_close(fp)                (fp)->vtable->fclose(fp)
 #define _al_fs_hook_entry_read(fp, size, ptr)      (fp)->vtable->fread(fp, size, ptr)
@@ -126,10 +126,10 @@ extern struct ALLEGRO_FS_HOOK_SYS_INTERFACE _al_stdio_sys_fshooks;
 
 #define _al_fs_hook_opendir(path) _al_sys_fshooks->opendir(path)
 #define _al_fs_hook_closedir(dir) (dir)->vtable->closedir(dir)
-#define _al_fs_hook_readdir(dir, size, name)  (dir)->vtable->readdir(dir, size, name)
+#define _al_fs_hook_readdir(dir)  (dir)->vtable->readdir(dir)
 
 #define _al_fs_hook_mktemp(template, ulink)     _al_sys_fshooks->mktemp(template, ulink)
-#define _al_fs_hook_getcwd(len, buf)     _al_sys_fshooks->getcwd(len, buf)
+#define _al_fs_hook_getcwd()             _al_sys_fshooks->getcwd()
 #define _al_fs_hook_chdir(path)          _al_sys_fshooks->chdir(path)
 
 #define _al_fs_hook_add_search_path(path)           _al_sys_fshooks->add_search_path(path)
diff --git a/include/allegro5/path.h b/include/allegro5/path.h
index b033cfc..828e6ef 100644
--- a/include/allegro5/path.h
+++ b/include/allegro5/path.h
@@ -15,6 +15,7 @@ AL_BEGIN_EXTERN_C
 typedef struct ALLEGRO_PATH ALLEGRO_PATH;
 
 AL_FUNC(ALLEGRO_PATH*, al_path_create, (const char *str));
+AL_FUNC(ALLEGRO_PATH*, al_path_create_dir, (const char *str));
 AL_FUNC(ALLEGRO_PATH*, al_path_clone, (const ALLEGRO_PATH *path));
 
 // FIXME: rename to, al_path_num_dir_components
diff --git a/src/fshook.c b/src/fshook.c
index 0da058b..7221e21 100644
--- a/src/fshook.c
+++ b/src/fshook.c
@@ -71,11 +71,11 @@ void al_close_entry(ALLEGRO_FS_ENTRY *handle)
 
 /* Function: al_get_entry_name
  */
-bool al_get_entry_name(ALLEGRO_FS_ENTRY *fp, size_t size, char *buf)
+ALLEGRO_PATH *al_get_entry_name(ALLEGRO_FS_ENTRY *fp)
 {
    ASSERT(fp != NULL);
 
-   return _al_fs_hook_entry_name(fp, size, buf);
+   return _al_fs_hook_entry_name(fp);
 }
 
 /* Function: al_fopen
@@ -199,13 +199,11 @@ bool al_closedir(ALLEGRO_FS_ENTRY *dir)
 
 /* Function: al_readdir
  */
-int32_t al_readdir(ALLEGRO_FS_ENTRY *dir, size_t size, char *name)
+ALLEGRO_FS_ENTRY *al_readdir(ALLEGRO_FS_ENTRY *dir)
 {
    ASSERT(dir != NULL);
-   ASSERT(size > 0);
-   ASSERT(name != NULL);
 
-   return _al_fs_hook_readdir(dir, size, name);
+   return _al_fs_hook_readdir(dir);
 }
 
 /* Function: al_get_entry_mode
@@ -299,12 +297,9 @@ ALLEGRO_FS_ENTRY *al_mktemp(const char *template, uint32_t ulink)
 
 /* Function: al_getcwd
  */
-bool al_getcwd(size_t len, char *buf)
+ALLEGRO_PATH *al_getcwd(void)
 {
-   ASSERT(buf != NULL);
-   ASSERT(len != 0);
-
-   return _al_fs_hook_getcwd(len, buf);
+   return _al_fs_hook_getcwd();
 }
 
 /* Function: al_chdir
@@ -786,6 +781,7 @@ char *al_find_resource(const char *base, const char *resource, uint32_t fm,
    char tmp[PATH_MAX];
    char base_new[256];
    const char *s;
+   bool r;
 
    ASSERT(base != NULL);
    ASSERT(resource != NULL);
@@ -815,9 +811,12 @@ char *al_find_resource(const char *base, const char *resource, uint32_t fm,
       return buffer;
    }
 
-   al_getcwd(PATH_MAX, tmp);
+   path = al_getcwd();
+   r = _al_find_resource_exists(al_path_to_string(path, '/'), "data",
+      resource, fm, buffer, len);
+   al_path_free(path);
    //printf("find_resource: getcwd\n");
-   if (_al_find_resource_exists(tmp, "data", resource, fm, buffer, len)) {
+   if (r) {
       return buffer;
    }
 
diff --git a/src/fshook_stdio.c b/src/fshook_stdio.c
index b2cf4a1..1b2f030 100644
--- a/src/fshook_stdio.c
+++ b/src/fshook_stdio.c
@@ -766,22 +766,29 @@ static bool al_fs_stdio_closedir(ALLEGRO_FS_ENTRY *fp)
    return true;
 }
 
-static int32_t al_fs_stdio_readdir(ALLEGRO_FS_ENTRY *fp, size_t size,
-   char *buf)
+static ALLEGRO_FS_ENTRY *al_fs_stdio_readdir(ALLEGRO_FS_ENTRY *fp)
 {
    ALLEGRO_FS_ENTRY_STDIO *fp_stdio = (ALLEGRO_FS_ENTRY_STDIO *) fp;
+   // FIXME: Must use readdir_r as Allegro allows file functions being
+   // called from different threads.
    struct dirent *ent = readdir(fp_stdio->hd.dir);
-   uint32_t ent_len = 0;
+   ALLEGRO_PATH *path;
+   ALLEGRO_FS_ENTRY *ret;
 
    if (!ent) {
       al_set_errno(errno);
-      return -1;
+      return NULL;
    }
 
-   ent_len = strlen(ent->d_name);
-   memcpy(buf, ent->d_name, _ALLEGRO_MIN(ent_len+1, size));
-
-   return 0;
+   /* TODO: Maybe we should keep an ALLEGRO_PATH for each entry in
+    * the first place?
+    */
+   path = al_path_create_dir(fp_stdio->found ? fp_stdio->found :
+      fp_stdio->path);
+   al_path_set_filename(path, ent->d_name);
+   ret = al_fs_stdio_create_handle(al_path_to_string(path, '/'));
+   al_path_free(path);
+   return ret;
 }
 
 static off_t al_fs_stdio_entry_size(ALLEGRO_FS_ENTRY *fp)
@@ -926,17 +933,18 @@ static ALLEGRO_FS_ENTRY *al_fs_stdio_mktemp(const char *template,
    return NULL;
 }
 
-static bool al_fs_stdio_getcwd(size_t len, char *buf)
+static ALLEGRO_PATH *al_fs_stdio_getcwd(void)
 {
-   char *cwd = getcwd(buf, len);
-   char sep[2] = { ALLEGRO_NATIVE_PATH_SEP, 0 };
+   char tmpdir[PATH_MAX];
+   char *cwd = getcwd(tmpdir, PATH_MAX);
+   size_t len;
    if (!cwd) {
       al_set_errno(errno);
-      return false;
+      return NULL;
    }
-   
-   ustrcat(buf, sep);
-   return true;
+   len = strlen(cwd);
+
+   return al_path_create_dir(tmpdir);
 }
 
 static bool al_fs_stdio_chdir(const char *path)
@@ -1154,19 +1162,13 @@ static bool al_fs_stdio_file_unlink(const char *path)
    return true;
 }
 
-static bool al_fs_stdio_fname(ALLEGRO_FS_ENTRY *fp, size_t size, char *buf)
+static ALLEGRO_PATH *al_fs_stdio_fname(ALLEGRO_FS_ENTRY *fp)
 {
    ALLEGRO_FS_ENTRY_STDIO *fp_stdio = (ALLEGRO_FS_ENTRY_STDIO *) fp;
-   uint32_t len = strlen(fp_stdio->path);
-
-   if(size < len+1) {
-      al_set_errno(ERANGE);
-      return false;
-   }
-   
-   memcpy(buf, fp_stdio->path, _ALLEGRO_MIN(len+1, size));
-
-   return true;
+   if (al_is_directory(fp))
+      return al_path_create_dir(fp_stdio->path);
+   else
+      return al_path_create(fp_stdio->path);
 }
 
 static off_t al_fs_stdio_file_size(const char *path)
diff --git a/src/path.c b/src/path.c
index 43ab9d8..9ddb07d 100644
--- a/src/path.c
+++ b/src/path.c
@@ -181,6 +181,20 @@ ALLEGRO_PATH *al_path_create(const char *str)
    return path;
 }
 
+/* Function: al_path_create_dir
+ */
+ALLEGRO_PATH *al_path_create_dir(const char *str)
+{
+   ALLEGRO_PATH *path = al_path_create(str);
+   if (al_ustr_length(path->filename)) {
+      ALLEGRO_USTR *last = path->filename;
+      path->filename = al_ustr_new("");
+      al_path_append(path, al_cstr(last));
+      al_ustr_free(last);
+   }
+   return path;
+}
+
 
 /* Function: al_path_clone
  */
@@ -563,7 +577,6 @@ bool al_path_emode(const ALLEGRO_PATH *path, uint32_t mode)
  */
 bool al_path_make_absolute(ALLEGRO_PATH *path)
 {
-   char cwd[PATH_MAX];
    ALLEGRO_PATH *cwd_path;
    int i;
 
@@ -573,11 +586,8 @@ bool al_path_make_absolute(ALLEGRO_PATH *path)
       return false;
    }
 
-   if (!al_getcwd(PATH_MAX, cwd)) {
-      return false;
-   }
-
-   cwd_path = al_path_create(cwd);
+   cwd_path = al_getcwd();
+   if (!cwd_path) return false;
 
    al_path_set_drive(path, al_path_get_drive(cwd_path));
 


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/