Fixed path.normalize
This commit is contained in:
parent
59d10066e6
commit
16dded0499
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user