#include "fastfetch.h"
#include "common/properties.h"
#include "common/io/io.h"
#include "util/mallocHelper.h"
#include <stdlib.h>
#include <ctype.h>
#ifdef _WIN32
#include "util/windows/getline.h"
#endif
bool ffParsePropLinePointer(const char** line, const char* start, FFstrbuf* buffer)
{
if(**line == '\0')
return false;
while(**line == ' ' || **line == '\t')
++(*line);
while(*start != '\0')
{
if(*start == ' ' || *start == '\t')
{
while(*start == ' ' || *start == '\t')
++start;
while(**line == ' ' || **line == '\t')
++(*line);
continue;
}
if(tolower(**line) != tolower(*start) || **line == '\0')
return false;
++(*line);
++start;
}
char valueEnd = '\n';
if(*(*line - 1) == '>')
valueEnd = '<';
while(**line == ' ' || **line == '\t')
++(*line);
if(**line == '"' || **line == '\'')
{
valueEnd = **line;
++(*line);
}
while(**line != valueEnd && **line != '\n' && **line != '\0')
{
ffStrbufAppendC(buffer, **line);
++(*line);
}
ffStrbufTrimRight(buffer, ' ');
return true;
}
bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer)
{
while(!ffParsePropLinePointer(&lines, start, buffer))
{
while(*lines != '\0' && *lines != '\n')
++lines;
if(*lines == '\0')
return false;
++lines;
}
return true;
}
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries)
{
FF_AUTO_CLOSE_FILE FILE* file = fopen(filename, "r");
if (file == NULL)
return false;
bool valueStorage[32];
bool* unsetValues = valueStorage;
if (numQueries > ARRAY_SIZE(valueStorage))
unsetValues = malloc(sizeof(bool) * numQueries);
bool allSet = true;
for (uint32_t i = 0; i < numQueries; i++)
{
unsetValues[i] = queries[i].buffer->length == 0;
if (unsetValues[i])
allSet = false;
}
if (!allSet)
{
FF_AUTO_FREE char* line = NULL;
size_t len = 0;
while (getline(&line, &len, file) != -1)
{
for(uint32_t i = 0; i < numQueries; i++)
{
if(!unsetValues[i])
continue;
uint32_t currentLength = queries[i].buffer->length;
queries[i].buffer->length = 0;
if(!ffParsePropLine(line, queries[i].start, queries[i].buffer))
queries[i].buffer->length = currentLength;
}
}
}
if(unsetValues != valueStorage)
free(unsetValues);
return true;
}
bool ffParsePropFileHomeValues(const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
{
FF_STRBUF_AUTO_DESTROY absolutePath = ffStrbufCreateF("%s/%s", instance.state.platform.homeDir.chars, relativeFile);
return ffParsePropFileValues(absolutePath.chars, numQueries, queries);
}
bool ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
{
bool foundAFile = false;
FF_LIST_FOR_EACH(FFstrbuf, dirPrefix, *list)
{
const uint32_t dirPrefixLength = dirPrefix->length;
ffStrbufAppendS(dirPrefix, relativeFile);
if(ffParsePropFileValues(dirPrefix->chars, numQueries, queries))
foundAFile = true;
ffStrbufSubstrBefore(dirPrefix, dirPrefixLength);
bool allSet = true;
for(uint32_t k = 0; k < numQueries; k++)
{
if(queries[k].buffer->length == 0)
{
allSet = false;
break;
}
}
if(allSet)
break;
}
return foundAFile;
}