2 * Copyright 2013 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #ifndef FOLLY_FILEGEN_H_
18 #error This file may only be included from folly/experimental/FileGen.h
21 #include <system_error>
23 #include "folly/experimental/StringGen.h"
29 class FileReader : public GenImpl<ByteRange, FileReader> {
31 FileReader(File file, std::unique_ptr<IOBuf> buffer)
32 : file_(std::move(file)),
33 buffer_(std::move(buffer)) {
38 bool apply(Body&& body) const {
42 n = ::read(file_.fd(), buffer_->writableTail(), buffer_->capacity());
43 } while (n == -1 && errno == EINTR);
45 throw std::system_error(errno, std::system_category(), "read failed");
50 if (!body(ByteRange(buffer_->tail(), n))) {
56 // Technically, there could be infinite files (e.g. /dev/random), but people
57 // who open those can do so at their own risk.
58 static constexpr bool infinite = false;
62 std::unique_ptr<IOBuf> buffer_;
65 class FileWriter : public Operator<FileWriter> {
67 FileWriter(File file, std::unique_ptr<IOBuf> buffer)
68 : file_(std::move(file)),
69 buffer_(std::move(buffer)) {
75 template <class Source, class Value>
76 void compose(const GenImpl<Value, Source>& source) const {
77 auto fn = [&](ByteRange v) {
78 if (!this->buffer_ || v.size() >= this->buffer_->capacity()) {
82 if (v.size() > this->buffer_->tailroom()) {
85 memcpy(this->buffer_->writableTail(), v.data(), v.size());
86 this->buffer_->append(v.size());
91 source.foreach(std::move(fn));
98 void write(ByteRange v) const {
102 n = ::write(file_.fd(), v.data(), v.size());
103 } while (n == -1 && errno == EINTR);
105 throw std::system_error(errno, std::system_category(),
112 void flushBuffer() const {
113 if (buffer_ && buffer_->length() != 0) {
114 write(ByteRange(buffer_->data(), buffer_->length()));
120 std::unique_ptr<IOBuf> buffer_;
123 } // namespace detail
125 inline auto byLine(File file, char delim='\n') ->
126 decltype(fromFile(std::move(file)) | eachAs<StringPiece>() | resplit(delim)) {
127 return fromFile(std::move(file)) | eachAs<StringPiece>() | resplit(delim);