Skip to content

Instantly share code, notes, and snippets.

@Redchards
Created September 8, 2015 09:33
Show Gist options
  • Save Redchards/bebd526f544fa0f36133 to your computer and use it in GitHub Desktop.
Save Redchards/bebd526f544fa0f36133 to your computer and use it in GitHub Desktop.
Simple C++ wrapper around C functions. Sometimes easier to use that C++standard file streaming function.
#include <File.hxx>
File::File(const std::string& pathName, const char* openMode) : fileInfos_(initPath(pathName)),
filePtr_(nullptr),
openMode_(openMode)
{
init();
}
File::File(std::string&& pathName, const char* openMode) : fileInfos_(initPath(std::move(pathName))),
filePtr_(nullptr),
openMode_(openMode)
{
init();
}
File::File(const File& other) : fileInfos_(other.fileInfos_.getFilePath()),
filePtr_(nullptr),
openMode_(other.openMode_)
{
init();
}
File::File(File&& other) : fileInfos_(std::move(other.fileInfos_.getFilePath()))
{
std::swap(filePtr_, other.filePtr_);
other.filePtr_ = nullptr;
std::swap(openMode_, other.openMode_);
other.openMode_ = 0;
init();
}
File::~File()
{
std::fclose(filePtr_);
}
bool File::operator==(const File& rhs) const noexcept
{
return ((filePtr_ == rhs.filePtr_) && (fileInfos_ == rhs.fileInfos_));
}
File::operator bool()
{
return fileInfos_.exists();
}
FileInfos File::getFileInfos() const noexcept
{
return fileInfos_;
}
size_t File::getCursorPosition() const noexcept
{
return std::ftell(filePtr_);
}
void File::setCursorPosition(size_t pos) const noexcept
{
std::fseek(filePtr_, pos, SEEK_SET);
}
char File::readByte() const
{
char tmp = std::fgetc(filePtr_);
if(tmp == EOF)
{
checkForReadError();
}
return tmp;
}
std::unique_ptr<char[]> File::read(size_t byteNum) const
{
// Set this to debug, to see if we attempt to read furhter than the EOF
/*if(bytes > fileInfos_.getFileSize() - ftell(filePtr_))
{
throw IOException(fileInfos_.getFilePath(), IOAction::READ);
}*/
std::unique_ptr<char[]> buf{ new char[byteNum] };
size_t result = std::fread(buf.get(), 1, byteNum, filePtr_);
if(result < byteNum)
{
checkForReadError();
}
return buf;
}
void File::writeByte(char byte) const
{
char tmp = std::fputc(byte, filePtr_);
if(tmp == EOF)
{
checkForWriteError();
}
}
void File::writeBuffer(const char* buf, size_t byteNum) const
{
size_t result = std::fwrite(buf, 1, byteNum, filePtr_);
if(result < byteNum)
{
checkForWriteError();
}
}
void File::rewind()
{
std::fseek(filePtr_, 0, SEEK_SET);
}
File File::create(const std::string& filePath, const char* openMode)
{
auto last = filePath.find_last_of(FileInfos::pathDelimiter);
struct stat s;
auto err = stat(filePath.substr(0, last).data(), &s);
std::cout << filePath.substr(0, last).data() << std::endl;
if(err != 0)
{
throw CStatException(err, filePath);
}
std::ofstream ff(filePath, std::ios::out);
ff.close();
File newFile(filePath, openMode);
newFile.fileInfos_.updateFileInfos();
newFile.init();
return newFile;
}
void File::init()
{
filePtr_ = std::fopen((fileInfos_.exists() ? fileInfos_.getFilePath().c_str() : ""), openMode_);
if(filePtr_ == nullptr)
{
throw IOException(fileInfos_.getFilePath(), IOAction::OPEN);
}
}
void File::checkForReadError() const
{
if((ferror(filePtr_) != 0))
{
throw IOException(fileInfos_.getFilePath(), IOAction::READ);
}
}
void File::checkForWriteError() const
{
if((ferror(filePtr_) != 0))
{
throw IOException(fileInfos_.getFilePath(), IOAction::WRITE);
}
}
#ifndef UZIP_FILE
#define UZIP_FILE
#include <FileInfos.hxx>
#include <cstring>
#include <fstream>
// NOTE : Should I reimplement it with stl instead of c lib ?
class File
{
public:
File(const std::string& pathName, const char* openMode = "rw");
File(std::string&& pathName, const char* openMode = "rw");
File(const File& other);
File(File&& other);
~File();
bool operator==(const File&) const noexcept;
operator bool();
FileInfos getFileInfos() const noexcept;
size_t getCursorPosition() const noexcept;
void setCursorPosition(size_t pos) const noexcept;
char readByte() const;
std::unique_ptr<char[]> read(size_t byteNum) const;
void writeByte(char byte) const;
void writeBuffer(const char* buf, size_t byteNum) const;
void rewind();
static File create(const std::string& filePath, const char* openMode = "rw");
private:
void init();
template<class T>
std::string initPath(T&& pathName) const;
void checkForReadError() const;
void checkForWriteError() const;
FileInfos fileInfos_;
FILE* filePtr_;
const char* openMode_;
};
template<class T>
std::string File::initPath(T&& pathName) const
{
if(pathName[0] == FileInfos::pathDelimiter)
{
return std::move(std::string(pathName));
}
std::string f(std::forward<T>(pathName));
auto last = f.find_last_of(FileInfos::pathDelimiter);
char* tmp{ get_current_dir_name() };
std::string retval = "";
if(last != std::string::npos)
{
retval = std::string(tmp + f.substr(last, f.length() - 1));
free(tmp);
return retval;
}
retval = std::string(tmp) + FileInfos::pathDelimiter + std::string(std::move(f));
free(tmp);
return retval;
}
#endif // UZIP_FILE
#include <FileInfos.hxx>
char FileInfos::pathDelimiter = '/';
bool FileInfos::operator==(const FileInfos& rhs) const noexcept
{
return (filePath_ == rhs.filePath_);
}
const std::string& FileInfos::getFilePath() const noexcept
{
return filePath_;
}
const std::string FileInfos::getFileName() const noexcept
{
auto last = filePath_.find_last_of(pathDelimiter);
return filePath_.substr(last, filePath_.length() - 1);
}
uint64 FileInfos::getFileSize() noexcept
{
updateFileInfos();
return fileStat_.st_size;
}
bool FileInfos::exists() noexcept
{
updateFileInfos();
return exists_;
}
std::unique_ptr<tm> FileInfos::getLastAccessTime() noexcept
{
updateFileInfos();
return std::unique_ptr<tm>{ gmtime(&(fileStat_.st_atime)) };
}
std::unique_ptr<tm> FileInfos::getLastModificationTime() noexcept
{
updateFileInfos();
return std::unique_ptr<tm>{ gmtime(&(fileStat_.st_mtime)) };
}
void FileInfos::updateFileInfos()
{
auto err = stat(filePath_.data(), &fileStat_);
if(err != 0)
{
if(err != ENOENT && err != ENOTDIR)
{
exists_ = false;
}
else
{
throw CStatException(err, filePath_);
}
}
}
#ifndef UZIP_FILE_INFOS
#define UZIP_FILE_INFOS
#include <CommonTypes.hxx>
#include <Exceptions.hxx>
#include <Platform.hxx>
#include <climits>
#include <ctime>
#include <unistd.h>
#include <sys/stat.h>
#include <memory>
#include <string>
#include <iostream>
class FileInfos
{
public:
template<class T>
FileInfos(T&& filePath) :
filePath_(filePath[0] == '/' ? std::forward<T>(filePath) : ""),
exists_(true),
fileStat_{}
{
updateFileInfos();
}
bool operator==(const FileInfos& rhs) const noexcept;
const std::string& getFilePath() const noexcept;
const std::string getFileName() const noexcept;
uint64 getFileSize() noexcept;
bool exists() noexcept;
std::unique_ptr<tm> getLastAccessTime() noexcept;
std::unique_ptr<tm> getLastModificationTime() noexcept;
void updateFileInfos();
static char pathDelimiter;
private:
const std::string filePath_;
bool exists_;
struct stat fileStat_;
// To change on other systems
};
#endif // UZIP_FILE_INFOS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment