| 241 | |
| 242 | template <typename ValueDescWriter, typename DataWriter> |
| 243 | Status HandleInvalidRow(ValueDescWriter* values_writer, DataWriter* parsed_writer, |
| 244 | const char* start, const char* data, int32_t num_cols, |
| 245 | const char** out_data) { |
| 246 | // Find the end of the line without newline or carriage return |
| 247 | auto end = data; |
| 248 | if (*(end - 1) == '\n') { |
| 249 | --end; |
| 250 | } |
| 251 | if (*(end - 1) == '\r') { |
| 252 | --end; |
| 253 | } |
| 254 | const int32_t batch_row_including_skipped = |
| 255 | batch_.num_rows_ + batch_.num_skipped_rows(); |
| 256 | InvalidRow row{batch_.num_cols_, num_cols, |
| 257 | first_row_ < 0 ? -1 : first_row_ + batch_row_including_skipped, |
| 258 | std::string_view(start, end - start)}; |
| 259 | |
| 260 | if (options_.invalid_row_handler && |
| 261 | options_.invalid_row_handler(row) == InvalidRowResult::Skip) { |
| 262 | values_writer->RollbackLine(); |
| 263 | parsed_writer->RollbackLine(); |
| 264 | if (!batch_.skipped_rows_.empty()) { |
| 265 | // Should be increasing (non-strictly) |
| 266 | DCHECK_GE(batch_.num_rows_, batch_.skipped_rows_.back()); |
| 267 | } |
| 268 | // Record the logical row number (not including skipped) since that |
| 269 | // is what we are going to look for later. |
| 270 | batch_.skipped_rows_.push_back(batch_.num_rows_); |
| 271 | *out_data = data; |
| 272 | return Status::OK(); |
| 273 | } |
| 274 | |
| 275 | return MismatchingColumns(row); |
| 276 | } |
| 277 | |
| 278 | template <typename SpecializedOptions, bool UseBulkFilter, typename ValueDescWriter, |
| 279 | typename DataWriter, typename BulkFilter> |
nothing calls this directly
no test coverage detected