diff options
author | Nilay Vaish <nilay@cs.wisc.edu> | 2014-10-11 15:02:23 -0500 |
---|---|---|
committer | Nilay Vaish <nilay@cs.wisc.edu> | 2014-10-11 15:02:23 -0500 |
commit | e8ed7b1d1b5bef31e9874f679a5797c2e00d06f1 (patch) | |
tree | 421c9c50377aa664958685914f5504c4c019e21f /ext/dsent/libutil | |
parent | a098fad174d8559037602b248b8e6f7f46bfebbb (diff) | |
download | gem5-e8ed7b1d1b5bef31e9874f679a5797c2e00d06f1.tar.xz |
ext: add the source code for DSENT
This patch adds a tool called DSENT to the ext/ directory. DSENT
is a tool that models power and area for on-chip networks. The next
patch adds a script for using the tool.
Diffstat (limited to 'ext/dsent/libutil')
-rw-r--r-- | ext/dsent/libutil/Assert.h | 22 | ||||
-rw-r--r-- | ext/dsent/libutil/Calculator.cc | 239 | ||||
-rw-r--r-- | ext/dsent/libutil/Calculator.h | 86 | ||||
-rw-r--r-- | ext/dsent/libutil/Config.cc | 144 | ||||
-rw-r--r-- | ext/dsent/libutil/Config.h | 37 | ||||
-rw-r--r-- | ext/dsent/libutil/Exception.cc | 17 | ||||
-rw-r--r-- | ext/dsent/libutil/Exception.h | 29 | ||||
-rw-r--r-- | ext/dsent/libutil/LibUtil.h | 37 | ||||
-rw-r--r-- | ext/dsent/libutil/Log.cc | 86 | ||||
-rw-r--r-- | ext/dsent/libutil/Log.h | 43 | ||||
-rw-r--r-- | ext/dsent/libutil/Makefile | 43 | ||||
-rw-r--r-- | ext/dsent/libutil/Map.h | 242 | ||||
-rw-r--r-- | ext/dsent/libutil/MathUtil.cc | 7 | ||||
-rw-r--r-- | ext/dsent/libutil/MathUtil.h | 21 | ||||
-rw-r--r-- | ext/dsent/libutil/OptionParser.cc | 177 | ||||
-rw-r--r-- | ext/dsent/libutil/OptionParser.h | 57 | ||||
-rw-r--r-- | ext/dsent/libutil/String.cc | 347 | ||||
-rw-r--r-- | ext/dsent/libutil/String.h | 218 |
18 files changed, 1852 insertions, 0 deletions
diff --git a/ext/dsent/libutil/Assert.h b/ext/dsent/libutil/Assert.h new file mode 100644 index 000000000..0fdd364b2 --- /dev/null +++ b/ext/dsent/libutil/Assert.h @@ -0,0 +1,22 @@ +#ifndef __ASSERT_H__ +#define __ASSERT_H__ + +#include "String.h" +#include "Exception.h" + +#ifdef NDEBUG +#define ASSERT(test_value_,exception_msg_) +#else +#define ASSERT(test_value_,msg_) \ + do \ + { \ + if(!(test_value_)) \ + { \ + const LibUtil::String& exception_msg = LibUtil::String::format("\nAt %s:%d\n", __FILE__, __LINE__) + (String)(msg_); \ + throw LibUtil::Exception(exception_msg); \ + } \ + } while(0); +#endif + +#endif // __ASSERT_H__ + diff --git a/ext/dsent/libutil/Calculator.cc b/ext/dsent/libutil/Calculator.cc new file mode 100644 index 000000000..e78e67287 --- /dev/null +++ b/ext/dsent/libutil/Calculator.cc @@ -0,0 +1,239 @@ +#include "Calculator.h" + +#include <cctype> +#include <iostream> + +namespace LibUtil +{ + using std::cout; + using std::endl; + using std::scientific; + + Calculator::Calculator() + { + m_reserved_chars_ = "+-*/;=()\\"; + } + + Calculator::~Calculator() + {} + + void Calculator::reset() + { + m_var_.clear(); + return; + } + + void Calculator::evaluateString(const String& str_) + { + istringstream ist(str_); + while(ist) + { + getToken(ist); + if(m_curr_token_ == END) break; + if(m_curr_token_ == SEP) continue; + if((m_curr_token_ == NAME) && (m_value_string_ == "print")) + { + getToken(ist); + + if(m_curr_token_ == STRING) + { + String print_str = m_value_string_; + + getToken(ist); + if(m_curr_token_ == SEP) + { + cout << print_str << endl; + } + else + { + double v = expr(ist, false); + cout << scientific << print_str << v << endl; + } + } + else + { + double v = expr(ist, false); + cout << scientific << v << endl; + } + } + else + { + expr(ist, false); + } + } + return; + } + + Calculator::Token Calculator::getToken(istringstream& ist_) + { + char ch; + do + { + ist_.get(ch); + if(!ist_) + { + m_curr_token_ = END; + return m_curr_token_; + } + } + while(ch != '\n' && isspace(ch)); + + switch(ch) + { + case '\n': + m_curr_token_ = END; + return m_curr_token_; + case ';': + m_curr_token_ = SEP; + return m_curr_token_; + case '*': + case '/': + case '+': + case '-': + case '(': + case ')': + case '=': + m_curr_token_ = Token(ch); + return m_curr_token_; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '.': + ist_.putback(ch); + ist_ >> m_value_number_; + m_curr_token_ = NUMBER; + return m_curr_token_; + case '"': + ist_.get(ch); + m_value_string_ = ""; + while(ist_ && ('"' != ch)) + { + m_value_string_ += String(1, ch); + ist_.get(ch); + } + m_curr_token_ = STRING; + return m_curr_token_; + case '$': + ist_.get(ch); + ASSERT((ch == '('), "[Error] Bad token: '(' expected"); + ist_.get(ch); + m_value_string_ = ""; + while(ist_ && (!isspace(ch)) && (')' != ch)) + { + m_value_string_ += String(1, ch); + ist_.get(ch); + } + m_curr_token_ = NAME2; + return m_curr_token_; + default: + if(isalpha(ch)) + { + m_value_string_ = ch; + ist_.get(ch); + while(ist_ && (isalnum(ch) || ('_' == ch))) + { + m_value_string_ += String(1, ch); + ist_.get(ch); + } + ist_.putback(ch); + m_curr_token_ = NAME; + return m_curr_token_; + } + else + { + String error_msg = "[Error] Bad token: '" + String(ch) + "'"; + throw Exception(error_msg); + } + } + } + + double Calculator::prim(istringstream& ist_, bool is_get_) + { + if(is_get_) + { + getToken(ist_); + } + + double v; + switch(m_curr_token_) + { + case NUMBER: + v = m_value_number_; + getToken(ist_); + return v; + case NAME: + if(getToken(ist_) == ASSIGN) + { + String var_name = m_value_string_; + v = expr(ist_, true); + m_var_.set(var_name, v); + } + else + { + v = m_var_.get(m_value_string_); + } + return v; + case NAME2: + v = getEnvVar(m_value_string_); + getToken(ist_); + return v; + case MINUS: + return -prim(ist_, true); + case LP: + v = expr(ist_, true); + ASSERT((m_curr_token_ == RP), "[Error] ')' expected"); + getToken(ist_); + return v; + default: + ASSERT(0, "[Error] primary expected, get: '" + String(int(m_curr_token_)) + "'"); + } + } + + double Calculator::term(istringstream& ist_, bool is_get_) + { + double left = prim(ist_, is_get_); + + while(1) + { + double d; + switch(m_curr_token_) + { + case MUL: + left *= prim(ist_, true); + break; + case DIV: + d = prim(ist_, true); + ASSERT(d, "[Error] divided by 0"); + left /= d; + break; + default: + return left; + } + } + } + + double Calculator::expr(istringstream& ist_, bool is_get_) + { + double left = term(ist_, is_get_); + + while(1) + { + switch(m_curr_token_) + { + case PLUS: + left += term(ist_, true); + break; + case MINUS: + left -= term(ist_, true); + break; + default: + return left; + } + } + } + + double Calculator::getEnvVar(const String& var_name_) const + { + return m_var_.get(var_name_); + } +} // namespace LibUtil + diff --git a/ext/dsent/libutil/Calculator.h b/ext/dsent/libutil/Calculator.h new file mode 100644 index 000000000..4fcdf471f --- /dev/null +++ b/ext/dsent/libutil/Calculator.h @@ -0,0 +1,86 @@ +#ifndef __LIBUTIL_CALCULATOR_H__ +#define __LIBUTIL_CALCULATOR_H__ + +#include <sstream> + +#include "String.h" +#include "Map.h" +#include "Assert.h" + +namespace LibUtil +{ + using std::istringstream; + + /* + * program: + * END // END is end-of-input + * expr_list END + * + * expr_list: + * expression SEP expr_list // SEP is semicolon + * expression + * print expression + * print STRING + * print STRING expression + * print STRING expression SEP expr_list + * + * + * expression: + * expression + term + * expression - term + * term + * + * term: + * term / primary + * term * primary + * primary + * + * primary: + * NUMBER + * NAME + * NAME = expression + * NAME string expression // NAME is print + * - primary + * ( expression ) + * + * string: + * + **/ + + class Calculator + { + protected: + enum Token + { + NAME, NAME2, NUMBER, STRING, END, + PLUS = '+', MINUS = '-', MUL = '*', DIV = '/', + SEP = ';', ASSIGN = '=', LP = '(', RP = ')' + }; + + public: + Calculator(); + virtual ~Calculator(); + + public: + void reset(); + void evaluateString(const String& str_); + + protected: + Token getToken(istringstream& ist_); + double prim(istringstream& ist_, bool is_get_); + double term(istringstream& ist_, bool is_get_); + double expr(istringstream& ist_, bool is_get_); + virtual double getEnvVar(const String& var_name_) const; + + protected: + String m_reserved_chars_; + Map<double> m_var_; + + Token m_curr_token_; + double m_value_number_; + String m_value_string_; + }; // class Calculator +} // namespace LibUtil + +#endif // __LIBUTIL_CALCULATOR_H__ + diff --git a/ext/dsent/libutil/Config.cc b/ext/dsent/libutil/Config.cc new file mode 100644 index 000000000..f858c6926 --- /dev/null +++ b/ext/dsent/libutil/Config.cc @@ -0,0 +1,144 @@ +#include "Config.h" + +#include <fstream> + +#include "Assert.h" + +namespace LibUtil +{ + Config::Config(const String& delimiter_, const String& comment_, const String& sentry_) + : mDelimiter(delimiter_), mComment(comment_), mSentry(sentry_) + {} + + Config::Config(const Config& config_) + : StringMap(config_) + { + mDelimiter = config_.mDelimiter; + mComment = config_.mComment; + mSentry = config_.mSentry; + } + + Config::~Config() + {} + + Config* Config::clone() const + { + return new Config(*this); + } + + void Config::readFile(const String& filename_) + { + std::ifstream fin(filename_.c_str()); + + ASSERT(fin, "File not found: " + filename_); + fin >> (*this); + return; + } + + void Config::readString(const String& str_) + { + String newString = str_; + newString.substitute(";", "\n"); + std::istringstream iss(newString, std::istringstream::in); + + iss >> (*this); + } + + std::ostream& operator<<(std::ostream& ost_, const Config& config_) + { + Config::ConstIterator it; + for(it = config_.begin(); it != config_.end(); it++) + { + ost_ << it->first << " " << config_.mDelimiter << " "; + ost_ << it->second << std::endl; + } + return ost_; + } + + std::istream& operator>>(std::istream& ist_, Config& config_) + { + // Set a Config from ist_ + // Read in keys and values, keeping internal whitespace + typedef String::size_type pos; + const String& delim = config_.mDelimiter; // separator + const String& comm = config_.mComment; // comment + const String& sentry = config_.mSentry; // end of file sentry + const pos skip = delim.length(); // length of separator + + String nextline = ""; // might need to read ahead to see where value ends + + while(ist_ || nextline.length() > 0) + { + // Read an entire line at a time + String line; + if(nextline.length() > 0) + { + line = nextline; // we read ahead; use it now + nextline = ""; + } + else + { + //std::getline(ist_, line); + safeGetline(ist_, line); + } + + // Ignore comments and the spaces on both ends + line = line.substr(0, line.find(comm)); + line.trim(); + + // Check for end of file sentry + if((sentry != "") && (line.find(sentry) != String::npos)) return ist_; + + if(line.length() == 0) + continue; + + // Parse the line if it contains a delimiter + pos delimPos = line.find(delim); + ASSERT((delimPos < String::npos), "Invalid config line: '" + line + "'"); + + // Extract the key + String key = line.substr(0, delimPos); + line.replace(0, delimPos+skip, ""); + + // See if value continues on the next line + // Stop at blank line, next line with a key, end of stream, + // or end of file sentry + bool terminate = false; + while(!terminate && ist_) + { + if(line.at(line.size() - 1) == '\\') + line.erase(line.size() - 1); + else + break; + + //std::getline(ist_, nextline); + safeGetline(ist_, nextline); + terminate = true; + + String nlcopy = nextline; + nlcopy.trim(); + if(nlcopy == "") continue; + + nextline = nextline.substr(0, nextline.find(comm)); + //if(nextline.find(delim) != String::npos) + // continue; + if((sentry != "") && (nextline.find(sentry) != String::npos)) + continue; + + //nlcopy = nextline; + //nlcopy.trim(); + //if(nlcopy != "") line += "\n"; + line += nextline; + nextline = ""; + terminate = false; + } + + // Store key and value + key.trim(); + line.trim(); + config_.set(key, line); // overwrites if key is repeated + } + return ist_; + } +} + diff --git a/ext/dsent/libutil/Config.h b/ext/dsent/libutil/Config.h new file mode 100644 index 000000000..a60c4b8fd --- /dev/null +++ b/ext/dsent/libutil/Config.h @@ -0,0 +1,37 @@ +#ifndef __LIBUTIL_CONFIG_H__ +#define __LIBUTIL_CONFIG_H__ + +#include <iostream> + +#include "Map.h" + +namespace LibUtil +{ + class Config : public StringMap + { + public: + Config(const String& delimiter_ = "=", const String& comment_ = "#", const String& sentry_ = "End"); + Config(const Config& config_); + virtual ~Config(); + + public: + // Make a copy of this instance + virtual Config* clone() const; + // Load the config from file + virtual void readFile(const String& filename_); + // Parse string and overwrite the Config instance if keys exist + virtual void readString(const String& str_); + + // Write or read map using standard IO + friend std::ostream& operator<<(std::ostream& ost_, const Config& config_); + friend std::istream& operator>>(std::istream& ist_, Config& config_); + + protected: + String mDelimiter; + String mComment; + String mSentry; + }; +} + +#endif // __LIBUTIL_CONFIG_H__ + diff --git a/ext/dsent/libutil/Exception.cc b/ext/dsent/libutil/Exception.cc new file mode 100644 index 000000000..c6db0e3fb --- /dev/null +++ b/ext/dsent/libutil/Exception.cc @@ -0,0 +1,17 @@ +#include "Exception.h" + +namespace LibUtil +{ + Exception::Exception(const String& exception_msg_) throw() + : exception(), mExceptionMsg(exception_msg_) + {} + + Exception::~Exception() throw() + {} + + const char* Exception::what() const throw() + { + return mExceptionMsg.c_str(); + } +} + diff --git a/ext/dsent/libutil/Exception.h b/ext/dsent/libutil/Exception.h new file mode 100644 index 000000000..88d68cce2 --- /dev/null +++ b/ext/dsent/libutil/Exception.h @@ -0,0 +1,29 @@ +#ifndef __EXCEPTION_H__ +#define __EXCEPTION_H__ + +#include <exception> + +#include "String.h" + +namespace LibUtil +{ + using std::exception; + + // Exception class handles the all exception messages in the program + class Exception : public exception + { + public: + // All constructors/destructors/functions in this class don't throw any events + Exception(const String& exception_msg_) throw(); + ~Exception() throw(); + + // Derived from std::exception class that returns a null-terminated char string + const char* what() const throw(); + + private: + String mExceptionMsg; + }; +} + +#endif // __EXCEPTION_H__ + diff --git a/ext/dsent/libutil/LibUtil.h b/ext/dsent/libutil/LibUtil.h new file mode 100644 index 000000000..12eb76fa0 --- /dev/null +++ b/ext/dsent/libutil/LibUtil.h @@ -0,0 +1,37 @@ +#ifndef __LIBUTIL_H__ +#define __LIBUTIL_H__ + +#include <vector> + +#include "String.h" +#include "Exception.h" +#include "Assert.h" +#include "Map.h" +#include "Log.h" +#include "Config.h" +#include "MathUtil.h" + +namespace LibUtil +{ + template<class T> void clearPtrVector(std::vector<T*>* vec_) + { + for(typename std::vector<T*>::iterator it = vec_->begin(); it != vec_->end(); ++it) + { + T* temp_T = (*it); + delete temp_T; + } + vec_->clear(); + return; + } + + template<class T> void deletePtrVector(std::vector<T*>* vec_) + { + clearPtrVector<T>(vec_); + delete vec_; + return; + } + +} // namespace LibUtil + +#endif // __LIBUTIL_H__ + diff --git a/ext/dsent/libutil/Log.cc b/ext/dsent/libutil/Log.cc new file mode 100644 index 000000000..cb4266bf9 --- /dev/null +++ b/ext/dsent/libutil/Log.cc @@ -0,0 +1,86 @@ +#include "Log.h" + +#include "Assert.h" + +namespace LibUtil +{ + using std::ostream; + using std::endl; + + Log* Log::msSingleton = NULL; + const bool Log::msIsLog = LIBUTIL_IS_LOG; + + void Log::allocate(const String& log_file_name_) + { + if(msIsLog) + { + // Allocate static Config instance + ASSERT(!msSingleton, "Log singleton is allocated"); + msSingleton = new Log(log_file_name_); + } + } + + void Log::release() + { + if(msIsLog) + { + ASSERT(msSingleton, "Log singleton is not allocated"); + delete msSingleton; + msSingleton = NULL; + } + return; + } + + void Log::print(const String& str_) + { + if(msIsLog) + { + ASSERT(msSingleton, "Log singleton is not allocated"); + msSingleton->ofs << str_; + } + return; + } + + void Log::print(ostream& stream_, const String& str_) + { + if(msIsLog) + { + ASSERT(msSingleton, "Log singleton is not allocated"); + msSingleton->ofs << str_; + } + stream_ << str_; + return; + } + + void Log::printLine(const String& str_) + { + if(msIsLog) + { + ASSERT(msSingleton, "Log singleton is not allocated"); + msSingleton->ofs << str_ << endl; + } + return; + } + + void Log::printLine(ostream& stream_, const String& str_) + { + if(msIsLog) + { + ASSERT(msSingleton, "Log singleton is not allocated"); + msSingleton->ofs << str_ << endl; + } + stream_ << str_ << endl; + return; + } + + Log::Log(const String& log_file_name_) + { + ofs.open(log_file_name_.c_str()); + } + + Log::~Log() + { + ofs.close(); + } +} + diff --git a/ext/dsent/libutil/Log.h b/ext/dsent/libutil/Log.h new file mode 100644 index 000000000..9c759e702 --- /dev/null +++ b/ext/dsent/libutil/Log.h @@ -0,0 +1,43 @@ +#ifndef __LOG_H__ +#define __LOG_H__ + +#include <cstdio> +#include <iostream> +#include <fstream> + +#include "String.h" + +#ifndef LIBUTIL_IS_LOG +#define LIBUTIL_IS_LOG false +#endif + +namespace LibUtil +{ + using std::cerr; + + class Log + { + public: + static void allocate(const String& log_file_name_); + static void release(); + + static void print(const String& str_); + static void print(std::ostream& stream_, const String& str_); + static void printLine(const String& str_); + static void printLine(std::ostream& stream_, const String& str_); + + protected: + static Log* msSingleton; + static const bool msIsLog; + + protected: + Log(const String& log_file_name_); + ~Log(); + + protected: + std::ofstream ofs; + }; +} + +#endif // __LOG_H__ + diff --git a/ext/dsent/libutil/Makefile b/ext/dsent/libutil/Makefile new file mode 100644 index 000000000..150028346 --- /dev/null +++ b/ext/dsent/libutil/Makefile @@ -0,0 +1,43 @@ + +# Define the directories that will be compiled +DIRS_TO_COMPILE := . \ + +DIRS = $(patsubst %,$(CURDIR)/%,$(DIRS_TO_COMPILE)) + +SRCS = $(foreach dir, $(DIRS), $(wildcard $(dir)/*.cc)) + +OBJS = $(SRCS:%.cc=%.o) + +DEF_FLAGS = + +ifdef LIBUTIL_IS_LOG + LIBUTIL_IS_LOG = true +else + LIBUTIL_IS_LOG = false +endif +DEF_FLAGS += -DLIBUTIL_IS_LOG=$(LIBUTIL_IS_LOG) + +INCLUDE_FLAGS = $(foreach dir, $(DIRS), -I$(dir)) +OPT_FLAGS = -O2 -g +WARN_FLAGS = -pedantic -Wall -W -Wextra -Werror +CXXFLAGS = $(OPT_FLAGS) $(WARN_FLAGS) $(INCLUDE_FLAGS) $(DEF_FLAGS) + +TARGET = $(CURDIR)/libutil.a + +all: $(TARGET) + +$(TARGET): $(OBJS) + ar rcs $@ $^ +#$(TARGET): $(OBJS) +# $(CXX) $(CXXFLAGS) $^ -o $(TARGET) + +%.o: %.cc + $(CXX) $(CXXFLAGS) -c $< -o $@ + +%/created: + mkdir -p $(dir $@) + touch $@ + +clean: + $(RM) -rf $(OBJS) $(TARGET) + diff --git a/ext/dsent/libutil/Map.h b/ext/dsent/libutil/Map.h new file mode 100644 index 000000000..0352c8634 --- /dev/null +++ b/ext/dsent/libutil/Map.h @@ -0,0 +1,242 @@ +#ifndef __MAP_H__ +#define __MAP_H__ + +#include <iostream> +#include <map> + +#include "String.h" +#include "Assert.h" + +namespace LibUtil +{ + using std::map; + + template<class T> class Map + { + public: + typedef typename map<String, T>::iterator Iterator; + typedef typename map<String, T>::const_iterator ConstIterator; + typedef typename map<String, T>::size_type SizeType; + + public: + Map(); + virtual ~Map(); + + public: + // Return a new copy of this Map instance + Map* clone() const; + // Copy map_ to this instance + void copyFrom(const Map<T>* map_); + // Return the size of the map + SizeType size() const; + // Check if the map is empty + bool isEmpty() const; + // Check if the key exists + bool keyExist(const String& key_) const; + // Get the value_ corresponding to the key_ + const T& get(const String& key_) const; + // Get the value_ corresponding to the key_ if the key_ exist, otherwise, the default_value_is returned + const T& getIfKeyExist(const String& key_, const T& default_value_ = T()) const; + // Add/Update a <key_, value_> entry + void set(const String& key_, const T& value_); + // Get iterator to the element + Iterator find(const String& key_); + ConstIterator find(const String& key_) const; + // Remove an entry corresponding to key_ + void remove(const String& key_); + // Remove an entry at 'it' + void remove(Iterator it); + // Remove all keys + void clear(); + // Merge a map. Values with same key will be overwritten. + void merge(const Map<T>* map_); + // Returns a MapIterator referring to the first element in the map + Iterator begin(); + ConstIterator begin() const; + // Returns a MapIterator referring to the past-the-end element in the map + Iterator end(); + ConstIterator end() const; + + protected: + Map(const Map& map_); + + protected: + map<String, T> mMap; + }; + + template<class T> Map<T>::Map() + {} + + template<class T> Map<T>::~Map() + {} + + template<class T> Map<T>* Map<T>::clone() const + { + return new Map<T>(*this); + } + + template<class T> void Map<T>::copyFrom(const Map<T>* map_) + { + // Remove all keys (it won't free the content if T is a pointer) + mMap.clear(); + + // Copy the contents + mMap = map_->mMap; + } + + template<class T> typename Map<T>::SizeType Map<T>::size() const + { + return mMap.size(); + } + + template<class T> bool Map<T>::isEmpty() const + { + return (mMap.empty()); + } + + template<class T> bool Map<T>::keyExist(const String& key_) const + { + ConstIterator it = mMap.find(key_); + return (it != mMap.end()); + } + + template<class T> const T& Map<T>::get(const String& key_) const + { + ConstIterator it; + + it = mMap.find(key_); + ASSERT((it != mMap.end()), "Key not found: " + key_); + return (it->second); + } + + template<class T> const T& Map<T>::getIfKeyExist(const String& key_, const T& default_value_) const + { + if(keyExist(key_)) + { + return get(key_); + } + else + { + return default_value_; + } + } + + template<class T> void Map<T>::set(const String& key_, const T& value_) + { + mMap[key_] = value_; + return; + } + + template<class T> typename Map<T>::Iterator Map<T>::find(const String& key_) + { + return mMap.find(key_); + } + + template<class T> typename Map<T>::ConstIterator Map<T>::find(const String& key_) const + { + return mMap.find(key_); + } + + template<class T> void Map<T>::remove(const String& key_) + { + mMap.erase(key_); + return; + } + + template<class T> void Map<T>::remove(Iterator it) + { + mMap.erase(it); + return; + } + + template<class T> void Map<T>::clear() + { + mMap.clear(); + return; + } + + template<class T> void Map<T>::merge(const Map<T>* map_) + { + ConstIterator it; + for(it = map_->begin(); it != map_->end(); it++) + { + const String& key = it->first; + const T& value = it->second; + set(key, value); + } + return; + } + + template<class T> typename Map<T>::Iterator Map<T>::begin() + { + return mMap.begin(); + } + + template<class T> typename Map<T>::ConstIterator Map<T>::begin() const + { + return mMap.begin(); + } + + template<class T> typename Map<T>::Iterator Map<T>::end() + { + return mMap.end(); + } + + template<class T> typename Map<T>::ConstIterator Map<T>::end() const + { + return mMap.end(); + } + + inline std::ostream& operator<<(std::ostream& ost_, const Map<String>& map_) + { + Map<String>::ConstIterator it; + for(it = map_.begin(); it != map_.end(); it++) + { + ost_ << it->first << " = " << it->second << std::endl; + } + return ost_; + } + + template<class T> Map<T>::Map(const Map<T>& map_) + : mMap(map_.mMap) + {} + + typedef Map<String> StringMap; + + + // Handy function to delete all pointers in a map + template<class T> void clearPtrMap(Map<T*>* map_) + { + for(typename Map<T*>::Iterator it = map_->begin(); it != map_->end(); ++it) + { + T* temp_T = it->second; + delete temp_T; + } + map_->clear(); + return; + } + + // Handy function to delete all pointers in a map and the map itself + template<class T> void deletePtrMap(Map<T*>* map_) + { + clearPtrMap<T>(map_); + delete map_; + return; + } + + // Handy function to clone all pointers in a map + template<class T> Map<T*>* clonePtrMap(const Map<T*>* map_) + { + Map<T*>* new_T_map = new Map<T*>; + for(typename Map<T*>::ConstIterator it = map_->begin(); it != map_->end(); ++it) + { + const String& temp_name = it->first; + const T* temp_T = it->second; + new_T_map->set(temp_name, temp_T->clone()); + } + return new_T_map; + } +} + +#endif // __MAP_H__ + diff --git a/ext/dsent/libutil/MathUtil.cc b/ext/dsent/libutil/MathUtil.cc new file mode 100644 index 000000000..0e177b5fc --- /dev/null +++ b/ext/dsent/libutil/MathUtil.cc @@ -0,0 +1,7 @@ +#include "MathUtil.h" + +namespace LibUtil +{ + const double Math::epsilon = 1e-15; +} // namespace LibUtil + diff --git a/ext/dsent/libutil/MathUtil.h b/ext/dsent/libutil/MathUtil.h new file mode 100644 index 000000000..1f3341ee1 --- /dev/null +++ b/ext/dsent/libutil/MathUtil.h @@ -0,0 +1,21 @@ +#ifndef __MATH_H__ +#define __MATH_H__ + +#include <cmath> + +namespace LibUtil +{ + class Math + { + public: + static const double epsilon; + + static inline bool isEqual(double value1_, double value2_) + { + return (std::fabs(value1_ - value2_) < epsilon); + } + }; +} // namespace LibUtil + +#endif // __MATH_H__ + diff --git a/ext/dsent/libutil/OptionParser.cc b/ext/dsent/libutil/OptionParser.cc new file mode 100644 index 000000000..6d2695f2d --- /dev/null +++ b/ext/dsent/libutil/OptionParser.cc @@ -0,0 +1,177 @@ +#include "OptionParser.h" + +#include <cstdlib> +#include <iostream> + +namespace LibUtil +{ + using std::cout; + using std::cerr; + using std::endl; + + OptionParser::OptionInfo::OptionInfo( + const String& var_name_, + bool has_arg_, + const String& arg_name_, + bool has_default_arg_value_, + const String& default_arg_value_, + const String& description_ + ) + : m_var_name_(var_name_), + m_has_arg_(has_arg_), + m_arg_name_(arg_name_), + m_has_default_arg_value_(has_default_arg_value_), + m_default_arg_value_(default_arg_value_), + m_description_(description_) + {} + + OptionParser::OptionInfo::~OptionInfo() + { + } + + OptionParser::OptionParser() + {} + + OptionParser::~OptionParser() + { + clearPtrMap(&m_option_infos_); + } + + void OptionParser::addOption( + const String& option_name_, + const String& var_name_, + bool has_arg_, + const String& arg_name_, + bool has_default_arg_value_, + const String& default_arg_value_, + const String& description_) + { + OptionInfo* option_info = new OptionInfo(var_name_, has_arg_, arg_name_, + has_default_arg_value_, default_arg_value_, description_); + + ASSERT(!m_option_infos_.keyExist(option_name_), "Option exists: " + option_name_); + + // Add the option name to an array for sorting + m_option_names_.push_back(option_name_); + + // Add option info + m_option_infos_.set(option_name_, option_info); + + // Set the default argument value + if(has_default_arg_value_) + { + set(var_name_, default_arg_value_); + } + + return; + } + + void OptionParser::parseArguments(int argc_, char** argv_) + { + bool is_print_options = false; + int arg_idx = 0; + + while(arg_idx < argc_) + { + String option_name = String(argv_[arg_idx]); + + // Print the options page if -help is specified + if(option_name == "-help") + { + is_print_options = true; + break; + } + else if(m_option_infos_.keyExist(option_name)) + { + const OptionInfo* option_info = m_option_infos_.get(option_name); + const String& var_name = option_info->getVarName(); + if(option_info->hasArg()) + { + if((arg_idx + 1) >= argc_) + { + cerr << "[Error] Missing argument for option: '" << option_name << "'" << endl; + is_print_options = true; + break; + } + + String option_arg = String(argv_[arg_idx + 1]); + set(var_name, option_arg); + + arg_idx += 2; + } + else + { + // If the option does not require an argument + // then set it to true + set(var_name, "true"); + + arg_idx += 1; + } + } + else + { + cerr << "[Error] Unknown option: '" << option_name << "'" << endl; + is_print_options = true; + break; + } + } + + // Check if all required options are set (the ones without default values) + vector<String>::const_iterator it; + for(it = m_option_names_.begin(); it != m_option_names_.end(); ++it) + { + const String& option_name = *it; + const OptionInfo* option_info = m_option_infos_.get(option_name); + + if(!option_info->hasDefaultArgValue()) + { + const String& var_name = option_info->getVarName(); + if(!keyExist(var_name)) + { + cerr << "[Error] Missing required option: '" << option_name << "'" << endl; + is_print_options = true; + } + } + } + + if(is_print_options) + { + printOptions(); + exit(0); + } + return; + } + + void OptionParser::printOptions() const + { + cout << endl; + cout << "Available options:" << endl; + cout << "==================" << endl << endl; + + vector<String>::const_iterator it; + for(it = m_option_names_.begin(); it != m_option_names_.end(); ++it) + { + const String& option_name = *it; + const OptionInfo* option_info = m_option_infos_.get(option_name); + + cout << option_name; + if(option_info->hasArg()) + { + cout << " <" << option_info->getArgName() << ">"; + } + cout << endl; + + cout << " " << option_info->getDescription() << endl; + if(option_info->hasArg() && option_info->hasDefaultArgValue()) + { + cout << " " << "Default: " << option_info->getDefaultArgValue() << endl; + } + cout << endl; + } + cout << "-help" << endl; + cout << " " << "Print this page" << endl; + cout << endl; + return; + } + +} // namespace LibUtil diff --git a/ext/dsent/libutil/OptionParser.h b/ext/dsent/libutil/OptionParser.h new file mode 100644 index 000000000..b98012a80 --- /dev/null +++ b/ext/dsent/libutil/OptionParser.h @@ -0,0 +1,57 @@ +#ifndef __LIBUTIL_OPTION_PARSER_H__ +#define __LIBUTIL_OPTION_PARSER_H__ + +#include <vector> + +#include "Map.h" + +namespace LibUtil +{ + using std::vector; + + // Simple option parser + class OptionParser : public StringMap + { + private: + class OptionInfo + { + public: + OptionInfo(const String& var_name_, bool has_arg_, const String& arg_name_, bool has_default_arg_value_, const String& default_arg_value_, const String& description_); + ~OptionInfo(); + + public: + inline const String& getVarName() const { return m_var_name_; } + inline bool hasArg() const { return m_has_arg_; } + inline const String& getArgName() const { return m_arg_name_; } + inline bool hasDefaultArgValue() const { return m_has_default_arg_value_; } + inline const String& getDefaultArgValue() const { return m_default_arg_value_; } + inline const String& getDescription() const { return m_description_; } + + private: + String m_var_name_; + bool m_has_arg_; + String m_arg_name_; + bool m_has_default_arg_value_; + String m_default_arg_value_; + String m_description_; + }; // class Option + + public: + OptionParser(); + virtual ~OptionParser(); + + public: + void addOption(const String& option_name_, const String& var_name_, bool has_arg_, const String& arg_name_, bool has_default_arg_value_, const String& default_arg_value_, const String& description_); + + void parseArguments(int argc_, char** argv_); + + void printOptions() const; + + protected: + vector<String> m_option_names_; + Map<OptionInfo*> m_option_infos_; + }; // class OptionParser +} // LibUtil + +#endif // __LIBUTIL_OPTION_PARSER_H__ + diff --git a/ext/dsent/libutil/String.cc b/ext/dsent/libutil/String.cc new file mode 100644 index 000000000..146e9f824 --- /dev/null +++ b/ext/dsent/libutil/String.cc @@ -0,0 +1,347 @@ +#include "String.h" + +#include <cstdarg> +#include <cstdio> +#include <iostream> +#include <ios> + +namespace LibUtil +{ + const unsigned int String::msBufferSize = 4096; + + String String::format(const String& format_, ...) + { + char buffer[msBufferSize]; + + va_list args; + va_start(args, format_); + vsnprintf(buffer, msBufferSize, format_.c_str(), args); + va_end(args); + + return (String)(buffer); + } + + String String::format(const String& format_, va_list args_) + { + char buffer[msBufferSize]; + + vsnprintf(buffer, msBufferSize, format_.c_str(), args_); + + return (String)(buffer); + } + + String::String() + {} + + String::String(const string& str_) + : string(str_) + {} + + String::String(const char* str_, size_t n_) + : string(str_, n_) + {} + + String::String(const char* str_) + : string(str_) + {} + + String::String(size_t n_, char c_) + : string(n_, c_) + {} + + String::String(int value_) + : string(toString<int>(value_)) + {} + + String::String(unsigned int value_) + : string(toString<unsigned int>(value_)) + {} + + String::String(long value_) + : string(toString<long>(value_)) + {} + + String::String(unsigned long value_) + : string(toString<unsigned long>(value_)) + {} + + String::String(float value_) + : string(toString<float>(value_)) + {} + + String::String(double value_) + : string(toString<double>(value_)) + {} + + String::String(bool value_) + : string(toString<bool>(value_)) + {} + + String::~String() + {} + + String& String::trim() + { + // Remove leading and trailing whitespace + static const char whitespace[] = " \n\t\v\r\f"; + erase(0, find_first_not_of(whitespace)); + erase(find_last_not_of(whitespace) + 1U); + return (*this); + } + + String& String::substitute(const String& str1_, const String& str2_) + { + size_t str1Size = str1_.size(); + size_t str2Size = str2_.size(); + + size_t pos; + pos = find(str1_); + while(pos != string::npos) + { + replace(pos, str1Size, str2_); + pos += str2Size; + pos = find(str1_, pos); + } + return (*this); + } + + vector<String> String::split(const char* delimiters_) const + { + vector<String> result; + + if(size() == 0) + { + return result; + } + + size_t currPos, nextPos; + currPos = 0; + nextPos = find_first_of(delimiters_); + while(1) + { + if(nextPos == string::npos) + { + if(currPos != size()) + { + result.push_back(substr(currPos)); + } + break; + } + + if(nextPos != currPos) + { + result.push_back(substr(currPos, nextPos - currPos)); + } + currPos = nextPos + 1; + nextPos = find_first_of(delimiters_, currPos); + } + + return result; + } + + vector<String> String::split(const String* delimiters_, unsigned int num_delimiters_) const + { + vector<String> result; + + if(size() == 0) + { + return result; + } + + if(num_delimiters_ == 1) + { + size_t currPos, nextPos; + currPos = 0; + nextPos = find(delimiters_[0]); + while(1) + { + if(nextPos == String::npos) + { + result.push_back(substr(currPos)); + break; + } + + if(nextPos != currPos) + { + result.push_back(substr(currPos, nextPos - currPos)); + } + currPos = nextPos + delimiters_[0].size(); + nextPos = find(delimiters_[0], currPos); + } + } + else + { + // Currently the length of the delimiters are not checked + unsigned int delimiterLength = 0; + size_t currPos, nextPos; + currPos = 0; + nextPos = size(); + for(unsigned int i = 0; i < num_delimiters_; ++i) + { + size_t tempPos = find(delimiters_[i], currPos); + if((tempPos != String::npos) && (tempPos < nextPos)) + { + nextPos = tempPos; + delimiterLength = delimiters_[i].size(); + } + } + while(1) + { + if((nextPos == String::npos) || (nextPos == size())) + { + result.push_back(substr(currPos)); + break; + } + + if(nextPos != currPos) + { + result.push_back(substr(currPos, nextPos - currPos)); + } + currPos = nextPos + delimiterLength; + nextPos = size(); + delimiterLength = 0; + for(unsigned int i = 0; i < num_delimiters_; ++i) + { + size_t tempPos = find(delimiters_[i], currPos); + if((tempPos != String::npos) && (tempPos < nextPos)) + { + nextPos = tempPos; + delimiterLength = delimiters_[i].size(); + } + } + } + } + return result; + } + + vector<String> String::splitByString(const String& delimiter_) const + { + return split(&delimiter_, 1); + } + + bool String::contain(const String& str_) const + { + return (find(str_) != String::npos); + } + + const char* String::toCString() const + { + return this->c_str(); + } + + int String::toInt() const + { + return fromString<int>(*this); + } + + unsigned int String::toUInt() const + { + return fromString<unsigned int>(*this); + } + + long String::toLong() const + { + return fromString<long>(*this); + } + + unsigned long String::toULong() const + { + return fromString<unsigned long>(*this); + } + + float String::toFloat() const + { + return fromString<float>(*this); + } + + double String::toDouble() const + { + return fromString<double>(*this); + } + + bool String::toBool() const + { + return fromString<bool>(*this); + } + + String::operator const char*() const + { + return this->c_str(); + } + + String::operator int() const + { + return fromString<int>(*this); + } + + String::operator unsigned int() const + { + return fromString<unsigned int>(*this); + } + + String::operator long() const + { + return fromString<long>(*this); + } + + String::operator unsigned long() const + { + return fromString<unsigned long>(*this); + } + + String::operator float() const + { + return fromString<float>(*this); + } + + String::operator double() const + { + return fromString<double>(*this); + } + + String::operator bool() const + { + return fromString<bool>(*this); + } + + String& String::operator=(char c_) + { + this->assign(1, c_); + return *this; + } + + std::istream& safeGetline(std::istream& is_, String& str_) + { + str_.clear(); + + // The characters in the stream are read one-by-one using a std::streambuf. + // That is faster than reading them one-by-one using the std::istream. + // Code that uses streambuf this way must be guarded by a sentry object. + // The sentry object performs various tasks, + // such as thread synchronization and updating the stream state. + + std::istream::sentry se(is_, true); + std::streambuf* sb = is_.rdbuf(); + + while(1) + { + int c = sb->sbumpc(); + switch(c) + { + case '\r': + c = sb->sgetc(); + if(c == '\n') + sb->sbumpc(); + return is_; + case '\n': + return is_; + case EOF: + is_.setstate(std::ios_base::failbit|std::ios_base::eofbit); + return is_; + default: + str_ += String(1, (char)c); + } + } + } +} // namespace LibUtil + diff --git a/ext/dsent/libutil/String.h b/ext/dsent/libutil/String.h new file mode 100644 index 000000000..95fe17565 --- /dev/null +++ b/ext/dsent/libutil/String.h @@ -0,0 +1,218 @@ +#ifndef __STRING_H__ +#define __STRING_H__ + +#include <string> +#include <cstdarg> +#include <vector> +#include <sstream> +#include <bitset> + +namespace LibUtil +{ + using std::string; + using std::vector; + + class String : public string + { + public: + static String format(const String& format_, ...); + static String format(const String& format_, va_list args_); + template<class T> static String toString(const T& value_); + static String toBitString(unsigned int value_, unsigned int num_bits_); + template<class T> static T fromString(const String& str_); + + private: + static const unsigned int msBufferSize; + + public: + String(); + String(const string& str_); + String(const char* str_, size_t n); + String(const char* str_); + String(size_t n, char c); + String(int value_); + String(unsigned int value_); + String(long value_); + String(unsigned long value_); + String(float value_); + String(double value_); + String(bool value_); + ~String(); + + public: + // Remove leading and trailing whitespace + String& trim(); + // Substitute str1 with str2 + String& substitute(const String& str1_, const String& str2_); + // Split the String into vector of Strings separated by delimiters_ + vector<String> split(const char* delimiters_) const; + vector<String> split(const String* delimiters_, unsigned int num_delimiters_ = 1) const; + vector<String> splitByString(const String& delimiters_) const; + + // Check if contains str + bool contain(const String& str_) const; + + public: + // Convertions + const char* toCString() const; + int toInt() const; + unsigned int toUInt() const; + long toLong() const; + unsigned long toULong() const; + float toFloat() const; + double toDouble() const; + bool toBool() const; + operator const char*() const; + operator int() const; + operator unsigned int() const; + operator long() const; + operator unsigned long() const; + operator float() const; + operator double() const; + operator bool() const; + String& operator=(char c_); + }; + + template<class T> String String::toString(const T& value_) + { + std::ostringstream ost; + ost << value_; + return ost.str(); + } + + template<> inline String String::toString<bool>(const bool& value_) + { + if(value_ == true) + { + return "TRUE"; + } + else + { + return "FALSE"; + } + } + + inline String String::toBitString(unsigned int value_, unsigned int num_bits_) + { + std::bitset<sizeof(unsigned int)*8> bitSet(value_); + String ret = String(bitSet.to_string()); + ret = ret.substr(ret.length()-num_bits_); + return ret; + } + + template<class T> T String::fromString(const String& str_) + { + T ret; + std::istringstream ist(str_); + ist >> ret; + return ret; + } + + template<> inline String String::fromString<String>(const String& str_) + { + return str_; + } + + template<> inline bool String::fromString<bool>(const String& str_) + { + bool ret; + if((str_ == String("TRUE")) || (str_ == String("true"))) + { + ret = true; + } + else if((str_ == string("FALSE")) || (str_ == String("false"))) + { + ret = false; + } + else + { + //std::cerr << "Invalid bool value: " << str_ << std::endl; + throw ("Invalid bool value: " + str_); + } + return ret; + } + + template<class T> String arrayToString( + const T* array_, unsigned int start_index_, unsigned int end_index_, + const String& delimiters_ + ) + { + // Ensure end_index_ >= start_index_ + 1 + if(end_index_ <= start_index_) + { + throw("Invalid index range: start_index = " + (String)start_index_ + ", end_index = " + (String)end_index_); + } + + String ret = "["; + for(unsigned int i = start_index_; i < (end_index_-1); ++i) + { + ret += (String)array_[i] + delimiters_; + } + ret += (String)array_[end_index_-1] + "]"; + return ret; + } + + template<class T> String arrayToString(const T* array_, unsigned int num_elements_) + { + return arrayToString(array_, 0, num_elements_, ", "); + } + + template<class T> String arrayToString(const T* array_, unsigned int start_index_, unsigned int end_index_) + { + return arrayToString(array_, start_index_, end_index_); + } + + template<class T> String vectorToString( + const vector<T>& vector_, unsigned int start_index_, unsigned int end_index_, + const String& delimiters_ + ) + { + // Ensure end_index_ >= start_index_ + 1, or if the vector is empty + if((end_index_ <= start_index_) || (end_index_ > vector_.size())) + { + // If the vector is empty, return empty array + if (vector_.size() == 0) + return "[]"; + + throw("Invalid index range: start_index = " + (String)start_index_ + ", end_index = " + (String)end_index_); + } + + String ret = "["; + for(unsigned int i = start_index_; i < (end_index_-1); ++i) + { + ret += (String)vector_[i] + delimiters_; + } + ret += (String)vector_[end_index_-1] + "]"; + return ret; + } + + template<class T> String vectorToString(const vector<T>& vector_) + { + return vectorToString(vector_, 0, vector_.size(), ", "); + } + + template<class T> String vectorToString(const vector<T>& vector_, unsigned int num_elements_) + { + return vectorToString(vector_, 0, num_elements_, ", "); + } + + template<class T> String vectorToString(const vector<T>& vector_, unsigned int start_index_, unsigned int end_index_) + { + return vectorToString(vector_, start_index_, end_index_); + } + + template<class T> vector<T> castStringVector(const vector<String>& vector_) + { + vector<T> ret_vector; + for(unsigned int i = 0; i < vector_.size(); ++i) + { + ret_vector.push_back((T)vector_[i]); + } + return ret_vector; + } + + std::istream& safeGetline(std::istream& is_, String& str_); +} // namespace LibUtil + +#endif // __STRING_H__ + |