From a50293a21710423cb8968aa3b33fb5d6649fdbb8 Mon Sep 17 00:00:00 2001 From: Phanes Date: Tue, 5 Dec 2017 07:51:55 -0500 Subject: [PATCH] now loads from either a units directory or a single units file --- src/loaders/Suite.cpp | 169 +++++++++++++++++++++++++++++++++++------- 1 file changed, 143 insertions(+), 26 deletions(-) diff --git a/src/loaders/Suite.cpp b/src/loaders/Suite.cpp index b589675..c710341 100644 --- a/src/loaders/Suite.cpp +++ b/src/loaders/Suite.cpp @@ -19,13 +19,52 @@ */ #include +#include +#include #include "Suite.h" +#include /// Suite_InvalidUnitMember - Exception thrown when a Suite tries to access a contained Unit's value that is not /// present in the Unit. -class Suite_InvalidUnitMember: public std::runtime_error { public: - // TODO rework this to accept the name of the member not able to be fetched. - Suite_InvalidUnitMember(): std::runtime_error("Suite: Attempted to access a member of a Unit that is not set.") {} +class SuiteException: public std::exception +{ +public: + /** Constructor (C strings). + * @param message C-style string error message. + * The string contents are copied upon construction. + * Hence, responsibility for deleting the char* lies + * with the caller. + */ + explicit SuiteException(const char* message): + msg_(message) + { + } + + /** Constructor (C++ STL strings). + * @param message The error message. + */ + explicit SuiteException(const std::string& message): + msg_(message) + {} + + /** Destructor. + * Virtual to allow for subclassing. + */ + virtual ~SuiteException() throw (){} + + /** Returns a pointer to the (constant) error description. + * @return A pointer to a const char*. The underlying memory + * is in posession of the Exception object. Callers must + * not attempt to free the memory. + */ + virtual const char* what() const throw (){ + return msg_.c_str(); + } + +protected: + /** Error message. + */ + std::string msg_; }; @@ -42,40 +81,115 @@ class Suite_InvalidUnitMember: public std::runtime_error { public: /// if the implementor so desires. Suite::Suite(): JSON_Loader() {}; + +bool is_file( std::string path) +{ + struct stat buf; + stat( path.c_str(), &buf ); + return S_ISREG(buf.st_mode); +} + +bool is_dir( std::string path ) +{ + struct stat buf; + stat( path.c_str(), &buf ); + return S_ISDIR(buf.st_mode); +} + +void get_units_from_dir( std::vector * files, std::string path ) +{ + DIR* dirFile = opendir( path.c_str() ); + if ( dirFile ) + { + std::string entry; + + struct dirent* hFile; + errno = 0; + while (( hFile = readdir( dirFile )) != NULL ) + { + if ( !strcmp( hFile->d_name, "." )) continue; + if ( !strcmp( hFile->d_name, ".." )) continue; + + // hidden files + if ( hFile->d_name[0] == '.' ) continue; + + // dirFile.name is the name of the file. Do whatever string comparison + // you want here. Something like: + if ( strstr( hFile->d_name, ".units" )) + { + std::string full_path = path + hFile->d_name; + files->push_back( full_path ); + } + } + closedir( dirFile ); + } else { + std::cout << "file not found" << std::endl; + } +} + + + /// Suite::load_units_file - Uses the json_root buffer on each run to append intact Units as they're /// deserialized from the provided file. /// -/// \param filename - The file to pull the JSON-formatted units from. +/// \param units_path - The file to pull the JSON-formatted units from. /// \param verbose - Whether to print verbose output to STDOUT. -void Suite::load_units_file( std::string filename, bool verbose ) +void Suite::load_units_file( std::string units_path, bool verbose ) { - // will use json_root buffer on each run to append to this->units vector as valid units are found. - this->load_json_file( filename, verbose ); + std::vector unit_files; - // staging buffer - Json::Value jbuff; - - // fill the jbuff staging buffer with a json::value object in the supplied filename - if ( this->get_serialized( jbuff, "units", verbose ) == 0) + if ( is_dir( units_path ) ) { - this->json_root = jbuff; + // we have a directory path. find all files ending in *.units and load them into a vector + get_units_from_dir( &unit_files, units_path ); } - // iterate through the json::value members that have been loaded. append to this->units vector - // buffer for units to append: - Unit tmp_U; - for ( int index = 0; index < this->json_root.size(); index++ ) + if ( is_file( units_path ) ) { - // assemble the unit from json_root using the built-in value operator - tmp_U.load_root( this->json_root[ index ] ); - if ( tmp_U.get_active() ) { - // append to this->units - this->units.push_back( tmp_U ); - if ( verbose ) { - std::cout << "Added unit \"" << tmp_U.get_name() << "\" to Suite." << std::endl; + unit_files.push_back( units_path ); + } + + std::ostringstream infostring; + infostring << "Unit files found: " << unit_files.size() << std::endl; + syslog(LOG_INFO, infostring.str().c_str() ); + std::cerr << infostring.str(); + + for ( int i = 0; i < unit_files.size(); i++ ) + { + // will use json_root buffer on each run to append to this->units vector as valid units are found. + this->load_json_file( unit_files[i], verbose ); + + // staging buffer + Json::Value jbuff; + + // fill the jbuff staging buffer with a json::value object in the supplied units_path + if ( this->get_serialized( jbuff, "units", verbose ) == 0) + { + this->json_root = jbuff; + } + + // iterate through the json::value members that have been loaded. append to this->units vector + // buffer for units to append: + Unit tmp_U; + for ( int index = 0; index < this->json_root.size(); index++ ) + { + // assemble the unit from json_root using the built-in value operator + tmp_U.load_root( this->json_root[ index ] ); + if ( tmp_U.get_active() ) { + // append to this->units + this->units.push_back( tmp_U ); + if ( verbose ) { + std::ostringstream infostring; + infostring << "Added unit \"" << tmp_U.get_name() << "\" to Suite." << std::endl; + syslog(LOG_INFO, infostring.str().c_str() ); + std::cout << infostring.str(); + } } } } + + + } /// Suite::get_unit - returns a contained Unit identified by name attribute. @@ -99,8 +213,11 @@ void Suite::get_unit(Unit & result, std::string provided_name) if (! foundMatch ) { - std::cerr << "Unit name \"" << provided_name << "\" was referenced but not defined!" << std::endl; - throw Suite_InvalidUnitMember(); + std::ostringstream infostring; + infostring << "Unit name \"" << provided_name << "\" was referenced but not defined!" << std::endl; + syslog(LOG_ERR, infostring.str().c_str() ); + std::cerr << infostring.str(); + throw SuiteException( infostring.str() ); } }