This commit is contained in:
2021-10-14 13:47:35 +02:00
commit 6625a8dfaa
4026 changed files with 844291 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+355
View File
@@ -0,0 +1,355 @@
/*********************************************************************
* Software License Agreement (AGPL-3 License)
*
* OpenViBE SDK
* Based on OpenViBE V1.1.0, Copyright (C) Inria, 2006-2015
* Copyright (C) Inria, 2015-2017,V1.0
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <ovICSV.h>
#include <fstream>
#include <string>
#include <vector>
namespace OpenViBE {
namespace CSV {
class CCSVHandler final : public ICSVHandler
{
public:
/**
* \brief Set lib value to default
*/
CCSVHandler() : m_inputTypeID(EStreamType::StreamedMatrix), m_dimSizes({}) {}
/**
* \brief Close the file if it is open.
*/
~CCSVHandler() override { this->closeFile(); }
/**
* \brief Get the floating point precision used to write float values.
*
* \return the Floating point precision.
*/
size_t getOutputFloatPrecision() override { return m_oPrecision; }
/**
* \brief Set the floating point precision used to write float values.
*
* \param precision the floating point precision.
*/
void setOutputFloatPrecision(const size_t precision) override { m_oPrecision = precision; }
void setFormatType(const EStreamType typeID) override;
EStreamType getFormatType() override { return m_inputTypeID; }
void setLastMatrixOnlyMode(const bool isActivated) override { m_lastMatrixOnly = isActivated; }
bool getLastMatrixOnlyMode() override { return m_lastMatrixOnly; }
bool setSignalInformation(const std::vector<std::string>& channelNames, size_t sampling, size_t nSamplePerBuffer) override;
bool getSignalInformation(std::vector<std::string>& channelNames, size_t& sampling, size_t& nSamplePerBuffer) override;
bool setSpectrumInformation(const std::vector<std::string>& channelNames, const std::vector<double>& frequencyAbscissa, size_t sampling) override;
bool getSpectrumInformation(std::vector<std::string>& channelNames, std::vector<double>& frequencyAbscissa, size_t& sampling) override;
bool setFeatureVectorInformation(const std::vector<std::string>& channelNames) override;
bool getFeatureVectorInformation(std::vector<std::string>& channelNames) override;
bool setStreamedMatrixInformation(const std::vector<size_t>& dimSizes, const std::vector<std::string>& labels) override;
bool getStreamedMatrixInformation(std::vector<size_t>& dimSizes, std::vector<std::string>& labels) override;
/**
* \brief Write the header to the file
*
* \retval True in case of success.
* \retval False in case of error.
*/
bool writeHeaderToFile() override;
/**
* \brief Write current available data to the file until the last stimulation or if you set that it will not have new event before a date.
*
* \retval True in case of success.
* \retval False in case of error.
*
* \sa noEventsUntilDate
*/
bool writeDataToFile() override;
/**
* \brief Write current available data to the file.
*
* \retval True in case of success.
* \retval False in case of error.
*/
bool writeAllDataToFile() override;
/**
* \brief Read samples and stimulations.
*
* \param lineNb Maximum number of lines to read. If there is no more data in the file, the number of lines read can be lower.
* \param chunks[out] Valid chunks read.
* \param stimulations[out] Valid stimulations read.
*
* \retval True in case of success, even if the number of lines is different than the lineNb parameter.
* \retval False in case of error.
*/
bool readSamplesAndEventsFromFile(size_t lineNb, std::vector<SMatrixChunk>& chunks, std::vector<SStimulationChunk>& stimulations) override;
/**
* \brief Open a OV CSV file.
*
* \retval True in case of success.
* \retval False in case of error.
*/
bool openFile(const std::string& fileName, EFileAccessMode mode) override;
/**
* \brief Close the opened file.
*
* \retval True in case of success.
* \retval False in case of error.
*/
bool closeFile() override;
/**
* \brief Add a single sample.
*
* \retval True in case of success.
* \retval False in case of error.
*/
bool addSample(const SMatrixChunk& sample) override;
/**
* \brief Add several samples.
*
* \retval True in case of success.
* \retval False in case of error.
*/
bool addBuffer(const std::vector<SMatrixChunk>& samples) override;
/**
* \brief Add a single stimulation.
*
* \retval True in case of success.
* \retval False in case of error.
*/
bool addEvent(uint64_t code, double date, double duration) override;
/**
* \brief Add several stimulations.
*
* \retval True in case of success.
* \retval False in case of error.
*/
bool addEvent(const SStimulationChunk& event) override;
/**
* \brief Guarantee that will not have new event before a date.
* This information is used to allow the library to write all the chunks available, before this date, to a file.
*
* \retval True in case of success.
* \retval False in case of error.
*
* \sa writeDataToFile
*/
bool noEventsUntilDate(double date) override;
ELogErrorCodes getLastLogError() override { return m_logError; }
std::string getLastErrorString() override { return m_lastStringError; }
/**
* \brief Check if there is still data to read in the file.
*
* \retval True if there is still data to read in the file.
* \retval False if there is no more data to read in the file.
*/
bool hasDataToRead() const override { return m_hasDataToRead; }
private:
/**
* \brief Split a string into a vector of strings.
*
* \param in String to split.
* \param delimiter Delimitor.
* \param out[out] Vector of string.
*/
void split(const std::string& in, char delimiter, std::vector<std::string>& out) const;
/**
* \brief Create a string with stimulations to add in the buffer.
*
* \param stimulationsToPrint stimulations to put into the buffer
*
* \return string with stimulations to write
*/
std::string stimulationsToString(const std::vector<SStimulationChunk>& stimulationsToPrint) const;
/**
* \brief Create a string representation of the header data.
*
* \retval true Header data as it should be written in the file
* \retval "" in case of error
*/
std::string createHeaderString();
/**
* \brief Set the buffer in function of data saved.
*
* \param canWriteAll true if it must write all lines, false if it write only the next buffer
* \param csv The CSV string.
*
* \retval true in case of success
* \retval false in case of wrong data sent
*/
bool createCSVStringFromData(bool canWriteAll, std::string& csv);
/**
* \brief Parsing header to read data.
*
* \retval true in case of correct header
* \retval false in case of incorrect header
*/
bool parseHeader();
/**
* \brief Parsing header to read signal data.
*
* \param header[out]
*
* \retval true in case of correct header
* \retval false in case of incorrect header
*/
bool parseSignalHeader(const std::vector<std::string>& header);
/**
* \brief Parsing header to read Spectrum data.
*
* \param header[out]
*
* \retval true in case of correct header
* \retval false in case of incorrect header
*/
bool parseSpectrumHeader(const std::vector<std::string>& header);
/**
* \brief Parsing header to read matrix data (Streamed Matrix, Covariance matrix and Feature Vector).
*
* \param header[out]
*
* \retval true in case of correct header
* \retval false in case of incorrect header
*/
bool parseMatrixHeader(const std::vector<std::string>& header);
/**
* \brief Read line data concerning time, epoch and matrix.
*
* \param line line to read
* \param sample[out] reference to stock data in
* \param lineNb index of the read line
*
* \retval true in case of success
* \retval false in case of error (as letters instead of numbers)
*/
bool readSampleChunk(const std::string& line, SMatrixChunk& sample, size_t lineNb);
/**
* \brief Read line data conerning stimulations.
*
* \param line the line to read
* \param stimulations[out] vector to stock stimulations in (identifier, date and duration)
* \param lineNb the line actually reading
*
* \retval true in case of success
* \retval false in case of error (as letters instead of numbers)
*/
bool readStimulationChunk(const std::string& line, std::vector<SStimulationChunk>& stimulations, size_t lineNb);
/**
* \brief Update position into the matrix while reading or writing.
*
* \param position[out] is the position into the matrix
*
* \retval true in case of success
* \retval false in case of browse matrix
*/
bool increasePositionIndexes(std::vector<size_t>& position);
/**
* \brief Read lines of the first epoch to found sample count per buffer.
*
* \retval true in case of success
* \retval false in case of error
*/
bool calculateSampleCountPerBuffer();
/**
* \brief Read a stream until a delimiter and provide the string before the delimiter.
*
* \param in The stream to read.
* \param out The string before the next delimitor.
* \param delimiter The delimiter .
* \param bufferHistory
*/
bool streamReader(std::istream& in, std::string& out, char delimiter, std::string& bufferHistory) const;
std::fstream m_fs;
std::string m_filename;
std::deque<SMatrixChunk> m_chunks;
std::deque<SStimulationChunk> m_stimulations;
ELogErrorCodes m_logError = LogErrorCodes_NoError;
std::string m_lastStringError = "";
EStreamType m_inputTypeID;
typedef std::istream& GetLine(std::istream& in, std::string& out, char delimiter);
size_t m_nDim = 0;
std::vector<size_t> m_dimSizes;
std::vector<std::string> m_dimLabels;
size_t m_nSamplePerBuffer = 0;
double m_noEventSince = 0;
std::vector<double> m_frequencyAbscissa;
size_t m_sampling = 0;
size_t m_nCol = 0;
bool m_hasInputType = false;
bool m_isFirstLineWritten = false;
bool m_isHeaderRead = false;
bool m_isSetInfoCalled = false;
bool m_hasEpoch = false;
size_t m_nSampleOriginal = 0;
size_t m_oPrecision = 10;
bool m_lastMatrixOnly = false;
std::string m_bufferReadFileLine; // Buffer used to store unused read chars.
bool m_hasDataToRead = true;
#if defined TARGET_OS_Linux || defined TARGET_OS_MacOS
bool m_isCRLFEOL = false; // Is a CRLF end of line
#endif
};
} // namespace CSV
} // namespace OpenViBE
@@ -0,0 +1,50 @@
#include <map>
#include <ovICSV.h>
namespace OpenViBE {
namespace CSV {
static const std::map<ELogErrorCodes, std::string> ERROR_MAP =
{
{ LogErrorCodes_ErrorWhileClosing, "Error while closing the file" },
{ LogErrorCodes_NoFileDefined, "No file defined yet" },
{ LogErrorCodes_CantOpenFile, "Could not open the file" },
{ LogErrorCodes_DurationError, "The duration can't be negative" },
{ LogErrorCodes_DateError, "The date can't be negative" },
{ LogErrorCodes_NoSample, "Their is no sample to add" },
{ LogErrorCodes_NoMatrixLabels, "No matrix labels" },
{ LogErrorCodes_WrongMatrixSize, "Matrix size is different from the initial size" },
{ LogErrorCodes_MatrixEmpty, "A matrix of the buffer is empty" },
{ LogErrorCodes_DimensionSizeZero, "Dimensions can not have size equal to 0" },
{ LogErrorCodes_DimensionSizeEmpty, "Dimension sizes vector is empty" },
{ LogErrorCodes_NoChannelsName, "No channel names in the vector" },
{ LogErrorCodes_SetInfoOnce, "The setTypeInformation function should be called only once" },
{ LogErrorCodes_WrongInputType, "Wrong input type" },
{ LogErrorCodes_WrongHeader, "Error in the header of the file" },
{ LogErrorCodes_WrongLineSize, "There is a difference between the current line size and the size that it should have" },
{ LogErrorCodes_SampleNotEmpty, "Matrix must be empty to store in results of reading" },
{ LogErrorCodes_NotEnoughLines, "Can't reach the line in parameter, not enough lines in the file" },
{ LogErrorCodes_NegativeStimulation, "Stimulations cannot have negatives values" },
{ LogErrorCodes_WrongSampleDate, "Sample dates must be correct (greater than or equal to zero, and start date less than end date)" },
{ LogErrorCodes_InvalidStimulationArgument, "Wrong stimulation entry" },
{ LogErrorCodes_StimulationSize, "Some stimulation(s) has/have incomplete parameter(s)" },
{ LogErrorCodes_EmptyColumn, "A column of the file is empty" },
{ LogErrorCodes_WrongDimensionSize, "Size of dimension sizes vector must be equal to the number of dimensions" },
{ LogErrorCodes_DimensionCountZero, "Number of dimension must be at least 1" },
{ LogErrorCodes_OutOfRangeException, "Convertion from string to number is impossible : string is out of range" },
{ LogErrorCodes_InvalidArgumentException, "An invalid argument exeption have been thrown" },
{ LogErrorCodes_CantWriteHeader, "Can not write header, data already began to be written or header already written" },
{ LogErrorCodes_ErrorWhileWriting, "Error occured while trying to write" },
{ LogErrorCodes_WrongParameters, "Error with (one of )the parameter(s)" },
{ LogErrorCodes_MissingData, "Missing data in file, file may be corrupted" }
};
std::string ICSVHandler::getLogError(const ELogErrorCodes code)
{
if (ERROR_MAP.count(code) != 0) { return ERROR_MAP.at(code); }
return "Unknow error";
}
} // namespace CSV
} // namespace OpenViBE