file.h revision c377920e
185147189SShuo Chen#pragma once
285147189SShuo Chen
385147189SShuo Chen#include <stdio.h>
485147189SShuo Chen#include <memory>
585147189SShuo Chen#include <string>
6c377920eSShuo Chen#include "muduo/base/Logging.h"  // CHECK_NOTNULL
785147189SShuo Chen
885147189SShuo Chen// Wrappers FILE* from stdio.
985147189SShuo Chenclass File
1085147189SShuo Chen{
1185147189SShuo Chen public:
12c377920eSShuo Chen  int64_t tell() const
1385147189SShuo Chen  {
1485147189SShuo Chen    return ::ftell(file_);
1585147189SShuo Chen  }
1685147189SShuo Chen
1785147189SShuo Chen  void close()
1885147189SShuo Chen  {
1985147189SShuo Chen    if (file_)
2085147189SShuo Chen      ::fclose(file_);
2185147189SShuo Chen    file_ = nullptr;
2285147189SShuo Chen    buffer_.reset();
2385147189SShuo Chen  }
2485147189SShuo Chen
25c377920eSShuo Chen  const std::string& filename() const
26c377920eSShuo Chen  {
27c377920eSShuo Chen    return filename_;
28c377920eSShuo Chen  }
29c377920eSShuo Chen
3085147189SShuo Chen  // https://github.com/coreutils/coreutils/blob/master/src/ioblksize.h
3185147189SShuo Chen  /* As of May 2014, 128KiB is determined to be the minimium
3285147189SShuo Chen   * blksize to best minimize system call overhead.
3385147189SShuo Chen   */
3485147189SShuo Chen  static const int kBufferSize = 1024 * 1024;
3585147189SShuo Chen
36c377920eSShuo Chen protected:
3785147189SShuo Chen  File(const std::string& filename, const char* mode, int bufsize=kBufferSize)
38c377920eSShuo Chen    : filename_(filename),
39c377920eSShuo Chen      file_(CHECK_NOTNULL(::fopen(filename.c_str(), mode))),
4085147189SShuo Chen      buffer_(CHECK_NOTNULL(new char[bufsize]))
4185147189SShuo Chen  {
4285147189SShuo Chen    ::setbuffer(file_, buffer_.get(), bufsize);
4385147189SShuo Chen  }
4485147189SShuo Chen
4585147189SShuo Chen  virtual ~File()
4685147189SShuo Chen  {
4785147189SShuo Chen    close();
4885147189SShuo Chen  }
4985147189SShuo Chen
5085147189SShuo Chen protected:
51c377920eSShuo Chen  std::string filename_;
5285147189SShuo Chen  FILE* file_ = nullptr;
5385147189SShuo Chen
5485147189SShuo Chen private:
5585147189SShuo Chen  std::unique_ptr<char[]> buffer_;
5685147189SShuo Chen
5785147189SShuo Chen  File(const File&) = delete;
5885147189SShuo Chen  void operator=(const File&) = delete;
5985147189SShuo Chen};
6085147189SShuo Chen
6185147189SShuo Chenclass InputFile : public File
6285147189SShuo Chen{
6385147189SShuo Chen public:
6485147189SShuo Chen  explicit InputFile(const char* filename, int bufsize=kBufferSize)
6585147189SShuo Chen    : File(filename, "r", bufsize)
6685147189SShuo Chen  {
6785147189SShuo Chen  }
6885147189SShuo Chen
6985147189SShuo Chen  bool getline(std::string* output)
7085147189SShuo Chen  {
7185147189SShuo Chen    char buf[1024] = "";
7285147189SShuo Chen    if (::fgets(buf, sizeof buf, file_))
7385147189SShuo Chen    {
7485147189SShuo Chen      *output = buf;
7585147189SShuo Chen      if (!output->empty() && output->back() == '\n')
7685147189SShuo Chen      {
7785147189SShuo Chen        output->resize(output->size()-1);
7885147189SShuo Chen      }
7985147189SShuo Chen      return true;
8085147189SShuo Chen    }
8185147189SShuo Chen    return false;
8285147189SShuo Chen  }
8385147189SShuo Chen};
8485147189SShuo Chen
8585147189SShuo Chenclass OutputFile : public File
8685147189SShuo Chen{
8785147189SShuo Chen public:
8885147189SShuo Chen  explicit OutputFile(const std::string& filename)
8985147189SShuo Chen    : File(filename, "w")
9085147189SShuo Chen  {
9185147189SShuo Chen  }
9285147189SShuo Chen
9385147189SShuo Chen  void write(std::string_view s)
9485147189SShuo Chen  {
9585147189SShuo Chen    ::fwrite(s.data(), 1, s.size(), file_);
9685147189SShuo Chen  }
9785147189SShuo Chen
9885147189SShuo Chen  void appendRecord(std::string_view s)
9985147189SShuo Chen  {
10085147189SShuo Chen    assert(s.size() < 255);
10185147189SShuo Chen    uint8_t len = s.size();
10285147189SShuo Chen    ::fwrite(&len, 1, sizeof len, file_);
10385147189SShuo Chen    ::fwrite(s.data(), 1, len, file_);
10485147189SShuo Chen    ++items_;
10585147189SShuo Chen  }
10685147189SShuo Chen
10785147189SShuo Chen  size_t items()
10885147189SShuo Chen  {
10985147189SShuo Chen    return items_;
11085147189SShuo Chen  }
11185147189SShuo Chen
11285147189SShuo Chen private:
11385147189SShuo Chen  size_t items_ = 0;
11485147189SShuo Chen};
11585147189SShuo Chen
116