390 lines
7.6 KiB
C++
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;
|
|
} |