enhanced qse_canonpath()
This commit is contained in:
parent
f2d60b9366
commit
e31e2c41ec
@ -100,6 +100,11 @@ int qse_isdrivecurpath (
|
|||||||
* qse_printf (QSE_T("%s\n")); // prints /usr/bin/sh
|
* qse_printf (QSE_T("%s\n")); // prints /usr/bin/sh
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
|
* Note that the output is empty returning 0 if the input @a path is empty,
|
||||||
|
* whereas a single period is produced if canonicalization results in the
|
||||||
|
* current directory logically without a single period in the input @a path.
|
||||||
|
* For example, dir/.. is canonicalized to a single period.
|
||||||
|
*
|
||||||
* The caller must ensure that it is large enough to hold the resulting
|
* The caller must ensure that it is large enough to hold the resulting
|
||||||
* canonical path before calling because this function does not check the
|
* canonical path before calling because this function does not check the
|
||||||
* size of the memory buffer. Since the canonical path cannot be larger
|
* size of the memory buffer. Since the canonical path cannot be larger
|
||||||
|
@ -67,9 +67,18 @@ qse_size_t qse_canonpath (const qse_char_t* path, qse_char_t* canon)
|
|||||||
qse_char_t* dst;
|
qse_char_t* dst;
|
||||||
qse_char_t* non_root_start;
|
qse_char_t* non_root_start;
|
||||||
int has_root = 0;
|
int has_root = 0;
|
||||||
int begins_with_curdir = 0;
|
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||||
|
int is_drive = 0;
|
||||||
|
#endif
|
||||||
qse_size_t canon_len;
|
qse_size_t canon_len;
|
||||||
|
|
||||||
|
if (path[0] == QSE_T('\0'))
|
||||||
|
{
|
||||||
|
/* if the source is empty, no translation is needed */
|
||||||
|
canon[0] = QSE_T('\0');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ptr = path;
|
ptr = path;
|
||||||
dst = canon;
|
dst = canon;
|
||||||
|
|
||||||
@ -80,6 +89,7 @@ qse_size_t qse_canonpath (const qse_char_t* path, qse_char_t* canon)
|
|||||||
*dst++ = *ptr++; /* drive letter */
|
*dst++ = *ptr++; /* drive letter */
|
||||||
*dst++ = *ptr++; /* colon */
|
*dst++ = *ptr++; /* colon */
|
||||||
|
|
||||||
|
is_drive = 1;
|
||||||
if (ISSEP(*ptr))
|
if (ISSEP(*ptr))
|
||||||
{
|
{
|
||||||
*dst++ = *ptr++; /* root directory */
|
*dst++ = *ptr++; /* root directory */
|
||||||
@ -112,20 +122,12 @@ qse_size_t qse_canonpath (const qse_char_t* path, qse_char_t* canon)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (ptr[0] == QSE_T('.') && ISSEPNIL(ptr[1]))
|
|
||||||
{
|
|
||||||
begins_with_curdir = 1;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
if (ISSEP(*ptr))
|
if (ISSEP(*ptr))
|
||||||
{
|
{
|
||||||
*dst++ = *ptr++; /* root directory */
|
*dst++ = *ptr++; /* root directory */
|
||||||
has_root = 1;
|
has_root = 1;
|
||||||
}
|
}
|
||||||
else if (ptr[0] == QSE_T('.') && ISSEPNIL(ptr[1]))
|
|
||||||
{
|
|
||||||
begins_with_curdir = 1;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* non_root_start points to the beginning of the canonicalized
|
/* non_root_start points to the beginning of the canonicalized
|
||||||
@ -263,20 +265,55 @@ qse_size_t qse_canonpath (const qse_char_t* path, qse_char_t* canon)
|
|||||||
canon_len = dst - canon;
|
canon_len = dst - canon;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canon_len <= 0 && begins_with_curdir)
|
if (canon_len <= 0)
|
||||||
{
|
{
|
||||||
/* when resolving to a single dot, a trailing separator is not
|
/* when resolving to a single dot, a trailing separator is not
|
||||||
* retained though the orignal path name contains it */
|
* retained though the orignal path name contains it. */
|
||||||
dst[0] = QSE_T('.');
|
canon[0] = QSE_T('.');
|
||||||
dst[1] = QSE_T('\0');
|
canon[1] = QSE_T('\0');
|
||||||
canon_len = 1;
|
canon_len = 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* drop a traling separator if the last segment is
|
||||||
|
* double slashes */
|
||||||
|
|
||||||
|
int adj_base_len = 3;
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||||
|
if (is_drive && !has_root)
|
||||||
|
{
|
||||||
|
/* A path like A:..\\\ need some adjustment for
|
||||||
|
* finalization below. */
|
||||||
|
adj_base_len += 2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (canon_len == adj_base_len)
|
||||||
|
{
|
||||||
|
/* i don't have to retains a trailing separator
|
||||||
|
* if the last segment is double slashes because
|
||||||
|
* the double slahses indicate a directory obviously */
|
||||||
|
if (canon[canon_len-3] == QSE_T('.') &&
|
||||||
|
canon[canon_len-2] == QSE_T('.') &&
|
||||||
|
ISSEP(canon[canon_len-1]))
|
||||||
|
{
|
||||||
|
canon[--canon_len] = QSE_T('\0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (canon_len > adj_base_len)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ISSEP(canon[canon_len-4]) &&
|
||||||
|
canon[canon_len-3] == QSE_T('.') &&
|
||||||
|
canon[canon_len-2] == QSE_T('.') &&
|
||||||
|
ISSEP(canon[canon_len-1]))
|
||||||
|
{
|
||||||
|
canon[--canon_len] = QSE_T('\0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return canon_len;
|
return canon_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_size_t qse_realpath (const qse_char_t* path, qse_char_t* real)
|
|
||||||
{
|
|
||||||
/* TODO: canonicalize path with symbolic links resolved */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user