Skip to content

Commit

Permalink
table: Doc added
Browse files Browse the repository at this point in the history
  • Loading branch information
Petr Laštovička committed May 18, 2022
1 parent d092350 commit aa9daad
Show file tree
Hide file tree
Showing 11 changed files with 596 additions and 86 deletions.
22 changes: 14 additions & 8 deletions Semestralni_prace/src/cz/lastaapps/vimxel/storage/storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,25 +57,28 @@ void Storage::exportData(shared_ptr<table::Table> table, const fs::path& path) {
}

void Storage::loadData(shared_ptr<table::Table>& table, const fs::path& path) {
table->deleteAll();
try {
ifstream file;
openFileForRead(path, file);
for (size_t y = 0; file; y++) {
for (size_t x = 0; file; x++) {
bool lineEnd;
string cellContent = move(importText(file, lineEnd));
auto insertRes = table->updateCell(table::Coordinates(x, y), cellContent);
if (!insertRes.success) throw invalid_argument("Cannot open file: "s + insertRes.message);
const string cellContent = importText(file, lineEnd);
const auto insertRes = table->updateCell(table::Coordinates(x, y), cellContent);
if (!insertRes.success)
throw invalid_argument("Cannot parse file: "s + insertRes.message);
if (lineEnd) break;
}
}
if (file.fail() || file.bad())
if (file.fail() && !file.eof())
throw runtime_error("Failed to load the file!");
table->clearChanged();
} catch (exception& e) {
} catch (exception* e) {
log(e->what());
table->deleteAll();
table->clearChanged();
throw e;
throw *e;
}
}

Expand Down Expand Up @@ -108,7 +111,10 @@ string Storage::importText(istream& stream, bool& lineEnd) {
char c;
stream >> noskipws;
stream >> c;
if (!stream) return "";
if (!stream) {
lineEnd = true;
return "";
}
bool isEncapsulated = c == ENCAPSULATOR;
if (!isEncapsulated) {
stream.unget();
Expand Down Expand Up @@ -151,7 +157,7 @@ void Storage::openFileForWrite(const fs::path& str, ofstream& stream) {
stream = ofstream(str, ios::out | ios::trunc);
}
void Storage::openFileForRead(const fs::path& str, ifstream& stream) {
if (!fs::exists(fs::path(str)))
if (!fs::exists(str))
throw invalid_argument("File does not exists");
stream = ifstream(str, ios::in);
}
Expand Down
65 changes: 63 additions & 2 deletions Semestralni_prace/src/cz/lastaapps/vimxel/storage/storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,92 @@ namespace fs = std::filesystem;

namespace cz::lastaapps::vimxel::storage {

/**
* @brief Manages all the IO operations
*/
class Storage final {
Storage() = delete;

public:
/**
* @brief Saves data in way they can be loaded next time, cell contents are saved
*
* @param table data to save
* @param path file to save data in
* @throw exception when writing file fails
*/
static void saveData(shared_ptr<table::Table> table, const fs::path& path);
/**
* @brief Exports data in CSV format, these data shouldn't be loaded next time
*
* @param table data to export
* @param path file to export data in
* @throw exception when writing file fails
*/
static void exportData(shared_ptr<table::Table> table, const fs::path& path);
/**
* @brief Loads data from file, they should be saved before by saveData() function
*
* @param table data storage to save cells into, is always cleared even if loading fails
* @param path file to read data from
* @throw exception when reading fails because of IO or because of malformed data
*/
static void loadData(shared_ptr<table::Table>& table, const fs::path& path);

private:
// used with CVS escaping
static constexpr char DELIMITER = ';';
static constexpr char LINE_DELIMITER = '\n';
static constexpr char ENCAPSULATOR = '"';
static void openFileForWrite(const fs::path& str, ofstream& stream);
static void openFileForRead(const fs::path& str, ifstream& stream);

/**
* @brief Creates output stream
*
* @param path file to file open
* @param stream place to assign stream to
*/
static void openFileForWrite(const fs::path& path, ofstream& stream);
/**
* @brief Creates input file stream
*
* @param path file to open
* @param stream place to assign stream to
*/
static void openFileForRead(const fs::path& path, ifstream& stream);

/**
* @brief Escapes text if needed to prevent problems with delimiter in text
*
* @param str text to escape
* @return excaped text
*/
static string escapeText(const string& str);
/**
* This is just a wrapper for importText(istream&, lineEnd)
*/
static string importText(const string& str);
/**
* @brief Does inverse operation for escapeText(), converts stream into normal expected data, just 1 cell per call
*
* @param stream stream to read data from
* @param lineEnd is set to true if line end was hit, if ; was hit, false is set
* @return unescaped content of a cell
*/
static string importText(istream& stream, bool& lineEnd);

// ha ha, my hidden tests
friend class StorageTester;
};

/**
* @brief File is wrongly encapsulated
*/
struct InvalidEncapsulation final : invalid_argument {
InvalidEncapsulation() : invalid_argument("Invalid encapsulation while reading a file") {}
};
/**
* @brief File is wrongly encapsulated, there is missing closing element
*/
struct SingleEncapsulator final : invalid_argument {
SingleEncapsulator() : invalid_argument("Single encapsulator found while reading a file") {}
};
Expand Down
5 changes: 2 additions & 3 deletions Semestralni_prace/src/cz/lastaapps/vimxel/table/cell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ namespace cz::lastaapps::vimxel::table {

// --- TextCell ---------------------------------------------------------------
TextCell::TextCell(string content, SSingleTerm term, bool inCycle)
: mContent(move(content)), mTerm(term), mInCycle(inCycle) {}
: mContent(move(content)), mTerm(term), mInCycle(inCycle) {}

const string& TextCell::getContent() const {
return mContent;
}
string TextCell::getValue() const {
if (mInCycle) return "CYCLE!";
return mTerm -> toString();
return mTerm->toString();
}
SSingleTerm TextCell::getTerm() const {
if (mInCycle) return EMPTY_TERM;
Expand All @@ -24,7 +24,6 @@ Cell* TextCell::clone() const {
return new TextCell(*this);
}


// --- EmptyCell --------------------------------------------------------------
const string& EmptyCell::getContent() const { return emptyString; }
string EmptyCell::getValue() const { return ""; }
Expand Down
71 changes: 59 additions & 12 deletions Semestralni_prace/src/cz/lastaapps/vimxel/table/cell.hpp
Original file line number Diff line number Diff line change
@@ -1,58 +1,105 @@
#ifndef H_CELL
#define H_CELL
#include <string>

#include "../expr/nodes/terms.hpp"
using namespace std;

namespace cz::lastaapps::vimxel::table {

using STerm = shared_ptr<expr::Term>;
using SSingleTerm = shared_ptr<expr::SingleTerm>;

/**
* @brief Represents a cell of a table
*
*/
class Cell {
public:
virtual ~Cell() {}
// real content
/**
* @brief Gets real content, what user has written
*
* @return cell content
*/
virtual const string& getContent() const = 0;
// value in table
/**
* @brief Get calculated value of the cell, but in string form
*
* @return cell value string
*/
virtual string getValue() const = 0;
// value for calculations
/**
* @brief Get calculated value of the cell
*
* @return cell value term
*/
virtual SSingleTerm getTerm() const = 0;
// cell in in a cycle
/**
* @brief Checks if the cell is in or depends on a cycle
*
* @return true if the cell is in a cycle
*/
virtual bool isInCycle() const = 0;

/**
* @brief Creates new copy of cell object
*
* @return new copy
*/
virtual Cell* clone() const = 0;

protected:
};

// just to save memory
const static auto EMPTY_TERM = make_shared<expr::DoubleTerm>(0.0L);

/**
* @brief Normal cell with content in it of any type
*/
class TextCell final : public Cell {
private:
private:
// user entered content
string mContent;
// value
SSingleTerm mTerm;
// if the cell is in a cycle
bool mInCycle;

public:
TextCell(string, SSingleTerm term, bool inCycle);
~TextCell() = default;
/**
* @brief Construct a new Text Cell object
*
* @param content cell content
* @param term cell term
* @param inCycle is cell in cycle
*/
TextCell(string content, SSingleTerm term, bool inCycle);
~TextCell() = default;

const string& getContent() const override;
string getValue() const override;
SSingleTerm getTerm() const override;
bool isInCycle() const override;
virtual Cell* clone() const override;
};

/**
* @brief Represents an empty cell
* This one shouldn't be saved into data storage (no item in preffered)
*/
class EmptyCell final : public Cell {
private:
private:
const string emptyString = "";

public:
~EmptyCell() = default;
~EmptyCell() = default;

const string& getContent() const override;
string getValue() const override;
SSingleTerm getTerm() const override;
bool isInCycle() const override;
virtual Cell* clone() const override;
};

} // namespace cz::lastaapps::vimexel::table
} // namespace cz::lastaapps::vimxel::table
#endif
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
#include "cellContract.hpp"


namespace cz::lastaapps::vimxel::table {
void CellContract::dataUpdatedAt(const Coordinates & coord) {
void CellContract::dataUpdatedAt(const Coordinates& coord) {
mCallback(coord);
}
void CellContract::registerCallback(Callback c) {
mCallback = c;
mCallback = c;
}
void CellContract::unregisterCallback() {
mCallback = Callback();
mCallback = Callback();
}
}
} // namespace cz::lastaapps::vimxel::table
41 changes: 33 additions & 8 deletions Semestralni_prace/src/cz/lastaapps/vimxel/table/cellContract.hpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,45 @@
#ifndef H_CELL_CONTRACT
#define H_CELL_CONTRACT
#include "coordinate.hpp"
#include <functional>
#include <list>

#include "coordinate.hpp"

using namespace std;
namespace cz::lastaapps::vimxel::table {

/**
* @brief Contract providing data from table to other app modules
*/
class CellContract {
using Callback = function<void(const Coordinates&)>;
// callback to call
Callback mCallback;
public:
virtual ~CellContract() {};
virtual string getDataAt(const Coordinates & coord) const = 0;
void dataUpdatedAt(const Coordinates & coord);
void registerCallback(Callback);
void unregisterCallback();

public:
virtual ~CellContract() = default;

/**
* @brief Gets the content of the cell at coord from data source
*
* @param coord the position of the cell
* @return cell content
*/
virtual string getDataAt(const Coordinates& coord) const = 0;
/**
* @brief called by data provider, notifies observers
*
* @param coord cell position
*/
void dataUpdatedAt(const Coordinates& coord);
/**
* @brief Register a callback, the old one is overwritten
*/
void registerCallback(Callback);
/**
* @brief unregisters callback
*/
void unregisterCallback();
};
}
} // namespace cz::lastaapps::vimxel::table
#endif
Loading

0 comments on commit aa9daad

Please sign in to comment.