Permalink
Browse files

path, refactor: rewrite path.basename/extname/dirname, more compatibl…

…e with node.js
  • Loading branch information...
xicilion committed Nov 7, 2017
1 parent bf6a561 commit eee418d9f4aa2526f40f7234c988015c1fb73fd5
Showing with 411 additions and 202 deletions.
  1. +128 −123 fibjs/include/path.h
  2. +283 −79 test/path_test.js
View
@@ -159,92 +159,59 @@ inline void resolvePath(exlib::string& strBuffer, exlib::string other)
strBuffer = p.str();
}
inline const char* split_path(const char* p)
inline const char* split_path(const char* p, int32_t len)
{
char ch;
const char* p1 = p;
const char* p2 = NULL;
if (len == 0)
return p;
if (qisascii(p[0]) && p[1] == ':') {
p += 2;
if (isPosixPathSlash(*p))
p++;
p2 = p;
} else if (isPosixPathSlash(p[0]) && isPosixPathSlash(p[1])) {
p += 2;
while (*p && !isPosixPathSlash(*p))
p++;
if (*p) {
p++;
while (*p && !isPosixPathSlash(*p))
p++;
if (*p)
p++;
}
const char* p1 = p + len - 1;
p2 = p;
}
while (*p) {
ch = *p++;
if (isPosixPathSlash(ch) && *p)
p2 = p - 1;
}
while (p1 > p && isPosixPathSlash(*p1))
p1--;
if (p2 == NULL)
p2 = p1;
if (isPosixPathSlash(*p2) && p2 == p1)
p2++;
while (p1 > p && !isPosixPathSlash(*p1))
p1--;
return p2;
return p1;
}
inline const char* split_path_win32(const char* p)
inline const char* split_path_win32(const char* p, int32_t len, bool share = false)
{
char ch;
const char* p1 = p;
const char* p2 = NULL;
const char* p1 = p + len;
if (qisascii(p[0]) && p[1] == ':') {
p += 2;
if (isWin32PathSlash(*p))
p++;
p2 = p;
} else if (isWin32PathSlash(p[0]) && isWin32PathSlash(p[1])) {
p += 2;
while (*p && !isWin32PathSlash(*p))
if (isWin32PathSlash(p[0]))
p++;
} else if (len > 3 && isWin32PathSlash(p[0]) && isWin32PathSlash(p[1])
&& !isWin32PathSlash(p[2])) {
if (*p) {
p += 3;
while (p < p1 && !isWin32PathSlash(*p))
p++;
while (*p && !isWin32PathSlash(*p))
p++;
if (p < p1) {
p++;
if (share) {
while (p < p1 && !isWin32PathSlash(*p))
p++;
if (*p)
p++;
if (p < p1)
p++;
}
}
p2 = p;
}
while (*p) {
ch = *p++;
if (isWin32PathSlash(ch) && *p)
p2 = p - 1;
}
if (p1 > p)
p1--;
if (p2 == NULL)
p2 = p1;
while (p1 > p && isWin32PathSlash(*p1))
p1--;
if (isWin32PathSlash(*p2) && p2 == p1)
p2++;
while (p1 > p && !isWin32PathSlash(*p1))
p1--;
return p2;
return p1;
}
inline void _normalize_array(std::vector<exlib::string>& a, bool removeSlash)
@@ -304,13 +271,12 @@ inline void _normalize_array(std::vector<exlib::string>& a, bool removeSlash)
}
}
inline result_t _normalize(exlib::string path, exlib::string& retVal, bool removeSlash = false)
inline void _path_array(exlib::string path, std::vector<exlib::string>& a)
{
const char* p = path.c_str();
int32_t len = (int32_t)path.length();
int32_t p1, i;
std::vector<exlib::string> a;
int32_t p1, i;
p1 = 0;
for (i = 0; i < len; i++)
@@ -319,7 +285,15 @@ inline result_t _normalize(exlib::string path, exlib::string& retVal, bool remov
p1 = i + 1;
}
a.push_back(exlib::string(p + p1, i - p1));
}
inline result_t _normalize(exlib::string path, exlib::string& retVal, bool removeSlash = false)
{
int32_t i;
std::vector<exlib::string> a;
_path_array(path, a);
_normalize_array(a, removeSlash);
retVal.clear();
@@ -332,23 +306,19 @@ inline result_t _normalize(exlib::string path, exlib::string& retVal, bool remov
return 0;
}
inline result_t _normalize_win32(exlib::string path, exlib::string& retVal, bool removeSlash = false)
inline void _path_array_win32(exlib::string path, std::vector<exlib::string>& a, char& drv_no,
exlib::string& domain, exlib::string& share)
{
const char* p = path.c_str();
int32_t len = (int32_t)path.length();
int32_t p1, i;
char drv_no = 0;
exlib::string domain;
exlib::string share;
if (qisascii(p[0]) && p[1] == ':') {
drv_no = p[0];
p += 2;
len -= 2;
}
std::vector<exlib::string> a;
p1 = 0;
for (i = 0; i < len; i++)
if (isWin32PathSlash(p[i])) {
@@ -370,7 +340,18 @@ inline result_t _normalize_win32(exlib::string path, exlib::string& retVal, bool
}
}
}
}
inline result_t _normalize_win32(exlib::string path, exlib::string& retVal, bool removeSlash = false)
{
int32_t i;
std::vector<exlib::string> a;
char drv_no = 0;
exlib::string domain;
exlib::string share;
_path_array_win32(path, a, drv_no, domain, share);
_normalize_array(a, removeSlash);
retVal.clear();
@@ -395,11 +376,10 @@ inline result_t _normalize_win32(exlib::string path, exlib::string& retVal, bool
return 0;
}
inline result_t _basename(exlib::string path, exlib::string ext,
exlib::string& retVal)
inline result_t _basename(exlib::string path, exlib::string ext, exlib::string& retVal)
{
const char* p1 = path.c_str();
const char* p2 = split_path(p1);
const char* p2 = split_path(p1, (int32_t)path.length());
const char* p3 = p1 + path.length();
int32_t extlen = (int32_t)ext.length();
@@ -409,20 +389,24 @@ inline result_t _basename(exlib::string path, exlib::string ext,
while (p3 > p2 && isPosixPathSlash(*(p3 - 1)))
p3--;
if (extlen && ((int32_t)(p3 - p2) >= extlen)
&& !qstrcmp(ext.c_str(), p3 - extlen, extlen))
p3 -= extlen;
if (extlen) {
if (p1 == p2 && extlen == path.length()
&& !qstrcmp(ext.c_str(), p3 - extlen, extlen))
p3 -= extlen;
else if ((int32_t)(p3 - p2) > extlen
&& !qstrcmp(ext.c_str(), p3 - extlen, extlen))
p3 -= extlen;
}
retVal.assign(p2, (int32_t)(p3 - p2));
return 0;
}
inline result_t _basename_win32(exlib::string path, exlib::string ext,
exlib::string& retVal)
inline result_t _basename_win32(exlib::string path, exlib::string ext, exlib::string& retVal)
{
const char* p1 = path.c_str();
const char* p2 = split_path_win32(p1);
const char* p2 = split_path_win32(p1, (int32_t)path.length());
const char* p3 = p1 + path.length();
int32_t extlen = (int32_t)ext.length();
@@ -432,9 +416,14 @@ inline result_t _basename_win32(exlib::string path, exlib::string ext,
while (p3 > p2 && isWin32PathSlash(*(p3 - 1)))
p3--;
if (extlen && ((int32_t)(p3 - p2) >= extlen)
&& !qstricmp(ext.c_str(), p3 - extlen, extlen))
p3 -= extlen;
if (extlen) {
if (p1 == p2 && extlen == path.length()
&& !qstrcmp(ext.c_str(), p3 - extlen, extlen))
p3 -= extlen;
else if ((int32_t)(p3 - p2) > extlen
&& !qstrcmp(ext.c_str(), p3 - extlen, extlen))
p3 -= extlen;
}
retVal.assign(p2, (int32_t)(p3 - p2));
@@ -443,70 +432,86 @@ inline result_t _basename_win32(exlib::string path, exlib::string ext,
inline result_t _extname(exlib::string path, exlib::string& retVal)
{
char ch;
const char* p1 = NULL;
const char* c_str = path.c_str();
if (*c_str == '.')
c_str++;
while (*c_str) {
ch = *c_str++;
if (isPosixPathSlash(ch)) {
if (*c_str == '.')
c_str++;
p1 = NULL;
} else if (ch == '.')
p1 = c_str - 1;
}
const char* p1 = path.c_str();
const char* p2 = split_path(p1, (int32_t)path.length());
const char* p3 = p1 + path.length();
const char* p4;
while (isPosixPathSlash(*p2))
p2++;
while (p3 > p2 && isPosixPathSlash(*(p3 - 1)))
p3--;
if (p3 - p2 == 2 && p2[0] == '.' && p2[1] == '.')
return 0;
if (p1)
retVal.assign(p1, (int32_t)(c_str - p1));
p4 = p3;
while (p4 > p2 + 1 && *(p4 - 1) != '.')
p4--;
if (p4 > p2 + 1)
retVal.assign(p4 - 1, (int32_t)(p3 - p4 + 1));
return 0;
}
inline result_t _extname_win32(exlib::string path, exlib::string& retVal)
{
char ch;
const char* p1 = NULL;
const char* c_str = path.c_str();
if (*c_str == '.')
c_str++;
while (*c_str) {
ch = *c_str++;
if (isWin32PathSlash(ch)) {
if (*c_str == '.')
c_str++;
p1 = NULL;
} else if (ch == '.')
p1 = c_str - 1;
}
const char* p1 = path.c_str();
const char* p2 = split_path_win32(p1, (int32_t)path.length());
const char* p3 = p1 + path.length();
const char* p4;
if (p1)
retVal.assign(p1, (int32_t)(c_str - p1));
while (isWin32PathSlash(*p2))
p2++;
while (p3 > p2 && isWin32PathSlash(*(p3 - 1)))
p3--;
if (p3 - p2 == 2 && p2[0] == '.' && p2[1] == '.')
return 0;
p4 = p3;
while (p4 > p2 + 1 && *(p4 - 1) != '.')
p4--;
if (p4 > p2 + 1)
retVal.assign(p4 - 1, (int32_t)(p3 - p4 + 1));
return 0;
}
inline result_t _dirname(exlib::string path, exlib::string& retVal)
{
const char* p1 = path.c_str();
const char* p2 = split_path(p1);
const char* p2 = split_path(p1, (int32_t)path.length());
if (p2 == p1 && !isPosixPathSlash(*p2)) {
retVal = ".";
return 0;
}
retVal.assign(p1, (int32_t)(p2 - p1));
if (retVal.empty())
retVal.assign(p2, 1);
return 0;
}
inline result_t _dirname_win32(exlib::string path, exlib::string& retVal)
{
const char* p1 = path.c_str();
const char* p2 = split_path_win32(p1);
const char* p2 = split_path_win32(p1, (int32_t)path.length(), true);
if (p2 == p1 && !isWin32PathSlash(*p2)) {
retVal = ".";
return 0;
}
retVal.assign(p1, (int32_t)(p2 - p1));
if (retVal.empty())
retVal.assign(p2, 1);
return 0;
}
Oops, something went wrong.

0 comments on commit eee418d

Please sign in to comment.