file.h revision 85147189
185147189SShuo Chen#pragma once 285147189SShuo Chen 385147189SShuo Chen#include <stdio.h> 485147189SShuo Chen#include <memory> 585147189SShuo Chen#include <string> 685147189SShuo Chen#include "muduo/base/Logging.h" 785147189SShuo Chen 885147189SShuo Chen// Wrappers FILE* from stdio. 985147189SShuo Chenclass File 1085147189SShuo Chen{ 1185147189SShuo Chen public: 1285147189SShuo Chen int64_t tell() 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 2585147189SShuo Chen protected: 2685147189SShuo Chen // https://github.com/coreutils/coreutils/blob/master/src/ioblksize.h 2785147189SShuo Chen /* As of May 2014, 128KiB is determined to be the minimium 2885147189SShuo Chen * blksize to best minimize system call overhead. 2985147189SShuo Chen */ 3085147189SShuo Chen static const int kBufferSize = 1024 * 1024; 3185147189SShuo Chen 3285147189SShuo Chen File(const std::string& filename, const char* mode, int bufsize=kBufferSize) 3385147189SShuo Chen : file_(CHECK_NOTNULL(::fopen(filename.c_str(), mode))), 3485147189SShuo Chen buffer_(CHECK_NOTNULL(new char[bufsize])) 3585147189SShuo Chen { 3685147189SShuo Chen ::setbuffer(file_, buffer_.get(), bufsize); 3785147189SShuo Chen } 3885147189SShuo Chen 3985147189SShuo Chen virtual ~File() 4085147189SShuo Chen { 4185147189SShuo Chen close(); 4285147189SShuo Chen } 4385147189SShuo Chen 4485147189SShuo Chen protected: 4585147189SShuo Chen FILE* file_ = nullptr; 4685147189SShuo Chen 4785147189SShuo Chen private: 4885147189SShuo Chen std::unique_ptr<char[]> buffer_; 4985147189SShuo Chen 5085147189SShuo Chen File(const File&) = delete; 5185147189SShuo Chen void operator=(const File&) = delete; 5285147189SShuo Chen}; 5385147189SShuo Chen 5485147189SShuo Chenclass InputFile : public File 5585147189SShuo Chen{ 5685147189SShuo Chen public: 5785147189SShuo Chen explicit InputFile(const char* filename, int bufsize=kBufferSize) 5885147189SShuo Chen : File(filename, "r", bufsize) 5985147189SShuo Chen { 6085147189SShuo Chen } 6185147189SShuo Chen 6285147189SShuo Chen bool getline(std::string* output) 6385147189SShuo Chen { 6485147189SShuo Chen char buf[1024] = ""; 6585147189SShuo Chen if (::fgets(buf, sizeof buf, file_)) 6685147189SShuo Chen { 6785147189SShuo Chen *output = buf; 6885147189SShuo Chen if (!output->empty() && output->back() == '\n') 6985147189SShuo Chen { 7085147189SShuo Chen output->resize(output->size()-1); 7185147189SShuo Chen } 7285147189SShuo Chen return true; 7385147189SShuo Chen } 7485147189SShuo Chen return false; 7585147189SShuo Chen } 7685147189SShuo Chen}; 7785147189SShuo Chen 7885147189SShuo Chenclass OutputFile : public File 7985147189SShuo Chen{ 8085147189SShuo Chen public: 8185147189SShuo Chen explicit OutputFile(const std::string& filename) 8285147189SShuo Chen : File(filename, "w") 8385147189SShuo Chen { 8485147189SShuo Chen } 8585147189SShuo Chen 8685147189SShuo Chen void write(std::string_view s) 8785147189SShuo Chen { 8885147189SShuo Chen ::fwrite(s.data(), 1, s.size(), file_); 8985147189SShuo Chen } 9085147189SShuo Chen 9185147189SShuo Chen void appendRecord(std::string_view s) 9285147189SShuo Chen { 9385147189SShuo Chen assert(s.size() < 255); 9485147189SShuo Chen uint8_t len = s.size(); 9585147189SShuo Chen ::fwrite(&len, 1, sizeof len, file_); 9685147189SShuo Chen ::fwrite(s.data(), 1, len, file_); 9785147189SShuo Chen ++items_; 9885147189SShuo Chen } 9985147189SShuo Chen 10085147189SShuo Chen size_t items() 10185147189SShuo Chen { 10285147189SShuo Chen return items_; 10385147189SShuo Chen } 10485147189SShuo Chen 10585147189SShuo Chen private: 10685147189SShuo Chen size_t items_ = 0; 10785147189SShuo Chen}; 10885147189SShuo Chen 109