added qse_canonpath()

This commit is contained in:
2011-10-14 00:49:54 +00:00
parent 624aeb41fd
commit 68537ad16a
13 changed files with 874 additions and 12 deletions

View File

@ -7,7 +7,8 @@ AM_CPPFLAGS = \
lib_LTLIBRARIES = libqsefs.la
libqsefs_la_SOURCES = \
dir.c
dir.c \
path.c
libqsefs_la_LDFLAGS = -version-info 1:0:0 -no-undefined -L../cmn -L$(libdir)
libqsefs_la_LIBADD = -lqsecmn

View File

@ -72,7 +72,7 @@ am__base_list = \
am__installdirs = "$(DESTDIR)$(libdir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
libqsefs_la_DEPENDENCIES =
am_libqsefs_la_OBJECTS = dir.lo
am_libqsefs_la_OBJECTS = dir.lo path.lo
libqsefs_la_OBJECTS = $(am_libqsefs_la_OBJECTS)
libqsefs_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@ -244,7 +244,8 @@ AM_CPPFLAGS = \
lib_LTLIBRARIES = libqsefs.la
libqsefs_la_SOURCES = \
dir.c
dir.c \
path.c
libqsefs_la_LDFLAGS = -version-info 1:0:0 -no-undefined -L../cmn -L$(libdir)
libqsefs_la_LIBADD = -lqsecmn
@ -323,6 +324,7 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dir.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/path.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<

View File

@ -29,24 +29,38 @@
struct qse_dir_t
{
QSE_DEFINE_COMMON_FIELDS (dir)
qse_dir_ent_t ent;
#if defined(_WIN32)
HANDLE handle;
WIN32_FIND_DATA wfd;
int no_more;
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* dir;
if (mmgr == QSE_NULL)
{
mmgr = QSE_MMGR_GETDFL();
QSE_ASSERTX (mmgr != QSE_NULL,
"Set the memory manager with QSE_MMGR_SETDFL()");
if (mmgr == QSE_NULL) return QSE_NULL;
}
dir = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(*dir));
if (dir == QSE_NULL) return QSE_NULL;
@ -59,13 +73,36 @@ qse_dir_t* qse_dir_open (
return dir;
}
void qse_dir_close (qse_dir_t* dir)
{
qse_dir_fini (dir);
QSE_MMGR_FREE (dir->mmgr, dir);
}
int qse_dir_init (qse_dir_t* dir, qse_mmgr_t* mmgr, const qse_char_t* name)
{
#if defined(_WIN32)
qse_char_t* dirname;
#endif
QSE_MEMSET (dir, 0, QSE_SIZEOF(*dir));
dir->mmgr = mmgr;
#if defined(_WIN32)
dir->handle = FindFirstFile (name, &dir->wfd);
if (dir->handle == INVALID_HANDLE_VALUE) return -1;
dirname = qse_strdup2 (name, QSE_T("\\*"), 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)
{
return -1;
}
return 0;
#else
return -1;
@ -82,7 +119,7 @@ void qse_dir_fini (qse_dir_t* dir)
qse_dir_ent_t* qse_dir_read (qse_dir_t* dir)
{
#if defined(_WIN32)
if (dir->no_more) return QSE_NULL;
if (dir->no_more_files) return QSE_NULL;
if (dir->wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
@ -92,7 +129,6 @@ 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;
dir->ent.size = li.QuadPart;
@ -102,7 +138,11 @@ qse_dir_ent_t* qse_dir_read (qse_dir_t* dir)
// TODO: proper management...
dir->ent.name = qse_strdup (dir->wfd.cFileName, dir->mmgr);
if (FindNextFile (dir->handle, &dir->wfd) == FALSE) dir->no_more = 1;
if (FindNextFile (dir->handle, &dir->wfd) == FALSE)
{
/*if (GetLastError() == ERROR_NO_MORE_FILES) */
dir->no_more_files = 1;
}
#endif
return &dir->ent;
@ -112,3 +152,14 @@ 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

138
qse/lib/fs/path.c Normal file
View File

@ -0,0 +1,138 @@
/*
* $Id
*
Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE.
QSE is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
QSE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
*/
#include <qse/types.h>
#include <qse/macros.h>
/*#include <qse/fs/path.h>*/
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
# define ISSEP(c) ((c) == QSE_T('/') || (c) == QSE_T('\\'))
#else
# define ISSEP(c) ((c) == QSE_T('/'))
#endif
#define ISSEPNIL(c) (ISSEP(c) || ((c) == QSE_T('\0')))
int qse_canonpath (const qse_char_t* path)
{
const qse_char_t* ptr;
qse_char_t* dst;
qse_char_t* root = QSE_NULL;
/* TODO: delete this. */
qse_char_t* buf = malloc (10000);
ptr = path;
dst = buf;
if (ISSEP(*ptr))
{
*dst++ = *ptr++;
#if defined(_WIN32)
/* handle UNC path */
if (ISSEP(*ptr))
{
*dst++ = *ptr++;
/* if it starts with \\, process host name */
while (!ISSEPNIL(*ptr)) *dst++ = *ptr++;
/* \ following the host name */
if (ISSEP(*ptr)) *dst++ = *ptr++;
}
#endif
}
root = dst;
do
{
const qse_char_t* seg;
qse_size_t len;
/* skip duplicate separators */
while (ISSEP(*ptr)) ptr++;
/* end of path reached */
if (*ptr == QSE_T('\0')) break;
seg = ptr;
while (!ISSEPNIL(*ptr)) ptr++;
len = ptr - seg;
if (len == 1 && seg[0] == QSE_T('.'))
{
/* eat up . */
}
else if (len == 2 && seg[0] == QSE_T('.') && seg[1] == QSE_T('.'))
{
/* eat up the previous segment */
/*if (!root) goto normal;*/
const qse_char_t* tmp;
tmp = dst;
if (tmp > root) tmp--;
while (tmp > root)
{
tmp--;
if (ISSEP(*tmp)) break;
}
if (root > buf)
{
/* mean that the path contains the root directory */
dst = tmp;
if (tmp == root) tmp++;
}
else
{
if (tmp == root) goto normal;
if (dst - tmp == 3 &&
tmp[0] == QSE_T('.') && tmp[1] == QSE_T('.'))
{
/* the previous segment ../ */
goto normal;
}
if (dst - tmp == 4 &&
ISSEP(tmp[0]) &&
tmp[1] == QSE_T('.') &&
tmp[2] == QSE_T('.'))
{
/* the previous segment is /../ */
goto normal;
}
dst = tmp + 1;
}
}
else
{
normal:
while (seg <= ptr) *dst++ = *seg++;
if (ISSEP(*ptr)) ptr++;
}
}
while (1);
*dst++ = QSE_T('\0');
return buf;
}