Files
bluflame/evoke-64k/trunk/filemon/filemon/filemon.cpp
2026-04-18 22:31:51 +02:00

390 lines
7.6 KiB
C++

#include "filemon.h"
#include <io.h>
#include <iostream>
#include <vector>
#include <Windows.h>
void TrimLeft(std::string& str, const char* chars2remove)
{
if (!str.empty())
{
std::string::size_type pos = str.find_first_not_of(chars2remove);
if (pos != std::string::npos)
str.erase(0,pos);
else
str.erase( str.begin() , str.end() ); // make empty
}
}
void TrimRight(std::string& str, const char* chars2remove)
{
if (!str.empty())
{
std::string::size_type pos = str.find_last_not_of(chars2remove);
if (pos != std::string::npos)
str.erase(pos+1);
else
str.erase( str.begin() , str.end() ); // make empty
}
}
std::string Trim(std::string& str, const char* chars2remove)
{
std::string temp = str;
TrimLeft(temp, chars2remove);
TrimRight(temp, chars2remove);
return temp;
}
struct AnyParam
{
};
struct ComboParam : AnyParam
{
ComboParam(const std::string& options)
: AnyParam()
, m_Options(options)
{
}
std::string m_Options;
};
struct RangeParam : AnyParam
{
RangeParam(const std::string& from, const std::string& to)
: AnyParam()
, m_From(from)
, m_To(to)
{
}
std::string m_From;
std::string m_To;
};
#ifndef FILEMON_ACTIVE
std::map<std::string, std::string> g_VariableTypes;
std::map<std::string, std::string> g_VariableDefaultValues;
std::map<int, std::string> g_FilesToMonitor;
std::map<std::string, void*> g_Variables;
#endif
std::map<std::string, AnyParam*> g_VariableParams;
std::map<std::string, int> g_LineNumber;
std::map<int, __time64_t> g_FileChangedDate;
char* TextFileRead(const std::string& as_FileName)
{
FILE* lh_File;
char* ls_Content_ = NULL;
size_t li_Count = 0;
if (as_FileName.empty())
{
throw "Error: No file to parse!";
}
fopen_s(&lh_File, as_FileName.c_str(), "rt");
if (lh_File == NULL)
{
std::string ls_Message = "Error: Can't open ";
ls_Message += as_FileName;
throw ls_Message.c_str();
}
fseek(lh_File, 0, SEEK_END);
li_Count = ftell(lh_File);
rewind(lh_File);
if (li_Count <= 0)
{
std::string ls_Message = "Error: File ";
ls_Message += as_FileName;
ls_Message += " was empty or returned negative file size!";
throw ls_Message.c_str();
}
ls_Content_ = new char[li_Count + 1];
li_Count = fread_s(ls_Content_, li_Count + 1, sizeof(char), li_Count, lh_File);
ls_Content_[li_Count] = 0;
fclose(lh_File);
return ls_Content_;
}
/*
Macros:
ANY(type) name = value;
RANGE(type, from, to) name = value;
COMBO(type, "value1, value2, ..., valueN") name = value;
Types:
float, int, bool
*/
void ParseLine(std::string line, int lineNumber)
{
if (line.at(0) == '#' || line.at(0) == '/')
return;
std::string string, macro, type, from, to, options, name, value;
if (line.substr(0, 3) == "ANY")
{
string = line.substr(3, line.length() - 3);
macro = "ANY";
}
else if (line.substr(0, 5) == "RANGE")
{
string = line.substr(5, line.length() - 5);
macro = "RANGE";
}
else if (line.substr(0, 5) == "COMBO")
{
string = line.substr(5, line.length() - 5);
macro = "COMBO";
}
if (macro.length() == 0)
return;
if (string.at(0) != '(')
return;
string = string.substr(1, line.length() - 1);
if (string.substr(0, 3) == "int")
{
string = string.substr(3, line.length() - 3);
type = "int";
}
else if (string.substr(0, 4) == "bool")
{
string = string.substr(4, line.length() - 4);
type = "bool";
}
else if (string.substr(0, 5) == "float")
{
string = string.substr(5, line.length() - 5);
type = "float";
}
if (type.length() == 0)
return;
if (macro == "RANGE")
{
string = Trim(string, " \t");
if (string.at(0) != ',')
return;
string = string.substr(1, line.length() - 1);
string = Trim(string, " \t");
int pos = string.find(',');
if (pos == -1)
return;
from = Trim(string.substr(0, pos), " \t");
string = Trim(string.substr(pos, line.length() - pos), " \t");
if (string.at(0) != ',')
return;
string = string.substr(1, line.length() - 1);
string = Trim(string, " \t");
pos = string.find(',');
if (pos == -1)
return;
to = Trim(string.substr(0, pos), " \t");
string = Trim(string.substr(pos, line.length() - pos), " \t");
}
else if (macro == "COMBO")
{
string = Trim(string, " \t");
if (string.at(0) != ',')
return;
string = string.substr(1, line.length() - 1);
string = Trim(string, " \t");
if (string.at(0) != '"')
return;
string = string.substr(1, line.length() - 1);
int pos = string.find('"');
if (pos == -1)
return;
options = Trim(string.substr(0, pos), " \t");
++pos;
string = Trim(string.substr(pos, line.length() - pos), " \t");
}
if (string.at(0) != ',')
return;
string = Trim(string.substr(1, line.length() - 1), " \t");
int pos = string.find(")");
if (pos == -1)
return;
name = Trim(string.substr(0, pos), " \t");
string = Trim(string.substr(pos, line.length() - pos), " \t");
if (string.at(0) != ')')
return;
string = Trim(string.substr(1, line.length() - 1), " \t");
if (string.at(0) != '=')
return;
string = Trim(string.substr(1, line.length() - 1), " \t");
pos = string.find(';');
if (pos == -1)
return;
value = Trim(string.substr(0, pos), " \t");
#ifdef FILEMON_ACTIVE
if (g_Variables.find(name) != g_Variables.end())
{
if (type == "bool")
{
*((bool*)g_Variables[name]) = (value == "true");
}
else if (type == "int")
{
sscanf_s(value.c_str(), "%d", (int*)g_Variables[name]);
}
else if (type == "float")
{
sscanf_s(value.c_str(), "%f", (float*)g_Variables[name]);
}
}
#endif
if (macro == "ANY")
{
g_VariableParams[name] = new AnyParam();
}
else if (macro == "RANGE")
{
g_VariableParams[name] = new RangeParam(from, to);
}
else if (macro == "COMBO")
{
g_VariableParams[name] = new ComboParam(options);
}
g_VariableTypes[name] = type;
g_VariableDefaultValues[name] = value;
g_LineNumber[name] = lineNumber;
}
void ParseFile(const std::string& filename)
{
char* content = TextFileRead(filename);
char* contentPtr = content;
char line[512];
int lineNumber = 1;
while (contentPtr[0] != 0)
{
int i = 0;
memset(line, 0, 512 * sizeof(char));
while (contentPtr[0] != '\n' && contentPtr[0] != '\r' && contentPtr[0] != 0)
{
line[i++] = *contentPtr++;
}
ParseLine(line, lineNumber);
++lineNumber;
while (contentPtr[0] == '\n' || contentPtr[0] == '\r')
{
++contentPtr;
}
}
}
int ParseDir(const std::string& dir)
{
for (std::map<std::string, AnyParam*>::iterator iter = g_VariableParams.begin(); iter != g_VariableParams.end(); ++iter)
delete iter->second;
g_VariableParams.clear();
g_VariableTypes.clear();
g_FilesToMonitor.clear();
g_FileChangedDate.clear();
// Create "$(Path)\*.txt" string
_finddata_t fdata;
std::string searchPath = dir;
if (searchPath.at(searchPath.length() - 1) != '\\')
searchPath += '\\';
std::string filesPath = searchPath;
searchPath += "*.txt";
long hfile = _findfirst(searchPath.c_str(), &fdata);
if (hfile == -1)
{
std::cout << "filemon: Didn't find any *.txt files in directory, exiting." << std::endl;
return 3;
}
std::vector<std::string> files;
int i = 0;
do
{
std::string fileName = fdata.name;
files.push_back(fileName);
g_FileChangedDate[i] = fdata.time_write;
g_FilesToMonitor[i] = filesPath + fileName;
ParseFile(g_FilesToMonitor[i]);
++i;
} while (_findnext(hfile, &fdata) == 0);
_findclose(hfile);
return 0;
}
unsigned long __stdcall MonitorFile(void* args)
{
int fileId = (int)args;
while (true)
{
_finddata_t fdata;
long hfile = _findfirst(g_FilesToMonitor[fileId].c_str(), &fdata);
if (hfile != -1)
{
if (fdata.time_write != g_FileChangedDate[fileId])
{
g_FileChangedDate[fileId] = fdata.time_write;
::Sleep(200);
ParseFile(g_FilesToMonitor[fileId]);
}
_findclose(hfile);
}
::Sleep(200);
}
return 0;
}