Класс для работы с форматом CSV в строковых и файловых потоках и интерфейсом контейнера.
Класс CSVTrickster, использующий вариативные шаблоны, предназначен для чтения и парсинга данных в формате CSV и записи данных в этом же формате.
В качестве источников данных могут использоваться файловые и строковые потоки. Запись данных производится в потоки указанных типов по выбору клиентского кода.
Класс предоставляет интерфейс в соответствии с концепцией контейнера. Внутри класса контейнер реализован как вектор стандартной библиотеки, содержащий кортежи, соответствующие строкам CSV файла.
Далее описывается интерфейс класса CSVTrickster с примерами его использования.
1) Типы
using row_type = std::tuple<TList ...>;//тип "строки" во внутреннем контейнере
using row_type_ref = std::tuple<TList ...>&;////тип "строки" во внутреннем контейнере по ссылке
using iterator_type = typename std::vector<row_type>::iterator;//тип итератора "строк" внутреннего контейнера
using const_iterator_type = typename std::vector<row_type>::const_iterator;// константный тип итератора "строк" внутреннего контейнера
template<size_t ColumnNum>
using column_type = typename std::tuple_element<ColumnNum, row_type>::type;// тип "колонки" внутреннего контейнера, ColumnNum - номер "колонки".
2) Конструкторы, оператор присваивания и деструктор.
а) Конструктор предоставляет по умолчанию данные для инициализации всех полей настроек (описаны ниже);
Для избежания путаницы при использовании аргументов конструктора используются "строгие" типы, по методике, описанной здесь.
б) Конструкторы копирования и перемещения создают глубокие копии содержимого исходного объекта, его настроек и состояния входных и выходных потоков;
в) Оператор перемещения полностью замещает содержимое существующего объекта новым.
г) Деструктор закрывает файловые потоки.
using CSVT = CSVTrickster<string, int>;
CSVT trikster;//конструктор
CSVT trikster2(trikster);//конструктор копирования
CSVT* ptrikster = new CSVT(Separator(','));//конструктор с измененным первым аргументом
*ptrikster = trikster;//оператор присваивания
delete ptrikster;//деструктор
3) Настройки.
char separator_;
char quote_;
char escape_;
bool ignore_bad_row_length_;
bool skip_empty_lines_;
std::size_t skip_first_lines_;
Настройки парсинга и выходных данных могут быть как назначены в конструкторе, так и изменены в процессе работы вызовом одноименных методов, возвращающих ссылку.
CSVT trikster;//разделитель ';' (по умолчанию)
trikster.separator() = ',';//теперь разделитель - запятая
4) Работа с потоками производится вызовом следующих методов
std::size_t parse(const StringSource& s, std::size_t n = std::numeric_limits<std::size_t>::max());
CSVTrikster<string , int, string, string, string, string, string> reader;
reader.skip_first_lines() = 1;
std::string s = "CurrentTime;AreaID;CounterID;Time;Speed;Class;ClassComment";
s += '\n';
s += "24-1-2018 17:29:6;0;0;2018-01-24T17:29:06;151,787;2;(5.5-7 m)";
s += '\n';
reader.parse(StringSource(s));
std::size_t parse(const FileSource& file_name, std::size_t n = std::numeric_limits<std::size_t>::max());
CSVTrikster<string , int, string, string, string, string, string> reader;
reader.parse(FileSource("Data.csv"));
void write(StringSink s);
using CSVT = CSVTrickster<string, int>;
CSVT trikster;
trikster.separator() = ',';
trikster.push_back("Gala", 1966);
trikster.push_back("Sophia", 2007);
std::string ssink;
trikster.write(StringSink(ssink));
void write(const FileSink& file_name);
Первые два метода производят чтение из файла или строки соответственно и парсинг данных. Вторые два записывают данные из внутреннего контейнера в строку или файл. Для перегрузки одноименных методов используются "строгие" типы, упомянутые выше.
5) Доступ к итераторам внутреннего контейнера
iterator_type begin();
iterator_type end();
const_iterator_type cbegin();
const_iterator_type cend();
using CSVT = CSVTrickster<string, int>;
CSVT trikster;
...............................
CSVT::iterator_type it;
for (it = trikster.begin();it!=trikster.end();it++)
{
if (std::get<0>(*it) == "Sophia")
break;
}
или так
for (auto e : trikster)
{
if (std::get<0>(e) == "Sophia")
break;
}
6) Доступ к "строкам" внутреннего контейнера по индексу
std::size_t rows() const;//размер вектора кортежей
row_type_ref operator[] (std::size_t i) ;//возврат кортежа из вектора по индексу
const row_type_ref operator[] (std::size_t i) const ;
row_type_ref at(std::size_t i) ;//возврат кортежа из вектора по индексу
const row_type_ref at(std::size_t i) const ;
Поведение функций в части генерации исключений при выходе индекса из диапазона аналогично одноименным методам std::vector.
7) Доступ к "колонкам" внутреннего контейнера
inline std::size_t columns() const;//число "колонок" = размер кортежa
template<typename ColumnType, std::size_t ColumnNumber>
std::vector<ColumnType> get_column();//получение вектора данных типа ColumnType "колонки" по индексу ColumnNumber. Параметры задаются при компиляции.
using CSVT = CSVTrickster<string, int>;
CSVT trikster;
...............................
std::vector<int> v(trikster.get_column<int, 1>());
8) Добавление, удаление "строк" , очистка внутреннего контейнера
template< class... Types >
void push_back(Types&&... args);
CSVTrickster<string, int> trikster;
trikster.push_back("Gala", 1966);
iterator_type insert(iterator_type it, row_type t);
CSVT::iterator_type it2 = trikster.insert(it, std::make_tuple("Alex", 1995));
iterator_type erase(iterator_type it);
iterator_type erase(iterator_type first, iterator_type last);
inline void clear();
inline bool empty() const;
9) Операторы сравнения (члены класса) производят сравнение содержимого внутренних контейнеров (текущие настройки не учитываются).
bool operator==(const CSVTrickster<TList ...>& rhs);
bool operator!=(const CSVTrickster<TList ...>& rhs);
И последнее. Для использования пользовательских типов необходимо перегрузить для своего класса операторы operator>> и operator<< для входных и выходных потоков, например:
class TimeAsString
{
string tas;
..........................................................
//Some internal data
public:
friend istringstream &operator >>(istringstream &out, TimeAsString &t)
{
out >> t.tas;
//convert tas to some internal data
................................................................................................
return out;
}
friend std::ostream &operator << (std::ostream & out, const TimeAsString &t)
{
//convert some internal data to tas
........................................................................................
return out << t.tas;
}
};
CSVTrickster<TimeAsString, int, float,std::string> trix;
В качестве источников данных могут использоваться файловые и строковые потоки. Запись данных производится в потоки указанных типов по выбору клиентского кода.
Класс предоставляет интерфейс в соответствии с концепцией контейнера. Внутри класса контейнер реализован как вектор стандартной библиотеки, содержащий кортежи, соответствующие строкам CSV файла.
Далее описывается интерфейс класса CSVTrickster с примерами его использования.
1) Типы
using row_type = std::tuple<TList ...>;//тип "строки" во внутреннем контейнере
using row_type_ref = std::tuple<TList ...>&;////тип "строки" во внутреннем контейнере по ссылке
using iterator_type = typename std::vector<row_type>::iterator;//тип итератора "строк" внутреннего контейнера
using const_iterator_type = typename std::vector<row_type>::const_iterator;// константный тип итератора "строк" внутреннего контейнера
template<size_t ColumnNum>
using column_type = typename std::tuple_element<ColumnNum, row_type>::type;// тип "колонки" внутреннего контейнера, ColumnNum - номер "колонки".
2) Конструкторы, оператор присваивания и деструктор.
а) Конструктор предоставляет по умолчанию данные для инициализации всех полей настроек (описаны ниже);
Для избежания путаницы при использовании аргументов конструктора используются "строгие" типы, по методике, описанной здесь.
б) Конструкторы копирования и перемещения создают глубокие копии содержимого исходного объекта, его настроек и состояния входных и выходных потоков;
в) Оператор перемещения полностью замещает содержимое существующего объекта новым.
г) Деструктор закрывает файловые потоки.
using CSVT = CSVTrickster<string, int>;
CSVT trikster;//конструктор
CSVT trikster2(trikster);//конструктор копирования
CSVT* ptrikster = new CSVT(Separator(','));//конструктор с измененным первым аргументом
*ptrikster = trikster;//оператор присваивания
delete ptrikster;//деструктор
3) Настройки.
char separator_;
char quote_;
char escape_;
bool ignore_bad_row_length_;
bool skip_empty_lines_;
std::size_t skip_first_lines_;
Настройки парсинга и выходных данных могут быть как назначены в конструкторе, так и изменены в процессе работы вызовом одноименных методов, возвращающих ссылку.
CSVT trikster;//разделитель ';' (по умолчанию)
trikster.separator() = ',';//теперь разделитель - запятая
4) Работа с потоками производится вызовом следующих методов
std::size_t parse(const StringSource& s, std::size_t n = std::numeric_limits<std::size_t>::max());
CSVTrikster<string , int, string, string, string, string, string> reader;
reader.skip_first_lines() = 1;
std::string s = "CurrentTime;AreaID;CounterID;Time;Speed;Class;ClassComment";
s += '\n';
s += "24-1-2018 17:29:6;0;0;2018-01-24T17:29:06;151,787;2;(5.5-7 m)";
s += '\n';
reader.parse(StringSource(s));
std::size_t parse(const FileSource& file_name, std::size_t n = std::numeric_limits<std::size_t>::max());
CSVTrikster<string , int, string, string, string, string, string> reader;
reader.parse(FileSource("Data.csv"));
void write(StringSink s);
using CSVT = CSVTrickster<string, int>;
CSVT trikster;
trikster.separator() = ',';
trikster.push_back("Gala", 1966);
trikster.push_back("Sophia", 2007);
std::string ssink;
trikster.write(StringSink(ssink));
void write(const FileSink& file_name);
trikster.write(FileSink("Data.csv"));
Первые два метода производят чтение из файла или строки соответственно и парсинг данных. Вторые два записывают данные из внутреннего контейнера в строку или файл. Для перегрузки одноименных методов используются "строгие" типы, упомянутые выше.
5) Доступ к итераторам внутреннего контейнера
iterator_type begin();
iterator_type end();
const_iterator_type cbegin();
const_iterator_type cend();
using CSVT = CSVTrickster<string, int>;
CSVT trikster;
...............................
CSVT::iterator_type it;
for (it = trikster.begin();it!=trikster.end();it++)
{
if (std::get<0>(*it) == "Sophia")
break;
}
или так
for (auto e : trikster)
{
if (std::get<0>(e) == "Sophia")
break;
}
6) Доступ к "строкам" внутреннего контейнера по индексу
std::size_t rows() const;//размер вектора кортежей
row_type_ref operator[] (std::size_t i) ;//возврат кортежа из вектора по индексу
const row_type_ref operator[] (std::size_t i) const ;
row_type_ref at(std::size_t i) ;//возврат кортежа из вектора по индексу
const row_type_ref at(std::size_t i) const ;
Поведение функций в части генерации исключений при выходе индекса из диапазона аналогично одноименным методам std::vector.
7) Доступ к "колонкам" внутреннего контейнера
inline std::size_t columns() const;//число "колонок" = размер кортежa
template<typename ColumnType, std::size_t ColumnNumber>
std::vector<ColumnType> get_column();//получение вектора данных типа ColumnType "колонки" по индексу ColumnNumber. Параметры задаются при компиляции.
using CSVT = CSVTrickster<string, int>;
CSVT trikster;
...............................
std::vector<int> v(trikster.get_column<int, 1>());
8) Добавление, удаление "строк" , очистка внутреннего контейнера
template< class... Types >
void push_back(Types&&... args);
CSVTrickster<string, int> trikster;
trikster.push_back("Gala", 1966);
iterator_type insert(iterator_type it, row_type t);
CSVT::iterator_type it2 = trikster.insert(it, std::make_tuple("Alex", 1995));
iterator_type erase(iterator_type it);
iterator_type erase(iterator_type first, iterator_type last);
inline void clear();
inline bool empty() const;
9) Операторы сравнения (члены класса) производят сравнение содержимого внутренних контейнеров (текущие настройки не учитываются).
bool operator==(const CSVTrickster<TList ...>& rhs);
bool operator!=(const CSVTrickster<TList ...>& rhs);
И последнее. Для использования пользовательских типов необходимо перегрузить для своего класса операторы operator>> и operator<< для входных и выходных потоков, например:
class TimeAsString
{
string tas;
..........................................................
//Some internal data
public:
friend istringstream &operator >>(istringstream &out, TimeAsString &t)
{
out >> t.tas;
//convert tas to some internal data
................................................................................................
return out;
}
friend std::ostream &operator << (std::ostream & out, const TimeAsString &t)
{
//convert some internal data to tas
........................................................................................
return out << t.tas;
}
};
CSVTrickster<TimeAsString, int, float,std::string> trix;
Комментарии
Отправить комментарий