-
Notifications
You must be signed in to change notification settings - Fork 0
/
TemplateTupleReader.h
149 lines (126 loc) · 5.55 KB
/
TemplateTupleReader.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//
// Created by user on 30.11.2020.
//
#pragma once
#include <iostream>
#include <tuple>
#include <sstream>
#include <string>
#include <fstream>
#include <stdexcept>
#include <type_traits>
#include "CSVParserException.h"
namespace TupleOperators {
static const unsigned int NEEDED_NUMBER_SKIPPED_SYMBOLS_FOR_SCREENING = 1;
class TupleReaderParams {
private:
unsigned int column_;
const char escapeSymbol_;
const char delimiter_;
public:
TupleReaderParams(const unsigned int column, const char escapeSymbol, const char delimiter) :
column_(column), escapeSymbol_(escapeSymbol), delimiter_(delimiter) {}
[[nodiscard]] unsigned int getColumn() const {
return column_;
}
[[nodiscard]] char getEscapeSymbol() const {
return escapeSymbol_;
}
[[nodiscard]] char getDelimiter() const {
return delimiter_;
}
void increaseColumn() {
++column_;
}
};
void throwExceptionIfEndOfFileMetEarlierThanShouldBe(std::istringstream &stream, const unsigned int column) {
if (stream.eof()) {
throw CSVParser::CSVParserException("less data was encountered than expected.", column,
CSVParser::ExceptionType::DataUnderflow);
}
}
void throwExceptionIfStreamFailedAfterReadingInputData(std::istringstream &stream,
const unsigned int column) {
if (stream.fail()) {
throw CSVParser::CSVParserException("", column, CSVParser::ExceptionType::InvalidData);
}
}
void throwExceptionIfExtraDataPresent(std::istringstream &stream, const unsigned int column) {
if (!stream.eof()) {
throw CSVParser::CSVParserException("more data was encountered than expected. This line will be skipped...",
column, CSVParser::ExceptionType::DataOverflow);
}
}
void skipSymbols(std::istringstream &stream, size_t skipSymbolsNumber) {
for (int skipSymbolsCounter = 0; skipSymbolsCounter < skipSymbolsNumber; skipSymbolsCounter++) {
stream.get();
}
}
bool isNextStreamSymbolEqualEscape(std::istringstream &stream, const char escapeSymbol) {
return stream.peek() == escapeSymbol;
}
bool isThereAnyFurtherEscapeSymbols(std::istringstream &stream, const char escapeSymbol) {
if (!stream.eof()) {
skipSymbols(stream, NEEDED_NUMBER_SKIPPED_SYMBOLS_FOR_SCREENING);
if (!stream.eof() && stream.peek() == escapeSymbol) {
return true;
} else {
stream.unget();
}
}
return false;
}
template<typename T>
void readFullValueContainingEscapesSymbol(T &data, std::istringstream &stream, TupleReaderParams &readerParams) {}
void readFullValueContainingEscapesSymbol(std::string &data, std::istringstream &stream,
TupleReaderParams &readerParams) {
if (stream.eof()) {
return;
}
skipSymbols(stream, NEEDED_NUMBER_SKIPPED_SYMBOLS_FOR_SCREENING);
while (isNextStreamSymbolEqualEscape(stream, readerParams.getEscapeSymbol())) {
throwExceptionIfEndOfFileMetEarlierThanShouldBe(stream, readerParams.getColumn());
size_t lastSymbolStringIndex = data.size() - 1;
data[lastSymbolStringIndex] = readerParams.getDelimiter();
std::string extraData;
skipSymbols(stream, NEEDED_NUMBER_SKIPPED_SYMBOLS_FOR_SCREENING);
stream >> extraData;
throwExceptionIfStreamFailedAfterReadingInputData(stream, readerParams.getColumn());
data += extraData;
if (!isThereAnyFurtherEscapeSymbols(stream, readerParams.getEscapeSymbol())) {
break;
}
}
}
template<typename First>
std::tuple<First>
readNextTuple(std::istringstream &stream, TupleReaderParams &readerParams) {
throwExceptionIfEndOfFileMetEarlierThanShouldBe(stream, readerParams.getColumn());
First inputData;
stream >> inputData;
throwExceptionIfStreamFailedAfterReadingInputData(stream, readerParams.getColumn());
readFullValueContainingEscapesSymbol(inputData, stream, readerParams);
throwExceptionIfExtraDataPresent(stream, readerParams.getColumn());
readerParams.increaseColumn();
return std::make_tuple(inputData);
}
template<typename First, typename Second, typename ...Args>
std::tuple<First, Second, Args...>
readNextTuple(std::istringstream &stream, TupleReaderParams &readerParams) {
throwExceptionIfEndOfFileMetEarlierThanShouldBe(stream, readerParams.getColumn());
First inputData;
stream >> inputData;
throwExceptionIfStreamFailedAfterReadingInputData(stream, readerParams.getColumn());
readFullValueContainingEscapesSymbol(inputData, stream, readerParams);
readerParams.increaseColumn();
return std::tuple_cat(std::make_tuple(inputData),
readNextTuple<Second, Args...>(stream, readerParams));
}
template<typename ...Args>
std::tuple<Args...>
getCsvFileCurrentRowsTuple(std::istringstream &stream, const char escapeSymbol, const char delimiter) {
unsigned int currentColumn = 0;
TupleReaderParams readerParams(currentColumn, escapeSymbol, delimiter);
return readNextTuple<Args...>(stream, readerParams);
}
}