Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
filelineiter.h
Go to the documentation of this file.
1// Copyright 2010-2024 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 <cstdint>
30#include <string>
31
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 // Initializes with a provided file, taking ownership of it.
121 //
122 // If file is nullptr, this class behaves as if the file was empty.
123 //
124 // Usage:
125 //
126 // File* file = nullptr;
127 // RETURN_IF_ERROR(file::Open(filename, "r", &file, file::Defaults()));
128 // for (const absl::string_view line : FileLines(filename, file)) {
129 // ...
130 // }
131 //
132 FileLines(absl::string_view filename, File* const file,
133 const int options = FileLineIterator::DEFAULT)
134 : file_(file), options_(options) {
135 if (!file_) {
136 return;
137 }
138 }
139
140 // Initializes the FileLines ignoring errors.
141 //
142 // Please prefer the other constructor combined with file::Open() in new code
143 // so that missing files are properly detected. This version would only print
144 // a warning and act as if the file was empty.
145 explicit FileLines(absl::string_view filename,
146 int options = FileLineIterator::DEFAULT)
147 : FileLines(
148 filename,
149 [&]() {
150 File* file = nullptr;
151 if (!file::Open(filename, "r", &file, file::Defaults()).ok()) {
152 LOG(WARNING) << "Could not open: " << filename;
153 }
154 return file;
155 }(),
156 options) {}
157
158 FileLines(const FileLines&) = delete;
159 FileLines& operator=(const FileLines&) = delete;
160
162 if (file_ != nullptr) file_->Close(file::Defaults()).IgnoreError();
163 }
164
165 FileLineIterator begin() { return FileLineIterator(file_, options_); }
166
167 FileLineIterator end() const { return FileLineIterator(nullptr, options_); }
168
169 private:
170 // Can be nullptr when the FileLines() constructor is used instead of
171 // FileLines::New().
172 File* file_;
173 const int options_;
174};
175
176#endif // OR_TOOLS_UTIL_FILELINEITER_H_
Implements the minimum interface for a range-based for loop iterator.
bool operator!=(const FileLineIterator &other) const
FileLineIterator(File *file, int options)
const std::string & operator*() const
FileLines & operator=(const FileLines &)=delete
FileLines(absl::string_view filename, File *const file, const int options=FileLineIterator::DEFAULT)
FileLines(const FileLines &)=delete
FileLineIterator end() const
FileLineIterator begin()
FileLines(absl::string_view filename, int options=FileLineIterator::DEFAULT)
Definition file.h:30
size_t Read(void *buff, size_t size)
Reads "size" bytes to buff from file, buff should be pre-allocated.
Definition file.cc:101
bool Close()
Closes the file.
Definition file.cc:66
Definition file.cc:169
absl::Status Open(absl::string_view filename, absl::string_view mode, File **f, Options options)
As of 2016-01, these methods can only be used with flags = file::Defaults().
Definition file.cc:170
Options Defaults()
Definition file.h:109