My old project for strange attractors
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 

209 lines
4.7 KiB

#ifndef LOGGER_HPP_INCLUDED
#define LOGGER_HPP_INCLUDED
#include <cstdio>
#include <iostream>
#include <stack>
#include <map>
#include <cassert>
#include <boost/date_time/posix_time/posix_time.hpp>
extern int verbose;
#define LogDebug(s, ...) \
if ( verbose >= 3 ) printf(s, ##__VA_ARGS__);
#define LogMoreInfo(s, ...) \
if ( verbose >= 2 ) printf(s, ##__VA_ARGS__);
#define LogInfo(s, ...) \
if ( verbose >= 1 ) printf(s, ##__VA_ARGS__);
#define LogError(s, ...) \
if ( verbose >= 0 ) { printf("%s, %s(), %d: ", __FILE__, __func__, __LINE__); printf(s, ##__VA_ARGS__); }
enum LoggingLevels {
LOG_ERROR,
LOG_INFO,
LOG_VERBOSE,
LOG_DEBUG
};
/*
Imported from Astrant:
Questions/Suggestions mail nick@astrant.net
*/
struct Logger {
Logger(LoggingLevels level, std::ostream& logging_stream_, std::string prefix_ = std::string(""))
: logging_stream(&logging_stream_)
, prefix(prefix_)
, level(level)
{}
void log(std::string what){
if (verbose < level) return;
*logging_stream << get_prefix() << "(" << what << ") took place at (" << boost::posix_time::microsec_clock::local_time() << std::endl;
}
void start(std::string what){
if (verbose < level) return;
Event e;
e.start = boost::posix_time::microsec_clock::local_time();
e.name = what;
EventMap::iterator it = event_map.find(what);
if(it != event_map.end()){
*logging_stream << get_prefix() << "WARNING: Overwriting event(" << e.name << "), did you forget to call stop()?";
} else {
event_name_stack.push(what);
}
event_map.insert(it, std::make_pair(what, e));
}
void stop() {
if (verbose < level) return;
assert(!event_name_stack.empty());
stop(event_name_stack.top());
}
private:
void stop(std::string what){
EventMap::iterator it = event_map.find(what);
if(it == event_map.end()){
*logging_stream << get_prefix() << "WARNING: No such, or already stopped, event(" << what << "), did you forget to call start()?";
} else {
it->second.end = boost::posix_time::microsec_clock::local_time();
log_event(it->second);
event_map.erase(it);
}
event_name_stack.pop();
}
struct Event {
boost::posix_time::ptime start;
boost::posix_time::ptime end;
std::string name;
};
// A map containing strings -> Event, used by start() and stop()
typedef std::map<std::string, Event> EventMap;
EventMap event_map;
// A stack used by 0-parameter stop() to stop the last start()ed event.
std::stack<std::string> event_name_stack;
std::ostream* logging_stream;
std::string prefix;
void log_event(Event const& e){
*logging_stream << get_prefix() << "Event(" << e.name << ") started at (" << e.start << ") ended at (" << e.end << ") duration (" << e.end - e.start << " ms) " << std::endl;
}
std::string get_prefix() const {
if(prefix == std::string("")){
return prefix;
} else {
return prefix + ": ";
}
}
LoggingLevels level;
};
/*
My progressbar class (as seen on github)
*/
struct Progressbar {
Progressbar(LoggingLevels level, std::ostream & out, std::string prefix = "", std::string begin = "", std::string end = "")
: out(out)
, begin(begin)
, prefix(prefix)
, end(end)
, level(level)
{
if (verbose < level) return;
if (begin != "") {
out << begin << std::endl;
}
show(0, 1, ' ');
}
~Progressbar(){
if (verbose < level) return;
show(1, 1, '=');
if (end != "") {
out << "\n" << end << std::endl;
} else {
out << std::endl;
}
}
template <typename T>
void show(T const & progress, T const & max, char delim = '>', char filling = '='){
if (verbose < level) return;
out << "\r";
size_t width = 79; // default terminal size :D
width -= prefix.size();
width -= 3; // [, > and ]
if (prefix != "") {
width -= 1;
out << prefix << ' ';
}
double ratio = (double) progress / (double) max;
size_t length = width * ratio;
std::string fill(length, filling);
std::string empty(width - length, ' ');
out << '[' << fill << delim << empty << ']' << std::flush;
}
private:
std::ostream & out;
std::string begin;
std::string prefix;
std::string end;
LoggingLevels level;
};
struct ProgressIndicator : private Progressbar {
ProgressIndicator(LoggingLevels level, std::ostream & out, std::string prefix = "", std::string begin = "", std::string end = "")
: Progressbar(level, out, prefix, begin, end)
, progress(0.0)
, backwards(false)
{}
void update(double dt = 0.037){
if(!backwards){
progress += dt;
if(progress >= 1.0){
progress = 1.0;
backwards = true;
}
} else {
progress -= dt;
if(progress <= 0.0){
progress = 0.0;
backwards = false;
}
}
show(progress, 1.0, backwards ? '<' : '>', ' ');
}
private:
double progress;
bool backwards;
};
#endif // LOGGER_HPP_INCLUDED