OR-Tools  8.1
filelineiter.h
Go to the documentation of this file.
1 // Copyright 2010-2018 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 // Allows to read a text file line by line with:
15 // for (const std::string& line : FileLines("myfile.txt")) { ... }
16 //
17 // More details:
18 // * The lines are separated by '\n' (which is removed by default) and have no
19 // size limits.
20 // * Consecutive '\n' result in empty lines being produced.
21 // * If not empty, the string after the last '\n' is produced as the last line.
22 // * Options are available to keep the trailing '\n' for each line, to remove
23 // carriage-return chararters ('\r'), and to remove blank lines.
24 //
25 #ifndef OR_TOOLS_UTIL_FILELINEITER_H_
26 #define OR_TOOLS_UTIL_FILELINEITER_H_
27 
28 #include "absl/strings/match.h"
29 #include "ortools/base/file.h"
30 #include "ortools/base/logging.h"
31 
32 // Implements the minimum interface for a range-based for loop iterator.
34  public:
35  enum {
36  DEFAULT = 0x0000,
38  KEEP_LINEFEED = 0x0001, // Terminating \n in result.
39  REMOVE_INLINE_CR = 0x0002, // Remove \r characters.
40  REMOVE_BLANK_LINES = 0x0004, // Remove empty or \n-only lines.
41  };
42 
43  FileLineIterator(File* file, int options)
44  : next_position_after_eol_(0),
45  buffer_size_(0),
46  file_(file),
47  options_(options) {
48  ReadNextLine();
49  }
50  const std::string& operator*() const { return line_; }
51  bool operator!=(const FileLineIterator& other) const {
52  return file_ != other.file_;
53  }
54  void operator++() { ReadNextLine(); }
55 
56  private:
57  bool HasOption(int option) const { return options_ & option; }
58 
59  void ReadNextLine() {
60  line_.clear();
61  if (file_ == nullptr) return;
62  do {
63  while (true) {
64  int i = next_position_after_eol_;
65  for (; i < buffer_size_; ++i) {
66  if (buffer_[i] == '\n') break;
67  }
68  if (i == buffer_size_) {
69  line_.append(&buffer_[next_position_after_eol_],
70  i - next_position_after_eol_);
71  buffer_size_ = file_->Read(&buffer_, kBufferSize);
72  if (buffer_size_ < 0) {
73  LOG(WARNING) << "Error while reading file.";
74  file_ = nullptr;
75  break;
76  }
77  next_position_after_eol_ = 0;
78  if (buffer_size_ == 0) {
79  if (line_.empty()) {
80  file_ = nullptr;
81  }
82  break;
83  }
84  } else {
85  line_.append(&buffer_[next_position_after_eol_],
86  i - next_position_after_eol_ + 1);
87  next_position_after_eol_ = i + 1;
88  break;
89  }
90  }
91  PostProcessLine();
92  } while (file_ != nullptr && HasOption(REMOVE_BLANK_LINES) &&
93  (line_.empty() || line_ == "\n"));
94  }
95 
96  void PostProcessLine() {
97  if (HasOption(REMOVE_INLINE_CR)) {
98  line_.erase(std::remove(line_.begin(), line_.end(), '\r'), line_.end());
99  }
100  const auto eol = std::find(line_.begin(), line_.end(), '\n');
101  if (!HasOption(KEEP_LINEFEED) && eol != line_.end()) {
102  line_.erase(eol);
103  }
104  }
105 
106  static constexpr int kBufferSize = 5 * 1024;
107  char buffer_[kBufferSize];
108  int next_position_after_eol_;
109  int64 buffer_size_;
110  File* file_;
111  std::string line_;
112  const int options_;
113 };
114 
115 class FileLines {
116  public:
117  FileLines(const std::string& filename, int options) : options_(options) {
118  if (!file::Open(filename, "r", &file_, file::Defaults()).ok()) return;
119  }
120 
121  explicit FileLines(const std::string& filename)
122  : FileLines(filename, FileLineIterator::DEFAULT) {}
123 
125  if (file_ != nullptr) file_->Close(file::Defaults()).IgnoreError();
126  }
127 
128  FileLineIterator begin() { return FileLineIterator(file_, options_); }
129 
130  FileLineIterator end() const { return FileLineIterator(nullptr, options_); }
131 
132  private:
133  File* file_;
134  const int options_;
135 };
136 
137 #endif // OR_TOOLS_UTIL_FILELINEITER_H_
File::Close
bool Close()
Definition: file.cc:48
FileLineIterator
Definition: filelineiter.h:33
LOG
#define LOG(severity)
Definition: base/logging.h:420
FileLines::~FileLines
~FileLines()
Definition: filelineiter.h:124
FileLineIterator::operator!=
bool operator!=(const FileLineIterator &other) const
Definition: filelineiter.h:51
FileLines::begin
FileLineIterator begin()
Definition: filelineiter.h:128
logging.h
FileLineIterator::REMOVE_INLINE_CR
@ REMOVE_INLINE_CR
Definition: filelineiter.h:39
WARNING
const int WARNING
Definition: log_severity.h:31
FileLines::FileLines
FileLines(const std::string &filename)
Definition: filelineiter.h:121
FileLines::FileLines
FileLines(const std::string &filename, int options)
Definition: filelineiter.h:117
FileLineIterator::REMOVE_BLANK_LINES
@ REMOVE_BLANK_LINES
Definition: filelineiter.h:40
int64
int64_t int64
Definition: integral_types.h:34
FileLineIterator::operator*
const std::string & operator*() const
Definition: filelineiter.h:50
file.h
File
Definition: base/file.h:32
FileLineIterator::operator++
void operator++()
Definition: filelineiter.h:54
File::Read
size_t Read(void *const buff, size_t size)
Definition: file.cc:70
file::Defaults
int Defaults()
Definition: base/file.h:119
file
Definition: file.cc:141
FileLines::end
FileLineIterator end() const
Definition: filelineiter.h:130
FileLineIterator::KEEP_LINEFEED
@ KEEP_LINEFEED
Definition: filelineiter.h:38
file::Open
absl::Status Open(const absl::string_view &filename, const absl::string_view &mode, File **f, int flags)
Definition: file.cc:142
FileLineIterator::FileLineIterator
FileLineIterator(File *file, int options)
Definition: filelineiter.h:43
FileLineIterator::REMOVE_LINEFEED
@ REMOVE_LINEFEED
Definition: filelineiter.h:37
FileLineIterator::DEFAULT
@ DEFAULT
Definition: filelineiter.h:36
FileLines
Definition: filelineiter.h:115