migrated fs/path.c to cmn/path.c
This commit is contained in:
@ -25,11 +25,12 @@ libqsecmn_la_SOURCES = \
|
||||
main.c \
|
||||
mem.c \
|
||||
mem.h \
|
||||
misc.c \
|
||||
oht.c \
|
||||
opt.c \
|
||||
pma.c \
|
||||
path-basename.c \
|
||||
path-canon.c \
|
||||
pio.c \
|
||||
pma.c \
|
||||
rbt.c \
|
||||
rex.c \
|
||||
sio.c \
|
||||
|
@ -75,17 +75,17 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||
libqsecmn_la_DEPENDENCIES =
|
||||
am_libqsecmn_la_OBJECTS = alg-search.lo alg-sort.lo assert.lo chr.lo \
|
||||
chr-cnv.lo dll.lo env.lo gdl.lo htb.lo lda.lo fio.lo fma.lo \
|
||||
main.lo mem.lo misc.lo oht.lo opt.lo pma.lo pio.lo rbt.lo \
|
||||
rex.lo sio.lo sll.lo str-beg.lo str-cat.lo str-chr.lo \
|
||||
str-cnv.lo str-cmp.lo str-cpy.lo str-del.lo str-dup.lo \
|
||||
str-dynm.lo str-dynw.lo str-end.lo str-excl.lo str-fcpy.lo \
|
||||
str-fnmat.lo str-incl.lo str-len.lo str-pac.lo str-pbrk.lo \
|
||||
str-put.lo str-rev.lo str-rot.lo str-set.lo str-spl.lo \
|
||||
str-spn.lo str-str.lo str-subst.lo str-tok.lo str-trm.lo \
|
||||
str-word.lo time.lo tio.lo tio-get.lo tio-put.lo tre.lo \
|
||||
tre-ast.lo tre-compile.lo tre-match-backtrack.lo \
|
||||
tre-match-parallel.lo tre-parse.lo tre-stack.lo stdio.lo \
|
||||
xma.lo
|
||||
main.lo mem.lo oht.lo opt.lo path-basename.lo path-canon.lo \
|
||||
pio.lo pma.lo rbt.lo rex.lo sio.lo sll.lo str-beg.lo \
|
||||
str-cat.lo str-chr.lo str-cnv.lo str-cmp.lo str-cpy.lo \
|
||||
str-del.lo str-dup.lo str-dynm.lo str-dynw.lo str-end.lo \
|
||||
str-excl.lo str-fcpy.lo str-fnmat.lo str-incl.lo str-len.lo \
|
||||
str-pac.lo str-pbrk.lo str-put.lo str-rev.lo str-rot.lo \
|
||||
str-set.lo str-spl.lo str-spn.lo str-str.lo str-subst.lo \
|
||||
str-tok.lo str-trm.lo str-word.lo time.lo tio.lo tio-get.lo \
|
||||
tio-put.lo tre.lo tre-ast.lo tre-compile.lo \
|
||||
tre-match-backtrack.lo tre-match-parallel.lo tre-parse.lo \
|
||||
tre-stack.lo stdio.lo xma.lo
|
||||
libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS)
|
||||
libqsecmn_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
@ -291,11 +291,12 @@ libqsecmn_la_SOURCES = \
|
||||
main.c \
|
||||
mem.c \
|
||||
mem.h \
|
||||
misc.c \
|
||||
oht.c \
|
||||
opt.c \
|
||||
pma.c \
|
||||
path-basename.c \
|
||||
path-canon.c \
|
||||
pio.c \
|
||||
pma.c \
|
||||
rbt.c \
|
||||
rex.c \
|
||||
sio.c \
|
||||
@ -448,9 +449,10 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lda.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oht.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/path-basename.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/path-canon.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pio.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pma.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rbt.Plo@am__quote@
|
||||
|
@ -18,7 +18,7 @@
|
||||
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <qse/cmn/misc.h>
|
||||
#include <qse/cmn/path.h>
|
||||
|
||||
|
||||
const qse_mchar_t* qse_mbsbasename (const qse_mchar_t* path)
|
230
qse/lib/cmn/path-canon.c
Normal file
230
qse/lib/cmn/path-canon.c
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* $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/cmn/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')))
|
||||
|
||||
qse_size_t qse_canonpath (const qse_char_t* path, qse_char_t* canon)
|
||||
{
|
||||
const qse_char_t* ptr;
|
||||
qse_char_t* dst;
|
||||
qse_char_t* non_root_start;
|
||||
int has_root = 0;
|
||||
|
||||
ptr = path;
|
||||
dst = canon;
|
||||
|
||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
if (((ptr[0] >= QSE_T('A') && ptr[0] <= QSE_T('Z')) ||
|
||||
(ptr[0] >= QSE_T('a') && ptr[0] <= QSE_T('z'))) &&
|
||||
ptr[1] == QSE_T(':'))
|
||||
{
|
||||
/* handle drive letter */
|
||||
*dst++ = *ptr++; /* drive letter */
|
||||
*dst++ = *ptr++; /* colon */
|
||||
|
||||
if (ISSEP(*ptr))
|
||||
{
|
||||
*dst++ = *ptr++; /* root directory */
|
||||
has_root = 1;
|
||||
}
|
||||
}
|
||||
else if (ISSEP(*ptr))
|
||||
{
|
||||
*dst++ = *ptr++; /* root directory */
|
||||
has_root = 1;
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* handle UNC path for Windows */
|
||||
if (ISSEP(*ptr))
|
||||
{
|
||||
*dst++ = *ptr++;
|
||||
|
||||
if (ISSEPNIL(*ptr))
|
||||
{
|
||||
/* if there is another separator after \\,
|
||||
* it's not an UNC path. */
|
||||
dst--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if it starts with \\, process host name */
|
||||
do { *dst++ = *ptr++; } while (!ISSEPNIL(*ptr));
|
||||
if (ISSEP(*ptr)) *dst++ = *ptr++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if (ISSEP(*ptr))
|
||||
{
|
||||
*dst++ = *ptr++; /* root directory */
|
||||
has_root = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* non_root_start points to the beginning of the canonicalized
|
||||
* path excluding the root directory part. */
|
||||
non_root_start = dst;
|
||||
|
||||
do
|
||||
{
|
||||
const qse_char_t* seg;
|
||||
qse_size_t seglen;
|
||||
|
||||
/* skip duplicate separators */
|
||||
while (ISSEP(*ptr)) ptr++;
|
||||
|
||||
/* end of path reached */
|
||||
if (*ptr == QSE_T('\0')) break;
|
||||
|
||||
/* find the next segment */
|
||||
seg = ptr;
|
||||
while (!ISSEPNIL(*ptr)) ptr++;
|
||||
seglen = ptr - seg;
|
||||
|
||||
/* handle the segment */
|
||||
if (seglen == 1 && seg[0] == QSE_T('.'))
|
||||
{
|
||||
/* eat up . */
|
||||
}
|
||||
else if (seglen == 2 && seg[0] == QSE_T('.') && seg[1] == QSE_T('.'))
|
||||
{
|
||||
/* eat up the previous segment */
|
||||
qse_char_t* tmp;
|
||||
|
||||
tmp = dst;
|
||||
if (tmp > non_root_start)
|
||||
{
|
||||
/* there is a previous segment. */
|
||||
|
||||
tmp--; /* skip the separator just before .. */
|
||||
|
||||
/* find the beginning of the previous segment */
|
||||
while (tmp > non_root_start)
|
||||
{
|
||||
tmp--;
|
||||
if (ISSEP(*tmp))
|
||||
{
|
||||
tmp++; /* position it next to the separator */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (has_root)
|
||||
{
|
||||
/*
|
||||
* Eat up the previous segment if it exists.
|
||||
*
|
||||
* If it doesn't exist, tmp == dst so dst = tmp keeps dst
|
||||
* unchanged. If it exists, tmp != dst. so dst = tmp
|
||||
* changes dst.
|
||||
*
|
||||
* path /abc/def/..
|
||||
* ^ ^
|
||||
* seg ptr
|
||||
*
|
||||
* canon /abc/def/
|
||||
* ^ ^
|
||||
* tmp dst
|
||||
*/
|
||||
dst = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_size_t prevlen;
|
||||
|
||||
prevlen = dst - tmp;
|
||||
|
||||
if (/*tmp == non_root_start &&*/ prevlen == 0)
|
||||
{
|
||||
/* there is no previous segment */
|
||||
goto normal;
|
||||
}
|
||||
|
||||
if (prevlen == 3 && tmp[0] == QSE_T('.') && tmp[1] == QSE_T('.'))
|
||||
{
|
||||
/* nothing to eat away because the previous segment is ../
|
||||
*
|
||||
* path ../../
|
||||
* ^ ^
|
||||
* seg ptr
|
||||
*
|
||||
* canon ../
|
||||
* ^ ^
|
||||
* tmp dst
|
||||
*/
|
||||
goto normal;
|
||||
}
|
||||
|
||||
dst = tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
normal:
|
||||
while (seg < ptr) *dst++ = *seg++;
|
||||
if (ISSEP(*ptr))
|
||||
{
|
||||
/* this segment ended with a separator */
|
||||
*dst++ = *seg++; /* copy the separator */
|
||||
ptr++; /* move forward the pointer */
|
||||
}
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
|
||||
if (dst > non_root_start && ISSEP(dst[-1]) && !ISSEP(ptr[-1]))
|
||||
{
|
||||
/* if the canoncal path composed so far ends with a separator
|
||||
* and the original path didn't end with the separator, delete
|
||||
* the ending separator.
|
||||
*
|
||||
* dst > non_root_start:
|
||||
* there is at least 1 character after the root directory part.
|
||||
* ISSEP(dst[-1]):
|
||||
* the canonical path ends with a separator.
|
||||
* ISSEP(ptr[-1]):
|
||||
* the origial path ends with a separator
|
||||
*/
|
||||
dst[-1] = QSE_T('\0');
|
||||
return dst - canon - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* just null-terminate the canonical path normally */
|
||||
dst[0] = QSE_T('\0');
|
||||
return dst - canon;
|
||||
}
|
||||
}
|
||||
|
||||
qse_size_t qse_realpath (const qse_char_t* path, qse_char_t* real)
|
||||
{
|
||||
/* TODO: canonicalize path with symbolic links resolved */
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user