From 29cd838eab01ed7110f3ccb2e8c6a35c8a31dbcc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:21:29 +0200 Subject: Adding upstream version 1:0.1.9998svn3589+dfsg. Signed-off-by: Daniel Baumann --- src/lib/nt_fullpath_cached.c | 136 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/lib/nt_fullpath_cached.c (limited to 'src/lib/nt_fullpath_cached.c') diff --git a/src/lib/nt_fullpath_cached.c b/src/lib/nt_fullpath_cached.c new file mode 100644 index 0000000..3692f0d --- /dev/null +++ b/src/lib/nt_fullpath_cached.c @@ -0,0 +1,136 @@ +/* $Id: nt_fullpath_cached.c 2849 2016-08-30 14:28:46Z bird $ */ +/** @file + * fixcase - fixes the case of paths, windows specific. + */ + +/* + * Copyright (c) 2004-2010 knut st. osmundsen + * + * This file is part of kBuild. + * + * kBuild is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * kBuild is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kBuild. If not, see + * + */ + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +#include "nt_fullpath.h" + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +typedef struct NTFULLPATHENTRY +{ + /** Pointer to the next entry with the same hash table index. */ + struct NTFULLPATHENTRY *pNext; + /** The input hash. */ + unsigned uHash; + /** The input length. */ + unsigned cchInput; + /** Length of the result. */ + unsigned cchResult; + /** The result string (stored immediately after this structure). */ + const char *pszResult; + /** The input string (variable length). */ + char szInput[1]; +} NTFULLPATHENTRY; +typedef NTFULLPATHENTRY *PNTFULLPATHENTRY; + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/** Number of result in the nt_fullpath cache. */ +size_t g_cNtFullPathHashEntries = 0; +/** Number of bytes used for nt_fullpath cache result entries. */ +size_t g_cbNtFullPathHashEntries = 0; +/** Number of hash table collsioins in the nt_fullpath cache. */ +size_t g_cNtFullPathHashCollisions = 0; +/** Hash table. */ +PNTFULLPATHENTRY g_apNtFullPathHashTab[16381]; + + +/** + * A nt_fullpath frontend which caches the result of previous calls. + */ +void +nt_fullpath_cached(const char *pszPath, char *pszFull, size_t cchFull) +{ + PNTFULLPATHENTRY pEntry; + unsigned cchInput; + unsigned idx; + unsigned cchResult; + + /* We use the sdbm hash algorithm here (see kDep.c for full details). */ + unsigned const char *puch = (unsigned const char *)pszPath; + unsigned uHash = 0; + unsigned uChar; + while ((uChar = *puch++) != 0) + uHash = uChar + (uHash << 6) + (uHash << 16) - uHash; + + cchInput = (unsigned)((uintptr_t)&puch[-1] - (uintptr_t)pszPath); + + /* Do the cache lookup. */ + idx = uHash % (sizeof(g_apNtFullPathHashTab) / sizeof(g_apNtFullPathHashTab[0])); + for (pEntry = g_apNtFullPathHashTab[idx]; pEntry != NULL; pEntry = pEntry->pNext) + if ( pEntry->uHash == uHash + && pEntry->cchInput == cchInput + && memcmp(pEntry->szInput, pszPath, cchInput) == 0) + { + if (cchFull > pEntry->cchResult) + memcpy(pszFull, pEntry->pszResult, pEntry->cchResult + 1); + else + { + assert(0); + memcpy(pszFull, pEntry->pszResult, cchFull); + pszFull[cchFull - 1] = '\0'; + } + return; + } + + /* Make the call... */ + nt_fullpath(pszPath, pszFull, cchFull); + + /* ... and cache the result. */ + cchResult = (unsigned)strlen(pszFull); + pEntry = malloc(sizeof(*pEntry) + cchInput + cchResult + 1); + if (pEntry) + { + g_cbNtFullPathHashEntries += sizeof(*pEntry) + cchInput + cchResult + 1; + pEntry->cchInput = cchInput; + pEntry->cchResult = cchResult; + pEntry->pszResult = &pEntry->szInput[cchInput + 1]; + pEntry->uHash = uHash; + memcpy(pEntry->szInput, pszPath, cchInput + 1); + memcpy((char *)pEntry->pszResult, pszFull, cchResult + 1); + + pEntry->pNext = g_apNtFullPathHashTab[idx]; + if (pEntry->pNext) + g_cNtFullPathHashCollisions++; + g_apNtFullPathHashTab[idx] = pEntry; + + g_cNtFullPathHashEntries++; + } +} + -- cgit v1.2.3