WSL/SLF GitLab Repository

Commit c02d0f1f authored by Mathias Bavay's avatar Mathias Bavay
Browse files

In order to properly import config files while supporting relative paths, it...

In order to properly import config files while supporting relative paths, it is necessary to internally expand the paths (as well as the symlinks) to check for multiple inclusions, to properly look for a file located relative to another one (instead of related to the execution directory). The IOUtils::cleanPath function has been expanded to support this kind of processing (with a flag to turn it on of off) and a few functions added (getPath, getFilename). The code for Windows has been written but not tested yet. The Posix implementation should also be tested on osx.
parent ee4045f6
......@@ -189,8 +189,8 @@ void Config::parseFile(const std::string& filename)
std::reverse(import_after.begin(), import_after.end());
while(!import_after.empty()) {
const string filename = import_after.back();
addFile(filename);
const string file_name = import_after.back();
addFile(file_name);
import_after.pop_back();
}
}
......@@ -222,17 +222,19 @@ void Config::parseLine(const unsigned int& linenr, std::vector<std::string> &imp
string key, value;
if(IOUtils::readKeyValuePair(line, "=", key, value, true)) {
if(key=="IMPORT_BEFORE") {
const std::string file_and_path = clean_import_path(value);
if(!accept_import_before)
throw IOException("Error in \""+sourcename+"\": IMPORT_BEFORE key MUST occur before any other key!", AT);
if(std::find(imported.begin(), imported.end(), value)!=imported.end())
if(std::find(imported.begin(), imported.end(), file_and_path)!=imported.end())
throw IOException("Can not import again \"" + value + "\": it has already been imported!", AT);
parseFile(value);
parseFile(file_and_path);
return;
}
if(key=="IMPORT_AFTER") {
if(std::find(imported.begin(), imported.end(), value)!=imported.end())
const std::string file_and_path = clean_import_path(value);
if(std::find(imported.begin(), imported.end(), file_and_path)!=imported.end())
throw IOException("Can not import again \"" + value + "\": it has already been imported!", AT);
import_after.push_back(value);
import_after.push_back(file_and_path);
return;
}
......@@ -287,6 +289,21 @@ std::string Config::extract_section(std::string key) const
return defaultSection;
}
std::string Config::clean_import_path(const std::string& in_path) const
{
#ifdef WIN32
const bool is_absolute = (in_path.size()>=2 && in_path[1]==':');
#else
const bool is_absolute = (in_path.size()>=1 && in_path[0]=='/');
#endif
//if this is a relative path, prefix the import path with the current path
const std::string prefix = (!is_absolute)? IOUtils::getPath(sourcename, true)+"/" : "";
const std::string path = IOUtils::getPath(prefix+in_path, true); //clean & resolve path
const std::string filename = IOUtils::getFilename(in_path);
return path + "/" + filename;
}
void Config::write(const std::string& filename) const
{
......
......@@ -279,6 +279,7 @@ class Config {
void parseFile(const std::string& filename);
void parseLine(const unsigned int& linenr, std::vector<std::string> &import_after, bool &accept_import_before, std::string &line, std::string &section);
std::string extract_section(std::string key) const;
std::string clean_import_path(const std::string& in_path) const;
std::map<std::string, std::string> properties; //Save key value pairs
std::vector<std::string> imported; //list of files already imported (to avoid circular references)
......
......@@ -122,16 +122,33 @@ void copy_file(const std::string& src, const std::string& dest)
fout.close();
}
std::string cleanPath(const std::string& in_path) {
std::string out_path(in_path);
size_t curr = out_path.find('\\', 0);
while(curr!=std::string::npos){
out_path.replace(curr, 1, "/");
curr = out_path.find('\\', curr);
std::string cleanPath(const std::string& in_path, const bool& resolve)
{
if(!resolve) { //do not resolve links, relative paths, etc
std::string out_path(in_path);
std::replace(out_path.begin(), out_path.end(), '\\', '/');
return out_path;
} else {
#ifdef WIN32
char out_buff[MAX_PATH], in_buff = in_path.c_str();
char *ptr1 = out_buff, *ptr2 = in_buff;
std::string out_path = (PathCanonicalize(ptr1,ptr2))? ptr1 : in_path;
std::replace(out_path.begin(), out_path.end(), '\\', '/');
return out_path;
#else //POSIX
std::string out_path(in_path);
std::replace(out_path.begin(), out_path.end(), '\\', '/');
char *real_path = realpath(out_path.c_str(), NULL); //POSIX
if(real_path!=NULL) {
const std::string tmp(real_path);
free(real_path);
return tmp;
} else
return out_path; //something failed in realpath, keep it as it is
#endif
}
//out_path.replace(out_path.begin(), out_path.end(), '\\', '/');
return out_path;
}
std::string getExtension(const std::string& filename)
......@@ -157,6 +174,26 @@ std::string removeExtension(const std::string& filename)
return filename.substr(0, startpos);
}
std::string getPath(const std::string& filename, const bool& resolve)
{
const std::string clean_filename = cleanPath(filename, resolve);
const size_t end_path = clean_filename.find_last_of("/");
if(end_path!=std::string::npos) {
return clean_filename.substr(0, end_path);
} else {
return cleanPath("./", resolve);
}
}
std::string getFilename(const std::string& path)
{
const size_t start_basename = path.find_last_of("/\\");
if(start_basename!=std::string::npos)
return path.substr(start_basename+1, std::string::npos);
else
return path;
}
void trim(std::string& str)
{
const std::string whitespaces(" \t\f\v\n\r");
......
......@@ -139,10 +139,12 @@ namespace IOUtils {
std::string getLogName();
/**
* @brief Replace "\" by "/" in a string so that a path string is cross plateform
* @brief Replace "\" by "/" in a string so that a path string is cross plateform, optionally resolve
* links, convert relative paths to absolute paths, etc
* @param in_path the path string to cleanup
* @param resolve resolve links, convert relative paths, etc? (default=false)
*/
std::string cleanPath(const std::string& in_path);
std::string cleanPath(const std::string& in_path, const bool& resolve=false);
/**
* @brief returns the extension part of a given filename.
......@@ -162,6 +164,21 @@ namespace IOUtils {
*/
std::string removeExtension(const std::string& filename);
/**
* @brief returns the path preceeding a given filename.
* @param filename filename to extract the path from
* @param resolve resolve links, convert relative paths, etc? (default=false)
* @return path
*/
std::string getPath(const std::string& filename, const bool& resolve=false);
/**
* @brief extract the file name from a path+filename string.
* @param path path to extract the true filename from
* @return filename
*/
std::string getFilename(const std::string& path);
/**
* @brief Removes trailing and leading whitespaces, tabs and newlines from a string.
* @param s The reference of the string to trim (in/out parameter)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment