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

View file

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

View file

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

View file

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

View file

@ -8,21 +8,19 @@
#include <functional>
#include <memory>
using std::unique_ptr;
namespace tape {
/**
* 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
*/
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
*/
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));
};

View file

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

View file

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

View file

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

View file

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

View file

@ -6,6 +6,12 @@
#include <iostream>
#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.
* 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;
return -1;
}
std::string out_name = argv[1]; // NOLINT
string out_name = argv[1]; // NOLINT
size_t cells = std::stoi(argv[2]); // NOLINT
std::ofstream out(out_name);
if (!out.is_open()) {
@ -25,11 +31,10 @@ int main(int argc, char *argv[]) {
return -1;
}
srand(time(nullptr));
out << std::setfill('0') << std::setw(tape::FT_CELL_SIZE)
<< std::to_string(rand());
out << setfill('0') << setw(tape::FT_CELL_SIZE) << to_string(rand());
for (size_t i = 1; i < cells; i++) {
out << tape::FT_DELIMETER << std::setfill('0')
<< std::setw(tape::FT_CELL_SIZE) << std::to_string(rand());
out << FT_DELIMETER << setfill('0') << setw(tape::FT_CELL_SIZE)
<< to_string(rand());
}
return 0;
}