mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-06-05 12:30:39 +02:00
saving work
This commit is contained in:
parent
1bffa4a86d
commit
f62cc229f9
@ -47,3 +47,4 @@ template <> DetectorType StringTo(std::string);
|
||||
template <> TimingMode StringTo(std::string);
|
||||
|
||||
using DataTypeVariants = std::variant<uint16_t, uint32_t>;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include <iostream>
|
||||
|
||||
|
||||
IFrame::IFrame(std::byte* bytes, ssize_t rows, ssize_t cols, ssize_t bitdepth)
|
||||
FrameImpl::FrameImpl(std::byte* bytes, ssize_t rows, ssize_t cols, ssize_t bitdepth)
|
||||
{
|
||||
this->rows = rows;
|
||||
this->cols = cols;
|
||||
@ -10,7 +10,7 @@ IFrame::IFrame(std::byte* bytes, ssize_t rows, ssize_t cols, ssize_t bitdepth)
|
||||
std::memcpy(data, bytes, bitdepth/8 * rows * cols);
|
||||
}
|
||||
|
||||
std::byte* IFrame::get(int row, int col) {
|
||||
std::byte* FrameImpl::get(int row, int col) {
|
||||
if (row < 0 || row >= rows || col < 0 || col >= cols) {
|
||||
std::cerr << "Invalid row or column index" << std::endl;
|
||||
return 0;
|
||||
|
@ -13,24 +13,29 @@
|
||||
* model class
|
||||
* should be able to work with streams coming from files or network
|
||||
*/
|
||||
class IFrame {
|
||||
|
||||
class FrameImpl {
|
||||
protected:
|
||||
std::byte* data{nullptr};
|
||||
ssize_t rows{};
|
||||
ssize_t cols{};
|
||||
ssize_t bitdepth{};
|
||||
public:
|
||||
IFrame(std::byte* fp, ssize_t rows, ssize_t cols, ssize_t bitdepth);
|
||||
FrameImpl(std::byte* fp, ssize_t rows, ssize_t cols, ssize_t bitdepth);
|
||||
std::byte* get(int row, int col);
|
||||
~IFrame(){
|
||||
~FrameImpl(){
|
||||
delete[] data;
|
||||
}
|
||||
};
|
||||
|
||||
template <class DataType> class Frame: public IFrame {
|
||||
template <class DataType> class Frame: public FrameImpl {
|
||||
public:
|
||||
Frame(std::byte* fp, ssize_t rows, ssize_t cols):IFrame(fp, rows, cols, sizeof(DataType)){}
|
||||
Frame(std::byte* fp, ssize_t rows, ssize_t cols):FrameImpl(fp, rows, cols, sizeof(DataType)){}
|
||||
DataType get(int row, int col){
|
||||
return *((DataType*) IFrame::get(row, col));
|
||||
return *((DataType*) FrameImpl::get(row, col));
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
typedef Frame<uint16_t> Frame16;
|
||||
typedef Frame<uint8_t> Frame8;
|
||||
typedef Frame<uint32_t> Frame32;
|
@ -1,14 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "Frame.hpp"
|
||||
#include "SubFile.hpp"
|
||||
#include "defs.hpp"
|
||||
#include <filesystem>
|
||||
#include <fmt/core.h>
|
||||
#include "SubFile.hpp"
|
||||
#include <iostream>
|
||||
#include "Frame.hpp"
|
||||
|
||||
|
||||
|
||||
|
||||
struct RawFileConfig {
|
||||
int module_gap_row{};
|
||||
@ -23,13 +20,16 @@ struct RawFileConfig {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class File {
|
||||
private:
|
||||
using config = RawFileConfig;
|
||||
|
||||
public:
|
||||
std::vector<SubFileBase*> subfiles;
|
||||
virtual FrameImpl* get_frame(int frame_number) = 0;
|
||||
|
||||
private:
|
||||
using config = RawFileConfig;
|
||||
|
||||
public:
|
||||
std::vector<SubFile*> subfiles;
|
||||
std::filesystem::path fname;
|
||||
std::filesystem::path base_path;
|
||||
std::string base_name, ext;
|
||||
@ -49,13 +49,13 @@ class File {
|
||||
using data_type = uint16_t;
|
||||
std::vector<xy> positions;
|
||||
|
||||
config cfg{0,0};
|
||||
config cfg{0, 0};
|
||||
// File();
|
||||
~File();
|
||||
|
||||
inline size_t bytes_per_frame() const { return rows * cols * bitdepth / 8; }
|
||||
inline size_t pixels() const { return rows * cols; }
|
||||
inline void set_config(int row,int col){
|
||||
inline void set_config(int row, int col) {
|
||||
cfg.module_gap_row = row;
|
||||
cfg.module_gap_col = col;
|
||||
}
|
||||
@ -63,21 +63,17 @@ class File {
|
||||
// TODO! Deal with fast quad and missing files
|
||||
void find_number_of_subfiles() {
|
||||
int n_mod = 0;
|
||||
while (std::filesystem::exists(data_fname(++n_mod, 0)));
|
||||
while (std::filesystem::exists(data_fname(++n_mod, 0)))
|
||||
;
|
||||
n_subfiles = n_mod;
|
||||
|
||||
}
|
||||
|
||||
inline std::filesystem::path master_fname() {
|
||||
return base_path /
|
||||
fmt::format("{}_master_{}{}", base_name, findex, ext);
|
||||
return base_path / fmt::format("{}_master_{}{}", base_name, findex, ext);
|
||||
}
|
||||
inline std::filesystem::path data_fname(int mod_id, int file_id) {
|
||||
return base_path / fmt::format("{}_d{}_f{}_{}.raw", base_name, file_id,
|
||||
mod_id, findex);
|
||||
return base_path / fmt::format("{}_d{}_f{}_{}.raw", base_name, file_id, mod_id, findex);
|
||||
}
|
||||
|
||||
|
||||
virtual Frame<uint16_t> get_frame(int frame_number)=0;
|
||||
// size_t total_frames();
|
||||
};
|
||||
|
@ -0,0 +1,29 @@
|
||||
#include <filesystem>
|
||||
#include "FileFactory.hpp"
|
||||
#include "File.hpp"
|
||||
class FileHandler{
|
||||
private:
|
||||
std::filesystem::path fpath;
|
||||
FileFactory* fileFactory;
|
||||
File* f;
|
||||
|
||||
public:
|
||||
FileHandler(std::filesystem::path fpath){
|
||||
this->fpath = fpath;
|
||||
this->fileFactory= FileFactory::get_factory(fpath);
|
||||
this->f= fileFactory->load_file();
|
||||
delete fileFactory;
|
||||
}
|
||||
|
||||
template <typename DataType>
|
||||
Frame<DataType>* get_frame(int index){
|
||||
FrameImpl* frame =f->get_frame(index);
|
||||
return static_cast<Frame<DataType>*>(frame);
|
||||
}
|
||||
|
||||
|
||||
|
||||
~FileHandler(){
|
||||
delete f;
|
||||
}
|
||||
};
|
@ -1,8 +1,7 @@
|
||||
#include "JsonFile.hpp"
|
||||
#include <typeinfo>
|
||||
|
||||
template <class T>
|
||||
Frame<T> JsonFile::get_frame(int frame_number){
|
||||
FrameImpl* JsonFile::get_frame(int frame_number){
|
||||
int subfile_id=frame_number/max_frames_per_file;
|
||||
std::byte* buffer;
|
||||
size_t frame_size = subfiles[subfile_id]->bytes_per_frame();
|
||||
@ -12,7 +11,7 @@ Frame<T> JsonFile::get_frame(int frame_number){
|
||||
|
||||
|
||||
|
||||
auto f = Frame<T>(buffer, rows, cols);
|
||||
auto f = new FrameImpl(buffer, rows, cols, bitdepth);
|
||||
|
||||
delete[] buffer;
|
||||
return f;
|
||||
|
@ -5,9 +5,7 @@
|
||||
|
||||
class JsonFile: public File
|
||||
{
|
||||
template <class T>
|
||||
Frame<T> get_frame(int frame_number);
|
||||
|
||||
IFrame get_frame(int frame_number);
|
||||
FrameImpl* get_frame(int frame_number);
|
||||
|
||||
};
|
@ -7,52 +7,42 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
template <class Header, class DataType>
|
||||
SubFile<Header, DataType>::SubFile(std::filesystem::path fname, ssize_t rows, ssize_t cols) {
|
||||
|
||||
SubFile::SubFile(std::filesystem::path fname, DetectorType detector, ssize_t rows, ssize_t cols, uint16_t bitdepth) {
|
||||
this->rows = rows;
|
||||
this->cols = cols;
|
||||
this->fname = fname;
|
||||
this->bitdepth = bitdepth;
|
||||
fp = fopen(fname.c_str(), "rb");
|
||||
if (fp == nullptr) {
|
||||
throw std::runtime_error("Could not open file " + fname.string());
|
||||
}
|
||||
std::cout<<"File opened"<<std::endl;
|
||||
n_frames = std::filesystem::file_size(fname) / (sizeof(Header) + rows * cols * sizeof(DataType));
|
||||
std::cout<<"Number of frames: "<<n_frames<<std::endl;
|
||||
std::cout << "File opened" << std::endl;
|
||||
n_frames = std::filesystem::file_size(fname) / (sizeof(sls_detector_header) + rows * cols * bitdepth / 8);
|
||||
std::cout << "Number of frames: " << n_frames << std::endl;
|
||||
|
||||
if (detector == DetectorType::Moench) {
|
||||
read_impl = &SubFile::read_impl_reorder<uint16_t>;
|
||||
} else if (detector == DetectorType::Jungfrau) {
|
||||
read_impl = &SubFile::read_impl_normal;
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("Detector type not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class Header, class DataType>
|
||||
size_t SubFile<Header, DataType>::get_frame(std::byte *buffer, int frame_number) {
|
||||
size_t SubFile::get_frame(std::byte *buffer, int frame_number) {
|
||||
if (frame_number >= n_frames or frame_number < 0) {
|
||||
throw std::runtime_error("Frame number out of range");
|
||||
}
|
||||
fseek(fp, sizeof(Header)+(sizeof(Header) + bytes_per_frame()) *frame_number, SEEK_SET);
|
||||
return read_impl(buffer);
|
||||
fseek(fp, sizeof(sls_detector_header) + (sizeof(sls_detector_header) + bytes_per_frame()) * frame_number, SEEK_SET);
|
||||
return (this->*read_impl)(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* NormalSubFile methods
|
||||
*/
|
||||
template <class Header, class DataType>
|
||||
NormalSubFile<Header, DataType>::NormalSubFile(std::filesystem::path fname, ssize_t rows, ssize_t cols)
|
||||
: SubFile<Header, DataType>(fname, rows, cols){};
|
||||
size_t SubFile::read_impl_normal(std::byte *buffer) { return fread(buffer, this->bytes_per_frame(), 1, this->fp); }
|
||||
|
||||
template <class Header, class DataType> size_t NormalSubFile<Header, DataType>::read_impl(std::byte *buffer) {
|
||||
return fread(buffer, this->bytes_per_frame(), 1, this->fp);
|
||||
};
|
||||
template <typename DataType> size_t SubFile::read_impl_reorder(std::byte *buffer) {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ReorderM03SubFile methods
|
||||
*/
|
||||
template <class Header, class DataType>
|
||||
ReorderM03SubFile<Header, DataType>::ReorderM03SubFile(std::filesystem::path fname, ssize_t rows, ssize_t cols)
|
||||
: SubFile<Header, DataType>(fname, rows, cols){};
|
||||
|
||||
template <class Header, class DataType>
|
||||
size_t ReorderM03SubFile<Header, DataType>::read_impl(std::byte *buffer) {
|
||||
std::vector<DataType> tmp(this->pixels_per_frame());
|
||||
size_t rc = fread(reinterpret_cast<char *>(&tmp[0]), this->bytes_per_frame(), 1, this->fp);
|
||||
|
||||
@ -79,13 +69,24 @@ size_t ReorderM03SubFile<Header, DataType>::read_impl(std::byte *buffer) {
|
||||
}
|
||||
return rc;
|
||||
};
|
||||
template <typename DataType> size_t SubFile::read_impl_flip(std::byte *buffer) {
|
||||
|
||||
template class NormalSubFile<sls_detector_header, uint16_t>;
|
||||
template class NormalSubFile<sls_detector_header, uint32_t>;
|
||||
template class ReorderM03SubFile<sls_detector_header, uint16_t>;
|
||||
// read to temporary buffer
|
||||
// TODO! benchmark direct reads
|
||||
std::vector<std::byte> tmp(this->bytes_per_frame());
|
||||
size_t rc = fread(reinterpret_cast<char *>(&tmp[0]), this->bytes_per_frame(), 1, this->fp);
|
||||
|
||||
// template size_t ReorderM03SubFile<sls_detector_header, uint16_t>::read_impl(std::byte *buffer);
|
||||
// template size_t ReorderM03SubFile<sls_detector_header, uint32_t>::read_impl(std::byte *buffer);
|
||||
// copy to place
|
||||
const size_t start = this->cols * (this->rows - 1) * sizeof(DataType);
|
||||
const size_t row_size = this->cols * sizeof(DataType);
|
||||
auto dst = buffer + start;
|
||||
auto src = &tmp[0];
|
||||
|
||||
// template size_t NormalSubFile<sls_detector_header, uint32_t>::read_impl(std::byte *buffer);
|
||||
// template size_t NormalSubFile<sls_detector_header, uint16_t>::read_impl(std::byte *buffer);
|
||||
for (int i = 0; i != this->rows; ++i) {
|
||||
memcpy(dst, src, row_size);
|
||||
dst -= row_size;
|
||||
src += row_size;
|
||||
}
|
||||
|
||||
return rc;
|
||||
};
|
||||
|
@ -4,50 +4,29 @@
|
||||
#include <filesystem>
|
||||
#include <variant>
|
||||
|
||||
class SubFileBase {
|
||||
class SubFile {
|
||||
protected:
|
||||
FILE *fp = nullptr;
|
||||
uint16_t bitdepth;
|
||||
|
||||
public:
|
||||
virtual inline size_t bytes_per_frame() =0;
|
||||
virtual inline size_t pixels_per_frame() =0;
|
||||
std::filesystem::path fname;
|
||||
// pointer to a read_impl function. pointer will be set to the appropriate read_impl function in the constructor
|
||||
size_t (SubFile::*read_impl)(std::byte *buffer) = nullptr;
|
||||
size_t read_impl_normal(std::byte *buffer);
|
||||
template <typename DataType> size_t read_impl_flip(std::byte *buffer);
|
||||
template <typename DataType> size_t read_impl_reorder(std::byte *buffer);
|
||||
|
||||
|
||||
SubFile(std::filesystem::path fname,DetectorType detector, ssize_t rows, ssize_t cols, uint16_t bitdepth);
|
||||
|
||||
size_t get_frame(std::byte *buffer, int frame_number);
|
||||
|
||||
// TODO: define the inlines as variables and assign them in constructor
|
||||
inline size_t bytes_per_frame() { return (bitdepth / 8) * rows * cols; }
|
||||
inline size_t pixels_per_frame() { return rows * cols; }
|
||||
std::filesystem::path fname;
|
||||
ssize_t rows{};
|
||||
ssize_t cols{};
|
||||
ssize_t n_frames{};
|
||||
int sub_file_index_{};
|
||||
virtual size_t read_impl(std::byte *buffer)=0;
|
||||
virtual size_t get_frame(std::byte *buffer, int frame_number)=0;
|
||||
|
||||
};
|
||||
|
||||
template <class Header, class DataType> class SubFile : public SubFileBase{
|
||||
public:
|
||||
SubFile(std::filesystem::path fname, ssize_t rows, ssize_t cols);
|
||||
inline size_t bytes_per_frame() override { return sizeof(DataType) * rows * cols; }
|
||||
inline size_t pixels_per_frame() override { return rows * cols; }
|
||||
virtual size_t read_impl(std::byte *buffer)=0;
|
||||
size_t get_frame(std::byte *buffer, int frame_number);
|
||||
|
||||
|
||||
};
|
||||
|
||||
template <class Header, class DataType> class NormalSubFile : public SubFile<Header, DataType> {
|
||||
public:
|
||||
NormalSubFile(std::filesystem::path fname, ssize_t rows, ssize_t cols);
|
||||
size_t read_impl(std::byte *buffer);
|
||||
};
|
||||
|
||||
template <class Header, class DataType> class ReorderM03SubFile : public SubFile<Header, DataType> {
|
||||
public:
|
||||
ReorderM03SubFile(std::filesystem::path fname, ssize_t rows, ssize_t cols);
|
||||
size_t read_impl(std::byte *buffer);
|
||||
};
|
||||
|
||||
using JungfrauSubFile = NormalSubFile<sls_detector_header, uint16_t>;
|
||||
using Moench03SubFile = ReorderM03SubFile<sls_detector_header, uint16_t>;
|
||||
using Mythen3SubFile = NormalSubFile<sls_detector_header, uint32_t>;
|
||||
|
||||
// using SubFileVariants = std::variant<JungfrauSubFile, Mythen3SubFile, Moench03SubFile>;
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
|
||||
|
||||
FileFactory* FileFactory::getFactory(std::filesystem::path fpath){
|
||||
FileFactory* FileFactory::get_factory(std::filesystem::path fpath, uint16_t bitdepth){
|
||||
// check if file exists
|
||||
if(!std::filesystem::exists(fpath)){
|
||||
throw std::runtime_error("File does not exist");
|
||||
@ -18,7 +18,7 @@
|
||||
}
|
||||
else if(fpath.extension() == ".json"){
|
||||
std::cout<<"Loading json file"<<std::endl;
|
||||
return new JsonFileFactory(fpath);
|
||||
return new JsonFileFactory(fpath, bitdepth);
|
||||
}
|
||||
//check if extension is numpy
|
||||
else if(fpath.extension() == ".npy"){
|
||||
|
@ -7,10 +7,11 @@ class FileFactory{
|
||||
// follows the factory pattern
|
||||
protected:
|
||||
std::filesystem::path fpath;
|
||||
uint16_t bitdepth;
|
||||
public:
|
||||
static FileFactory* getFactory(std::filesystem::path);
|
||||
static FileFactory* get_factory(std::filesystem::path,uint16_t bitdepth=16);
|
||||
// virtual int deleteFile() = 0;
|
||||
virtual File* loadFile()=0;//TODO: add option to load all file to memory or keep it on disk
|
||||
virtual File* load_file()=0;//TODO: add option to load all file to memory or keep it on disk
|
||||
virtual void parse_metadata(File*)=0;
|
||||
|
||||
|
||||
|
@ -9,13 +9,14 @@
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
JsonFileFactory::JsonFileFactory(std::filesystem::path fpath) {
|
||||
JsonFileFactory::JsonFileFactory(std::filesystem::path fpath, uint16_t bitdepth=16) {
|
||||
if (not is_master_file(fpath))
|
||||
throw std::runtime_error("Json file is not a master file");
|
||||
this->fpath = fpath;
|
||||
this->bitdepth = bitdepth;
|
||||
}
|
||||
|
||||
void JsonFileFactory::parse_metadata(File* file) {
|
||||
void JsonFileFactory::parse_metadata(File *file) {
|
||||
std::cout << "Parsing metadata" << std::endl;
|
||||
std::ifstream ifs(file->master_fname());
|
||||
json j;
|
||||
@ -35,6 +36,9 @@ void JsonFileFactory::parse_metadata(File* file) {
|
||||
std::cerr << "master file does not have Dynamic Range. Defaulting to 16 bit" << '\n';
|
||||
file->bitdepth = 16;
|
||||
}
|
||||
// if (file->bitdepth != this->bitdepth)
|
||||
// throw std::runtime_error("Bitdepth mismatch: file bitdepth (" + std::to_string(file->bitdepth) +
|
||||
// ") != specified bitdepth (" + std::to_string(this->bitdepth) + ")");
|
||||
|
||||
// only Eiger had quad
|
||||
if (file->type == DetectorType::Eiger) {
|
||||
@ -42,22 +46,17 @@ void JsonFileFactory::parse_metadata(File* file) {
|
||||
}
|
||||
}
|
||||
|
||||
void JsonFileFactory::open_subfiles(File* file) {
|
||||
void JsonFileFactory::open_subfiles(File *file) {
|
||||
for (int i = 0; i != file->n_subfiles; ++i) {
|
||||
if (file->type == DetectorType::Jungfrau) {
|
||||
file->subfiles.push_back(new JungfrauSubFile(file->data_fname(i, 0), file->subfile_rows, file->subfile_cols));
|
||||
} else if (file->type == DetectorType::Mythen3)
|
||||
file->subfiles.push_back(new Mythen3SubFile(file->data_fname(i, 0), file->subfile_rows, file->subfile_cols));
|
||||
else if (file->type == DetectorType::Moench)
|
||||
file->subfiles.push_back(new Moench03SubFile(file->data_fname(i, 0), file->subfile_rows, file->subfile_cols));
|
||||
else
|
||||
throw std::runtime_error("File not supported");
|
||||
|
||||
file->subfiles.push_back(
|
||||
new SubFile(file->data_fname(i, 0), file->type, file->subfile_rows, file->subfile_cols, file->bitdepth));
|
||||
}
|
||||
}
|
||||
|
||||
File* JsonFileFactory::loadFile() {
|
||||
File *JsonFileFactory::load_file() {
|
||||
std::cout << "Loading json file" << std::endl;
|
||||
JsonFile* file = new JsonFile();
|
||||
JsonFile *file = new JsonFile();
|
||||
file->fname = fpath;
|
||||
this->parse_fname(file);
|
||||
this->parse_metadata(file);
|
||||
|
@ -5,9 +5,9 @@ class JsonFileFactory: public FileFactory
|
||||
private:
|
||||
/* data */
|
||||
public:
|
||||
File* loadFile() override;
|
||||
File* load_file() override;
|
||||
void parse_metadata(File*) override;
|
||||
JsonFileFactory(std::filesystem::path fpath);
|
||||
JsonFileFactory(std::filesystem::path fpath, uint16_t bitdepth);
|
||||
void open_subfiles(File*);
|
||||
|
||||
|
||||
|
39
src/main.cpp
39
src/main.cpp
@ -1,37 +1,22 @@
|
||||
// Your First C++ Program
|
||||
#include <iostream>
|
||||
#include "file_io/file_factory/FileFactory.hpp"
|
||||
|
||||
void test(File* f,int frame_number){
|
||||
#include <FileHandler.hpp>
|
||||
void test(FileHandler* f,int frame_number){
|
||||
std::cout << "frame number: " << frame_number << std::endl;
|
||||
auto frame = f->get_frame(frame_number);
|
||||
std::cout << frame.get(0,0) << ' ';
|
||||
std::cout << frame.get(0,1) << ' ';
|
||||
std::cout << frame.get(1,0) << ' ';
|
||||
std::cout << frame.get(511,1023) << std::endl;
|
||||
|
||||
Frame16* frame = f->get_frame<uint16_t>(frame_number);
|
||||
std::cout << frame->get(0,0) << ' ';
|
||||
std::cout << frame->get(0,1) << ' ';
|
||||
std::cout << frame->get(1,0) << ' ';
|
||||
std::cout << frame->get(511,1023) << std::endl;
|
||||
|
||||
delete frame;
|
||||
}
|
||||
|
||||
int main() {
|
||||
FileFactory* fileFactory=FileFactory::getFactory(std::filesystem::path("/home/l_bechir/github/aare")/"data"/"jungfrau_single_master_0.json");
|
||||
File* f = fileFactory->loadFile();
|
||||
std::filesystem::path fpath("/home/l_bechir/github/aare/data/jungfrau_single_master_0.json");
|
||||
FileHandler* fileHandler = new FileHandler(fpath);
|
||||
test(fileHandler,0);
|
||||
|
||||
test(f,0);
|
||||
test(f,1);
|
||||
test(f,2);
|
||||
test(f,3);
|
||||
test(f,4);
|
||||
test(f,5);
|
||||
test(f,6);
|
||||
test(f,7);
|
||||
test(f,8);
|
||||
test(f,9);
|
||||
delete fileHandler;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
delete fileFactory;
|
||||
delete f;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user