OR-Tools  9.3
filelineiter.h
Go to the documentation of this file.
1// Copyright 2010-2021 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 characters ('\r'), and to remove blank lines.
24//
25#ifndef OR_TOOLS_UTIL_FILELINEITER_H_
26#define OR_TOOLS_UTIL_FILELINEITER_H_
27
28#include <algorithm>
29#include <string>
30
31#include "absl/strings/match.h"
32#include "ortools/base/file.h"
34
35// Implements the minimum interface for a range-based for loop iterator.
37 public:
38 enum {
39 DEFAULT = 0x0000,
41 KEEP_LINEFEED = 0x0001, // Terminating \n in result.
42 REMOVE_INLINE_CR = 0x0002, // Remove \r characters.
43 REMOVE_BLANK_LINES = 0x0004, // Remove empty or \n-only lines.
44 };
45
46 FileLineIterator(File* file, int options)
47 : next_position_after_eol_(0),
48 buffer_size_(0),
49 file_(file),
50 options_(options) {
51 ReadNextLine();
52 }
53 const std::string& operator*() const { return line_; }
54 bool operator!=(const FileLineIterator& other) const {
55 return file_ != other.file_;
56 }
57 void operator++() { ReadNextLine(); }
58
59 private:
60 bool HasOption(int option) const { return options_ & option; }
61
62 void ReadNextLine() {
63 line_.clear();
64 if (file_ == nullptr) return;
65 do {
66 while (true) {
67 int i = next_position_after_eol_;
68 for (; i < buffer_size_; ++i) {
69 if (buffer_[i] == '\n') break;
70 }
71 if (i == buffer_size_) {
72 line_.append(&buffer_[next_position_after_eol_],
73 i - next_position_after_eol_);
74 buffer_size_ = file_->Read(&buffer_, kBufferSize);
75 if (buffer_size_ < 0) {
76 LOG(WARNING) << "Error while reading file.";
77 file_ = nullptr;
78 break;
79 }
80 next_position_after_eol_ = 0;
81 if (buffer_size_ == 0) {
82 if (line_.empty()) {
83 file_ = nullptr;
84 }
85 break;
86 }
87 } else {
88 line_.append(&buffer_[next_position_after_eol_],
89 i - next_position_after_eol_ + 1);
90 next_position_after_eol_ = i + 1;
91 break;
92 }
93 }
94 PostProcessLine();
95 } while (file_ != nullptr && HasOption(REMOVE_BLANK_LINES) &&
96 (line_.empty() || line_ == "\n"));
97 }
98
99 void PostProcessLine() {
100 if (HasOption(REMOVE_INLINE_CR)) {
101 line_.erase(std::remove(line_.begin(), line_.end(), '\r'), line_.end());
102 }
103 const auto eol = std::find(line_.begin(), line_.end(), '\n');
104 if (!HasOption(KEEP_LINEFEED) && eol != line_.end()) {
105 line_.erase(eol);
106 }
107 }
108
109 static constexpr int kBufferSize = 5 * 1024;
110 char buffer_[kBufferSize];
111 int next_position_after_eol_;
112 int64_t buffer_size_;
113 File* file_;
114 std::string line_;
115 const int options_;
116};
117
119 public:
120 FileLines(const std::string& filename, int options) : options_(options) {
121 if (!file::Open(filename, "r", &file_, file::Defaults()).ok()) {
122 LOG(WARNING) << "Could not open: " << filename;
123 return;
124 }
125 }
126
127 explicit FileLines(const std::string& filename)
128 : FileLines(filename, FileLineIterator::DEFAULT) {}
129
131 if (file_ != nullptr) file_->Close(file::Defaults()).IgnoreError();
132 }
133
134 FileLineIterator begin() { return FileLineIterator(file_, options_); }
135
136 FileLineIterator end() const { return FileLineIterator(nullptr, options_); }
137
138 private:
139 File* file_;
140 const int options_;
141};
142
143#endif // OR_TOOLS_UTIL_FILELINEITER_H_
#define LOG(severity)
Definition: base/logging.h:420
Definition: base/file.h:33
size_t Read(void *const buff, size_t size)
Definition: base/file.cc:70
bool Close()
Definition: base/file.cc:48
const std::string & operator*() const
Definition: filelineiter.h:53
bool operator!=(const FileLineIterator &other) const
Definition: filelineiter.h:54
FileLineIterator(File *file, int options)
Definition: filelineiter.h:46
FileLineIterator end() const
Definition: filelineiter.h:136
FileLines(const std::string &filename)
Definition: filelineiter.h:127
FileLineIterator begin()
Definition: filelineiter.h:134
FileLines(const std::string &filename, int options)
Definition: filelineiter.h:120
const int WARNING
Definition: log_severity.h:31
int Defaults()
Definition: base/file.h:120
absl::Status Open(const absl::string_view &filename, const absl::string_view &mode, File **f, int flags)
Definition: base/file.cc:142