lib/file: implement open function

Soda
Shwoomple 2022-09-28 08:21:39 +05:30
parent e8d41efeef
commit 9610f4a4a2
5 changed files with 201 additions and 5 deletions

View File

@ -39,6 +39,7 @@ COMPILE_COMMANDS=(
"$CXX_WITH_FLAGS src/test/nbt_write_string_failure_mode.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_write_string_failure_mode"
"$CXX_WITH_FLAGS src/test/nbt_tags.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_tags"
"$CXX_WITH_FLAGS src/test/nbt_size_helpers.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_size_helpers"
"$CXX_WITH_FLAGS src/test/file.cpp -I./include -Lbin/lib -l:file.so -o bin/test/file"
)
for command in ${!COMPILE_COMMANDS[@]}; do
echo "${COMPILE_COMMANDS[command]}"

View File

@ -91,6 +91,10 @@ namespace ErrorCodes {
const uint8_t INVALID_TYPE = 8;
//file errors
const uint8_t FILE_READ_FAILED = 9;
const uint8_t FILE_NOT_FOUND = 10;
const uint8_t UNIMPLEMENTED = 254;
const uint8_t UNKNOWN = 255;

View File

@ -1,7 +1,7 @@
// Copyright 2022, FOSS-VG Developers and Contributers
//
// Author(s):
// <add authors here>
// Bodgemaster, Shwoomple
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
@ -16,4 +16,156 @@
// version 3 along with this program.
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
#include <fstream>
#include <filesystem>
#include <exception>
#include <vector>
#include <string>
#include "tinyutf8/tinyutf8.h"
#include "file.hpp"
#include "error.h"
File::File(std::string path, char mode, uint64_t cursorPosition): mode(mode), path(path), cursorPosition(cursorPosition){
switch(this->mode){
case 'w':
case 'm':
this->fileStream.open(path, std::fstream::out | std::fstream::binary);
break;
case 'r':
case 'e':
this->fileStream.open(path, std::fstream::in | std::fstream::binary);
break;
case 'a':
this->fileStream.open(path, std::fstream::app | std::fstream::binary);
break;
default:
break;
}
try{
std::filesystem::path filePath = path;
this->size = ErrorOr<uint64_t>(std::filesystem::file_size(filePath));
}catch(std::exception e){
this->size = ErrorOr<uint64_t>(true, ErrorCodes::FILE_NOT_FOUND);
}
}
File::File(const File& file){
this->mode = file.getMode();
this->isOpen = file.isOpen;
this->eof = file.eof;
this->path = file.path;
this->cursorPosition = file.cursorPosition;
this->size = file.size;
if(this->isOpen){
this->open();
}
}
File& File::operator=(const File& file){
File cpFile(file);
return cpFile;
}
void File::open(){
switch(this->mode){
case 'w':
case 'm':
this->fileStream.open(this->path, std::fstream::out | std::fstream::binary);
break;
case 'r':
case 'e':
this->fileStream.open(this->path, std::fstream::in | std::fstream::binary);
break;
case 'a':
this->fileStream.open(this->path, std::fstream::app | std::fstream::binary);
break;
default:
break;
}
try{
std::filesystem::path filePath = this->path;
this->size = ErrorOr<uint64_t>(std::filesystem::file_size(filePath));
}catch(std::exception e){
this->size = ErrorOr<uint64_t>(true, ErrorCodes::FILE_NOT_FOUND);
}
}
void File::close(){
this->fileStream.close();
this->isOpen = false;
}
char File::getMode() const{
return this->mode;
}
ErrorOr<uint8_t> File::readByte(){
if(this->size.isError){
return ErrorOr<uint8_t>(true, this->size.errorCode);
}
this->cursorPosition += 1;
this->fileStream.seekg(this->cursorPosition);
char* byte = new char;
try{
this->fileStream.read(byte, 1);
delete byte;
}catch(std::exception e){
return ErrorOr<uint8_t>(true, ErrorCodes::FILE_READ_FAILED);
}
return ErrorOr<uint8_t>((uint8_t) *byte);
}
ErrorOr<std::vector<uint8_t>> File::read(uint64_t bytes){
if(this->size.isError){
return ErrorOr<std::vector<uint8_t>>(true, this->size.errorCode);
}
this->cursorPosition += 1;
this->fileStream.seekg(this->cursorPosition);
char* buffer = new char[bytes];
std::vector<uint8_t> data;
try{
this->fileStream.read(buffer, bytes);
for(uint64_t i=0; i<bytes; i++){
data.push_back((uint8_t) buffer[i]);
}
delete[] buffer;
}catch(std::exception e){
return ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::FILE_READ_FAILED);
}
return ErrorOr<std::vector<uint8_t>>(data);
}
ErrorOr<tiny_utf8::string> File::readString(uint64_t bytes){
if(this->size.isError){
return ErrorOr<tiny_utf8::string>(true, this->size.errorCode);
}
ErrorOr<std::vector<uint8_t>> data = this->read(bytes);
if(data.isError){
return ErrorOr<tiny_utf8::string>(true, data.errorCode);
}
std::string s;
for(auto byte: data.value){
s.push_back(byte);
}
return ErrorOr<tiny_utf8::string>(tiny_utf8::string(s));
}
ErrorOr<File*> File::open(std::string path, char mode, uint64_t startPosition){
File *file = new File(path, mode, startPosition);
file->isOpen = true;
file->eof = false;
if(file->size.isError){
return ErrorOr<File*>(true, file->size.errorCode); //if file is not found
}
return ErrorOr<File*>(file);
}

View File

@ -1,7 +1,7 @@
// Copyright 2022, FOSS-VG Developers and Contributers
//
// Author(s):
// BodgeMaster
// BodgeMaster, Shwoomple
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
@ -18,31 +18,39 @@
#include <cstdint>
#include <string>
#include <fstream>
#include <vector>
#include <tinyutf8/tinyutf8.h>
#include "error.hpp"
class File {
private:
//TODO: add other necessary internals to this section as needed
char mode;
std::fstream fileStream;
//TODO: add other necessary details to the constructor as needed
// For example, the fstream (or whatever mechanism is used) needs
// to be handed over from File::open() to the File object.
//
// Remember to add a destructor to the public section if pointers
// are to be used.
File(char mode, uint64_t cursorPosition);
File(std::string path, char mode, uint64_t cursorPosition);
public:
bool isOpen;
bool eof;
std::string path;
uint64_t cursorPosition;
// may be error if not a regular file or size cannot be determined
ErrorOr<uint64_t> size;
File() = default;
File(const File& file);
File& operator=(const File& file);
void open();
void close();
char getMode() const;
// only applicable to read and edit modes
// moves the cursor to the right of the read section
@ -86,5 +94,5 @@ class File {
//
// A startPosition of 0xFFFFFFFF is considered to be the end of
// the file whatever its size.
static ErrorOr<File> open(std::string path, char mode, uint64_t startPosition=0);
};
static ErrorOr<File*> open(std::string path, char mode, uint64_t startPosition=0);
};

31
src/test/file.cpp Normal file
View File

@ -0,0 +1,31 @@
// Copyright 2022, FOSS-VG Developers and Contributers
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, version 3.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// version 3 along with this program.
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
#include "assert.hpp"
#include "tinyutf8/tinyutf8.h"
#include "../lib/file.hpp"
int main(){
std::cout << "################################################################################" << std::endl;
std::cout << "File tests" << std::endl;
std::cout << "################################################################################" << std::endl;
File *file;
//read test
file = File::open("../../resources/unicode_data/normal_utf-8", 'r').value;
tiny_utf8::string data = file->readString(file->size.value).value;
std::cout << file->size.isError << std::endl;
std::cout << data << std::endl;
}