Kaynağa Gözat

Changes to CMake build system and adds additional logging functionality

Caleb Fangmeier 8 yıl önce
ebeveyn
işleme
6cc0f0d55e
6 değiştirilmiş dosya ile 140 ekleme ve 22 silme
  1. 33 0
      argparse.hpp
  2. 2 2
      container.hpp
  3. 1 1
      dataset.hpp
  4. 4 0
      filval.hpp
  5. 78 0
      log.hpp
  6. 22 19
      value.hpp

+ 33 - 0
argparse.hpp

@@ -0,0 +1,33 @@
+#ifndef argparse_hpp
+#define argparse_hpp
+#include <algorithm>
+#include <string>
+#include <vector>
+namespace filval::util{
+/// \see http://stackoverflow.com/questions/865668/how-to-parse-command-line-arguments-in-c#868894
+class ArgParser{
+    private:
+        std::vector <std::string> tokens;
+        std::string empty_string;
+    public:
+        ArgParser (int &argc, char **argv){
+            for (int i=1; i < argc; ++i)
+                this->tokens.push_back(std::string(argv[i]));
+        }
+        /// @author iain
+        const std::string& getCmdOption(const std::string &option) const{
+            std::vector<std::string>::const_iterator itr;
+            itr =  std::find(this->tokens.begin(), this->tokens.end(), option);
+            if (itr != this->tokens.end() && ++itr != this->tokens.end()){
+                return *itr;
+            }
+            return empty_string;
+        }
+        /// @author iain
+        bool cmdOptionExists(const std::string &option) const{
+            return std::find(this->tokens.begin(), this->tokens.end(), option)
+                   != this->tokens.end();
+        }
+};
+}
+#endif // argparse_hpp

+ 2 - 2
container.hpp

@@ -66,7 +66,7 @@ class ContainerVector : public Container<std::vector<T> >{
           :Container<std::vector<T> >(name, container),
            value(value){ }
         ContainerVector(const std::string& name, Value<T>* value)
-          :Container<std::vector<T> >(name, NULL),
+          :Container<std::vector<T> >(name, nullptr),
            value(value){
             this->container = new std::vector<T>();
         }
@@ -85,7 +85,7 @@ class ContainerMean : public Container<T>{
         }
     public:
         ContainerMean(const std::string& name, Value<T>* value)
-          :Container<std::vector<T> >(name, NULL),
+          :Container<std::vector<T> >(name, nullptr),
            value(value){
             this->container = new T();
         }

+ 1 - 1
dataset.hpp

@@ -39,7 +39,7 @@ class DataSet{
         }
         GenContainer* get_container(std::string container_name){
             GenContainer* c = containers[container_name];
-            if (c == NULL){
+            if (c == nullptr){
                 std::cout << "Request for container \"" << container_name << "\" failed. Doesn't exist." << std::endl;
                 exit(-1);
             }

+ 4 - 0
filval.hpp

@@ -1,7 +1,11 @@
 #ifndef filval_hpp
 #define filval_hpp
+#define FILVAL_VERSION_MAJOR @FILVAL_VERSION_MAJOR@
+#define FILVALTutorial_VERSION_MINOR @FILVAL_VERSION_MINOR@
 #include "value.hpp"
 #include "filter.hpp"
 #include "container.hpp"
 #include "dataset.hpp"
+#include "log.hpp"
+#include "argparse.hpp"
 #endif // filval_hpp

+ 78 - 0
log.hpp

@@ -0,0 +1,78 @@
+#ifndef log_hpp
+#define log_hpp
+
+#include <iostream>
+#include <fstream>
+#include <cstring>
+#include <map>
+
+namespace filval::util{
+enum LogPriority {
+    kLogEmergency = 7,   // system is unusable
+    kLogAlert     = 6,   // action must be taken immediately
+    kLogCritical  = 5,    // critical conditions
+    kLogError     = 4,     // error conditions
+    kLogWarning   = 3, // warning conditions
+    kLogNotice    = 2,  // normal, but significant, condition
+    kLogInfo      = 1,    // informational message
+    kLogDebug     = 0    // debug-level message
+};
+
+#define CRITICAL(x,y) std::clog << filval::util::LogPriority::kLogCritical << __FILE__ << "@L" << __LINE__ << " :: " << x << std::flush; exit(y)
+#define ERROR(x) std::clog << filval::util::LogPriority::kLogError << __FILE__ << "@L" << __LINE__ << " :: " << x << std::flush
+#define WARNING(x) std::clog << filval::util::LogPriority::kLogWarning << x << std::flush
+#define INFO(x) std::clog << filval::util::LogPriority::kLogInfo << x << std::flush
+#define DEBUG(x) std::clog << filval::util::LogPriority::kLogDebug << __FILE__ << "@L" << __LINE__ << " :: " << x << std::flush
+
+/**
+ * /see http://stackoverflow.com/questions/2638654/redirect-c-stdclog-to-syslog-on-unix
+ */
+std::ostream& operator<< (std::ostream& os, const LogPriority& log_priority);
+
+class Log : public std::basic_streambuf<char, std::char_traits<char> > {
+private:
+    std::string buffer_;
+    std::ofstream logfile;
+    LogPriority priority_curr;
+    LogPriority priority_set;
+    std::map<LogPriority,std::string> name_map = {{kLogEmergency, "EMERGENCY"},
+                                                  {kLogAlert,     "ALERT"},
+                                                  {kLogCritical,  "CRITICAL"},
+                                                  {kLogError,     "ERROR"},
+                                                  {kLogWarning,   "WARNING"},
+                                                  {kLogNotice,    "NOTICE"},
+                                                  {kLogInfo,      "INFO"},
+                                                  {kLogDebug,     "DEBUG"}};
+
+    friend std::ostream& operator<< (std::ostream& os, const LogPriority& log_priority){
+        static_cast<Log *>(os.rdbuf())->priority_curr = log_priority;
+        return os;
+    }
+protected:
+    int sync(){
+        if (buffer_.length()) {
+            if (priority_curr >= priority_set){
+                logfile << name_map[priority_curr] << ": " <<  buffer_ << std::endl << std::flush;
+            }
+            buffer_.erase();
+            /* priority_curr = kLogDebug; // default to debug for each message */
+        }
+        return 0;
+    }
+    int overflow(int c){
+        if (c != EOF) {
+            buffer_ += static_cast<char>(c);
+        } else {
+            sync();
+        }
+        return c;
+    }
+public:
+    explicit Log(std::string filename, LogPriority priority)
+      :logfile(filename, std::ofstream::out){
+        priority_set = priority;
+        priority_curr = kLogDebug;
+    }
+};
+}
+#endif // log_hpp

+ 22 - 19
value.hpp

@@ -42,6 +42,7 @@
 #ifndef value_hpp
 #define value_hpp
 #include <iostream>
+#include <sstream>
 #include <utility>
 #include <algorithm>
 #include <map>
@@ -50,6 +51,8 @@
 #include <initializer_list>
 #include <functional>
 
+#include "log.hpp"
+
 /**
  * The namespace containing all filval classes and functions.
  */
@@ -120,7 +123,7 @@ class GenValue{
         inline static std::map<const std::string, GenValue*> aliases;
     public:
         GenValue(const std::string& name)
-          :name(name) {
+          :name(name){
             values[name] = this;
         }
 
@@ -135,51 +138,51 @@ class GenValue{
         }
 
         static GenValue* get_value(const std::string& name){
-            if (aliases[name] != NULL)
+            if (aliases[name] != nullptr)
                 return aliases[name];
-            else if (values[name] != NULL)
+            else if (values[name] != nullptr)
                 return values[name];
             else{
-                std::cout << "ERROR: Could not find alias or value \"" << name << "\"" << std::endl;
-                std::cout << "I'll tell you the ones I know about." << std::endl;
-                summary();
-                std::cout << "Aborting... :(" << std::endl;
-                exit(-1);
+                ERROR("Could not find alias or value \"" << name << "\". I'll tell you the ones I know about."
+                        << summary());
+                CRITICAL("Aborting... :(", -1);
             }
         }
 
         static void alias(const std::string& name, GenValue* value){
-            if (aliases[name] != NULL){
-                std::cout << "WARNING: alias \"" << name << "\" overrides previous entry." << std::endl;
+            if (aliases[name] != nullptr){
+                WARNING("WARNING: alias \"" << name << "\" overrides previous entry.");
             }
             aliases[name] = value;
         }
 
         static GenValue* alias(const std::string& name){
-            if (values[name] != NULL){
-                std::cout << "WARNING: alias \"" << name << "\" does not exist." << std::endl;
+            if (values[name] != nullptr){
+                WARNING("Alias \"" << name << "\" does not exist.");
             }
             return aliases[name];
         }
 
-        static void summary(){
-            std::cout << "The following values have been created: " << std::endl;
+        static std::string summary(){
+            std::stringstream ss;
+            ss << "The following values have been created: " << std::endl;
             for (auto value : values){
-                if (value.second == NULL) continue;
-                std::cout << "\t\"" << value.first << "\" at address " << value.second << std::endl;
+                if (value.second == nullptr) continue;
+                ss << "\t\"" << value.first << "\" at address " << value.second << std::endl;
             }
-            std::cout << "And these aliases:" << std::endl;
+            ss << "And these aliases:" << std::endl;
             for (auto alias : aliases){
                 std::string orig("VOID");
-                if (alias.second == NULL) continue;
+                if (alias.second == nullptr) continue;
                 for (auto value : values){
                     if (alias.second == value.second){
                         orig = value.second->get_name();
                         break;
                     }
                 }
-                std::cout << "\t\"" << alias.first << "\" referring to \"" << orig << "\"" << std::endl;
+                ss << "\t\"" << alias.first << "\" referring to \"" << orig << "\"" << std::endl;
             }
+            return ss.str();
         }
 };