diff --git a/headers/assets/scaffold_texts.hpp b/headers/assets/scaffold_texts.hpp index ef82e0d..6660b33 100644 --- a/headers/assets/scaffold_texts.hpp +++ b/headers/assets/scaffold_texts.hpp @@ -6,7 +6,7 @@ namespace assets::scaffold_texts { using std::string; - const string GITIGNORE = R"( + const string GITIGNORE = R"( .internals build environments/*.env @@ -39,8 +39,8 @@ namespace assets::scaffold_texts { using ALLOWED_ENV_DATA_TYPES = std::variant; - ALLOWED_ENV_DATA_TYPES get_env(const string key); - void prepare_env(std::map env); + ALLOWED_ENV_DATA_TYPES get_env(const string& key); + void prepare_env(std::map& env); } #endif @@ -61,7 +61,9 @@ namespace assets::scaffold_texts { #include "cbt_tools/utils.hpp" - namespace cbt_tools::env_manager { + namespace { + using namespace cbt_tools::env_manager; + namespace fs = std::filesystem; using std::cerr; @@ -76,36 +78,36 @@ namespace assets::scaffold_texts { std::map env_values; // Add/update necessary parsers as required - std::map> PARSERS{ - { "bool", [](const string key, const string value) { + std::map> PARSERS{ + { "bool", [](const string& key, const string& value) { if (value.compare("true") == 0 || value.compare("false") == 0) { return value.compare("true") == 0 ? true : false; } else { throw std::invalid_argument("Could not parse value for '" + key + "' to 'bool' type. Expected either 'true' or 'false'."); } }}, - { "int", [](const string key, const string value) { + { "int", [](const string& key, const string& value) { try { return std::stoi(value); - } catch (const std::invalid_argument &e) { + } catch (const std::invalid_argument& e) { throw std::invalid_argument("Could not parse value for '" + key + "' to 'int' type."); - } catch (const std::out_of_range &e) { + } catch (const std::out_of_range& e) { throw std::invalid_argument("Value for '" + key + "' falls out of range of 'int' type."); } }}, - { "float", [](const string key, const string value) { + { "float", [](const string& key, const string& value) { try { return std::stof(value); - } catch (const std::invalid_argument &e) { + } catch (const std::invalid_argument& e) { throw std::invalid_argument("Could not parse value for '" + key + "' to 'float' type."); - } catch (const std::out_of_range &e) { + } catch (const std::out_of_range& e) { throw std::invalid_argument("Value for '" + key + "' falls out of range of 'float' type."); } }}, - { "string", []([[maybe_unused]] const string _, const string value) { return value; } }, + { "string", []([[maybe_unused]] const string& _, const string& value) { return value; } }, }; - void __set(const string key, const string value) { + void set(const string& key, const string& value) { // Use the below conditional checks and keep adding the keys // that have been defined in 'environments/.env.template' file @@ -121,16 +123,7 @@ namespace assets::scaffold_texts { } // You would typically not need to touch this function - ALLOWED_ENV_DATA_TYPES get_env(const string key) { - if (env_values.contains(key)) { - return env_values[key]; - } else { - throw std::invalid_argument("Trying to access invalid key '" + key + "'"); - } - } - - // You would typically not need to touch this function - void __read_template_file() { + void read_template_file() { const string template_file_name{ "environments/.env.template" }; if (fs::exists(template_file_name)) { @@ -154,7 +147,7 @@ namespace assets::scaffold_texts { } // You would typically not need to touch this function - void __read_env_file(const string env) { + void read_env_file(const string& env) { const string env_file_name{ "environments/" + env + ".env" }; ifstream env_file(env_file_name); @@ -168,22 +161,33 @@ namespace assets::scaffold_texts { if (!env_template.contains(key)) { throw std::domain_error("Key '" + key + "' absent in 'environments/.env.template'"); } else { - __set(key, value); + set(key, value); } } } + } + namespace cbt_tools::env_manager { // You would typically not need to touch this function - void prepare_env(std::map env) { + ALLOWED_ENV_DATA_TYPES get_env(const string& key) { + if (env_values.contains(key)) { + return env_values[key]; + } else { + throw std::invalid_argument("Trying to access invalid key '" + key + "'"); + } + } + + // You would typically not need to touch this function + void prepare_env(std::map& env) { try { - __read_template_file(); + read_template_file(); if (env["env"].length() != 0) { - __read_env_file(env["env"]); + read_env_file(env["env"]); } else { - __read_env_file("local"); + read_env_file("local"); } - } catch (const std::exception &e) { + } catch (const std::exception& e) { cerr << endl << "Exception: " << e.what() << endl << endl; std::exit(EXIT_FAILURE); } @@ -206,7 +210,7 @@ namespace assets::scaffold_texts { // Note: Edit this parent class *only if* the harness provided is not upto your requirements class TestSuite { public: - virtual void add_test_case(const std::string title, std::function test_case) final { + virtual void add_test_case(const std::string& title, std::function test_case) final { test_cases.push_back(std::make_tuple(title, test_case)); } virtual void run() final { @@ -249,7 +253,7 @@ namespace assets::scaffold_texts { namespace cbt_tools::utils { using std::string; - std::tuple get_key_value_pair_from_line(const string line, const string delimiter); + std::tuple get_key_value_pair_from_line(const string& line, const string& delimiter); } #endif @@ -264,7 +268,7 @@ namespace assets::scaffold_texts { namespace cbt_tools::utils { using std::string; - std::tuple get_key_value_pair_from_line(const string line, const string delimiter) { + std::tuple get_key_value_pair_from_line(const string& line, const string& delimiter) { const int delimiter_position = line.find(delimiter); const string key = line.substr(0, delimiter_position); @@ -283,12 +287,13 @@ namespace assets::scaffold_texts { #include namespace @NAMESPACE { + void a_function(); + int sum(const int a, const int b); enum class Sex { MALE, - FEMALE, - NON_BINARY + FEMALE }; struct Person { @@ -310,18 +315,26 @@ namespace assets::scaffold_texts { class SampleCompany { public: - SampleCompany(const std::string location); - bool fire(const std::string employee_id, const std::string reason); + explicit SampleCompany(const std::string& name, const std::string& location, const Employee& founder); + + std::string get_name() const; std::string get_location() const; - Employee hire(const Person person); - bool is_candidate_eligible(const Person person) const; + Employee get_founder() const; + int strength() const; + + bool is_candidate_eligible(const Person& person) const; + void hire(const Person& person); + bool fire(const std::string& employee_id, const std::string& reason); + std::vector list_absentees() const; + friend std::ostream& operator<<(std::ostream& out, const SampleCompany& company); private: + std::string name; + std::string location; Employee founder; std::vector employees; - std::string location; }; } @@ -350,7 +363,7 @@ namespace assets::scaffold_texts { cbt_tools::env_manager::prepare_env(env); std::cout << "args[0]: " << args[0] << std::endl; - std::cout << "env[\"HOME\"]: " << env["HOME"] << std::endl; + std::cout << "env[\"HOME\"]: " << env["HOME"] << std::endl << std::endl; const std::string sample_env_key { "a_float_entry" }; auto env_value = cbt_tools::env_manager::get_env(sample_env_key); @@ -360,7 +373,19 @@ namespace assets::scaffold_texts { std::cout << "Env. value of '" << sample_env_key << "' is: " << value << std::endl; } - std::cout << "Sum of 2 and 3 is: " << sample::sum(2, 3) << std::endl; + std::cout << std::endl << "Sum of 2 and 3 is: " << sample::sum(2, 3) << std::endl << std::endl; + + sample::SampleCompany company("MyCompany", "MyLocation", sample::Employee{ + .id{ "#E1" }, + .first_name{ "First" }, + .last_name{ "Name" }, + .sex{ sample::Sex::MALE } + }); + + company.hire(sample::Person{ .first_name{ "F1" }, .last_name{ "L1" }, .sex{ sample::Sex::MALE } }); + company.hire(sample::Person{ .first_name{ "F2" }, .last_name{ "L2" }, .sex{ sample::Sex::FEMALE } }); + + std::cout << company; return EXIT_SUCCESS; } @@ -369,31 +394,88 @@ namespace assets::scaffold_texts { const string SAMPLE_CPP = R"( #include "@FILE_NAME" + #include #include + namespace { + using namespace @NAMESPACE; + + // Define all private functionalities here. These are auxiliary items + // that will be available only in this file. + + void some_helper() { + std::cout << "Helper called!"; + } + } + namespace @NAMESPACE { + void a_function() { + some_helper(); + } + int sum(const int a, const int b) { return a + b; } std::ostream& operator<<(std::ostream& out, const Person& person) { - out << person.first_name << std::endl; + out << "Person{" + << " first_name: " << std::quoted(person.first_name) + << ", last_name: " << std::quoted(person.last_name) + << ", sex: " << (person.sex == Sex::MALE ? 'M' : 'F') + << " }"; + return out; } std::ostream& operator<<(std::ostream& out, const Employee& employee) { - out << employee.id << std::endl; + out << "Employee{" + << " id: " << std::quoted(employee.id) + << ", first_name: " << std::quoted(employee.first_name) + << ", last_name: " << std::quoted(employee.last_name) + << ", sex: " << (employee.sex == Sex::MALE ? 'M' : 'F') + << " }"; + return out; } - SampleCompany::SampleCompany(std::string location): location(location){} + SampleCompany::SampleCompany(const std::string& name, const std::string& location, const Employee& founder): + name{ name }, + location{ location }, + founder{ founder } {} + + std::string SampleCompany::get_name() const { + return this->name; + } std::string SampleCompany::get_location() const { return this->location; } + Employee SampleCompany::get_founder() const { + return this->founder; + } + + int SampleCompany::strength() const { + return this->employees.size() + 1; + } + + void SampleCompany::hire(const Person& person) { + this->employees.push_back(Employee{ + .id{ "#E" + std::to_string(this->employees.size() + 1) }, + .first_name{ person.first_name }, + .last_name{ person.last_name }, + .sex{ person.sex } + }); + } + std::ostream& operator<<(std::ostream& out, const SampleCompany& company) { - out << company.get_location() << std::endl; + out << "Company{\n" + << " name: " << std::quoted(company.get_name()) << "\n" + << " location: " << std::quoted(company.get_location()) << "\n" + << " founder: " << company.get_founder() << "\n" + << " strength: " << company.strength() << "\n" + << "}" << std::endl; + return out; } } @@ -428,7 +510,6 @@ namespace assets::scaffold_texts { // add your environment variables and functionalities here, if necessary int sample_env_int{ 0 }; - @NAMESPACE::SampleCompany sample_company{ "Sample location" }; }; int main() { @@ -436,16 +517,37 @@ namespace assets::scaffold_texts { std::cout << std::endl << std::setw(8) << "EXECUTE " << __FILE__ << std::endl << std::endl; - test_suite.add_test_case("Test that sum of 5 and 6 is 11", []() { - assert((@NAMESPACE::sum(5, 6) == 11)); + test_suite.add_test_case("Sum of 5 and 6 is 11", []() { + assert((sample::sum(5, 6) == 11)); }); - test_suite.add_test_case("Test that sum of 5 and 6 is not 12", []() { - assert((@NAMESPACE::sum(5, 6) != 12)); + test_suite.add_test_case("Sum of 5 and 6 is not 12", []() { + assert((sample::sum(5, 6) != 12)); }); - - test_suite.add_test_case("Test that sum of 3 and 7 is 10", []() { - assert((@NAMESPACE::sum(3, 7) == 10)); + + test_suite.add_test_case("Company foundation strength is 1", []() { + sample::SampleCompany company("MyCompany", "MyLocation", sample::Employee{ + .id{ "#E1" }, + .first_name{ "First" }, + .last_name{ "Name" }, + .sex{ sample::Sex::MALE } + }); + + assert((company.strength() == 1)); + }); + + test_suite.add_test_case("Company's strength is 3 upon hiring of 2 candidates", []() { + sample::SampleCompany company("MyCompany", "MyLocation", sample::Employee{ + .id{ "#E1" }, + .first_name{ "First" }, + .last_name{ "Name" }, + .sex{ sample::Sex::MALE } + }); + + company.hire(sample::Person{ .first_name{ "F1" }, .last_name{ "L1" }, .sex{ sample::Sex::MALE } }); + company.hire(sample::Person{ .first_name{ "F2" }, .last_name{ "L2" }, .sex{ sample::Sex::FEMALE } }); + + assert((company.strength() == 3)); }); test_suite.run(); diff --git a/headers/commands.hpp b/headers/commands.hpp index fda8443..e7af149 100644 --- a/headers/commands.hpp +++ b/headers/commands.hpp @@ -4,9 +4,9 @@ #include namespace commands { - void create_project(const std::string project_name); + void create_project(const std::string& project_name); - void create_file(const std::string file_name); + void create_file(const std::string& file_name); void compile_project(); void clear_build(); @@ -21,4 +21,4 @@ namespace commands { void show_usage(); } -#endif \ No newline at end of file +#endif diff --git a/headers/workspace/env_manager.hpp b/headers/workspace/env_manager.hpp index 07d95dc..e15be35 100644 --- a/headers/workspace/env_manager.hpp +++ b/headers/workspace/env_manager.hpp @@ -10,8 +10,8 @@ namespace workspace::env_manager { using ALLOWED_ENV_DATA_TYPES = std::variant; - ALLOWED_ENV_DATA_TYPES get_env(const string key); - void prepare_env(std::map env); + ALLOWED_ENV_DATA_TYPES get_env(const string& key); + void prepare_env(std::map& env); } -#endif \ No newline at end of file +#endif diff --git a/headers/workspace/modification_identifier.hpp b/headers/workspace/modification_identifier.hpp index 8641a32..814c7a3 100644 --- a/headers/workspace/modification_identifier.hpp +++ b/headers/workspace/modification_identifier.hpp @@ -4,14 +4,17 @@ #include #include #include +#include #include "workspace/project_config.hpp" namespace workspace::modification_identifier { namespace fs = std::filesystem; + using FileHash = decltype(fs::hash_value(std::declval())); + struct SourceFile { - std::size_t hash; + FileHash hash; std::string file_name; std::size_t last_modified_timestamp; @@ -20,19 +23,17 @@ namespace workspace::modification_identifier { mutable bool affected; mutable bool was_successful; - }; - struct __SourceFileComparator { - bool operator()(const SourceFile& left, const SourceFile& right) const { - return left.hash < right.hash; + bool operator<(const SourceFile& another_file) const { + return this->hash < another_file.hash; } }; - using SourceFiles = std::set; + using SourceFiles = std::set; std::size_t get_current_fileclock_timestamp(); SourceFiles list_all_files_annotated(const workspace::project_config::Project& project); - void persist_annotations(SourceFiles& bucket); + void persist_annotations(const SourceFiles& bucket); } #endif diff --git a/headers/workspace/project_config.hpp b/headers/workspace/project_config.hpp index 1757293..d43dee4 100644 --- a/headers/workspace/project_config.hpp +++ b/headers/workspace/project_config.hpp @@ -19,11 +19,9 @@ namespace workspace::project_config { struct Author { string name; string email_id; - }; - - struct __AuthorComparator { - bool operator()(const Author &left, const Author &right) const { - return left.name > right.name; + + bool operator<(const Author &another_author) const { + return this->name < another_author.name; } }; @@ -40,16 +38,16 @@ namespace workspace::project_config { string description; string version; - std::set authors; + std::set authors; std::set platforms; Config config; }; - string platform_to_string(const Platform platform); - Platform string_to_platform(const string platform); + string platform_to_string(const Platform& platform); + Platform string_to_platform(const string& platform); Project convert_cfg_to_model(); - string convert_model_to_cfg(const Project project, const bool add_disclaimer_text = true); + string convert_model_to_cfg(const Project& project, const bool add_disclaimer_text = true); } #endif diff --git a/headers/workspace/scaffold.hpp b/headers/workspace/scaffold.hpp index 2f26aef..56774e5 100644 --- a/headers/workspace/scaffold.hpp +++ b/headers/workspace/scaffold.hpp @@ -7,19 +7,21 @@ #include "workspace/modification_identifier.hpp" namespace workspace::scaffold { + using std::string; + const std::regex IMPORT_R{ "@FILE_NAME" }; const std::regex GUARD_R{ "@GUARD" }; const std::regex NAMESPACE_R{ "@NAMESPACE" }; const std::regex RELATIVE_SRC_R{ "@RELATIVE_SRC_FILE_NAME" }; - void create_file(const std::string project_name, const std::string file_name, const bool verbose = true); - bool create_directory(const std::string project_name, const std::string sub_directory = "", const bool multi_directory = false, const bool verbose = true); + void create_file(const string& project_name, const string& file_name, const bool verbose = true); + bool create_directory(const string& project_name, const string& sub_directory = "", const bool multi_directory = false, const bool verbose = true); void create_build_tree_as_necessary(); void create_internals_tree_as_necessary(); - void purge_old_binaries(const std::string path, workspace::modification_identifier::SourceFiles& annotated_files); + void purge_old_binaries(const string& path, const workspace::modification_identifier::SourceFiles& annotated_files); void exit_if_command_not_invoked_from_within_workspace(); } -#endif \ No newline at end of file +#endif diff --git a/headers/workspace/util.hpp b/headers/workspace/util.hpp index 27c993d..9603aee 100644 --- a/headers/workspace/util.hpp +++ b/headers/workspace/util.hpp @@ -15,15 +15,15 @@ namespace workspace::util { string change_case(string text, const TextCase casing); std::tuple does_name_contain_special_characters(const string& text, const bool is_it_for_project); - std::tuple is_valid_project_name(const string project_name); - std::tuple is_valid_file_name(const string file_name); - std::tuple get_qualified_names(const string full_file_path); - string convert_stemmed_name_to_guard_name(const string stemmed_name); - string convert_stemmed_name_to_namespace_name(const string stemmed_name); - std::tuple get_key_value_pair_from_line(const string line, const string delimiter); - string get_platform_formatted_filename(const string file_name); + std::tuple is_valid_project_name(const string& project_name); + std::tuple is_valid_file_name(const string& file_name); + std::tuple get_qualified_names(const string& full_file_path); + string convert_stemmed_name_to_guard_name(const string& stemmed_name); + string convert_stemmed_name_to_namespace_name(const string& stemmed_name); + std::tuple get_key_value_pair_from_line(const string& line, const string& delimiter); + string get_platform_formatted_filename(const string& file_name); string get_platform_formatted_filename(std::filesystem::path path); string get_ISO_date(); } -#endif \ No newline at end of file +#endif diff --git a/src/commands.cpp b/src/commands.cpp index 65840f0..2a96fc9 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -18,7 +18,7 @@ namespace commands { using std::string; using namespace workspace::project_config; - void create_project(const string project_name) { + void create_project(const string& project_name) { if (fs::exists(project_name)) { cout << "Directory '" << project_name << "' already exists!" << endl; return; @@ -72,7 +72,7 @@ namespace commands { } } - void create_file(const string file_name) { + void create_file(const string& file_name) { const auto [is_valid, reason_if_any] = workspace::util::is_valid_file_name(file_name); if (!is_valid) { @@ -193,7 +193,7 @@ namespace commands { const string SEPARATOR{ fs::path::preferred_separator }; for (auto dir_entry = fs::recursive_directory_iterator("build"); dir_entry != fs::recursive_directory_iterator(); ++dir_entry) { - const string normalised_path{ workspace::util::get_platform_formatted_filename(dir_entry -> path().string()) }; + const string normalised_path{ workspace::util::get_platform_formatted_filename(dir_entry->path().string()) }; if (!normalised_path.starts_with(BUILD_PATH)) { dir_entry.disable_recursion_pending(); @@ -201,7 +201,7 @@ namespace commands { if (fs::is_directory(*dir_entry)) { const int files_count = std::count_if( - fs::directory_iterator(dir_entry -> path()), + fs::directory_iterator(dir_entry->path()), {}, [](auto& file){ return file.is_regular_file(); } ); diff --git a/src/main.cpp b/src/main.cpp index a309819..98a2775 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -6,14 +7,7 @@ #include "commands.hpp" #include "workspace/scaffold.hpp" -using std::cerr; -using std::cout; -using std::endl; -using std::exception; -using std::string; -using std::vector; - -void parse_commands_and_execute(vector arguments) { +void parse_commands_and_execute(std::vector& arguments) { try { if (arguments.size() == 3) { if (arguments[1].compare("create-project") == 0) { @@ -47,19 +41,19 @@ void parse_commands_and_execute(vector arguments) { } else { commands::show_usage(); } - } catch (const exception & e) { - cerr << "Exception: " << e.what() << endl << endl; + } catch (const std::exception& e) { + std::cerr << "Exception: " << e.what() << std::endl << std::endl; std::exit(EXIT_FAILURE); } catch (...) { - cerr << "Something went wrong!" << endl << endl; + std::cerr << "Something went wrong!" << std::endl << std::endl; std::exit(EXIT_FAILURE); } } int main(const int argc, char *argv[]) { - vector args(argv, argv + argc); + std::vector args(argv, argv + argc); - cout << endl; + std::cout << std::endl; if (args.size() == 1) { commands::show_usage(); @@ -67,7 +61,7 @@ int main(const int argc, char *argv[]) { parse_commands_and_execute(args); } - cout << endl; + std::cout << std::endl; return EXIT_SUCCESS; } diff --git a/src/workspace/env_manager.cpp b/src/workspace/env_manager.cpp index 83b6e14..cc18c62 100644 --- a/src/workspace/env_manager.cpp +++ b/src/workspace/env_manager.cpp @@ -12,7 +12,9 @@ #include "workspace/util.hpp" -namespace workspace::env_manager { +namespace { + using namespace workspace::env_manager; + namespace fs = std::filesystem; using std::cerr; @@ -26,15 +28,15 @@ namespace workspace::env_manager { std::map env_template; std::map env_values; - std::map> PARSERS{ - { "bool", [](const string key, const string value) { + std::map> PARSERS{ + { "bool", [](const string& key, const string& value) { if (value.compare("true") == 0 || value.compare("false") == 0) { return value.compare("true") == 0 ? true : false; } else { throw std::invalid_argument("Could not parse value for '" + key + "' to 'bool' type. Expected either 'true' or 'false'."); } }}, - { "int", [](const string key, const string value) { + { "int", [](const string& key, const string& value) { try { return std::stoi(value); } catch (const std::invalid_argument &e) { @@ -43,7 +45,7 @@ namespace workspace::env_manager { throw std::invalid_argument("Value for '" + key + "' falls out of range of 'int' type."); } }}, - { "float", [](const string key, const string value) { + { "float", [](const string& key, const string& value) { try { return std::stof(value); } catch (const std::invalid_argument &e) { @@ -52,10 +54,10 @@ namespace workspace::env_manager { throw std::invalid_argument("Value for '" + key + "' falls out of range of 'float' type."); } }}, - { "string", []([[maybe_unused]] const string _, const string value) { return value; } }, + { "string", []([[maybe_unused]] const string& _, const string& value) { return value; } }, }; - void __set(const string key, const string value) { + void set_kv(const string& key, const string& value) { if (key.compare("a_bool_entry") == 0) { env_values["a_bool_entry"] = PARSERS["bool"](key, value); } else if (key.compare("an_int_entry") == 0) { @@ -67,15 +69,7 @@ namespace workspace::env_manager { } } - ALLOWED_ENV_DATA_TYPES get_env(const string key) { - if (env_values.contains(key)) { - return env_values[key]; - } else { - throw std::invalid_argument("Trying to access invalid key '" + key + "'"); - } - } - - void __read_template_file() { + void read_template_file() { const string template_file_name{ "environments/.env.template" }; if (fs::exists(template_file_name)) { @@ -98,7 +92,7 @@ namespace workspace::env_manager { } } - void __read_env_file(const string env) { + void read_env_file(const string& env) { const string env_file_name{ "environments/" + env + ".env" }; ifstream env_file(env_file_name); @@ -112,19 +106,29 @@ namespace workspace::env_manager { if (!env_template.contains(key)) { throw std::domain_error("Key '" + key + "' absent in 'environments/.env.template'"); } else { - __set(key, value); + set_kv(key, value); } } } +} - void prepare_env(std::map env) { +namespace workspace::env_manager { + ALLOWED_ENV_DATA_TYPES get_env(const string& key) { + if (env_values.contains(key)) { + return env_values[key]; + } else { + throw std::invalid_argument("Trying to access invalid key '" + key + "'"); + } + } + + void prepare_env(std::map& env) { try { - __read_template_file(); + read_template_file(); if (env["env"].length() != 0) { - __read_env_file(env["env"]); + read_env_file(env["env"]); } else { - __read_env_file("local"); + read_env_file("local"); } } catch (const std::exception &e) { cerr << endl << "Exception: " << e.what() << endl << endl; diff --git a/src/workspace/modification_identifier.cpp b/src/workspace/modification_identifier.cpp index 9f04a98..0c24687 100644 --- a/src/workspace/modification_identifier.cpp +++ b/src/workspace/modification_identifier.cpp @@ -14,33 +14,35 @@ #include "workspace/project_config.hpp" #include "workspace/util.hpp" -namespace workspace::modification_identifier { +namespace { + using namespace workspace::modification_identifier; + namespace cr = std::chrono; namespace fs = std::filesystem; using std::string; - using DB = std::map; + using DB = std::map; using RawDependencyTree = std::map>; const string MAKEFILE_PATH{ ".internals/tmp/makefile" }; const string TIMESTAMPS_PATH{ ".internals/timestamps.txt" }; - - std::tuple __compute_hash_and_file_pair(const string file_name) { + + std::tuple compute_hash_and_file_pair(const string& file_name) { const string normalised_file_name = workspace::util::get_platform_formatted_filename(file_name); const fs::path normalised_path = fs::path(normalised_file_name); return std::make_tuple(fs::hash_value(normalised_file_name), normalised_path); } - std::size_t __get_last_modified_timestamp(const fs::path path) { + std::size_t get_last_modified_timestamp(const fs::path& path) { return static_cast(cr::duration_cast(fs::last_write_time(path).time_since_epoch()).count()); } - std::tuple __parse_line(const string line) { + std::tuple parse_line(const string& line) { std::stringstream stream(line); - std::size_t hash; + FileHash hash; stream >> hash; stream.ignore(1); @@ -76,7 +78,7 @@ namespace workspace::modification_identifier { }); } - DB __read_internal_timestamps_file() { + DB read_internal_timestamps_file() { const string timestamps_file_name{ ".internals/timestamps.txt" }; DB files_with_timestamps{}; @@ -91,7 +93,7 @@ namespace workspace::modification_identifier { continue; } - const auto [hash, source_file] = __parse_line(line); + const auto [hash, source_file] = parse_line(line); files_with_timestamps[hash] = source_file; } } else { @@ -101,16 +103,16 @@ namespace workspace::modification_identifier { return files_with_timestamps; } - void __generate_makefile(const workspace::project_config::Project& project) { + void generate_makefile(const workspace::project_config::Project& project) { string files{ "src/*.cpp " }; const string SEPARATOR{ fs::path::preferred_separator }; for (auto dir_entry = fs::recursive_directory_iterator("src"); dir_entry != fs::recursive_directory_iterator(); ++dir_entry) { - const string normalised_path{ workspace::util::get_platform_formatted_filename(dir_entry -> path().string()) }; + const string normalised_path{ workspace::util::get_platform_formatted_filename(dir_entry->path().string()) }; if (fs::is_directory(*dir_entry)) { const int files_count = std::count_if( - fs::directory_iterator(dir_entry -> path()), + fs::directory_iterator(dir_entry->path()), {}, [](auto& file){ return file.is_regular_file(); } ); @@ -132,7 +134,7 @@ namespace workspace::modification_identifier { } } - RawDependencyTree __parse_makefile() { + RawDependencyTree parse_makefile() { const string makefile_name{ MAKEFILE_PATH }; if (fs::exists(makefile_name)) { @@ -173,7 +175,7 @@ namespace workspace::modification_identifier { const std::sregex_iterator words = std::sregex_iterator(line.begin(), line.end(), pattern); for (std::sregex_iterator match = words; match != std::sregex_iterator(); ++match) { - string file = match -> str(); + string file = match->str(); if (current_file.empty()) { current_file = file; @@ -195,7 +197,7 @@ namespace workspace::modification_identifier { } } - RawDependencyTree __convert_to_hpp_pov(RawDependencyTree& cpp_pov) { + RawDependencyTree convert_to_hpp_pov(const RawDependencyTree& cpp_pov) { RawDependencyTree hpp_pov; for (auto const& [file, dependencies]: cpp_pov) { @@ -211,13 +213,13 @@ namespace workspace::modification_identifier { return hpp_pov; } - SourceFile __get_or_construct_source_file(const string file_name, DB& timestamps_history) { - const auto [hash, file_path] = __compute_hash_and_file_pair(file_name); + SourceFile get_or_construct_source_file(const string& file_name, DB& timestamps_history) { + const auto [hash, file_path] = compute_hash_and_file_pair(file_name); if (timestamps_history.contains(hash)) { SourceFile source_file = timestamps_history[hash]; - const std::size_t file_last_modified_timestamp = __get_last_modified_timestamp(file_path); + const FileHash file_last_modified_timestamp = get_last_modified_timestamp(file_path); source_file.file_name = workspace::util::get_platform_formatted_filename(file_path); @@ -235,7 +237,7 @@ namespace workspace::modification_identifier { return SourceFile{ .hash{ hash }, .file_name{ workspace::util::get_platform_formatted_filename(file_path) }, - .last_modified_timestamp{ __get_last_modified_timestamp(file_path) }, + .last_modified_timestamp{ get_last_modified_timestamp(file_path) }, .compilation_start_timestamp{ static_cast(0) }, .compilation_end_timestamp{ static_cast(0) }, .affected { true }, @@ -244,18 +246,18 @@ namespace workspace::modification_identifier { } } - SourceFiles __construct_annotated_list_of_source_files( + SourceFiles construct_annotated_list_of_source_files( RawDependencyTree& hpp_pov, DB& timestamps_history ) { SourceFiles bucket{}; for (auto& [header_file, dependants]: hpp_pov) { - SourceFile hpp_file{ __get_or_construct_source_file(header_file, timestamps_history) }; + SourceFile hpp_file{ get_or_construct_source_file(header_file, timestamps_history) }; bucket.insert(hpp_file); for (auto& dependant: dependants) { - SourceFile cpp_file{ __get_or_construct_source_file(dependant, timestamps_history) }; + SourceFile cpp_file{ get_or_construct_source_file(dependant, timestamps_history) }; if (hpp_file.affected) { cpp_file.affected = true; @@ -265,8 +267,8 @@ namespace workspace::modification_identifier { bucket.insert(cpp_file); } else { if (auto existing_file = bucket.find(cpp_file); existing_file != bucket.end()) { - if (!existing_file -> affected && hpp_file.affected) { - existing_file -> affected = true; + if (!existing_file->affected && hpp_file.affected) { + existing_file->affected = true; } } } @@ -275,27 +277,29 @@ namespace workspace::modification_identifier { return bucket; } +} +namespace workspace::modification_identifier { std::size_t get_current_fileclock_timestamp() { return static_cast(cr::duration_cast(cr::file_clock::now().time_since_epoch()).count()); } SourceFiles list_all_files_annotated(const workspace::project_config::Project& project) { - DB timestamps_history = __read_internal_timestamps_file(); + DB timestamps_history = read_internal_timestamps_file(); - __generate_makefile(project); + generate_makefile(project); - RawDependencyTree cpp_pov = __parse_makefile(); - RawDependencyTree hpp_pov = __convert_to_hpp_pov(cpp_pov); + RawDependencyTree cpp_pov = parse_makefile(); + RawDependencyTree hpp_pov = convert_to_hpp_pov(cpp_pov); - SourceFiles bucket = __construct_annotated_list_of_source_files(hpp_pov, timestamps_history); + SourceFiles bucket = construct_annotated_list_of_source_files(hpp_pov, timestamps_history); fs::remove(MAKEFILE_PATH); return bucket; } - void persist_annotations(SourceFiles& bucket) { + void persist_annotations(const SourceFiles& bucket) { if (fs::exists(TIMESTAMPS_PATH)) { fs::remove(TIMESTAMPS_PATH); } diff --git a/src/workspace/project_config.cpp b/src/workspace/project_config.cpp index d2d52ed..35f88e9 100644 --- a/src/workspace/project_config.cpp +++ b/src/workspace/project_config.cpp @@ -15,7 +15,7 @@ namespace workspace::project_config { const string DELIMITER{ "=" }; const string LINE_COMMENT{ ";" }; - string platform_to_string(const Platform platform) { + string platform_to_string(const Platform& platform) { using enum workspace::project_config::Platform; switch(platform) { @@ -28,7 +28,7 @@ namespace workspace::project_config { } } - Platform string_to_platform(const string platform) { + Platform string_to_platform(const string& platform) { using enum workspace::project_config::Platform; if (platform.compare("bsd") == 0) { return BSD; } @@ -110,7 +110,7 @@ namespace workspace::project_config { } } - string convert_model_to_cfg(const Project project, const bool add_disclaimer_text) { + string convert_model_to_cfg(const Project& project, const bool add_disclaimer_text) { const string disclaimer_text{ std::string("; Since a rudimentary INI parser is used, ensure that the actual `key` and") + "\n; `value` pairs follow the same `key` and `value` format in this file which was" + "\n; provided while creation of the project. Also, ensure that each pair is" diff --git a/src/workspace/scaffold.cpp b/src/workspace/scaffold.cpp index 48e1f02..2e2c373 100644 --- a/src/workspace/scaffold.cpp +++ b/src/workspace/scaffold.cpp @@ -15,7 +15,9 @@ #include "workspace/project_config.hpp" #include "workspace/util.hpp" -namespace workspace::scaffold { +namespace { + using namespace workspace::scaffold; + namespace fs = std::filesystem; using namespace assets::scaffold_texts; @@ -26,7 +28,7 @@ namespace workspace::scaffold { using std::stringstream; using std::vector; - string __remove_raw_literal_indentations(const string raw_literal) { + string remove_raw_literal_indentations(const string& raw_literal) { string line, final_string; stringstream stream(raw_literal); vector lines; @@ -45,29 +47,29 @@ namespace workspace::scaffold { return final_string; } - string __get_predefined_text_content(const string file_name, const string project_name) { + string get_predefined_text_content(const string& file_name, const string& project_name) { if (file_name.compare(".gitignore") == 0) { - return __remove_raw_literal_indentations(GITIGNORE); + return remove_raw_literal_indentations(GITIGNORE); } else if (file_name.compare("docs/LICENSE.txt") == 0) { - return __remove_raw_literal_indentations(LICENSE_TXT); + return remove_raw_literal_indentations(LICENSE_TXT); } else if (file_name.compare("docs/Roadmap.md") == 0) { - return __remove_raw_literal_indentations(ROADMAP_MD); + return remove_raw_literal_indentations(ROADMAP_MD); } else if (file_name.compare("environments/.env.template") == 0) { - return __remove_raw_literal_indentations(ENV_TEMPLATE); + return remove_raw_literal_indentations(ENV_TEMPLATE); } else if (file_name.starts_with("environments/") && file_name.ends_with(".env")) { - return __remove_raw_literal_indentations(ENV_FILE); + return remove_raw_literal_indentations(ENV_FILE); } else if (file_name.compare("headers/cbt_tools/env_manager.hpp") == 0) { - return __remove_raw_literal_indentations(CBT_TOOLS_ENV_MANAGER_HPP); + return remove_raw_literal_indentations(CBT_TOOLS_ENV_MANAGER_HPP); } else if (file_name.compare("headers/cbt_tools/test_harness.hpp") == 0) { - return __remove_raw_literal_indentations(CBT_TOOLS_TEST_HARNESS_HPP); + return remove_raw_literal_indentations(CBT_TOOLS_TEST_HARNESS_HPP); } else if (file_name.compare("headers/cbt_tools/utils.hpp") == 0) { - return __remove_raw_literal_indentations(CBT_TOOLS_UTILS_HPP); + return remove_raw_literal_indentations(CBT_TOOLS_UTILS_HPP); } else if (file_name.compare("src/cbt_tools/env_manager.cpp") == 0) { - return __remove_raw_literal_indentations(CBT_TOOLS_ENV_MANAGER_CPP); + return remove_raw_literal_indentations(CBT_TOOLS_ENV_MANAGER_CPP); } else if (file_name.compare("src/cbt_tools/utils.cpp") == 0) { - return __remove_raw_literal_indentations(CBT_TOOLS_UTILS_CPP); + return remove_raw_literal_indentations(CBT_TOOLS_UTILS_CPP); } else if (file_name.ends_with(".hpp")) { - const string text{ __remove_raw_literal_indentations(SAMPLE_HPP) }; + const string text{ remove_raw_literal_indentations(SAMPLE_HPP) }; const auto [stemmed_name, guard_name, namespace_name] = workspace::util::get_qualified_names(file_name); const string with_guard = std::regex_replace(text, GUARD_R, guard_name); @@ -76,9 +78,9 @@ namespace workspace::scaffold { return final_text; } else if (file_name.compare("src/main.cpp") == 0) { - return __remove_raw_literal_indentations(MAIN_CPP); + return remove_raw_literal_indentations(MAIN_CPP); } else if (file_name.starts_with("tests/unit_tests/")) { - const string text{ __remove_raw_literal_indentations(SAMPLE_TEST_CPP) }; + const string text{ remove_raw_literal_indentations(SAMPLE_TEST_CPP) }; const auto [stemmed_name, _, namespace_name] = workspace::util::get_qualified_names(file_name); const string with_import = std::regex_replace(text, IMPORT_R, stemmed_name + ".cpp"); @@ -93,7 +95,7 @@ namespace workspace::scaffold { return final_text; } else if (file_name.ends_with(".cpp")) { - const string text{ __remove_raw_literal_indentations(SAMPLE_CPP) }; + const string text{ remove_raw_literal_indentations(SAMPLE_CPP) }; const auto [stemmed_name, _, namespace_name] = workspace::util::get_qualified_names(file_name); const string with_import = std::regex_replace(text, IMPORT_R, stemmed_name + ".hpp"); @@ -101,7 +103,7 @@ namespace workspace::scaffold { return final_text; } else if (file_name.compare("README.md") == 0) { - return __remove_raw_literal_indentations(README_MD); + return remove_raw_literal_indentations(README_MD); } else if (file_name.compare("project.cfg") == 0) { using namespace workspace::project_config; @@ -128,8 +130,10 @@ namespace workspace::scaffold { return ""; } } +} - void create_file(const string project_name, const string file_name, const bool verbose) { +namespace workspace::scaffold { + void create_file(const string& project_name, const string& file_name, const bool verbose) { const string full_path = (project_name.length() != 0 ? (project_name + "/") : project_name) + file_name; if (fs::exists(full_path)) { @@ -142,7 +146,7 @@ namespace workspace::scaffold { } ofstream file_to_write(full_path); - file_to_write << __get_predefined_text_content(file_name, project_name); + file_to_write << get_predefined_text_content(file_name, project_name); file_to_write.close(); if (verbose) { @@ -151,7 +155,7 @@ namespace workspace::scaffold { } } - bool create_directory(const string project_name, const string sub_directory, const bool multi_directory, const bool verbose) { + bool create_directory(const string& project_name, const string& sub_directory, const bool multi_directory, const bool verbose) { string full_path = (project_name.length() != 0 ? (project_name + "/") : project_name) + sub_directory + (sub_directory.length() != 0 ? "/" : ""); @@ -195,15 +199,13 @@ namespace workspace::scaffold { } } - void purge_old_binaries(const string path, workspace::modification_identifier::SourceFiles& annotated_files) { + void purge_old_binaries(const string& path, const workspace::modification_identifier::SourceFiles& annotated_files) { if (path.compare("build/binaries/") != 0 && path.compare("build/test_binaries/unit_tests/") != 0) { throw std::domain_error("Unknown path '" + path + "' provided for purging. Only 'build/binaries/' and 'build/test_binaries/unit_tests/' allowed."); } std::vector cpp_files{}; - const string MAIN_FILE{ "src" + string(1, fs::path::preferred_separator) + "main.cpp" }; - const auto literal_length_of_src{ string("src/").length() }; const auto literal_length_of_source_file_extension{ string(".cpp").length() }; const auto literal_length_of_binary_file_extension{ string(".o").length() }; diff --git a/src/workspace/util.cpp b/src/workspace/util.cpp index c2e66c8..7fac432 100644 --- a/src/workspace/util.cpp +++ b/src/workspace/util.cpp @@ -57,7 +57,7 @@ namespace workspace::util { return std::make_tuple(false, ""); } - std::tuple is_valid_project_name(const string project_name) { + std::tuple is_valid_project_name(const string& project_name) { const string lowercased_project_name = change_case(project_name, TextCase::LOWER_CASE); if (lowercased_project_name.find('/') != lowercased_project_name.npos || lowercased_project_name.find('\\') != lowercased_project_name.npos) { @@ -73,7 +73,7 @@ namespace workspace::util { } } - std::tuple is_valid_file_name(const string file_name) { + std::tuple is_valid_file_name(const string& file_name) { const string lowercased_file_name = change_case(file_name, TextCase::LOWER_CASE); if (lowercased_file_name.starts_with("headers/") && lowercased_file_name.length() == string("headers/").length()) { @@ -97,7 +97,7 @@ namespace workspace::util { } } - std::tuple get_qualified_names(const string full_file_path) { + std::tuple get_qualified_names(const string& full_file_path) { string stemmed_name{""}; const int literal_length_of_headers = string("headers/").length(); @@ -120,7 +120,7 @@ namespace workspace::util { ); } - string convert_stemmed_name_to_guard_name(const string stemmed_name) { + string convert_stemmed_name_to_guard_name(const string& stemmed_name) { return std::regex_replace( change_case(stemmed_name, TextCase::UPPER_CASE), std::regex("/", std::regex_constants::basic), @@ -128,7 +128,7 @@ namespace workspace::util { ); } - string convert_stemmed_name_to_namespace_name(const string stemmed_name) { + string convert_stemmed_name_to_namespace_name(const string& stemmed_name) { return std::regex_replace( change_case(stemmed_name, TextCase::LOWER_CASE), std::regex("/", std::regex_constants::basic), @@ -136,7 +136,7 @@ namespace workspace::util { ); } - std::tuple get_key_value_pair_from_line(const string line, const string delimiter) { + std::tuple get_key_value_pair_from_line(const string& line, const string& delimiter) { const int delimiter_position = line.find(delimiter); const string key = line.substr(0, delimiter_position); @@ -145,7 +145,7 @@ namespace workspace::util { return std::make_tuple(key, value); } - string get_platform_formatted_filename(const string file_name) { + string get_platform_formatted_filename(const string& file_name) { return get_platform_formatted_filename(std::filesystem::path(file_name)); }