45 class ReadStreamCSV :
public ReadStream {
47 ReadStreamCSV(std::istream&
file,
const std::map<std::string, std::string>& rwOperation,
72 if (!getline(
file, line)) {
76 if (!line.empty() && line.back() ==
'\r') {
77 line = line.substr(0, line.length() - 1);
83 size_t columnsFilled = 0;
84 for (uint32_t column = 0; columnsFilled <
arity; column++) {
85 size_t charactersRead = 0;
86 std::string element =
nextElement(line, start, end);
97 charactersRead = element.size();
120 default:
fatal(
"invalid type attribute: `%c`", ty[0]);
123 if (charactersRead != element.size()) {
124 throw std::invalid_argument(
125 "Expected: " +
delimiter +
" or \\n. Got: " + element[charactersRead]);
128 std::stringstream errorMessage;
129 errorMessage <<
"Error converting <" + element +
"> in column " << column + 1 <<
" in line "
131 throw std::invalid_argument(errorMessage.str());
144 assert(element.size() > 0);
151 }
else if (
isPrefix(
"0x", element)) {
159 std::string
nextElement(
const std::string& line,
size_t& start,
size_t& end) {
164 int record_parens = 0;
165 size_t next_delimiter = line.find(
delimiter, start);
168 while (end < std::min(next_delimiter, line.length()) || record_parens != 0) {
170 if (line[end] ==
'[') {
172 }
else if (line[end] ==
']') {
177 if (record_parens < 0) {
185 if (end == next_delimiter && record_parens != 0) {
186 next_delimiter = line.find(
delimiter, end);
191 if (record_parens != 0) {
192 std::stringstream errorMessage;
193 errorMessage <<
"Unbalanced record parenthesis " <<
lineNumber <<
"; ";
194 throw std::invalid_argument(errorMessage.str());
197 end = std::min(line.find(
delimiter, start), line.length());
202 std::stringstream errorMessage;
203 errorMessage <<
"Values missing in line " <<
lineNumber <<
"; ";
204 throw std::invalid_argument(errorMessage.str());
207 element = line.substr(start, end - start);
214 const std::map<std::string, std::string>& rwOperation,
const unsigned arity_)
const {
215 std::string columnString =
getOr(rwOperation,
"columns",
"");
216 std::map<int, int> inputColumnMap;
218 if (!columnString.empty()) {
219 std::istringstream iss(columnString);
222 while (std::getline(iss, mapping,
':')) {
223 inputColumnMap[stoi(mapping)] = index++;
225 if (inputColumnMap.size() < arity_) {
226 throw std::invalid_argument(
"Invalid column set was given: <" + columnString +
">");
229 while (inputColumnMap.size() < arity_) {
230 int size =
static_cast<int>(inputColumnMap.size());
234 return inputColumnMap;
251 throw std::invalid_argument(
"Cannot open fact file " +
baseName +
"\n");
254 if (
getOr(rwOperation,
"headers",
"false") ==
"true") {
269 }
catch (std::exception&
e) {
270 std::stringstream errorMessage;
271 errorMessage <<
e.what();
272 errorMessage <<
"cannot parse fact file " <<
baseName <<
"!\n";
273 throw std::invalid_argument(errorMessage.str());
287 static std::string
getFileName(
const std::map<std::string, std::string>& rwOperation) {
288 auto name =
getOr(rwOperation,
"filename", rwOperation.at(
"name") +
".facts");
289 if (name.front() !=
'/') {
290 name =
getOr(rwOperation,
"fact-dir",
".") +
"/" + name;
307 return mk<ReadStreamCSV>(std::cin, rwOperation, symbolTable, recordTable);
310 const std::string&
getName()
const override {
311 static const std::string name =
"stdin";
321 return mk<ReadFileCSV>(rwOperation, symbolTable, recordTable);
324 const std::string&
getName()
const override {
325 static const std::string name =
"file";