OR-Tools  8.2
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"
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
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_
#define LOG(severity)
Definition: base/logging.h:420
Definition: base/file.h:32
size_t Read(void *const buff, size_t size)
Definition: file.cc:70
bool Close()
Definition: file.cc:48
const std::string & operator*() const
Definition: filelineiter.h:50
bool operator!=(const FileLineIterator &other) const
Definition: filelineiter.h:51
FileLineIterator(File *file, int options)
Definition: filelineiter.h:43
FileLineIterator end() const
Definition: filelineiter.h:130
FileLines(const std::string &filename)
Definition: filelineiter.h:121
FileLineIterator begin()
Definition: filelineiter.h:128
FileLines(const std::string &filename, int options)
Definition: filelineiter.h:117
int64_t int64
const int WARNING
Definition: log_severity.h:31
Definition: file.cc:141
absl::Status Open(const absl::string_view &filename, const absl::string_view &mode, File **f, int flags)
Definition: file.cc:142
int Defaults()
Definition: base/file.h:119