/**
* Copyright (c) 2018 Cornell University.
*
* Author: Ted Yin <tederminant@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _SALTICIDAE_COMMON_H
#define _SALTICIDAE_COMMON_H
#include <string>
#include <exception>
#include <cstdarg>
#include <vector>
#include <unordered_map>
#include <functional>
#include <getopt.h>
#include <event2/event.h>
namespace salticidae {
void sec2tv(double t, struct timeval &tv);
void event_add_with_timeout(struct event *ev, double timeout);
std::string trim(const std::string &s,
const std::string &space = "\t\r\n ");
std::vector<std::string> split(const std::string &s, const std::string &delim);
std::vector<std::string> trim_all(const std::vector<std::string> &ss);
class SalticidaeError: public std::exception {
std::string msg;
public:
SalticidaeError();
SalticidaeError(const std::string &fmt, ...);
operator std::string() const;
};
class Logger {
protected:
FILE *output;
bool opened;
const char *prefix;
void write(const char *tag, const char *fmt, va_list ap);
public:
Logger(const char *prefix):
output(stderr), opened(false), prefix(prefix) {}
Logger(const char *prefix, FILE *f):
output(f), opened(false), prefix(prefix) {}
Logger(const char *prefix, const char *filename):
opened(true), prefix(prefix) {
if ((output = fopen(filename, "w")) == nullptr)
throw SalticidaeError("logger cannot open file");
}
~Logger() {
if (opened) fclose(output);
}
void debug(const char *fmt, ...);
void info(const char *fmt, ...);
void warning(const char *fmt, ...);
void error(const char *fmt, ...);
};
extern Logger logger;
#ifdef SALTICIDAE_DEBUG_LOG
#define SALTICIDAE_NORMAL_LOG
#define SALTICIDAE_ENABLE_LOG_DEBUG
#endif
#ifdef SALTICIDAE_NORMAL_LOG
#define SALTICIDAE_ENABLE_LOG_INFO
#define SALTICIDAE_ENABLE_LOG_WARN
#endif
#ifdef SALTICIDAE_ENABLE_LOG_INFO
#define SALTICIDAE_LOG_INFO(...) salticidae::logger.info(__VA_ARGS__)
#else
#define SALTICIDAE_LOG_INFO(...) ((void)0)
#endif
#ifdef SALTICIDAE_ENABLE_LOG_DEBUG
#define SALTICIDAE_LOG_DEBUG(...) salticidae::logger.debug(__VA_ARGS__)
#else
#define SALTICIDAE_LOG_DEBUG(...) ((void)0)
#endif
#ifdef SALTICIDAE_ENABLE_LOG_WARN
#define SALTICIDAE_LOG_WARN(...) salticidae::logger.warning(__VA_ARGS__)
#else
#define SALTICIDAE_LOG_WARN(...) ((void)0)
#endif
#define SALTICIDAE_LOG_ERROR(...) salticidae::logger.error(__VA_ARGS__)
class ElapsedTime {
struct timeval t0;
clock_t cpu_t0;
public:
double elapsed_sec;
double cpu_elapsed_sec;
void start();
void stop(bool show_info = false);
};
class Config {
public:
enum Action {
SWITCH_ON,
SET_VAL,
APPEND
};
class OptVal {
public:
virtual void switch_on() {
throw SalticidaeError("undefined OptVal behavior: set_val");
}
virtual void set_val(const std::string &) {
throw SalticidaeError("undefined OptVal behavior: set_val");
}
virtual void append(const std::string &) {
throw SalticidaeError("undefined OptVal behavior: append");
}
virtual ~OptVal() = default;
};
class OptValFlag: public OptVal {
bool val;
public:
OptValFlag() = default;
OptValFlag(bool val): val(val) {}
void switch_on() override { val = true; }
bool &get() { return val; }
};
class OptValStr: public OptVal {
std::string val;
public:
OptValStr() = default;
OptValStr(const std::string &val): val(val) {}
void set_val(const std::string &strval) override {
val = strval;
}
std::string &get() { return val; }
};
class OptValInt: public OptVal {
int val;
public:
OptValInt() = default;
OptValInt(int val): val(val) {}
void set_val(const std::string &strval) override {
size_t idx;
try {
val = stoi(strval, &idx);
} catch (std::invalid_argument &) {
throw SalticidaeError("invalid integer");
}
}
int &get