Added using directives to avoid excessive namespaecs

Added explicit include directories to each file, even if an already included header defined them
Removed using directives from header files
This commit is contained in:
Egor 2024-10-28 12:32:14 +02:00
parent f8bfc78cad
commit ad976a5a9e
10 changed files with 121 additions and 83 deletions

View file

@ -1,19 +1,27 @@
#include "tape_config.h" #include "tape_config.h"
#include "tapelib/filetape.h"
#include "tapelib/tape.h"
#include "tapelib/tape_util.h" #include "tapelib/tape_util.h"
#include <chrono> #include <chrono>
#include <cstddef> #include <cstddef>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <memory>
#include <string> #include <string>
using std::string;
using std::chrono::high_resolution_clock;
using std::chrono::milliseconds;
using namespace tape;
size_t get_mem_peak() { size_t get_mem_peak() {
const static std::string mem_info_file = "/proc/self/status"; const static string mem_info_file = "/proc/self/status";
const static std::string mem_field = "VmPeak:"; const static string mem_field = "VmPeak:";
std::ifstream status(mem_info_file); std::ifstream status(mem_info_file);
size_t mem = 0; size_t mem = 0;
std::string line; string line;
while (std::getline(status, line)) { while (std::getline(status, line)) {
if (line.find(mem_field) != std::string::npos) { if (line.find(mem_field) != string::npos) {
std::stringstream mem_line(line.substr(mem_field.size())); std::stringstream mem_line(line.substr(mem_field.size()));
mem_line >> mem; mem_line >> mem;
return mem; return mem;
@ -36,29 +44,27 @@ int main(int argc, char *argv[]) {
!read_settings_from_file(settings)) { !read_settings_from_file(settings)) {
return -1; return -1;
} }
tape::FileTape input(settings.input_file_name, settings.ft_settings); FileTape input(settings.input_file_name, settings.ft_settings);
if (!input.is_open()) { if (!input.is_open()) {
std::cerr << "Failed to create INPUT tape - file not found or " std::cerr << "Failed to create INPUT tape - file not found or "
"insufficient permissions" "insufficient permissions"
<< std::endl; << std::endl;
return -1; return -1;
} }
tape::FileTape output(input, settings.output_file_name, FileTape output(input, settings.output_file_name, settings.ft_settings);
settings.ft_settings);
if (!output.is_open()) { if (!output.is_open()) {
std::cerr << "Failed to create OUTPUT tape - insufficient permissions" std::cerr << "Failed to create OUTPUT tape - insufficient permissions"
<< std::endl; << std::endl;
return -1; return -1;
} }
// tmp tape factory that captures settings.ft_settings from local scope // tmp tape factory that captures settings.ft_settings from local scope
tape::TempTapeFactory factory = TempTapeFactory factory = [&](size_t cells) -> std::unique_ptr<Tape> {
[&](size_t cells) -> std::unique_ptr<tape::Tape> { return std::make_unique<FileTape>(
return std::make_unique<tape::FileTape>( FileTape(cells, settings.ft_settings));
tape::FileTape(cells, settings.ft_settings));
}; };
auto start = std::chrono::high_resolution_clock::now(); auto start = high_resolution_clock::now();
tape::external_sort(input, output, factory, settings.memory_limit); external_sort(input, output, factory, settings.memory_limit);
auto end = std::chrono::high_resolution_clock::now(); auto end = high_resolution_clock::now();
auto duration = std::chrono::duration_cast<milliseconds>(end - start); auto duration = std::chrono::duration_cast<milliseconds>(end - start);
std::cout << "Successfully sorted " << settings.input_file_name << " into " std::cout << "Successfully sorted " << settings.input_file_name << " into "
<< settings.output_file_name << std::endl; << settings.output_file_name << std::endl;

View file

@ -1,10 +1,17 @@
#include "tape_config.h" #include "tape_config.h"
#include "tapelib/filetape.h"
#include <bits/getopt_core.h> #include <bits/getopt_core.h>
#include <chrono>
#include <cstddef>
#include <fstream> #include <fstream>
#include <getopt.h> #include <getopt.h>
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <vector>
using std::string;
using std::chrono::milliseconds;
const static struct std::vector<option> CMD_OPTS{ const static struct std::vector<option> CMD_OPTS{
{.name = "write-delay", {.name = "write-delay",
@ -32,9 +39,9 @@ const static struct std::vector<option> CMD_OPTS{
{.name = "help", .has_arg = no_argument, .flag = nullptr, .val = 'h'}, {.name = "help", .has_arg = no_argument, .flag = nullptr, .val = 'h'},
{.name = nullptr, .has_arg = no_argument, .flag = nullptr, .val = 0}}; {.name = nullptr, .has_arg = no_argument, .flag = nullptr, .val = 0}};
std::chrono::milliseconds parse_delay(const std::string &input) { milliseconds parse_delay(const string &input) {
int delay_ms = std::stoi(input); int delay_ms = std::stoi(input);
return std::chrono::milliseconds(delay_ms); return milliseconds(delay_ms);
} }
AppSettings parse_command_line(int argc, char **argv) { AppSettings parse_command_line(int argc, char **argv) {
@ -105,15 +112,15 @@ bool read_settings_from_file(AppSettings &settings) {
<< std::endl; << std::endl;
return false; return false;
} }
std::string line; string line;
size_t line_number = 1; size_t line_number = 1;
while (std::getline(config, line)) { while (std::getline(config, line)) {
size_t delim_index = line.find(CFG_DELIMETER); size_t delim_index = line.find(CFG_DELIMETER);
if (delim_index >= line.size()) { if (delim_index >= line.size()) {
continue; continue;
} }
std::string key = line.substr(0, delim_index); string key = line.substr(0, delim_index);
std::string value = line.substr(delim_index + 1); string value = line.substr(delim_index + 1);
try { try {
if (key == "write-delay") { if (key == "write-delay") {
settings.ft_settings.write_delay = parse_delay(value); settings.ft_settings.write_delay = parse_delay(value);

View file

@ -2,6 +2,8 @@
#define TAPE_CONFIG_H #define TAPE_CONFIG_H
#include "tapelib/filetape.h" #include "tapelib/filetape.h"
#include <cstddef>
#include <string>
// stringizing opearator to convert macro into string literal // stringizing opearator to convert macro into string literal
#define xstr(s) str(s) #define xstr(s) str(s)

View file

@ -3,11 +3,12 @@
#include "tape.h" #include "tape.h"
#include <chrono> #include <chrono>
#include <cstddef>
#include <cstdint>
#include <fstream> #include <fstream>
#include <string>
#include <vector> #include <vector>
using std::chrono::milliseconds;
namespace tape { namespace tape {
/** /**
@ -15,17 +16,17 @@ namespace tape {
* such as read dealy, write delay etc. * such as read dealy, write delay etc.
*/ */
struct FileTapeSettings { struct FileTapeSettings {
milliseconds read_delay; std::chrono::milliseconds read_delay;
milliseconds write_delay; std::chrono::milliseconds write_delay;
milliseconds seek_forward_delay; std::chrono::milliseconds seek_forward_delay;
milliseconds seek_backwards_delay; std::chrono::milliseconds seek_backwards_delay;
}; };
const static struct FileTapeSettings FT_DEFAULT_SETTINGS = const static struct FileTapeSettings FT_DEFAULT_SETTINGS =
FileTapeSettings{.read_delay = milliseconds(0), FileTapeSettings{.read_delay = std::chrono::milliseconds(0),
.write_delay = milliseconds(0), .write_delay = std::chrono::milliseconds(0),
.seek_forward_delay = milliseconds(0), .seek_forward_delay = std::chrono::milliseconds(0),
.seek_backwards_delay = milliseconds(0)}; .seek_backwards_delay = std::chrono::milliseconds(0)};
const static char FT_DELIMETER = '\n'; const static char FT_DELIMETER = '\n';

View file

@ -8,21 +8,19 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
using std::unique_ptr;
namespace tape { namespace tape {
/** /**
* Lambda, which takes the amount of cells a tape should have and returns * Lambda, which takes the amount of cells a tape should have and returns
* a unique pointer to a temporary Tape with the specified amount of cells * a unique pointer to a temporary Tape with the specified amount of cells
*/ */
using TempTapeFactory = std::function<unique_ptr<Tape>(size_t)>; using TempTapeFactory = std::function<std::unique_ptr<Tape>(size_t)>;
/** /**
* TempTapeFactory that creates a new temporary FileTape * TempTapeFactory that creates a new temporary FileTape
*/ */
const static inline TempTapeFactory FILETAPE_FACTORY = const static inline TempTapeFactory FILETAPE_FACTORY =
[](size_t cells) -> unique_ptr<Tape> { [](size_t cells) -> std::unique_ptr<Tape> {
return std::make_unique<FileTape>(FileTape(cells)); return std::make_unique<FileTape>(FileTape(cells));
}; };

View file

@ -1,36 +1,43 @@
#include "tapelib/filetape.h" #include "tapelib/filetape.h"
#include <array>
#include <cstddef> #include <cstddef>
#include <cstdint>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <sstream>
#include <string> #include <string>
#include <thread> #include <thread>
#include <vector>
using std::fstream; using std::fstream;
using std::setfill;
using std::setw;
using std::string;
using std::to_string;
using std::this_thread::sleep_for;
using tape::FileTape; using tape::FileTape;
std::string generate_tmp_file_name() { std::string generate_tmp_file_name() {
std::array<char, L_tmpnam> tmp_file_name{}; std::array<char, L_tmpnam> tmp_file_name{};
// tmpnam is unsafe, but its cross-platform
std::tmpnam(tmp_file_name.data()); std::tmpnam(tmp_file_name.data());
return tmp_file_name.data(); return tmp_file_name.data();
} }
FileTape::FileTape(const std::string file_name, const FileTapeSettings settings) FileTape::FileTape(const string file_name, const FileTapeSettings settings)
: settings(settings), file_name(file_name) { : settings(settings), file_name(file_name) {
this->file = fstream(file_name); this->file = fstream(file_name);
} }
FileTape::FileTape(const size_t cells, const std::string file_name, FileTape::FileTape(const size_t cells, const string file_name,
const FileTapeSettings settings) const FileTapeSettings settings)
: FileTape(file_name, settings) { : FileTape(file_name, settings) {
this->file = this->file =
fstream(this->file_name, fstream::in | fstream::out | fstream::trunc); fstream(this->file_name, fstream::in | fstream::out | fstream::trunc);
this->file << std::setfill('0') << std::setw(tape::FT_CELL_SIZE) << '0'; this->file << setfill('0') << setw(FT_CELL_SIZE) << '0';
for (size_t i = 1; i < cells; i++) { for (size_t i = 1; i < cells; i++) {
this->file << FT_DELIMETER << std::setfill('0') this->file << FT_DELIMETER << setfill('0') << setw(FT_CELL_SIZE) << '0';
<< std::setw(FT_CELL_SIZE) << '0';
} }
this->file.seekg(0, fstream::beg); this->file.seekg(0, fstream::beg);
} }
@ -40,22 +47,21 @@ FileTape::FileTape(const size_t cells, const FileTapeSettings settings)
this->tmp = true; this->tmp = true;
} }
FileTape::FileTape(FileTape &same_size_as, const std::string file_name, FileTape::FileTape(FileTape &same_size_as, const string file_name,
const FileTapeSettings settings) const FileTapeSettings settings)
: settings(settings), file_name(file_name) { : settings(settings), file_name(file_name) {
this->file = this->file =
fstream(this->file_name, fstream::in | fstream::out | fstream::trunc); fstream(this->file_name, fstream::in | fstream::out | fstream::trunc);
this->file << std::setfill('0') << std::setw(tape::FT_CELL_SIZE) << '0'; this->file << setfill('0') << setw(tape::FT_CELL_SIZE) << '0';
while (same_size_as.seek_forward()) { while (same_size_as.seek_forward()) {
file << tape::FT_DELIMETER << std::setfill('0') file << FT_DELIMETER << setfill('0') << setw(FT_CELL_SIZE) << '0';
<< std::setw(tape::FT_CELL_SIZE) << '0';
} }
this->file.seekg(0, fstream::beg); this->file.seekg(0, fstream::beg);
same_size_as.file.seekg(0, fstream::beg); same_size_as.file.seekg(0, fstream::beg);
} }
FileTape::FileTape(FileTape &same_size_as, const FileTapeSettings settings) FileTape::FileTape(FileTape &same_size_as, const FileTapeSettings settings)
: tape::FileTape(same_size_as, generate_tmp_file_name(), settings) { : FileTape(same_size_as, generate_tmp_file_name(), settings) {
this->tmp = true; this->tmp = true;
} }
@ -68,17 +74,16 @@ FileTape::FileTape(const std::vector<uint32_t> &data,
if (data.empty()) { if (data.empty()) {
return; return;
} }
this->file << std::setfill('0') << std::setw(FT_CELL_SIZE) this->file << setfill('0') << setw(FT_CELL_SIZE) << to_string(data[0]);
<< std::to_string(data[0]);
for (size_t i = 1; i < data.size(); i++) { for (size_t i = 1; i < data.size(); i++) {
this->file << FT_DELIMETER << std::setfill('0') this->file << FT_DELIMETER << setfill('0') << setw(FT_CELL_SIZE)
<< std::setw(FT_CELL_SIZE) << std::to_string(data[i]); << to_string(data[i]);
} }
this->file.seekg(0, fstream::beg); this->file.seekg(0, fstream::beg);
} }
bool FileTape::seek_backwards() { bool FileTape::seek_backwards() {
std::this_thread::sleep_for(this->settings.seek_backwards_delay); sleep_for(this->settings.seek_backwards_delay);
if (this->file.tellg() == 0) { if (this->file.tellg() == 0) {
return false; return false;
} }
@ -87,7 +92,7 @@ bool FileTape::seek_backwards() {
} }
bool FileTape::seek_forward() { bool FileTape::seek_forward() {
std::this_thread::sleep_for(this->settings.seek_forward_delay); sleep_for(this->settings.seek_forward_delay);
this->file.seekg(FT_SEEK_OFFSET, fstream::cur); this->file.seekg(FT_SEEK_OFFSET, fstream::cur);
this->file.peek(); // peek to check if eof is reached this->file.peek(); // peek to check if eof is reached
if (this->file.eof()) { if (this->file.eof()) {
@ -99,7 +104,7 @@ bool FileTape::seek_forward() {
} }
uint32_t FileTape::read() { uint32_t FileTape::read() {
std::this_thread::sleep_for(this->settings.read_delay); sleep_for(this->settings.read_delay);
uint32_t data = 0; uint32_t data = 0;
this->file >> data; this->file >> data;
if (this->file.eof()) { if (this->file.eof()) {
@ -112,10 +117,9 @@ uint32_t FileTape::read() {
} }
void FileTape::write(const uint32_t data) { void FileTape::write(const uint32_t data) {
std::this_thread::sleep_for(this->settings.write_delay); sleep_for(this->settings.write_delay);
std::stringstream cell; std::stringstream cell;
cell << std::setfill('0') << std::setw(FT_CELL_SIZE) cell << setfill('0') << setw(FT_CELL_SIZE) << to_string(data);
<< std::to_string(data);
this->file.write(cell.str().data(), FT_CELL_SIZE); this->file.write(cell.str().data(), FT_CELL_SIZE);
this->file.seekg(-FT_SEEK_OFFSET + 1, fstream::cur); this->file.seekg(-FT_SEEK_OFFSET + 1, fstream::cur);
} }

View file

@ -1,5 +1,11 @@
#include "tapelib/tape_util.h" #include "tapelib/tape_util.h"
#include "tapelib/tape.h"
#include <algorithm> #include <algorithm>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <vector>
using std::unique_ptr; using std::unique_ptr;
using std::vector; using std::vector;

View file

@ -1,14 +1,21 @@
#include "tapelib/filetape.h"
#include "tapelib/tape.h"
#include "tapelib/tape_util.h" #include "tapelib/tape_util.h"
#include <algorithm> #include <algorithm>
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
#include <cstdint>
#include <vector>
const static std::vector<uint32_t> TEST_DATA = {123, 26, 87, 266, 111, 234, using std::vector;
6, 63, 28, 1, 90, 33}; using namespace tape;
const static std::vector<uint32_t> TEST_DATA_SORTED = {
1, 6, 26, 28, 33, 63, 87, 90, 111, 123, 234, 266};
std::vector<uint32_t> read_from_tape_backwards(tape::Tape &tape) { const static vector<uint32_t> TEST_DATA = {123, 26, 87, 266, 111, 234,
std::vector<uint32_t> data; 6, 63, 28, 1, 90, 33};
const static vector<uint32_t> TEST_DATA_SORTED = {1, 6, 26, 28, 33, 63,
87, 90, 111, 123, 234, 266};
vector<uint32_t> read_from_tape_backwards(Tape &tape) {
vector<uint32_t> data;
do { do {
data.push_back(tape.read()); data.push_back(tape.read());
} while (tape.seek_backwards()); } while (tape.seek_backwards());
@ -16,40 +23,39 @@ std::vector<uint32_t> read_from_tape_backwards(tape::Tape &tape) {
return data; return data;
} }
// NOLINTBEGIN(*-magic-numbers) // NOLINTBEGIN
TEST_CASE("Sorting FileTape with external sort", "[sort]") { TEST_CASE("Sorting FileTape with external sort", "[sort]") {
tape::FileTape input(TEST_DATA); FileTape input(TEST_DATA);
tape::FileTape output(input); FileTape output(input);
SECTION("Sorting with no limitations") { SECTION("Sorting with no limitations") {
tape::external_sort(input, output, tape::FILETAPE_FACTORY); external_sort(input, output, FILETAPE_FACTORY);
REQUIRE(read_from_tape_backwards(output) == TEST_DATA_SORTED); REQUIRE(read_from_tape_backwards(output) == TEST_DATA_SORTED);
} }
SECTION("Sorting with 4 elements in memory limit") { SECTION("Sorting with 4 elements in memory limit") {
tape::external_sort(input, output, tape::FILETAPE_FACTORY, 4); external_sort(input, output, FILETAPE_FACTORY, 4);
REQUIRE(read_from_tape_backwards(output) == TEST_DATA_SORTED); REQUIRE(read_from_tape_backwards(output) == TEST_DATA_SORTED);
} }
SECTION("Sorting with 9 elements in memory limit") { SECTION("Sorting with 9 elements in memory limit") {
tape::external_sort(input, output, tape::FILETAPE_FACTORY, 9); external_sort(input, output, FILETAPE_FACTORY, 9);
REQUIRE(read_from_tape_backwards(output) == TEST_DATA_SORTED); REQUIRE(read_from_tape_backwards(output) == TEST_DATA_SORTED);
} }
SECTION("Sorting with vector size elements in memory limit") { SECTION("Sorting with vector size elements in memory limit") {
tape::external_sort(input, output, tape::FILETAPE_FACTORY, external_sort(input, output, FILETAPE_FACTORY, TEST_DATA.size());
TEST_DATA.size());
REQUIRE(read_from_tape_backwards(output) == TEST_DATA_SORTED); REQUIRE(read_from_tape_backwards(output) == TEST_DATA_SORTED);
} }
SECTION("Sorting with 1000 elements in memory limit") { SECTION("Sorting with 1000 elements in memory limit") {
tape::external_sort(input, output, tape::FILETAPE_FACTORY, 1000); external_sort(input, output, FILETAPE_FACTORY, 1000);
REQUIRE(read_from_tape_backwards(output) == TEST_DATA_SORTED); REQUIRE(read_from_tape_backwards(output) == TEST_DATA_SORTED);
} }
SECTION("Sorting with 1 elements in memory limit") { SECTION("Sorting with 1 elements in memory limit") {
tape::external_sort(input, output, tape::FILETAPE_FACTORY, 1); external_sort(input, output, FILETAPE_FACTORY, 1);
REQUIRE(read_from_tape_backwards(output) == TEST_DATA_SORTED); REQUIRE(read_from_tape_backwards(output) == TEST_DATA_SORTED);
} }
} }
// NOLINTEND(*-magic-numbers) // NOLINTEND

View file

@ -1,13 +1,16 @@
#include "tapelib/filetape.h" #include "tapelib/filetape.h"
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
#include <cstdint>
#include <vector> #include <vector>
const static std::vector<uint32_t> TEST_DATA = {1, 12345, 0, 2222222222, using std::vector;
4294967295}; using namespace tape;
// NOLINTBEGIN(readability-function-cognitive-complexity) const static vector<uint32_t> TEST_DATA = {1, 12345, 0, 2222222222, 4294967295};
// NOLINTBEGIN
TEST_CASE("Reading data from a FileTape", "[filetape]") { TEST_CASE("Reading data from a FileTape", "[filetape]") {
tape::FileTape tape(TEST_DATA); FileTape tape(TEST_DATA);
SECTION("Read all data sequentially") { SECTION("Read all data sequentially") {
REQUIRE(tape.read() == TEST_DATA[0]); REQUIRE(tape.read() == TEST_DATA[0]);
@ -38,7 +41,7 @@ TEST_CASE("Reading data from a FileTape", "[filetape]") {
} }
TEST_CASE("Seeking forward and backwards", "[filetape]") { TEST_CASE("Seeking forward and backwards", "[filetape]") {
tape::FileTape tape(TEST_DATA); FileTape tape(TEST_DATA);
SECTION("Rewinding at the beginning of a file tape") { SECTION("Rewinding at the beginning of a file tape") {
REQUIRE(tape.seek_backwards() == false); REQUIRE(tape.seek_backwards() == false);
@ -67,7 +70,7 @@ TEST_CASE("Seeking forward and backwards", "[filetape]") {
} }
TEST_CASE("Writing to a file tape", "[filetape]") { TEST_CASE("Writing to a file tape", "[filetape]") {
tape::FileTape tape(3); FileTape tape(3);
tape.write(0); tape.write(0);
REQUIRE(tape.read() == 0); REQUIRE(tape.read() == 0);
@ -83,4 +86,4 @@ TEST_CASE("Writing to a file tape", "[filetape]") {
tape.write(4); tape.write(4);
REQUIRE(tape.read() == 4); REQUIRE(tape.read() == 4);
} }
// NOLINTEND(readability-function-cognitive-complexity) // NOLINTEND

View file

@ -6,6 +6,12 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
using std::setfill;
using std::setw;
using std::string;
using std::to_string;
using namespace tape;
/** /**
* Generate big input data sets for external sort testing. * Generate big input data sets for external sort testing.
* Takes 2 positional arguments - first one is the ouput file name, * Takes 2 positional arguments - first one is the ouput file name,
@ -17,7 +23,7 @@ int main(int argc, char *argv[]) {
std::cerr << "Not enough arguments" << std::endl; std::cerr << "Not enough arguments" << std::endl;
return -1; return -1;
} }
std::string out_name = argv[1]; // NOLINT string out_name = argv[1]; // NOLINT
size_t cells = std::stoi(argv[2]); // NOLINT size_t cells = std::stoi(argv[2]); // NOLINT
std::ofstream out(out_name); std::ofstream out(out_name);
if (!out.is_open()) { if (!out.is_open()) {
@ -25,11 +31,10 @@ int main(int argc, char *argv[]) {
return -1; return -1;
} }
srand(time(nullptr)); srand(time(nullptr));
out << std::setfill('0') << std::setw(tape::FT_CELL_SIZE) out << setfill('0') << setw(tape::FT_CELL_SIZE) << to_string(rand());
<< std::to_string(rand());
for (size_t i = 1; i < cells; i++) { for (size_t i = 1; i < cells; i++) {
out << tape::FT_DELIMETER << std::setfill('0') out << FT_DELIMETER << setfill('0') << setw(tape::FT_CELL_SIZE)
<< std::setw(tape::FT_CELL_SIZE) << std::to_string(rand()); << to_string(rand());
} }
return 0; return 0;
} }