- adjustment to cherry-picked commit.

This commit is contained in:
Christoph Oelckers 2019-10-30 18:21:59 +01:00
parent 9b21fe0c28
commit 418ec0d829
1 changed files with 10 additions and 175 deletions

View File

@ -132,183 +132,17 @@ static void G_AddSteamPaths(TArray<FString> &searchpaths, const char *basepath)
AddSearchPath(searchpaths, path);
}
//-------------------------------------------------------------------------
//
// A bare-bones "parser" for Valve's KeyValues VDF format.
// There is no guarantee this will function properly with ill-formed files.
//
//-------------------------------------------------------------------------
static void KeyValues_SkipWhitespace(char **vdfbuf, char * const vdfbufend)
static TArray<FString>* g_searchpaths;
static void AddAnItem(const char* item)
{
while (((*vdfbuf)[0] == ' ' || (*vdfbuf)[0] == '\n' || (*vdfbuf)[0] == '\r' || (*vdfbuf)[0] == '\t' || (*vdfbuf)[0] == '\0') && *vdfbuf < vdfbufend)
(*vdfbuf)++;
// comments
if ((*vdfbuf) + 2 < vdfbufend && (*vdfbuf)[0] == '/' && (*vdfbuf)[1] == '/')
{
while ((*vdfbuf)[0] != '\n' && (*vdfbuf)[0] != '\r' && *vdfbuf < vdfbufend)
(*vdfbuf)++;
KeyValues_SkipWhitespace(vdfbuf, vdfbufend);
}
}
static void KeyValues_SkipToEndOfQuotedToken(char **vdfbuf, char * const vdfbufend)
{
(*vdfbuf)++;
while ((*vdfbuf)[0] != '\"' && (*vdfbuf)[-1] != '\\' && *vdfbuf < vdfbufend)
(*vdfbuf)++;
}
static void KeyValues_SkipToEndOfUnquotedToken(char **vdfbuf, char * const vdfbufend)
{
while ((*vdfbuf)[0] != ' ' && (*vdfbuf)[0] != '\n' && (*vdfbuf)[0] != '\r' && (*vdfbuf)[0] != '\t' && (*vdfbuf)[0] != '\0' && *vdfbuf < vdfbufend)
(*vdfbuf)++;
}
static void KeyValues_SkipNextWhatever(char **vdfbuf, char * const vdfbufend)
{
KeyValues_SkipWhitespace(vdfbuf, vdfbufend);
if (*vdfbuf == vdfbufend)
return;
if ((*vdfbuf)[0] == '{')
{
(*vdfbuf)++;
do
{
KeyValues_SkipNextWhatever(vdfbuf, vdfbufend);
}
while ((*vdfbuf)[0] != '}');
(*vdfbuf)++;
}
else if ((*vdfbuf)[0] == '\"')
KeyValues_SkipToEndOfQuotedToken(vdfbuf, vdfbufend);
else if ((*vdfbuf)[0] != '}')
KeyValues_SkipToEndOfUnquotedToken(vdfbuf, vdfbufend);
KeyValues_SkipWhitespace(vdfbuf, vdfbufend);
}
static char* KeyValues_NormalizeToken(char **vdfbuf, char * const vdfbufend)
{
char *token = *vdfbuf;
if ((*vdfbuf)[0] == '\"' && *vdfbuf < vdfbufend)
{
token++;
KeyValues_SkipToEndOfQuotedToken(vdfbuf, vdfbufend);
(*vdfbuf)[0] = '\0';
// account for escape sequences
char *writeseeker = token, *readseeker = token;
while (readseeker <= *vdfbuf)
{
if (readseeker[0] == '\\')
readseeker++;
writeseeker[0] = readseeker[0];
writeseeker++;
readseeker++;
AddSearchPath(*g_searchpaths, item);
}
return token;
}
KeyValues_SkipToEndOfUnquotedToken(vdfbuf, vdfbufend);
(*vdfbuf)[0] = '\0';
return token;
}
static void KeyValues_FindKey(char **vdfbuf, char * const vdfbufend, const char *token)
{
char *ParentKey = KeyValues_NormalizeToken(vdfbuf, vdfbufend);
if (token != NULL) // pass in NULL to find the next key instead of a specific one
while (Bstrcmp(ParentKey, token) != 0 && *vdfbuf < vdfbufend)
{
KeyValues_SkipNextWhatever(vdfbuf, vdfbufend);
ParentKey = KeyValues_NormalizeToken(vdfbuf, vdfbufend);
}
KeyValues_SkipWhitespace(vdfbuf, vdfbufend);
}
static int32_t KeyValues_FindParentKey(char **vdfbuf, char * const vdfbufend, const char *token)
{
KeyValues_SkipWhitespace(vdfbuf, vdfbufend);
// end of scope
if ((*vdfbuf)[0] == '}')
return 0;
KeyValues_FindKey(vdfbuf, vdfbufend, token);
// ignore the wrong type
while ((*vdfbuf)[0] != '{' && *vdfbuf < vdfbufend)
{
KeyValues_SkipNextWhatever(vdfbuf, vdfbufend);
KeyValues_FindKey(vdfbuf, vdfbufend, token);
}
if (*vdfbuf == vdfbufend)
return 0;
return 1;
}
static char* KeyValues_FindKeyValue(char **vdfbuf, char * const vdfbufend, const char *token)
{
KeyValues_SkipWhitespace(vdfbuf, vdfbufend);
// end of scope
if ((*vdfbuf)[0] == '}')
return NULL;
KeyValues_FindKey(vdfbuf, vdfbufend, token);
// ignore the wrong type
while ((*vdfbuf)[0] == '{' && *vdfbuf < vdfbufend)
{
KeyValues_SkipNextWhatever(vdfbuf, vdfbufend);
KeyValues_FindKey(vdfbuf, vdfbufend, token);
}
KeyValues_SkipWhitespace(vdfbuf, vdfbufend);
if (*vdfbuf == vdfbufend)
return NULL;
return KeyValues_NormalizeToken(vdfbuf, vdfbufend);
}
//-------------------------------------------------------------------------
//
//
//
//-------------------------------------------------------------------------
static void G_ParseSteamKeyValuesForPaths(TArray<FString> &searchpaths, const char *vdf)
{
FileReader fr;
if (fr.Open(vdf))
{
auto data = fr.Read();
if (data.Size() == 0) return;
}
auto vdfvuf = (char*)data.Data();
auto vdfbufend = vdfbuf + data.Size();
if (KeyValues_FindParentKey(&vdfbuf, vdfbufend, "LibraryFolders"))
{
char *result;
vdfbuf++;
while ((result = KeyValues_FindKeyValue(&vdfbuf, vdfbufend, NULL)) != NULL)
G_AddSteamPaths(searchpaths, result);
}
}
#endif
#if defined (__FreeBSD__) || defined(__OpenBSD__) || defined (__linux__)
#ifndef __APPLE__
//-------------------------------------------------------------------------
//
@ -325,17 +159,17 @@ void G_AddExternalSearchPaths(TArray<FString> &searchpaths)
G_AddSteamPaths(searchpaths, buf);
path.Format("%s/.steam/steam/steamapps/libraryfolders.vdf", homepath);
G_ParseSteamKeyValuesForPaths(searchpaths, buf);
g_searchpaths = &searchpaths;
G_ParseSteamKeyValuesForPaths(searchpaths, buf, AddAnItem);
}
#elif defined __APPLE__
#else
//-------------------------------------------------------------------------
//
//
//
//-------------------------------------------------------------------------
void G_AddExternalSearchPaths(TArray<FString> &searchpaths)
{
char *applications[] = { osx_getapplicationsdir(0), osx_getapplicationsdir(1) };
@ -346,13 +180,14 @@ void G_AddExternalSearchPaths(TArray<FString> &searchpaths)
char buf[BMAX_PATH];
int32_t i;
g_searchpaths = &searchpaths;
for (i = 0; i < 2; i++)
{
path.Format("%s/Steam", support[i]);
G_AddSteamPaths(searchpaths, buf);
path.Format("%s/Steam/steamapps/libraryfolders.vdf", support[i]);
G_ParseSteamKeyValuesForPaths(searchpaths, buf);
G_ParseSteamKeyValuesForPaths(searchpaths, buf, AddAnItem);
// Duke Nukem 3D: Atomic Edition (GOG.com)
path.Format("%s/Duke Nukem 3D.app/Contents/Resources/Duke Nukem 3D.boxer/C.harddisk", applications[i]);