erius
ad976a5a9e
Added explicit include directories to each file, even if an already included header defined them Removed using directives from header files
210 lines
7 KiB
C++
210 lines
7 KiB
C++
#ifndef FILE_TAPE_H
|
|
#define FILE_TAPE_H
|
|
|
|
#include "tape.h"
|
|
#include <chrono>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace tape {
|
|
|
|
/**
|
|
* Strcuture for storing all possible settings for a file tape,
|
|
* such as read dealy, write delay etc.
|
|
*/
|
|
struct FileTapeSettings {
|
|
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 = 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';
|
|
|
|
// uint32_t digits max count is 10
|
|
const static int FT_CELL_SIZE = 10;
|
|
const static int FT_SEEK_OFFSET = FT_CELL_SIZE + 1;
|
|
|
|
/**
|
|
* Mock tape implementation that uses text files as data source.
|
|
*
|
|
* Simulates tape operations by artificially pausing the execution of some
|
|
* methods using time intervals, specified in command line arguments or a
|
|
* configuration file. Each cell is represented as a plain text 32-bit unsigned
|
|
* int, padded to FT_CELL_SIZE with leading zeroes, separated by FT_DELIMETER.
|
|
* Each cell MUST be FT_CELL_SIZE long to correctly implement write operation
|
|
* without re-writing the entire file.
|
|
*
|
|
* Example of a valid file for a FileTape
|
|
* - example.txt
|
|
* 000000001
|
|
* 000000034
|
|
* 000001234
|
|
* 123456789
|
|
* 000000000
|
|
*/
|
|
class FileTape : public Tape {
|
|
private:
|
|
std::string file_name;
|
|
std::fstream file;
|
|
FileTapeSettings settings;
|
|
bool tmp = false;
|
|
|
|
public:
|
|
/**
|
|
* Creating copies of FileTape creates 2+ fstreams to one file, which
|
|
* could introduce IO errors or data races if implemented incorrectly -
|
|
* mark the copy constructor as deleted. Moving is fine.
|
|
*/
|
|
FileTape(const FileTape &) = delete;
|
|
FileTape(FileTape &&) noexcept = default;
|
|
FileTape &operator=(const FileTape &) = delete;
|
|
FileTape &operator=(FileTape &&tape) = default;
|
|
|
|
/**
|
|
* Initializes a new instance of FileTape that will open an existing file
|
|
* with the specified name, already filled with data. File must be read and
|
|
* write accessible.
|
|
*
|
|
* @param file_name Name of a file to be opened.
|
|
* @param settings FileTape settings
|
|
*/
|
|
FileTape(std::string file_name,
|
|
FileTapeSettings settings = FT_DEFAULT_SETTINGS);
|
|
|
|
/**
|
|
* Initializes a new instance of FileTape that will create and open a file
|
|
* with the specified name and fill it with *cells* amount of zeroed cells.
|
|
* File must not exist and directory must be write accessible.
|
|
*
|
|
* Writing operations when filling file with zeroes will not introduce any
|
|
* delay.
|
|
*
|
|
* @param size Size of a newly created FileTpae
|
|
* @param file_name Name of a file to be created and opened
|
|
* @param settings FileTape settings
|
|
*/
|
|
FileTape(size_t cells, std::string file_name,
|
|
FileTapeSettings settings = FT_DEFAULT_SETTINGS);
|
|
|
|
/**
|
|
* Initializes a new instance of FileTape that will create and open a file
|
|
* with the specified name and fill it with zeroed cells - the amount of
|
|
* cells will be the same as the specified FileTape.
|
|
* File must not exist and directory must be write accessible.
|
|
*
|
|
* This is necessary in the situations when the FileTapse size is a bigger
|
|
* than size_t max value. Seeking will not introduce delay during this
|
|
* operation.
|
|
*
|
|
* @param same_size_as FileTape, the size of which will be carried over to
|
|
* the new FileTape
|
|
* @param file_name Name of a file to be created and opened
|
|
* @param settings FileTape settings
|
|
*/
|
|
FileTape(FileTape &same_size_as, std::string file_name,
|
|
FileTapeSettings = FT_DEFAULT_SETTINGS);
|
|
|
|
/**
|
|
* Initializes a new instance of FileTape that will create and open a
|
|
* temporary file and fill it with *cells* amount of zeroed cells.
|
|
*
|
|
* Writing operations when filling file with zeroes will not introduce any
|
|
* delay.
|
|
*
|
|
* @param size Size of a newly created FileTape
|
|
* @param settings FileTape settings
|
|
*/
|
|
FileTape(size_t cells, FileTapeSettings settings = FT_DEFAULT_SETTINGS);
|
|
|
|
/**
|
|
* Initializes a new instance of FileTape that will create and open a
|
|
* temporary file and fill it with zeroed cells -
|
|
* the amount of cells will be the same as the specified FileTape. File must
|
|
* not exist and directory must be write accessible.
|
|
*
|
|
* This is necessary in the situations when the FileTapse size is a bigger
|
|
* than size_t max value. Seeking will not introduce delay during this
|
|
* operation.
|
|
*
|
|
* @param same_size_as FileTape, the size of which will be carried over to
|
|
* the new FileTape
|
|
* @param file_name Name of a file to be created and opened
|
|
* @param settings FileTape settings
|
|
*/
|
|
FileTape(FileTape &same_size_as, FileTapeSettings = FT_DEFAULT_SETTINGS);
|
|
|
|
/**
|
|
* Initializes a new instance of FileTape that will create and open a
|
|
* temporary file, and fill it with the data from the provided vector.
|
|
*
|
|
* Writing operations when copying vector to a FileTape will not have any
|
|
* delay.
|
|
* Use this constructor ONLY FOR TESTING. Do NOT use it to copy one
|
|
* FileTape's data to another.
|
|
*
|
|
* @param data Vector of uint32 contents of which will be copied to FileTape
|
|
* @param settings FileTape settings
|
|
*/
|
|
FileTape(const std::vector<uint32_t> &data,
|
|
FileTapeSettings settings = FT_DEFAULT_SETTINGS);
|
|
|
|
/**
|
|
* Advances the underlying fstream to a new line.
|
|
*
|
|
* @return false if empty line is reached, otherwise true.
|
|
*/
|
|
bool seek_forward() override;
|
|
|
|
/**
|
|
* Rewinds the underlying fstream to a previous line.
|
|
*
|
|
* @return false if called from the first line of a file, otherwise true.
|
|
*/
|
|
bool seek_backwards() override;
|
|
|
|
/**
|
|
* Reads and parses data from the current line.
|
|
*
|
|
* @return number from the line, or 0 if data can not be parsed.
|
|
*/
|
|
uint32_t read() override;
|
|
|
|
/**
|
|
* Writes data to the current line.
|
|
*
|
|
* @param data Number, that should be written to the current line.
|
|
*/
|
|
void write(uint32_t data) override;
|
|
|
|
/**
|
|
* Close the undetlying fstream, and, in case the FileTape is marked as
|
|
* temporary (tmp is set to true), remove the temporary file
|
|
*/
|
|
~FileTape() override;
|
|
|
|
// Define getters in header file since they are implicitly inlined
|
|
|
|
bool is_tmp() const { return this->tmp; }
|
|
|
|
bool is_open() const { return this->file.is_open(); }
|
|
|
|
const FileTapeSettings &get_settings() const { return this->settings; }
|
|
|
|
const std::string &get_file_name() const { return this->file_name; }
|
|
|
|
const std::fstream &get_file() const { return this->file; }
|
|
};
|
|
|
|
} // namespace tape
|
|
|
|
#endif // !FILE_TAPE_H
|