commit 0bf715057339239463139b3831f73d5c9d2f66c6
parent cd91cc4be424b8c0ff76f99101126ac911aaf795
Author: Fabian Wermelinger <fabianw@mavt.ethz.ch>
Date: Mon, 3 Jul 2017 10:03:48 +0200
added -outpath option for different output path (than input)
Diffstat:
3 files changed, 209 insertions(+), 63 deletions(-)
diff --git a/apps/polaroidCamera/SceneProcessor.cpp b/apps/polaroidCamera/SceneProcessor.cpp
@@ -87,10 +87,7 @@ void SceneProcessor::process1212(const vector<char*>& scenes)
{
_load_cam(mycam, scenes[i]);
- string basename(scenes[i]);
- if (basename.find_last_of(".") != string::npos)
- basename = basename.substr(0, basename.find_last_of("."));
-
+ std::string basename = _outpath(std::string(scenes[i]));
m_photo->set_name(basename);
mycam.capture(*m_photo);
@@ -139,10 +136,7 @@ void SceneProcessor::process1122(const vector<char*>& scenes)
{
Polaroid& cam = mycams[i];
- string basename(scenes[i]);
- if (basename.find_last_of(".") != string::npos)
- basename = basename.substr(0, basename.find_last_of("."));
-
+ std::string basename = _outpath(std::string(scenes[i]));
m_photo->set_name(basename);
cam.capture(*m_photo);
diff --git a/apps/polaroidCamera/SceneProcessor.h b/apps/polaroidCamera/SceneProcessor.h
@@ -7,6 +7,9 @@
#define SCENEPROCESSOR_H_UWGYBVIW
#include <vector>
+#include <string>
+#include <sstream>
+#include <set>
#include "ArgumentParser.h"
#include "OrganizerMPI.h"
@@ -33,6 +36,43 @@ private:
m_photo = nullptr;
}
+ std::vector<std::string> _splitpath(const std::string& str, const char delim='/')
+ {
+ std::vector<std::string> result;
+ const std::set<char> delimiters{delim};
+ std::string path("");
+
+ char const* pch = str.c_str();
+ char const* start = pch;
+ for(; *pch; ++pch)
+ {
+ if (delimiters.find(*pch) != delimiters.end())
+ {
+ if (start != pch)
+ {
+ std::string subpath(start, pch);
+ path += subpath;
+ start = pch;
+ }
+ }
+ }
+ result.push_back(path);
+ result.push_back(start+1);
+ return result;
+ }
+
+ std::string _outpath(const std::string& input, const char delim='/')
+ {
+ const std::vector<std::string> splitp = _splitpath(input, delim);
+ std::ostringstream output;
+ if (m_parser.exist("outpath"))
+ output << m_parser("outpath").asString();
+ else
+ output << splitp[0];
+ output << delim << splitp[1];
+ return output.str();
+ }
+
public:
SceneProcessor(ArgumentParser& parser, OrganizerMPI& mpi) : m_parser(parser), m_mpi(mpi), m_cartridge(nullptr), m_photo(nullptr) {}
~SceneProcessor() { _dispose(); }
diff --git a/include/ArgumentParser.h b/include/ArgumentParser.h
@@ -18,6 +18,7 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
+#include <ctime>
#include <map>
#include <vector>
#include <string>
@@ -25,6 +26,7 @@
#include <sstream>
#include <iomanip>
#include <fstream>
+#include <ostream>
#include <limits>
@@ -41,6 +43,21 @@ public:
Value(string content_) : content(content_) { /*printf("%s\n",content.c_str());*/ }
+ Value(const Value& c) : content(c.content) {}
+
+ Value& operator=(const Value& rhs)
+ {
+ if (this != &rhs)
+ content = rhs.content;
+ return *this;
+ }
+ Value& operator+=(const Value& rhs)
+ {
+ content += " " + rhs.content;
+ return *this;
+ }
+ Value operator+(const Value& rhs) { return Value(content + " " + rhs.content); }
+
double asDouble(double def=0)
{
if (content == "")
@@ -82,8 +99,15 @@ public:
return content;
}
+
+ friend std::ostream& operator<<(std::ostream& lhs, const Value& rhs)
+ {
+ lhs << rhs.content;
+ return lhs;
+ }
};
+
class CommandlineParser
{
private:
@@ -94,28 +118,40 @@ private:
protected:
map<string,Value> mapArguments;
+ inline void _normalizeKey(std::string& key) const
+ {
+ if (key[0] == '-') key.erase(0,1);
+ if (key[0] == '+') key.erase(0,1);
+ }
+
+ inline bool _existKey(const std::string& key, const std::map<std::string,Value>& container) const
+ {
+ std::map<std::string,Value>::const_iterator it = container.find(key);
+ return it != container.end();
+ }
+
public:
- Value& operator()(const string arg)
+ Value& operator()(string key)
{
+ _normalizeKey(key);
if (bStrictMode)
{
- map<string,Value>::const_iterator it = mapArguments.find(arg);
-
- if (it == mapArguments.end())
+ if (!_existKey(key,mapArguments))
{
- printf("Runtime option NOT SPECIFIED! ABORTING! name: %s\n",arg.data());
+ printf("Runtime option NOT SPECIFIED! ABORTING! name: %s\n",key.data());
abort();
}
}
- if (bVerbose) printf("%s is %s\n", arg.data(), mapArguments[arg].asString().data());
- return mapArguments[arg];
+ if (bVerbose) printf("%s is %s\n", key.data(), mapArguments[key].asString().data());
+ return mapArguments[key];
}
- bool check(const string arg) const
+ inline bool check(string key) const
{
- return mapArguments.find(arg) != mapArguments.end();
+ _normalizeKey(key);
+ return _existKey(key,mapArguments);
}
CommandlineParser(const int argc, const char ** argv) : mapArguments(), iArgC(argc), vArgV(argv), bStrictMode(false), bVerbose(true)
@@ -127,7 +163,11 @@ public:
int itemCount = 0;
for (int j=i+1; j<argc; j++)
- if (argv[j][0] == '-')
+ {
+ const bool leadingDash = (argv[j][0] == '-');
+ const char c = argv[j][1];
+ const bool firstNumeric = ((c >= '0' && c <= '9') || c == 0) ? true : false;
+ if (leadingDash && !firstNumeric)
break;
else
{
@@ -137,11 +177,27 @@ public:
values += argv[j];
itemCount++;
}
+ }
if (itemCount == 0)
values = "true";
- mapArguments[argv[i]] = Value(values);
+ std::string key(argv[i]);
+ key.erase(0,1); // remove leading '-'
+ if (key[0] == '+')
+ {
+ key.erase(0,1);
+ if (!_existKey(key,mapArguments))
+ mapArguments[key] = Value(values); // skip leading white space
+ else
+ mapArguments[key] += Value(values);
+ }
+ else
+ {
+ if (!_existKey(key,mapArguments))
+ mapArguments[key] = Value(values);
+ }
+
i += itemCount;
}
@@ -210,13 +266,18 @@ class ArgumentParser: public CommandlineParser
typedef std::map<std::string, Value*> pArgMap;
typedef std::map<std::string, ArgMap* > FileMap;
- // keep a reference form option origin
+ const char commentStart;
+
+ // keep a reference from option origin
ArgMap from_commandline;
FileMap from_files;
pArgMap from_code;
+ // for runtime interaction (we keep the original map)
+ ArgMap mapRuntime;
+
// helper
- void _ignoreComments(std::ifstream& stream, const char commentChar = '#')
+ void _ignoreComments(std::istream& stream, const char commentChar)
{
stream >> std::ws;
int nextchar = stream.peek();
@@ -228,37 +289,52 @@ class ArgumentParser: public CommandlineParser
}
}
- bool _existKey(std::string& key) const
+ void _parseFile(std::ifstream& stream, ArgMap& container)
{
- const std::string og_key = key;
- bool bExist = true;
-
- // look for both possible keys (i.e. with leading "-" and without)
- ArgMap::const_iterator it = mapArguments.find(key);
- if (it == mapArguments.end())
+ // read (key value) pairs from input file, ignore comments
+ // beginning with commentStart
+ _ignoreComments(stream, commentStart);
+ while (!stream.eof())
{
- if (key[0] == '-') key = key.erase(0, 1);
- else key = "-" + key;
- it = mapArguments.find(key);
- if (it == mapArguments.end())
+ std::string line, key, val;
+ std::getline(stream, line);
+ std::istringstream lineStream(line);
+ lineStream >> key;
+ lineStream >> val;
+ _ignoreComments(lineStream, commentStart);
+ while(!lineStream.eof())
{
- key = og_key;
- bExist = false;
+ std::string multiVal;
+ lineStream >> multiVal;
+ val += (" " + multiVal);
+ _ignoreComments(lineStream, commentStart);
}
- }
- return bExist;
- }
- inline std::string _stripKey(std::string key) const
- {
- if (key[0] == '-') key = key.erase(0, 1);
- return key;
+ const Value V(val);
+ if (key[0] == '-')
+ key.erase(0,1);
+
+ if (key[0] == '+')
+ {
+ key.erase(0,1);
+ if (!_existKey(key,container)) // skip leading white space
+ container[key] = V;
+ else
+ container[key] += V;
+ }
+ else if (!_existKey(key,container))
+ container[key] = V;
+ _ignoreComments(stream, commentStart);
+ }
}
public:
- ArgumentParser(const int _argc, const char ** _argv):
- CommandlineParser(_argc, _argv) { from_commandline = mapArguments; }
+ ArgumentParser(const int _argc, const char ** _argv, const char cstart='#'):
+ CommandlineParser(_argc, _argv), commentStart(cstart)
+ {
+ from_commandline = mapArguments;
+ }
virtual ~ArgumentParser()
{
@@ -272,33 +348,69 @@ public:
ArgMap& myFMap = *(from_files[filepath]);
std::ifstream confFile(filepath.c_str());
- if (confFile.is_open())
+ if (confFile.good())
{
- // read (key value) pairs from input file, ignore comments
- // beginning with "#"
- std::string key, val;
- while (!confFile.eof())
- {
- _ignoreComments(confFile);
- confFile >> key >> val;
- if (_existKey(key)) continue;
- std::pair<string, Value> item(key, Value(val));
- mapArguments.insert(item); // add to parent container
- myFMap.insert(item); // add to private container
- }
+ _parseFile(confFile, mapArguments);
+ confFile.clear();
+ confFile.seekg(0, ios::beg);
+ _parseFile(confFile, myFMap); // we keep a reference for each separate file read
}
+ confFile.close();
}
Value& operator()(std::string key)
{
- const bool bDefaultInCode = !_existKey(key);
+ _normalizeKey(key);
+ const bool bDefaultInCode = !_existKey(key,mapArguments);
Value& retval = CommandlineParser::operator()(key);
if (bDefaultInCode) from_code[key] = &retval;
return retval;
}
- inline bool check(std::string key) const { return _existKey(key); }
- inline bool exist(std::string key) const { return _existKey(key); }
+ inline bool exist(std::string key) const { return check(key); }
+
+ void write_runtime_environment() const
+ {
+ time_t rawtime;
+ std::time(&rawtime);
+ struct tm* timeinfo = std::localtime(&rawtime);
+ char buf[256];
+ std::strftime(buf, 256, "%A, %h %d %Y, %r", timeinfo);
+
+ std::ofstream runtime("runtime_environment.conf");
+ runtime << commentStart << " RUNTIME ENVIRONMENT SETTINGS" << std::endl;
+ runtime << commentStart << " ============================" << std::endl;
+ runtime << commentStart << " " << buf << std::endl;
+ runtime << commentStart << " Use this file to set runtime parameter interactively." << std::endl;
+ runtime << commentStart << " The parameter are read every \"refreshperiod\" steps." << std::endl;
+ runtime << commentStart << " When editing this file, you may use comments and string concatenation." << std::endl;
+ runtime << commentStart << " The simulation can be terminated without killing it by setting \"exit\" to true." << std::endl;
+ runtime << commentStart << " (This will write a serialized restart state. Set \"exitsave\" to false if not desired.)" << std::endl;
+ runtime << commentStart << std::endl;
+ runtime << commentStart << " !!! WARNING !!! EDITING THIS FILE CAN POTENTIALLY CRASH YOUR SIMULATION !!! WARNING !!!" << std::endl;
+ for (typename std::map<std::string,Value>::const_iterator it = mapArguments.begin(); it != mapArguments.end(); ++it)
+ runtime << it->first << '\t' << it->second << std::endl;
+ }
+
+ void read_runtime_environment()
+ {
+ mapRuntime.clear();
+ std::ifstream runtime("runtime_environment.conf");
+ if (runtime.good())
+ _parseFile(runtime, mapRuntime);
+ runtime.close();
+ }
+
+ Value& parseRuntime(std::string key)
+ {
+ _normalizeKey(key);
+ if (!_existKey(key,mapRuntime))
+ {
+ printf("ERROR: Runtime parsing for key %s NOT FOUND!! Check your runtime_environment.conf file\n",key.data());
+ abort();
+ }
+ return mapRuntime[key];
+ }
void print_args()
{
@@ -329,7 +441,7 @@ public:
{
std::cout.width(50);
std::cout.fill('.');
- std::cout << std::left << _stripKey(it->first);
+ std::cout << std::left << it->first;
std::cout << ": " << it->second.asString() << std::endl;
}
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl;
@@ -349,7 +461,7 @@ public:
{
std::cout.width(50);
std::cout.fill('.');
- std::cout << std::left << _stripKey(it->first);
+ std::cout << std::left << it->first;
std::cout << ": " << it->second.asString() << std::endl;
}
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl;
@@ -360,13 +472,13 @@ public:
// defaults defined in code
if (!from_code.empty())
{
- std::cout << "* Defined in Code:" << std::endl;
+ std::cout << "* Defaults in Code:" << std::endl;
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl;
for(pArgMap::iterator it=from_code.begin(); it!=from_code.end(); it++)
{
std::cout.width(50);
std::cout.fill('.');
- std::cout << std::left << _stripKey(it->first);
+ std::cout << std::left << it->first;
std::cout << ": " << it->second->asString() << std::endl;
}
std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl;