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));