10 #include <boost/algorithm/string/classification.hpp> 11 #include <boost/algorithm/string/constants.hpp> 12 #include <boost/algorithm/string/split.hpp> 21 : separator_(1, separator), values_(cols) {
25 : separator_(1, separator) {
34 boost::split(values_, line, boost::is_any_of(separator_),
35 boost::algorithm::token_compress_off);
47 for (
size_t i = 0; i < values_.size(); ++i) {
66 values_.resize(values_.size() - count);
75 CSVRow::checkIndex(
const size_t at)
const {
76 if (at >= values_.size()) {
77 isc_throw(CSVFileError,
"value index '" << at <<
"' of the CSV row" 78 " is out of bounds; maximal index is '" 79 << (values_.size() - 1) <<
"'");
84 : filename_(filename), fs_(), cols_(0), read_msg_() {
103 std::ifstream fs(filename_.c_str());
104 const bool file_exists = fs.good();
106 return (file_exists);
111 checkStreamStatusAndReset(
"flush");
128 if (std::find(cols_.begin(), cols_.end(), col_name) != cols_.end()) {
132 cols_.push_back(col_name);
137 checkStreamStatusAndReset(
"append");
153 fs_->seekp(0, std::ios_base::end);
154 fs_->seekg(0, std::ios_base::end);
157 std::string text = row.
render();
158 *fs_ << text << std::endl;
162 << text <<
"' to the file '" << filename_ <<
"'");
167 CSVFile::checkStreamStatusAndReset(
const std::string& operation)
const {
170 << operation <<
"' on file '" << filename_ <<
"'");
172 }
else if (!fs_->is_open()) {
174 isc_throw(CSVFileError,
"closed stream when performing '" 175 << operation <<
"' on file '" << filename_ <<
"'");
183 CSVFile::size()
const {
184 std::ifstream fs(filename_.c_str());
192 std::ifstream::pos_type pos;
196 fs.seekg(0, std::ifstream::end);
199 }
catch (
const std::exception&) {
207 for (
size_t i = 0; i < cols_.size(); ++i) {
208 if (cols_[i] == col_name) {
217 if (col_index >= cols_.size()) {
219 " CSV file '" << filename_ <<
"' is out of range; the CSV" 220 " file has only " << cols_.size() <<
" columns ");
222 return (cols_[col_index]);
234 checkStreamStatusAndReset(
"get next row");
243 std::getline(*fs_, line);
246 if (line.empty() && fs_->eof()) {
250 }
else if (!fs_->good()) {
253 setReadMsg(
"error reading a row from CSV file '" 254 + std::string(filename_) +
"'");
261 return (skip_validation ?
true :
validate(row));
267 if (size() == static_cast<std::streampos>(0)) {
272 fs_.reset(
new std::fstream(filename_.c_str()));
279 if (!fs_->is_open()) {
287 << filename_ <<
"'");
292 if (!
next(header,
true)) {
294 " CSV file '" << filename_ <<
"': " 301 <<
"' in CSV file '" << filename_ <<
"': " 316 fs_->seekp(0, std::ios_base::end);
317 fs_->seekg(0, std::ios_base::end);
320 " CSV file '" << filename_ <<
"'");
325 }
catch (
const std::exception&) {
338 " created CSV file '" << filename_ <<
"'");
343 fs_.reset(
new std::fstream(filename_.c_str(), std::fstream::out));
344 if (!fs_->is_open()) {
354 *fs_ << header << std::endl;
356 }
catch (
const std::exception& ex) {
368 std::ostringstream s;
369 s <<
"the size of the row '" << row <<
"' doesn't match the number of" bool exists() const
Checks if the CSV file exists and can be opened for reading.
virtual bool validateHeader(const CSVRow &header)
This function validates the header of the CSV file.
virtual void recreate()
Creates a new CSV file.
size_t getColumnCount() const
Returns the number of columns in the file.
static CSVRow EMPTY_ROW()
Represents empty row.
virtual ~CSVFile()
Destructor.
CSVFile(const std::string &filename)
Constructor.
void append(const CSVRow &row) const
Writes the CSV row into the file.
std::ostream & operator<<(std::ostream &os, const CSVRow &row)
Overrides standard output stream operator for CSVRow object.
std::string getFilename() const
Returns the path to the CSV file.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
void trim(const size_t count)
Trims a given number of elements from the end of a row.
virtual bool validate(const CSVRow &row)
Validate the row read from a file.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void addColumnInternal(const std::string &col_name)
Adds a column regardless if the file is open or not.
size_t getValuesCount() const
Returns number of values in a CSV row.
void parse(const std::string &line)
Parse the CSV file row.
void close()
Closes the CSV file.
Represents a single row of the CSV file.
void setReadMsg(const std::string &read_msg)
Sets error message after row validation.
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-dhcp-ddns.
CSVRow(const size_t cols=0, const char separator=',')
Constructor, creates the raw to be used for output.
void addColumn(const std::string &col_name)
Adds new column name.
void flush() const
Flushes a file.
std::string getColumnName(const size_t col_index) const
Returns the name of the column.
std::string getReadMsg() const
Returns the description of the last error returned by the CSVFile::next function.
size_t getColumnIndex(const std::string &col_name) const
Returns the index of the column having specified name.
std::string readAt(const size_t at) const
Retrieves a value from the internal container.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
void writeAt(const size_t at, const char *value)
Replaces the value at specified index.
bool next(CSVRow &row, const bool skip_validation=false)
Reads next row from CSV file.
std::string render() const
Creates a text representation of the CSV file row.
virtual void open(const bool seek_to_end=false)
Opens existing file or creates a new one.
Exception thrown when an error occurs during CSV file processing.