OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
foreign_storage::RegexFileBufferParser Class Reference

#include <RegexFileBufferParser.h>

+ Inheritance diagram for foreign_storage::RegexFileBufferParser:
+ Collaboration diagram for foreign_storage::RegexFileBufferParser:

Public Member Functions

 RegexFileBufferParser (const ForeignTable *foreign_table)
 
ParseBufferResult parseBuffer (ParseBufferRequest &request, bool convert_data_blocks, bool columns_are_pre_filtered=false, bool skip_dict_encoding=false) const override
 
import_export::CopyParams validateAndGetCopyParams (const ForeignTable *foreign_table) const override
 
size_t findRowEndPosition (size_t &alloc_size, std::unique_ptr< char[]> &buffer, size_t &buffer_size, const import_export::CopyParams &copy_params, const size_t buffer_first_row_index, unsigned int &num_rows_in_buffer, FileReader *file_reader) const override
 
void validateFiles (const FileReader *file_reader, const ForeignTable *foreign_table) const override
 

Static Public Member Functions

static void setMaxBufferResize (size_t max_buffer_resize)
 
- Static Public Member Functions inherited from foreign_storage::TextFileBufferParser
static std::map< int,
DataBlockPtr
convertImportBuffersToDataBlocks (const std::vector< std::unique_ptr< import_export::TypedImportBuffer >> &import_buffers, const bool skip_dict_encoding=false)
 
static bool isCoordinateScalar (const std::string_view datum)
 
static void processGeoColumn (std::vector< std::unique_ptr< import_export::TypedImportBuffer >> &import_buffers, size_t &col_idx, const import_export::CopyParams &copy_params, std::list< const ColumnDescriptor * >::iterator &cd_it, std::vector< std::string_view > &row, size_t &import_idx, bool is_null, size_t first_row_index, size_t row_index_plus_one, std::shared_ptr< Catalog_Namespace::Catalog > catalog)
 
static void fillRejectedRowWithInvalidData (const std::list< const ColumnDescriptor * > &columns, std::list< const ColumnDescriptor * >::iterator &cd_it, const size_t col_idx, ParseBufferRequest &request)
 
static bool isNullDatum (const std::string_view datum, const ColumnDescriptor *column, const std::string &null_indicator)
 

Static Public Attributes

static const std::string LINE_REGEX_KEY = "LINE_REGEX"
 
static const std::string LINE_START_REGEX_KEY = "LINE_START_REGEX"
 
static const std::string HEADER_KEY = "HEADER"
 
- Static Public Attributes inherited from foreign_storage::TextFileBufferParser
static const std::string BUFFER_SIZE_KEY = "BUFFER_SIZE"
 

Protected Member Functions

virtual bool regexMatchColumns (const std::string &row_str, const boost::regex &line_regex, size_t logical_column_count, std::vector< std::string > &parsed_columns_str, std::vector< std::string_view > &parsed_columns_sv, const std::string &file_path) const
 
virtual bool shouldRemoveNonMatches () const
 
virtual bool shouldTruncateStringValues () const
 

Static Private Member Functions

static size_t getMaxBufferResize ()
 

Private Attributes

boost::regex line_regex_
 
std::optional< boost::regex > line_start_regex_
 

Static Private Attributes

static size_t max_buffer_resize_
 
static bool skip_first_line_ {false}
 

Detailed Description

Definition at line 23 of file RegexFileBufferParser.h.

Constructor & Destructor Documentation

foreign_storage::RegexFileBufferParser::RegexFileBufferParser ( const ForeignTable foreign_table)

Definition at line 152 of file RegexFileBufferParser.cpp.

153  : line_regex_(get_line_regex(foreign_table))
154  , line_start_regex_(get_line_start_regex(foreign_table)) {}
std::string get_line_regex(const ForeignTable *foreign_table)
std::optional< std::string > get_line_start_regex(const ForeignTable *foreign_table)
std::optional< boost::regex > line_start_regex_

Member Function Documentation

size_t foreign_storage::RegexFileBufferParser::findRowEndPosition ( size_t &  alloc_size,
std::unique_ptr< char[]> &  buffer,
size_t &  buffer_size,
const import_export::CopyParams copy_params,
const size_t  buffer_first_row_index,
unsigned int &  num_rows_in_buffer,
FileReader file_reader 
) const
overridevirtual

Finds and returns the offset of the end of the last row in the given buffer. If the buffer does not contain at least one row, the buffer is extended with more content from the file until a row is read. An exception is thrown if the buffer is extended to a maximum threshold and at least one row has still not been read.

Implements foreign_storage::TextFileBufferParser.

Definition at line 388 of file RegexFileBufferParser.cpp.

References CHECK, CHECK_EQ, CHECK_GT, import_export::delimited_parser::extend_buffer(), foreign_storage::anonymous_namespace{RegexFileBufferParser.cpp}::find_last_end_of_line(), foreign_storage::anonymous_namespace{RegexFileBufferParser.cpp}::get_row_count(), getMaxBufferResize(), foreign_storage::FileReader::isEndOfLastFile(), foreign_storage::FileReader::isScanFinished(), import_export::CopyParams::line_delim, line_regex_, line_start_regex_, foreign_storage::anonymous_namespace{RegexFileBufferParser.cpp}::line_starts_with_regex(), import_export::delimited_parser::max_buffer_resize, and shouldRemoveNonMatches().

395  {
396  CHECK_GT(buffer_size, static_cast<size_t>(0));
397  size_t start_pos{0};
398  size_t end_pos = buffer_size - 1;
399  bool found_end_pos{false};
400  while (!found_end_pos) {
401  try {
402  end_pos = find_last_end_of_line(
403  buffer.get(), buffer_size, start_pos, end_pos, copy_params.line_delim);
404  if (file_reader->isEndOfLastFile()) {
405  CHECK_EQ(end_pos, buffer_size - 1);
406  found_end_pos = true;
407  } else if (line_start_regex_.has_value()) {
408  // When a LINE_START_REGEX option is present and the file reader is not at the end
409  // of file, return the position of the end of line before the last line that
410  // matches the line start regex, since the last line that matches the line start
411  // regex in this buffer may still have to include/concatenate lines beyond this
412  // buffer.
413  CHECK_GT(end_pos, static_cast<size_t>(0));
414  auto old_end_pos = end_pos;
415  end_pos = find_last_end_of_line(buffer.get(),
416  buffer_size,
417  start_pos,
418  old_end_pos - 1,
419  copy_params.line_delim);
420  while (!line_starts_with_regex(
421  buffer.get(), end_pos + 1, old_end_pos, line_start_regex_.value())) {
422  old_end_pos = end_pos;
423  end_pos = find_last_end_of_line(buffer.get(),
424  buffer_size,
425  start_pos,
426  old_end_pos - 1,
427  copy_params.line_delim);
428  }
429  found_end_pos = true;
430  } else {
431  found_end_pos = true;
432  }
433  } catch (InsufficientBufferSizeException& e) {
435  if (alloc_size >= max_buffer_resize || file_reader->isScanFinished()) {
436  throw;
437  }
438  start_pos = buffer_size;
440  buffer, buffer_size, alloc_size, nullptr, file_reader, max_buffer_resize);
441  end_pos = buffer_size - 1;
442  }
443  }
444  CHECK(found_end_pos);
445  num_rows_in_buffer = get_row_count(buffer.get(),
446  0,
447  end_pos,
448  copy_params.line_delim,
450  line_regex_,
452  return end_pos + 1;
453 }
#define CHECK_EQ(x, y)
Definition: Logger.h:301
virtual bool isScanFinished() const =0
virtual bool isEndOfLastFile()=0
#define CHECK_GT(x, y)
Definition: Logger.h:305
void extend_buffer(std::unique_ptr< char[]> &buffer, size_t &buffer_size, size_t &alloc_size, FILE *file, foreign_storage::FileReader *file_reader, size_t max_buffer_resize)
std::optional< boost::regex > line_start_regex_
size_t find_last_end_of_line(const char *buffer, size_t buffer_size, size_t start, size_t end, char line_delim)
#define CHECK(condition)
Definition: Logger.h:291
size_t get_row_count(const char *buffer, size_t start, size_t end, char line_delim, const std::optional< boost::regex > &line_start_regex, const boost::regex &line_regex, bool remove_non_matches)
bool line_starts_with_regex(const char *buffer, size_t start, size_t end, const boost::regex &line_start_regex)

+ Here is the call graph for this function:

size_t foreign_storage::RegexFileBufferParser::getMaxBufferResize ( )
staticprivate

Definition at line 479 of file RegexFileBufferParser.cpp.

References max_buffer_resize_.

Referenced by findRowEndPosition().

479  {
480  return max_buffer_resize_;
481 }

+ Here is the caller graph for this function:

ParseBufferResult foreign_storage::RegexFileBufferParser::parseBuffer ( ParseBufferRequest request,
bool  convert_data_blocks,
bool  columns_are_pre_filtered = false,
bool  skip_dict_encoding = false 
) const
overridevirtual

Parses a given file buffer and returns data blocks for each column in the file along with metadata related to rows and row offsets within the buffer.

Implements foreign_storage::TextFileBufferParser.

Definition at line 160 of file RegexFileBufferParser.cpp.

References foreign_storage::ParseBufferRequest::begin_pos, foreign_storage::ParseBufferRequest::buffer, CHECK, foreign_storage::TextFileBufferParser::convertImportBuffersToDataBlocks(), foreign_storage::ParseBufferRequest::copy_params, foreign_storage::ParseBufferRequest::end_pos, foreign_storage::ParseBufferRequest::file_offset, foreign_storage::TextFileBufferParser::fillRejectedRowWithInvalidData(), foreign_storage::ParseBufferRequest::first_row_index, foreign_storage::ParseBufferRequest::foreign_table_schema, foreign_storage::anonymous_namespace{RegexFileBufferParser.cpp}::get_next_row(), foreign_storage::ParseBufferRequest::getCatalog(), foreign_storage::ParseBufferRequest::getColumns(), foreign_storage::ParseBufferRequest::getFilePath(), foreign_storage::ParseBufferRequest::import_buffers, is_null(), foreign_storage::TextFileBufferParser::isNullDatum(), import_export::CopyParams::line_delim, line_regex_, line_start_regex_, StringDictionary::MAX_STRLEN, import_export::CopyParams::null_str, foreign_storage::ParseBufferRequest::process_row_count, foreign_storage::TextFileBufferParser::processGeoColumn(), regexMatchColumns(), run_benchmark_import::result, shouldRemoveNonMatches(), shouldTruncateStringValues(), and foreign_storage::ParseBufferRequest::track_rejected_rows.

163  {
164  CHECK(request.buffer);
165  char* buffer_start = request.buffer.get() + request.begin_pos;
166  const char* buffer_end = request.buffer.get() + request.end_pos;
167 
168  std::vector<size_t> row_offsets;
169  row_offsets.emplace_back(request.file_offset + request.begin_pos);
170 
171  size_t current_row_id = 0;
172  size_t row_count = 0;
173  auto logical_column_count = request.foreign_table_schema->getLogicalColumns().size();
174  std::vector<std::string> parsed_columns_str;
175  parsed_columns_str.reserve(logical_column_count);
176  std::vector<std::string_view> parsed_columns_sv;
177  parsed_columns_sv.reserve(logical_column_count);
178 
179  ParseBufferResult result{};
180 
181  std::string row_str;
182  size_t remaining_row_count = request.process_row_count;
183  auto curr = buffer_start;
184  while (curr < buffer_end && remaining_row_count > 0) {
185  try {
186  row_str = get_next_row(
187  curr, buffer_end - 1, request.copy_params.line_delim, line_start_regex_);
188  curr += row_str.length() + 1;
189  current_row_id = row_count++;
190  remaining_row_count--;
191 
192  bool skip_all_columns =
193  std::all_of(request.import_buffers.begin(),
194  request.import_buffers.end(),
195  [](const auto& import_buffer) { return !import_buffer; });
196  if (!skip_all_columns) {
197  auto columns = request.getColumns();
198 
199  bool set_all_nulls = false;
200  try {
201  parsed_columns_str.clear();
202  parsed_columns_sv.clear();
203  set_all_nulls = regexMatchColumns(row_str,
204  line_regex_,
205  logical_column_count,
206  parsed_columns_str,
207  parsed_columns_sv,
208  request.getFilePath());
209  if (set_all_nulls && shouldRemoveNonMatches()) {
210  current_row_id = row_count--;
211  remaining_row_count++;
212  continue;
213  }
214  } catch (const ForeignStorageException& e) {
215  if (request.track_rejected_rows) {
216  result.rejected_rows.insert(current_row_id);
217  auto cd_it = columns.begin();
218  fillRejectedRowWithInvalidData(columns, cd_it, 0, request);
219  continue;
220  } else {
221  throw;
222  }
223  }
224 
225  size_t parsed_column_index = 0;
226  size_t import_buffer_index = 0;
227 
228  for (auto cd_it = columns.begin(); cd_it != columns.end(); ++cd_it) {
229  auto cd = *cd_it;
230  const auto& column_type = cd->columnType;
231  if (request.import_buffers[import_buffer_index]) {
232  bool is_null = false;
233  try {
234  is_null =
235  (set_all_nulls || isNullDatum(parsed_columns_sv[parsed_column_index],
236  cd,
237  request.copy_params.null_str));
238  } catch (const std::exception& e) {
239  if (request.track_rejected_rows) {
240  result.rejected_rows.insert(current_row_id);
242  columns, cd_it, import_buffer_index, request);
243  break; // skip rest of row
244  } else {
245  throw;
246  }
247  }
248  if (column_type.is_geometry()) {
249  auto starting_import_buffer_index = import_buffer_index;
250  try {
251  processGeoColumn(request.import_buffers,
252  import_buffer_index,
253  request.copy_params,
254  cd_it,
255  parsed_columns_sv,
256  parsed_column_index,
257  is_null,
258  request.first_row_index,
259  row_count,
260  request.getCatalog());
261  } catch (const std::exception& e) {
262  if (request.track_rejected_rows) {
263  result.rejected_rows.insert(current_row_id);
265  columns, cd_it, starting_import_buffer_index, request);
266  break; // skip rest of row
267  } else {
268  throw;
269  }
270  }
271  // Skip remaining physical columns
272  for (int i = 0; i < cd->columnType.get_physical_cols(); ++i) {
273  ++cd_it;
274  }
275  } else {
276  try {
277  auto& column_sv = parsed_columns_sv[parsed_column_index];
278  if (column_type.is_string() && shouldTruncateStringValues() &&
279  column_sv.length() > StringDictionary::MAX_STRLEN) {
280  column_sv = column_sv.substr(0, StringDictionary::MAX_STRLEN);
281  }
282  request.import_buffers[import_buffer_index]->add_value(
283  cd,
284  parsed_columns_sv[parsed_column_index],
285  is_null,
286  request.copy_params);
287  } catch (const std::exception& e) {
288  if (request.track_rejected_rows) {
289  result.rejected_rows.insert(current_row_id);
291  columns, cd_it, import_buffer_index, request);
292  break; // skip rest of row
293  } else {
294  throw;
295  }
296  }
297  parsed_column_index++;
298  import_buffer_index++;
299  }
300  } else {
301  // Skip column
302  for (int i = 0; i < column_type.get_physical_cols(); i++) {
303  import_buffer_index++;
304  cd_it++;
305  }
306  parsed_column_index++;
307  import_buffer_index++;
308  }
309  }
310  }
311  } catch (const ForeignStorageException& e) {
312  throw;
313  } catch (const std::exception& e) {
314  throw ForeignStorageException("Parsing failure \"" + std::string(e.what()) +
315  "\" in row \"" + row_str + "\" in file \"" +
316  request.getFilePath() + "\"");
317  }
318  }
319  row_offsets.emplace_back(request.file_offset + (curr - request.buffer.get()));
320 
321  result.row_offsets = row_offsets;
322  result.row_count = row_count;
323  if (convert_data_blocks) {
324  result.column_id_to_data_blocks_map =
325  convertImportBuffersToDataBlocks(request.import_buffers, skip_dict_encoding);
326  }
327  return result;
328 }
static std::map< int, DataBlockPtr > convertImportBuffersToDataBlocks(const std::vector< std::unique_ptr< import_export::TypedImportBuffer >> &import_buffers, const bool skip_dict_encoding=false)
static void processGeoColumn(std::vector< std::unique_ptr< import_export::TypedImportBuffer >> &import_buffers, size_t &col_idx, const import_export::CopyParams &copy_params, std::list< const ColumnDescriptor * >::iterator &cd_it, std::vector< std::string_view > &row, size_t &import_idx, bool is_null, size_t first_row_index, size_t row_index_plus_one, std::shared_ptr< Catalog_Namespace::Catalog > catalog)
static void fillRejectedRowWithInvalidData(const std::list< const ColumnDescriptor * > &columns, std::list< const ColumnDescriptor * >::iterator &cd_it, const size_t col_idx, ParseBufferRequest &request)
CONSTEXPR DEVICE bool is_null(const T &value)
std::string get_next_row(const char *curr, const char *buffer_end, char line_delim, const std::optional< boost::regex > &line_start_regex)
std::optional< boost::regex > line_start_regex_
virtual bool regexMatchColumns(const std::string &row_str, const boost::regex &line_regex, size_t logical_column_count, std::vector< std::string > &parsed_columns_str, std::vector< std::string_view > &parsed_columns_sv, const std::string &file_path) const
#define CHECK(condition)
Definition: Logger.h:291
static bool isNullDatum(const std::string_view datum, const ColumnDescriptor *column, const std::string &null_indicator)
static constexpr size_t MAX_STRLEN

+ Here is the call graph for this function:

bool foreign_storage::RegexFileBufferParser::regexMatchColumns ( const std::string &  row_str,
const boost::regex &  line_regex,
size_t  logical_column_count,
std::vector< std::string > &  parsed_columns_str,
std::vector< std::string_view > &  parsed_columns_sv,
const std::string &  file_path 
) const
protectedvirtual

Reimplemented in foreign_storage::LogFileBufferParser.

Definition at line 330 of file RegexFileBufferParser.cpp.

References CHECK_GT, and foreign_storage::throw_number_of_columns_mismatch_error().

Referenced by parseBuffer(), and foreign_storage::LogFileBufferParser::regexMatchColumns().

336  {
337  boost::smatch match;
338  bool set_all_nulls{false};
339  if (boost::regex_match(row_str, match, line_regex)) {
340  auto matched_column_count = match.size() - 1 + parsed_columns_sv.size();
341  if (logical_column_count != matched_column_count) {
343  logical_column_count, matched_column_count, file_path);
344  }
345  CHECK_GT(match.size(), static_cast<size_t>(1));
346  for (size_t i = 1; i < match.size(); i++) {
347  parsed_columns_str.emplace_back(match[i].str());
348  parsed_columns_sv.emplace_back(parsed_columns_str.back());
349  }
350  } else {
351  parsed_columns_str.clear();
352  parsed_columns_sv =
353  std::vector<std::string_view>(logical_column_count, std::string_view{});
354  set_all_nulls = true;
355  }
356  return set_all_nulls;
357 }
#define CHECK_GT(x, y)
Definition: Logger.h:305
void throw_number_of_columns_mismatch_error(size_t num_table_cols, size_t num_file_cols, const std::string &file_path)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void foreign_storage::RegexFileBufferParser::setMaxBufferResize ( size_t  max_buffer_resize)
static
bool foreign_storage::RegexFileBufferParser::shouldRemoveNonMatches ( ) const
protectedvirtual

Reimplemented in foreign_storage::LogFileBufferParser.

Definition at line 483 of file RegexFileBufferParser.cpp.

Referenced by findRowEndPosition(), and parseBuffer().

483  {
484  return false;
485 }

+ Here is the caller graph for this function:

bool foreign_storage::RegexFileBufferParser::shouldTruncateStringValues ( ) const
protectedvirtual

Reimplemented in foreign_storage::LogFileBufferParser.

Definition at line 487 of file RegexFileBufferParser.cpp.

Referenced by parseBuffer().

487  {
488  return false;
489 }

+ Here is the caller graph for this function:

import_export::CopyParams foreign_storage::RegexFileBufferParser::validateAndGetCopyParams ( const ForeignTable foreign_table) const
overridevirtual

Validates foreign table parse options and returns a CopyParams object upon successful validation. An exception is thrown if validation fails.

Implements foreign_storage::TextFileBufferParser.

Definition at line 359 of file RegexFileBufferParser.cpp.

References foreign_storage::TextFileBufferParser::BUFFER_SIZE_KEY, foreign_storage::ForeignTable::GEO_VALIDATE_GEOMETRY_KEY, HEADER_KEY, import_export::kHasHeader, import_export::kNoHeader, foreign_storage::OptionsContainer::options, import_export::CopyParams::plain_text, foreign_storage::AbstractFileStorageDataWrapper::THREADS_KEY, and foreign_storage::anonymous_namespace{CsvFileBufferParser.cpp}::validate_and_get_bool_value().

360  {
361  import_export::CopyParams copy_params{};
362  copy_params.plain_text = true;
363  auto has_header = validate_and_get_bool_value(foreign_table, HEADER_KEY);
364  if (has_header.has_value()) {
365  if (has_header.value()) {
366  copy_params.has_header = import_export::ImportHeaderRow::kHasHeader;
367  } else {
368  copy_params.has_header = import_export::ImportHeaderRow::kNoHeader;
369  }
370  } else {
371  // By default, regex parsed files are not assumed to have headers.
372  copy_params.has_header = import_export::ImportHeaderRow::kNoHeader;
373  }
374  if (auto it = foreign_table->options.find(BUFFER_SIZE_KEY);
375  it != foreign_table->options.end()) {
376  copy_params.buffer_size = std::stoi(it->second);
377  }
378  if (auto it = foreign_table->options.find(AbstractFileStorageDataWrapper::THREADS_KEY);
379  it != foreign_table->options.end()) {
380  copy_params.threads = std::stoi(it->second);
381  }
382  copy_params.geo_validate_geometry =
384  .value_or(copy_params.geo_validate_geometry);
385  return copy_params;
386 }
std::optional< bool > validate_and_get_bool_value(const ForeignTable *foreign_table, const std::string &option_name)
static constexpr const char * GEO_VALIDATE_GEOMETRY_KEY
Definition: ForeignTable.h:49

+ Here is the call graph for this function:

void foreign_storage::RegexFileBufferParser::validateFiles ( const FileReader file_reader,
const ForeignTable foreign_table 
) const
overridevirtual

Performs basic validation of files to be parsed.

Implements foreign_storage::TextFileBufferParser.

Definition at line 455 of file RegexFileBufferParser.cpp.

References CHECK, foreign_storage::anonymous_namespace{RegexFileBufferParser.cpp}::get_line_start_regex(), foreign_storage::FileReader::getFirstLineForEachFile(), parse_ast::line, line_start_regex_, and foreign_storage::anonymous_namespace{RegexFileBufferParser.cpp}::line_starts_with_regex().

456  {
457  if (line_start_regex_.has_value()) {
458  // When a LINE_START_REGEX option is specified, at least the first line in each file
459  // has to start with the specified regex.
460  auto first_line_by_file_path = file_reader->getFirstLineForEachFile();
461  for (const auto& [file_path, line] : first_line_by_file_path) {
462  if (!line.empty() &&
464  line.c_str(), 0, line.length() - 1, line_start_regex_.value())) {
465  auto line_start_regex = get_line_start_regex(foreign_table);
466  CHECK(line_start_regex.has_value());
467  throw ForeignStorageException{"First line in file \"" + file_path +
468  "\" does not match line start regex \"" +
469  line_start_regex.value() + "\""};
470  }
471  }
472  }
473 }
std::optional< std::string > get_line_start_regex(const ForeignTable *foreign_table)
std::optional< boost::regex > line_start_regex_
tuple line
Definition: parse_ast.py:10
#define CHECK(condition)
Definition: Logger.h:291
bool line_starts_with_regex(const char *buffer, size_t start, size_t end, const boost::regex &line_start_regex)

+ Here is the call graph for this function:

Member Data Documentation

const std::string foreign_storage::RegexFileBufferParser::HEADER_KEY = "HEADER"
inlinestatic

Definition at line 51 of file RegexFileBufferParser.h.

Referenced by validateAndGetCopyParams().

boost::regex foreign_storage::RegexFileBufferParser::line_regex_
private

Definition at line 74 of file RegexFileBufferParser.h.

Referenced by findRowEndPosition(), and parseBuffer().

std::optional<boost::regex> foreign_storage::RegexFileBufferParser::line_start_regex_
private

Definition at line 75 of file RegexFileBufferParser.h.

Referenced by findRowEndPosition(), parseBuffer(), and validateFiles().

const std::string foreign_storage::RegexFileBufferParser::LINE_START_REGEX_KEY = "LINE_START_REGEX"
inlinestatic
size_t foreign_storage::RegexFileBufferParser::max_buffer_resize_
inlinestaticprivate
bool foreign_storage::RegexFileBufferParser::skip_first_line_ {false}
inlinestaticprivate

Definition at line 72 of file RegexFileBufferParser.h.


The documentation for this class was generated from the following files: