20    : separator_(1, separator), values_(cols) {
 
 
   24    : separator_(1, separator) {
 
 
   39    while (prev_pos < line.size()) {
 
   41        sep_pos = line.find_first_of(separator_, prev_pos);
 
   42        if (sep_pos == std::string::npos) {
 
   47        len = sep_pos - prev_pos;
 
   48        values_.push_back(line.substr(prev_pos, len));
 
   51        prev_pos = sep_pos + 1;
 
   55    len = line.size() - prev_pos;
 
   56    values_.push_back(line.substr(prev_pos, len));
 
 
   73    for (
size_t i = 0; i < values_.size(); ++i) {
 
 
   97    values_.resize(values_.size() - count);
 
 
  106CSVRow::checkIndex(
const size_t at)
 const {
 
  107    if (at >= values_.size()) {
 
  108        isc_throw(CSVFileError, 
"value index '" << at << 
"' of the CSV row" 
  109                  " is out of bounds; maximal index is '" 
  110                  << (values_.size() - 1) << 
"'");
 
  115    : filename_(filename), fs_(), cols_(0), read_msg_() {
 
 
  134    std::ifstream fs(filename_.c_str());
 
  135    const bool file_exists = fs.good();
 
  137    return (file_exists);
 
 
  142    checkStreamStatusAndReset(
"flush");
 
 
  159    if (std::find(cols_.begin(), cols_.end(), col_name) != cols_.end()) {
 
  163    cols_.push_back(col_name);
 
 
  168    checkStreamStatusAndReset(
"append");
 
  184    fs_->seekp(0, std::ios_base::end);
 
  185    fs_->seekg(0, std::ios_base::end);
 
  188    std::string text = row.
render();
 
  189    *fs_ << text << std::endl;
 
  193                  << text << 
"' to the file '" << filename_ << 
"'");
 
 
  198CSVFile::checkStreamStatusAndReset(
const std::string& operation)
 const {
 
  201                  << operation << 
"' on file '" << filename_ << 
"'");
 
  203    } 
else if (!fs_->is_open()) {
 
  205        isc_throw(CSVFileError, 
"closed stream when performing '" 
  206                  << operation << 
"' on file '" << filename_ << 
"'");
 
  214CSVFile::size()
 const {
 
  215    std::ifstream fs(filename_.c_str());
 
  223    std::ifstream::pos_type pos;
 
  227        fs.seekg(0, std::ifstream::end);
 
  230    } 
catch (
const std::exception&) {
 
  238    for (
size_t i = 0; i < cols_.size(); ++i) {
 
  239        if (cols_[i] == col_name) {
 
 
  248    if (col_index >= cols_.size()) {
 
  250                  " CSV file '" << filename_ << 
"' is out of range; the CSV" 
  251                  " file has only  " << cols_.size() << 
" columns ");
 
  253    return (cols_[col_index]);
 
 
  265        checkStreamStatusAndReset(
"get next row");
 
  274    while (fs_->good() && line.empty()) {
 
  275        std::getline(*fs_, line);
 
  285        } 
else if (!fs_->good()) {
 
  288            setReadMsg(
"error reading a row from CSV file '" 
  289                    + std::string(filename_) + 
"'");
 
  298    return (skip_validation ? 
true : 
validate(row));
 
 
  304    if (size() == 
static_cast<std::streampos
>(0)) {
 
  309        fs_.reset(
new std::fstream(filename_.c_str()));
 
  316            if (!fs_->is_open()) {
 
  324                          << filename_ << 
"'");
 
  329            if (!
next(header, 
true)) {
 
  331                          " CSV file '" << filename_ << 
"': " 
  338                          << 
"' in CSV file '" << filename_ << 
"': " 
  353                fs_->seekp(0, std::ios_base::end);
 
  354                fs_->seekg(0, std::ios_base::end);
 
  357                              " CSV file '" << filename_ << 
"'");
 
  362        } 
catch (
const std::exception&) {
 
 
  375                  " created CSV file '" << filename_ << 
"'");
 
  380    fs_.reset(
new std::fstream(filename_.c_str(), std::fstream::out));
 
  381    if (!fs_->is_open()) {
 
  391        *fs_ << header << std::endl;
 
  393    } 
catch (
const std::exception& ex) {
 
 
  405        std::ostringstream s;
 
  406        s << 
"the size of the row '" << row << 
"' doesn't match the number of" 
 
  432const std::string CSVRow::escape_tag(
"&#x");
 
  442    std::string escape_chars(characters + escape_tag[0]);
 
  446    char_pos = orig_str.find_first_of(escape_chars, prev_pos);
 
  447    if (char_pos == std::string::npos) {
 
  451    std::stringstream ss;
 
  452    while (char_pos < orig_str.size()) {
 
  454        ss << orig_str.substr(prev_pos, char_pos - prev_pos);
 
  457        ss << escape_tag << std::hex << std::setw(2)
 
  458           << 
static_cast<uint16_t
>(orig_str[char_pos]);
 
  464        char_pos = orig_str.find_first_of(escape_chars, prev_pos);
 
  467        if (char_pos == std::string::npos) {
 
  468            ss << orig_str.substr(prev_pos, char_pos - prev_pos);
 
 
  481    size_t start_pos = 0;
 
  484    esc_pos = escaped_str.find(escape_tag, start_pos);
 
  485    if (esc_pos == std::string::npos) {
 
  491    std::stringstream ss;
 
  492    while (esc_pos < escaped_str.size()) {
 
  494        ss << escaped_str.substr(start_pos, esc_pos - start_pos);
 
  498        unsigned int escaped_char = 0;
 
  499        bool converted = 
true;
 
  500        size_t dig_pos = esc_pos + escape_tag.size();
 
  501        if (dig_pos <= escaped_str.size() - 2) {
 
  502            for (
int i = 0; i < 2; ++i) {
 
  503                uint8_t digit = escaped_str[dig_pos];
 
  505                if (digit >= 
'a' && digit <= 
'f') {
 
  506                    digit = digit - 
'a' + 10;
 
  507                } 
else if (digit >= 
'A' && digit <= 
'F') {
 
  508                    digit = digit - 
'A' + 10;
 
  509                } 
else if (digit >= 
'0' && digit <= 
'9') {
 
  517                    escaped_char = digit << 4;
 
  519                    escaped_char |= digit;
 
  528            ss << static_cast<unsigned char>(escaped_char);
 
  535            esc_pos += escape_tag.size();
 
  542        esc_pos = escaped_str.find(escape_tag, start_pos);
 
  545        if (esc_pos == std::string::npos) {
 
  547            ss << escaped_str.substr(start_pos, esc_pos - start_pos);
 
 
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
Exception thrown when an error occurs during CSV file processing.
std::string getColumnName(const size_t col_index) const
Returns the name of the column.
void close()
Closes the CSV file.
size_t getColumnCount() const
Returns the number of columns in the file.
virtual ~CSVFile()
Destructor.
bool exists() const
Checks if the CSV file exists and can be opened for reading.
virtual bool validate(const CSVRow &row)
Validate the row read from a file.
static CSVRow EMPTY_ROW()
Represents empty row.
void setReadMsg(const std::string &read_msg)
Sets error message after row validation.
CSVFile(const std::string &filename)
Constructor.
std::string getFilename() const
Returns the path to the CSV file.
void flush() const
Flushes a file.
virtual bool validateHeader(const CSVRow &header)
This function validates the header of the CSV file.
void addColumnInternal(const std::string &col_name)
Adds a column regardless if the file is open or not.
virtual void recreate()
Creates a new CSV file.
std::string getReadMsg() const
Returns the description of the last error returned by the CSVFile::next function.
void append(const CSVRow &row) const
Writes the CSV row into the file.
void addColumn(const std::string &col_name)
Adds new column name.
size_t getColumnIndex(const std::string &col_name) const
Returns the index of the column having specified name.
virtual void open(const bool seek_to_end=false)
Opens existing file or creates a new one.
bool next(CSVRow &row, const bool skip_validation=false)
Reads next row from CSV file.
Represents a single row of the CSV file.
std::string render() const
Creates a text representation of the CSV file row.
static std::string unescapeCharacters(const std::string &escaped_str)
Returns a copy of a string with special characters unescaped.
std::string readAtEscaped(const size_t at) const
Retrieves a value from the internal container, free of escaped characters.
size_t getValuesCount() const
Returns number of values in a CSV row.
void trim(const size_t count)
Trims a given number of elements from the end of a row.
CSVRow(const size_t cols=0, const char separator=',')
Constructor, creates the raw to be used for output.
void writeAt(const size_t at, const char *value)
Replaces the value at specified index.
static std::string escapeCharacters(const std::string &orig_str, const std::string &characters)
Returns a copy of a string with special characters escaped.
std::string readAt(const size_t at) const
Retrieves a value from the internal container.
void writeAtEscaped(const size_t at, const std::string &value)
Replaces the value at the specified index with a value that has had special characters escaped.
void parse(const std::string &line)
Parse the CSV file row.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
std::ostream & operator<<(std::ostream &os, const CSVRow &row)
Overrides standard output stream operator for CSVRow object.
Defines the logger used by the top-level component of kea-lfc.