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