/*
* The ManaPlus Client
* Copyright (C) 2014 The ManaPlus Developers
*
* This file is part of The ManaPlus Client.
*
* This program 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
* any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "lintmanager.h"
#include "rulebase.h"
#include <dirent.h>
#include <fstream>
#include <regex>
#include <sys/stat.h>
#include "localconsts.h"
LintManager lint;
LintManager::LintManager()
{
}
void LintManager::run(std::string path)
{
enumFiles(path);
}
void LintManager::addRule(RuleBase *const rule)
{
mRules.push_back(rule);
}
void LintManager::deleteRule(RuleBase *const rule)
{
FOR_EACH (std::vector<RuleBase*>::iterator, it, mRules)
{
if (*it == rule)
{
mRules.erase(it);
return;
}
}
}
void LintManager::enumFiles(std::string path)
{
path += "/";
struct dirent *next_file = nullptr;
DIR *const dir = opendir(path.c_str());
struct stat s;
std::vector<std::string> dirs;
while ((next_file = readdir(dir)))
{
const std::string file = next_file->d_name;
if (file != "." && file != "..")
{
char *realPath = realpath((path + file).c_str(), nullptr);
stat(realPath, &s);
if (S_ISDIR(s.st_mode))
dirs.push_back(path + file);
else
processFile(realPath);
}
}
if (dir)
closedir(dir);
FOR_EACH (std::vector<std::string>::const_iterator, it, dirs)
enumFiles(*it);
}
void LintManager::processFile(std::string fileName)
{
// printf("file: %s\n", fileName.c_str());
mFileName = fileName;
selectRulesForFile();
if (!mSelectedRules.empty())
{
readFile();
applyRulesToFile();
}
}
void LintManager::applyRulesToFile()
{
FOR_EACH (std::vector<RuleBase*>::iterator, it, mSelectedRules)
{
RuleBase *const rule = *it;
int line = 0;
FOR_EACH (std::vector<std::string>::const_iterator, itStr, mFileData)
{
const std::string &str = *itStr;
rule->setLine(line);
rule->parseLine(str);
line ++;
}
}
}
void LintManager::readFile()
{
// printf("readFile: %s\n", mFileName.c_str());
std::ifstream file;
char line[3001];
mFileData.clear();
file.open(mFileName.c_str(), std::ios::in);
if (!file.is_open())
return;
while (file.getline(line, 3000))
mFileData.push_back(line);
if (file.is_open())
file.close();
}
void LintManager::selectRulesForFile()
{
// printf("selectRulesForFile: %s\n", mFileName.c_str());
mSelectedRules.clear();
FOR_EACH (std::vector<RuleBase*>::iterator, it, mRules)
{
RuleBase *const rule = *it;
if (isMatchFile(rule))
{
// printf("set file %s, for rule %s\n",
// mFileName.c_str(), rule->getName().c_str());
rule->setFile(mFileName);
rule->init();
mSelectedRules.push_back(rule);
}
}
}
bool LintManager::isMatchFile(RuleBase *const rule)
{
// printf("isMatchFile: %s\n", mFileName.c_str());
const std::set<std::string> &masks = rule->getMasks();
FOR_EACH (std::set<std::string>::const_iterator, it, masks)
{
std::regex exp(*it);
if (std::regex_match (mFileName, exp))
return true;
}
return false;
}