Fixed path.normalize

This commit is contained in:
StiX 2015-08-12 00:21:23 +02:00
parent 59d10066e6
commit 16dded0499
2 changed files with 115 additions and 47 deletions

View File

@ -1,30 +1,23 @@
/** /**
* \file path_normalize.c * \file path_normalize.c
* \brief Removes any weirdness from a file system path string. * \brief Removes any weirdness from a file system path string.
* \author Copyright (c) 2013 Jason Perkins and the Premake project * \author Copyright (c) 2013 Jason Perkins and the Premake project
*/ */
#include "premake.h" #include "premake.h"
#include <ctype.h>
#include <string.h> #include <string.h>
int path_normalize(lua_State* L) static void* normalize_substring(const char* str, const char* endPtr, char* writePtr) {
{ const char* const source = str;
char buffer[0x4000]; const char* const writeBegin = writePtr;
char* src; const char* ptr;
char* dst; char last = 0;
char* ptr; char ch;
char last;
const char* path = luaL_checkstring(L, 1); while (str != endPtr) {
strcpy(buffer, path); ch = (*str);
src = buffer;
dst = buffer;
last = '\0';
while (*src != '\0') {
char ch = (*src);
/* make sure we're using '/' for all separators */ /* make sure we're using '/' for all separators */
if (ch == '\\') { if (ch == '\\') {
@ -33,55 +26,108 @@ int path_normalize(lua_State* L)
/* filter out .. */ /* filter out .. */
if (ch == '.' && last == '.') { if (ch == '.' && last == '.') {
ptr = dst - 3; last = 0;
while (ptr >= buffer) {
ptr = writePtr - 3;
while (ptr >= writeBegin) {
if (ptr[0] == '/' && ptr[1] != '.' && ptr[2] != '.') { if (ptr[0] == '/' && ptr[1] != '.' && ptr[2] != '.') {
dst = ptr; writePtr -= writePtr - ptr;
/* special fix for cases, when '..' is the last chars in path i.e. d:\game\.., this should be converted into d:\,
but without this case, it will be converted into d: */
if (writePtr - 1 >= writeBegin && *(writePtr - 1) == ':' && str + 1 == endPtr) {
++writePtr;
}
break; break;
} }
--ptr; --ptr;
} }
if (ptr >= buffer) {
++src; if (ptr < writeBegin) {
continue; *(writePtr++) = ch;
} }
++str;
continue;
} }
/* filter out /./ */ /* filter out /./ */
if (ch == '/' && last == '.') { if (ch == '/' && last == '.') {
ptr = dst - 2; ptr = str - 2;
if (ptr >= buffer && ptr[0] == '/') { if (*ptr == '/') { // there is no need to check whether ptr >= source since all the leading ./ will be skipped in path_normalize
dst = ptr; if (ptr - 1 < source || *(ptr - 1) != ':') {
--writePtr;
}
++str;
continue; continue;
} }
} }
/* add to the result, filtering out duplicate slashes */ /* add to the result, filtering out duplicate slashes */
if (ch != '/' || last != '/') { if (ch != '/' || last != '/') {
*(dst++) = ch; *(writePtr++) = ch;
} }
/* ...except at the start of a string, for UNC paths */ last = ch;
if (src != buffer) { ++str;
last = (*src);
}
++src;
} }
/* remove any trailing slashes */ /* remove any trailing slashes, except those, that follow the ':', to avoid a path corruption i.e. D:\ -> D: */
for (--src; src > buffer && *src == '/'; --src) { while (*(--endPtr) == '/' && *(endPtr - 1) != ':') {
*src = '\0'; --writePtr;
} }
/* remove any leading "./" sequences */ *writePtr = *str;
src = buffer;
while (strncmp(src, "./", 2) == 0) {
src += 2;
}
*dst = '\0'; return writePtr;
lua_pushstring(L, src); }
int path_normalize(lua_State* L)
{
const char* path = luaL_checkstring(L, 1);
const char* readPtr = path;
char buffer[0x4000] = { 0 };
char* writePtr = buffer;
const char* endPtr;
// skip leading white spaces
while (*readPtr && isspace(*readPtr)) {
++readPtr;
}
endPtr = readPtr;
while (*endPtr) {
/* remove any leading "./" sequences */
while (strncmp(readPtr, "./", 2) == 0) {
readPtr += 2;
}
// find the end of sub path
while (*endPtr && !isspace(*endPtr)) {
++endPtr;
}
writePtr = normalize_substring(readPtr, endPtr, writePtr);
// skip any white spaces between sub paths
while (*endPtr && isspace(*endPtr)) {
*(writePtr++) = *(endPtr++);
}
readPtr = endPtr;
}
// skip any trailing white spaces
while (isspace(*(--endPtr))) {
--writePtr;
}
*writePtr = 0;
lua_pushstring(L, buffer);
return 1; return 1;
} }

View File

@ -427,6 +427,14 @@
test.isequal("../../../test/*.h", p) test.isequal("../../../test/*.h", p)
end end
function suite.normalize_Test5()
test.isequal("test", path.normalize("./test"))
test.isequal("d:/", path.normalize("d:/"))
test.isequal("d:/", path.normalize("d:/./"))
local p = path.normalize("d:/game/..")
test.isequal("d:/", p)
end
function suite.normalize_trailingDots1() function suite.normalize_trailingDots1()
local p = path.normalize("../game/test/..") local p = path.normalize("../game/test/..")
test.isequal("../game", p) test.isequal("../game", p)
@ -446,3 +454,17 @@
test.isequal("d:/ProjectB/bin", path.normalize("d:/ProjectA/../ProjectB/bin")) test.isequal("d:/ProjectB/bin", path.normalize("d:/ProjectA/../ProjectB/bin"))
test.isequal("/ProjectB/bin", path.normalize("/ProjectA/../ProjectB/bin")) test.isequal("/ProjectB/bin", path.normalize("/ProjectA/../ProjectB/bin"))
end end
function suite.normalize_leadingWhitespaces()
test.isequal("d:/game", path.normalize("\t\n d:/game"))
end
function suite.normalize_multPath()
test.isequal("../a/b ../c/d", path.normalize("../a/b ../c/d"))
test.isequal("d:/test ../a/b", path.normalize("d:/game/../test ../a/b"))
test.isequal("d:/game/test ../a/b", path.normalize("d:/game/./test ../a/b"))
test.isequal("d:/test ../a/b", path.normalize(" d:/game/../test ../a/b"))
test.isequal("d:/game ../a/b", path.normalize(" d:/game ../a/./b"))
test.isequal("d:/game ../a/b", path.normalize("d:/game/ ../a/b"))
test.isequal("d:/game", path.normalize("d:/game/ "))
end