added qse_canonpath()
This commit is contained in:
@ -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
|
||||
|
@ -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 $@ $<
|
||||
|
@ -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
138
qse/lib/fs/path.c
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user