Move path.normalize() to native code for performance

This commit is contained in:
Jason Perkins 2013-12-22 14:14:31 -05:00
parent 3af52fd900
commit 1bbefc56aa
5 changed files with 82 additions and 64 deletions

View File

@ -185,29 +185,6 @@
end
--
-- Remove any extraneous weirdness from a path, such as double slashes or
-- leading single dots.
--
-- @param p
-- The path to normalize.
-- @return
-- A path known weirdnesses removed.
--
function path.normalize(p)
-- trim off any leading "./" sequences
while p:startswith("./") do
p = p:sub(3)
end
-- remove any "//" sequences from path concatenation
p = p:gsub("//", "/")
return p
end
--
-- Takes a path which is relative to one location and makes it relative
-- to another location instead.

View File

@ -8,45 +8,6 @@
#include <string.h>
static void normalize(char* buffer, const char* path)
{
char* src;
char* dst;
char last;
strcpy(buffer, path);
do_translate(buffer, '/');
/* remove any duplicate slashes within the path */
src = buffer;
dst = buffer;
last = '\0';
while (*src != '\0') {
/* if I don't have consecutive slashes, keep the char */
if (*src != '/' || last != '/') {
*(dst++) = *src;
}
/* Allow double-slash at the start of the string, so absolute
* UNC paths can be expressed, but nowhere else */
if (src != buffer) {
last = (*src);
}
/* check the next one */
++src;
}
/* remove any trailing slashes */
for (--src; src > buffer && *src == '/'; --src) {
*src = '\0';
}
*dst = '\0';
}
int path_getrelative(lua_State* L)
{
int i, last, count;
@ -57,8 +18,8 @@ int path_getrelative(lua_State* L)
const char* p2 = luaL_checkstring(L, 2);
/* normalize the paths */
normalize(src, p1);
normalize(dst, p2);
do_normalize(L, src, p1);
do_normalize(L, dst, p2);
/* same directory? */
if (strcmp(src, dst) == 0) {

77
src/host/path_normalize.c Normal file
View File

@ -0,0 +1,77 @@
/**
* \file path_normalize.c
* \brief Removes any weirdness from a file system path string.
* \author Copyright (c) 2013 Jason Perkins and the Premake project
*/
#include "premake.h"
#include <string.h>
int path_normalize(lua_State* L)
{
char buffer[0x4000];
char* src;
char* dst;
char last;
const char* path = luaL_checkstring(L, 1);
strcpy(buffer, path);
src = buffer;
dst = buffer;
last = '\0';
while (*src != '\0') {
char ch = (*src);
/* make sure we're using '/' for all separators */
if (ch == '\\') {
ch = '/';
}
/* add to the result, filtering out duplicate slashes */
if (ch != '/' || last != '/') {
*(dst++) = ch;
}
/* ...except at the start of a string, for UNC paths */
if (src != buffer) {
last = (*src);
}
++src;
}
/* remove any trailing slashes */
for (--src; src > buffer && *src == '/'; --src) {
*src = '\0';
}
/* remove any leading "./" sequences */
src = buffer;
while (strncmp(src, "./", 2) == 0) {
src += 2;
}
*dst = '\0';
lua_pushstring(L, src);
return 1;
}
/* Call the scripted path.normalize(), to allow for overrides */
void do_normalize(lua_State* L, char* buffer, const char* path)
{
int top = lua_gettop(L);
lua_getglobal(L, "path");
lua_getfield(L, -1, "normalize");
lua_pushstring(L, path);
lua_call(L, 1, 1);
path = luaL_checkstring(L, -1);
strcpy(buffer, path);
lua_settop(L, top);
}

View File

@ -41,6 +41,7 @@ static const luaL_Reg path_functions[] = {
{ "getrelative", path_getrelative },
{ "isabsolute", path_isabsolute },
{ "join", path_join },
{ "normalize", path_normalize },
{ "translate", path_translate },
{ NULL, NULL }
};

View File

@ -57,6 +57,7 @@ unsigned long do_hash(const char* str, int seed);
int do_getcwd(char* buffer, size_t size);
int do_isabsolute(const char* path);
int do_isfile(const char* filename);
void do_normalize(lua_State* L, char* buffer, const char* path);
void do_translate(char* value, const char sep);
@ -65,6 +66,7 @@ int path_getabsolute(lua_State* L);
int path_getrelative(lua_State* L);
int path_isabsolute(lua_State* L);
int path_join(lua_State* L);
int path_normalize(lua_State* L);
int path_translate(lua_State* L);
int os_chdir(lua_State* L);
int os_copyfile(lua_State* L);