added qse_stradup() and related functions
coded qse_dir_change() for win32
This commit is contained in:
@ -21,16 +21,21 @@
|
||||
#include <qse/cmn/path.h>
|
||||
|
||||
|
||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
# define ISMSEP(c) ((c) == QSE_MT('/') || (c) == QSE_MT('\\'))
|
||||
# define ISWSEP(c) ((c) == QSE_WT('/') || (c) == QSE_WT('\\'))
|
||||
#else
|
||||
# define ISMSEP(c) ((c) == QSE_MT('/'))
|
||||
# define ISWSEP(c) ((c) == QSE_WT('/'))
|
||||
#endif
|
||||
|
||||
const qse_mchar_t* qse_mbsbasename (const qse_mchar_t* path)
|
||||
{
|
||||
const qse_mchar_t* p, * last = QSE_NULL;
|
||||
|
||||
for (p = path; *p != QSE_MT('\0'); p++)
|
||||
{
|
||||
if (*p == QSE_MT('/')) last = p;
|
||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
else if (*p == QSE_MT('\\')) last = p;
|
||||
#endif
|
||||
if (ISMSEP(*p)) last = p;
|
||||
}
|
||||
|
||||
return (last == QSE_NULL)? path: (last + 1);
|
||||
@ -42,10 +47,7 @@ const qse_wchar_t* qse_wcsbasename (const qse_wchar_t* path)
|
||||
|
||||
for (p = path; *p != QSE_WT('\0'); p++)
|
||||
{
|
||||
if (*p == QSE_WT('/')) last = p;
|
||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
else if (*p == QSE_WT('\\')) last = p;
|
||||
#endif
|
||||
if (ISWSEP(*p)) last = p;
|
||||
}
|
||||
|
||||
return (last == QSE_NULL)? path: (last + 1);
|
||||
|
@ -72,6 +72,27 @@ qse_mchar_t* qse_mbsxdup2 (
|
||||
return tmp;
|
||||
}
|
||||
|
||||
qse_mchar_t* qse_mbsadup (const qse_mchar_t* str[], qse_mmgr_t* mmgr)
|
||||
{
|
||||
qse_mchar_t* buf, * ptr;
|
||||
qse_size_t i;
|
||||
qse_size_t capa = 0;
|
||||
|
||||
QSE_ASSERT (mmgr != QSE_NULL);
|
||||
|
||||
for (i = 0; str[i]; i++) capa += qse_mbslen(str[i]);
|
||||
|
||||
buf = (qse_mchar_t*) QSE_MMGR_ALLOC (mmgr, (capa+1)*QSE_SIZEOF(*buf));
|
||||
if (buf == QSE_NULL) return QSE_NULL;
|
||||
|
||||
ptr = buf;
|
||||
for (i = 0; str[i]; i++) ptr += qse_mbscpy (ptr, str[i]);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
qse_wchar_t* qse_wcsdup (const qse_wchar_t* str, qse_mmgr_t* mmgr)
|
||||
{
|
||||
qse_wchar_t* tmp;
|
||||
@ -124,3 +145,23 @@ qse_wchar_t* qse_wcsxdup2 (
|
||||
qse_wcsncpy (tmp + len1, str2, len2);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
qse_wchar_t* qse_wcsadup (const qse_wchar_t* str[], qse_mmgr_t* mmgr)
|
||||
{
|
||||
qse_wchar_t* buf, * ptr;
|
||||
qse_size_t i;
|
||||
qse_size_t capa = 0;
|
||||
|
||||
QSE_ASSERT (mmgr != QSE_NULL);
|
||||
|
||||
for (i = 0; str[i]; i++) capa += qse_wcslen(str[i]);
|
||||
|
||||
buf = (qse_wchar_t*) QSE_MMGR_ALLOC (mmgr, (capa+1)*QSE_SIZEOF(*buf));
|
||||
if (buf == QSE_NULL) return QSE_NULL;
|
||||
|
||||
ptr = buf;
|
||||
for (i = 0; str[i]; i++) ptr += qse_wcscpy (ptr, str[i]);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
217
qse/lib/fs/dir.c
217
qse/lib/fs/dir.c
@ -19,35 +19,36 @@
|
||||
*/
|
||||
|
||||
#include <qse/fs/dir.h>
|
||||
#include "../cmn/mem.h"
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/path.h>
|
||||
#include "../cmn/mem.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#elif defined(__OS2__)
|
||||
# error NOT IMPLEMENTED
|
||||
#elif defined(__DOS__)
|
||||
# error NOT IMPLEMENTED
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <dirent.h>
|
||||
#endif
|
||||
|
||||
struct qse_dir_t
|
||||
typedef struct info_t info_t;
|
||||
struct info_t
|
||||
{
|
||||
QSE_DEFINE_COMMON_FIELDS (dir)
|
||||
|
||||
qse_dir_ent_t ent;
|
||||
qse_xstr_t name;
|
||||
|
||||
#if defined(_WIN32)
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATA wfd;
|
||||
int no_more_files;
|
||||
#else
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
QSE_IMPLEMENT_COMMON_FUNCTIONS (dir)
|
||||
|
||||
int qse_dir_init (qse_dir_t* dir, qse_mmgr_t* mmgr, const qse_char_t* name);
|
||||
void qse_dir_fini (qse_dir_t* dir);
|
||||
|
||||
qse_dir_t* qse_dir_open (
|
||||
qse_mmgr_t* mmgr, qse_size_t xtnsize, const qse_char_t* name)
|
||||
qse_dir_t* qse_dir_open (qse_mmgr_t* mmgr, qse_size_t xtnsize)
|
||||
{
|
||||
qse_dir_t* dir;
|
||||
|
||||
@ -61,10 +62,10 @@ qse_dir_t* qse_dir_open (
|
||||
if (mmgr == QSE_NULL) return QSE_NULL;
|
||||
}
|
||||
|
||||
dir = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(*dir));
|
||||
dir = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(*dir) + xtnsize);
|
||||
if (dir == QSE_NULL) return QSE_NULL;
|
||||
|
||||
if (qse_dir_init (dir, mmgr, name) <= -1)
|
||||
if (qse_dir_init (dir, mmgr) <= -1)
|
||||
{
|
||||
QSE_MMGR_FREE (mmgr, dir);
|
||||
return QSE_NULL;
|
||||
@ -79,49 +80,184 @@ void qse_dir_close (qse_dir_t* dir)
|
||||
QSE_MMGR_FREE (dir->mmgr, dir);
|
||||
}
|
||||
|
||||
int qse_dir_init (qse_dir_t* dir, qse_mmgr_t* mmgr, const qse_char_t* name)
|
||||
int qse_dir_init (qse_dir_t* dir, qse_mmgr_t* mmgr)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
qse_char_t* dirname;
|
||||
#endif
|
||||
|
||||
QSE_MEMSET (dir, 0, QSE_SIZEOF(*dir));
|
||||
dir->mmgr = mmgr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qse_dir_fini (qse_dir_t* dir)
|
||||
{
|
||||
info_t* info = dir->info;
|
||||
if (info)
|
||||
{
|
||||
if (info->name.ptr)
|
||||
{
|
||||
QSE_ASSERT (info->name.len > 0);
|
||||
QSE_MMGR_FREE (dir->mmgr, info->name.ptr);
|
||||
info->name.ptr = QSE_NULL;
|
||||
info->name.len = 0;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
dirname = qse_strdup2 (name, QSE_T("\\*"), dir->mmgr);
|
||||
if (info->handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FindClose (info->handle);
|
||||
info->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
QSE_MMGR_FREE (dir->mmgr, info);
|
||||
dir->info = QSE_NULL;
|
||||
}
|
||||
|
||||
if (dir->curdir)
|
||||
{
|
||||
QSE_MMGR_FREE (dir->mmgr, dir->curdir);
|
||||
dir->curdir = QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int is_absolute (const qse_char_t* name)
|
||||
{
|
||||
if (name[0] == QSE_T('/')) return 1;
|
||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
if (name[0] == QSE_T('\\')) return 1;
|
||||
if (((name[0] >= QSE_T('A') && name[0] <= QSE_T('Z')) ||
|
||||
(name[0] >= QSE_T('a') && name[0] <= QSE_T('a'))) &&
|
||||
name[1] == QSE_T(':')) return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qse_dir_change (qse_dir_t* dir, const qse_char_t* name)
|
||||
{
|
||||
info_t* info = dir->info;
|
||||
#if defined(_WIN32)
|
||||
qse_char_t* dirname;
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATA wfd;
|
||||
const qse_char_t* tmp_name[4];
|
||||
qse_size_t idx;
|
||||
#endif
|
||||
|
||||
if (name[0] == QSE_T('\0'))
|
||||
{
|
||||
/* dir->errnum = QSE_DIR_EINVAL; */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* TODO: if name is a relative path??? combine it with the current path
|
||||
and canonicalize it to get the actual path */
|
||||
|
||||
if (info == QSE_NULL)
|
||||
{
|
||||
info = QSE_MMGR_ALLOC (dir->mmgr, QSE_SIZEOF(*info));
|
||||
if (info == QSE_NULL) return -1;
|
||||
|
||||
QSE_MEMSET (info, 0, QSE_SIZEOF(*info));
|
||||
#if defined(_WIN32)
|
||||
info->handle = INVALID_HANDLE_VALUE;
|
||||
#endif
|
||||
|
||||
dir->info = info;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
idx = 0;
|
||||
if (!is_absolute(name) && dir->curdir)
|
||||
tmp_name[idx++] = dir->curdir;
|
||||
tmp_name[idx++] = name;
|
||||
tmp_name[idx++] = QSE_T("\\ ");
|
||||
tmp_name[idx] = QSE_NULL;
|
||||
|
||||
dirname = qse_stradup (tmp_name, dir->mmgr);
|
||||
if (dirname == QSE_NULL)
|
||||
{
|
||||
/* dir->errnum = QSE_DIR_ENOMEM; */
|
||||
return -1;
|
||||
}
|
||||
dir->handle = FindFirstFile (dirname, &dir->wfd);
|
||||
QSE_MMGR_FREE (dir->mmgr, dirname);
|
||||
|
||||
if (dir->handle == INVALID_HANDLE_VALUE)
|
||||
idx = qse_canonpath (dirname, dirname);
|
||||
/* Put the asterisk after canonicalization to prevent side-effects.
|
||||
* otherwise, .\* would be transformed to * by qse_canonpath() */
|
||||
dirname[idx-1] = QSE_T('*');
|
||||
|
||||
handle = FindFirstFile (dirname, &wfd);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* dir->errnum = QSE_DIR_ESYSTEM; */
|
||||
QSE_MMGR_FREE (dir->mmgr, dirname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (info->handle != INVALID_HANDLE_VALUE)
|
||||
FindClose (info->handle);
|
||||
|
||||
QSE_MEMSET (info, 0, QSE_SIZEOF(*info));
|
||||
info->handle = handle;
|
||||
info->wfd = wfd;
|
||||
|
||||
if (dir->curdir) QSE_MMGR_FREE (dir->mmgr, dir->curdir);
|
||||
dirname[idx-1] = QSE_T('\0'); /* drop the asterisk */
|
||||
dir->curdir = dirname;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void qse_dir_fini (qse_dir_t* dir)
|
||||
static int set_entry_name (qse_dir_t* dir, const qse_char_t* name)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
FindClose (dir->handle);
|
||||
#endif
|
||||
info_t* info = dir->info;
|
||||
qse_size_t len;
|
||||
|
||||
QSE_ASSERT (info != QSE_NULL);
|
||||
|
||||
len = qse_strlen (name);
|
||||
if (len > info->name.len)
|
||||
{
|
||||
qse_char_t* tmp;
|
||||
|
||||
/* TOOD: round up len to the nearlest multiples of something (32, 64, ??)*/
|
||||
tmp = QSE_MMGR_REALLOC (
|
||||
dir->mmgr,
|
||||
info->name.ptr,
|
||||
(len + 1) * QSE_SIZEOF(*tmp)
|
||||
);
|
||||
if (tmp == QSE_NULL)
|
||||
{
|
||||
/* dir->errnum = QSE_DIR_ENOMEM; */
|
||||
return -1;
|
||||
}
|
||||
|
||||
info->name.len = len;
|
||||
info->name.ptr = tmp;
|
||||
}
|
||||
|
||||
qse_strcpy (info->name.ptr, name);
|
||||
dir->ent.name = info->name.ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
qse_dir_ent_t* qse_dir_read (qse_dir_t* dir)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
if (dir->no_more_files) return QSE_NULL;
|
||||
info_t* info = dir->info;
|
||||
if (info == QSE_NULL) return QSE_NULL;
|
||||
|
||||
if (dir->wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
#if defined(_WIN32)
|
||||
if (info->no_more_files)
|
||||
{
|
||||
/*
|
||||
dir->errnum = QSE_DIR_ENOENT;
|
||||
*/
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
if (info->wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
dir->ent.size = 0;
|
||||
dir->ent.type = QSE_DIR_ENT_DIRECTORY;
|
||||
@ -129,19 +265,18 @@ qse_dir_ent_t* qse_dir_read (qse_dir_t* dir)
|
||||
else
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
li.LowPart = dir->wfd.nFileSizeLow;
|
||||
li.HighPart = dir->wfd.nFileSizeHigh;
|
||||
li.LowPart = info->wfd.nFileSizeLow;
|
||||
li.HighPart = info->wfd.nFileSizeHigh;
|
||||
dir->ent.size = li.QuadPart;
|
||||
dir->ent.type = QSE_DIR_ENT_UNKNOWN;
|
||||
}
|
||||
|
||||
// TODO: proper management...
|
||||
dir->ent.name = qse_strdup (dir->wfd.cFileName, dir->mmgr);
|
||||
if (set_entry_name (dir, info->wfd.cFileName) <= -1) return QSE_NULL;
|
||||
|
||||
if (FindNextFile (dir->handle, &dir->wfd) == FALSE)
|
||||
if (FindNextFile (info->handle, &info->wfd) == FALSE)
|
||||
{
|
||||
/*if (GetLastError() == ERROR_NO_MORE_FILES) */
|
||||
dir->no_more_files = 1;
|
||||
info->no_more_files = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -153,13 +288,3 @@ int qse_dir_rewind (qse_dir_t* dir)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int qse_dir_change (qse_dir_t* dir, const qse_char_t* name)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
qse_strxdup (dir->current,
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user