mirror of
https://github.com/holub/mame
synced 2025-07-04 09:28:51 +03:00
Filesystem code refactoring (#11570)
- Separate fs::block_t and fs::filesystem_t to a new source file and header - Remove inclusion of flopimg.h from fsmgr.h
This commit is contained in:
parent
7edf0aa2ab
commit
d8f1b27939
@ -75,6 +75,8 @@ project "formats"
|
|||||||
|
|
||||||
MAME_DIR .. "src/lib/formats/fsmgr.h",
|
MAME_DIR .. "src/lib/formats/fsmgr.h",
|
||||||
MAME_DIR .. "src/lib/formats/fsmgr.cpp",
|
MAME_DIR .. "src/lib/formats/fsmgr.cpp",
|
||||||
|
MAME_DIR .. "src/lib/formats/fsblk.h",
|
||||||
|
MAME_DIR .. "src/lib/formats/fsblk.cpp",
|
||||||
MAME_DIR .. "src/lib/formats/fsblk_vec.h",
|
MAME_DIR .. "src/lib/formats/fsblk_vec.h",
|
||||||
MAME_DIR .. "src/lib/formats/fsblk_vec.cpp",
|
MAME_DIR .. "src/lib/formats/fsblk_vec.cpp",
|
||||||
MAME_DIR .. "src/lib/formats/fs_unformatted.h",
|
MAME_DIR .. "src/lib/formats/fs_unformatted.h",
|
||||||
|
@ -12,10 +12,13 @@
|
|||||||
|
|
||||||
#include "fs_cbmdos.h"
|
#include "fs_cbmdos.h"
|
||||||
#include "d64_dsk.h"
|
#include "d64_dsk.h"
|
||||||
|
#include "fsblk.h"
|
||||||
|
|
||||||
#include "corestr.h"
|
#include "corestr.h"
|
||||||
#include "strformat.h"
|
#include "strformat.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
@ -13,10 +13,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
#include "fsmgr.h"
|
#include "fsmgr.h"
|
||||||
#include <optional>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
namespace fs {
|
namespace fs {
|
||||||
|
|
||||||
|
@ -15,10 +15,13 @@
|
|||||||
|
|
||||||
#include "fs_coco_os9.h"
|
#include "fs_coco_os9.h"
|
||||||
#include "coco_rawdsk.h"
|
#include "coco_rawdsk.h"
|
||||||
|
#include "fsblk.h"
|
||||||
|
|
||||||
#include "multibyte.h"
|
#include "multibyte.h"
|
||||||
#include "strformat.h"
|
#include "strformat.h"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
|
||||||
using namespace fs;
|
using namespace fs;
|
||||||
|
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "fsmgr.h"
|
#include "fsmgr.h"
|
||||||
#include <optional>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
namespace fs {
|
namespace fs {
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include "fs_coco_rsdos.h"
|
#include "fs_coco_rsdos.h"
|
||||||
#include "coco_rawdsk.h"
|
#include "coco_rawdsk.h"
|
||||||
|
#include "fsblk.h"
|
||||||
|
|
||||||
#include "util/strformat.h"
|
#include "util/strformat.h"
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "fsmgr.h"
|
#include "fsmgr.h"
|
||||||
#include <optional>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
namespace fs {
|
namespace fs {
|
||||||
|
|
||||||
|
@ -141,10 +141,13 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "fs_fat.h"
|
#include "fs_fat.h"
|
||||||
|
#include "fsblk.h"
|
||||||
#include "pc_dsk.h"
|
#include "pc_dsk.h"
|
||||||
|
|
||||||
#include "strformat.h"
|
#include "strformat.h"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
using namespace fs;
|
using namespace fs;
|
||||||
|
|
||||||
const fs::pc_fat_image fs::PC_FAT;
|
const fs::pc_fat_image fs::PC_FAT;
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "fsmgr.h"
|
#include "fsmgr.h"
|
||||||
#include <optional>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
namespace fs {
|
namespace fs {
|
||||||
|
|
||||||
|
using u8 = uint8_t;
|
||||||
|
|
||||||
// ======================> fat_image
|
// ======================> fat_image
|
||||||
|
|
||||||
class fat_image : public manager_t {
|
class fat_image : public manager_t {
|
||||||
|
@ -59,8 +59,11 @@
|
|||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
#include "fs_hp98x5.h"
|
#include "fs_hp98x5.h"
|
||||||
|
#include "fsblk.h"
|
||||||
#include "hpi_dsk.h"
|
#include "hpi_dsk.h"
|
||||||
|
|
||||||
#include "strformat.h"
|
#include "strformat.h"
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
@ -9,16 +9,20 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include "fs_hplif.h"
|
#include "fs_hplif.h"
|
||||||
|
#include "fsblk.h"
|
||||||
#include "hp300_dsk.h"
|
#include "hp300_dsk.h"
|
||||||
|
|
||||||
#include "corestr.h"
|
#include "corestr.h"
|
||||||
#include "osdcomm.h"
|
#include "osdcomm.h"
|
||||||
#include "strformat.h"
|
#include "strformat.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace fs {
|
namespace fs {
|
||||||
const hplif_image HPLIF;
|
const hplif_image HPLIF;
|
||||||
};
|
};
|
||||||
|
@ -13,10 +13,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
#include "fsmgr.h"
|
#include "fsmgr.h"
|
||||||
#include <optional>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
namespace fs {
|
namespace fs {
|
||||||
|
|
||||||
@ -39,7 +36,6 @@ namespace fs {
|
|||||||
virtual std::vector<meta_description> file_meta_description() const override;
|
virtual std::vector<meta_description> file_meta_description() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern const hplif_image HPLIF;
|
extern const hplif_image HPLIF;
|
||||||
|
|
||||||
} // namespace fs
|
} // namespace fs
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
#include "fs_isis.h"
|
#include "fs_isis.h"
|
||||||
|
#include "fsblk.h"
|
||||||
#include "img_dsk.h"
|
#include "img_dsk.h"
|
||||||
|
|
||||||
#include "multibyte.h"
|
#include "multibyte.h"
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
// Management of Oric Jasmin floppy images
|
// Management of Oric Jasmin floppy images
|
||||||
|
|
||||||
#include "fs_oric_jasmin.h"
|
#include "fs_oric_jasmin.h"
|
||||||
|
#include "fsblk.h"
|
||||||
#include "oric_dsk.h"
|
#include "oric_dsk.h"
|
||||||
|
|
||||||
#include "multibyte.h"
|
#include "multibyte.h"
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "fs_prodos.h"
|
#include "fs_prodos.h"
|
||||||
#include "ap_dsk35.h"
|
#include "ap_dsk35.h"
|
||||||
|
#include "fsblk.h"
|
||||||
|
|
||||||
#include "multibyte.h"
|
#include "multibyte.h"
|
||||||
#include "strformat.h"
|
#include "strformat.h"
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
// Creation of unformatted floppy images
|
// Creation of unformatted floppy images
|
||||||
|
|
||||||
#include "fs_unformatted.h"
|
#include "fs_unformatted.h"
|
||||||
|
#include "flopimg.h"
|
||||||
|
#include "fsblk.h"
|
||||||
|
|
||||||
namespace fs {
|
namespace fs {
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include "fsmgr.h"
|
#include "fsmgr.h"
|
||||||
|
|
||||||
|
class floppy_image;
|
||||||
|
|
||||||
namespace fs {
|
namespace fs {
|
||||||
|
|
||||||
class unformatted_image : public manager_t {
|
class unformatted_image : public manager_t {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
// Management of VTech images
|
// Management of VTech images
|
||||||
|
|
||||||
#include "fs_vtech.h"
|
#include "fs_vtech.h"
|
||||||
|
#include "fsblk.h"
|
||||||
#include "vt_dsk.h"
|
#include "vt_dsk.h"
|
||||||
|
|
||||||
#include "multibyte.h"
|
#include "multibyte.h"
|
||||||
|
254
src/lib/formats/fsblk.cpp
Normal file
254
src/lib/formats/fsblk.cpp
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
// Filesystem operations on mounted image blocks
|
||||||
|
|
||||||
|
#include "fsblk.h"
|
||||||
|
|
||||||
|
#include "multibyte.h"
|
||||||
|
#include "strformat.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace fs {
|
||||||
|
|
||||||
|
void refcounted_inner::ref()
|
||||||
|
{
|
||||||
|
m_ref ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refcounted_inner::ref_weak()
|
||||||
|
{
|
||||||
|
m_weak_ref ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool refcounted_inner::unref()
|
||||||
|
{
|
||||||
|
m_ref --;
|
||||||
|
if(m_ref == 0) {
|
||||||
|
if(m_weak_ref)
|
||||||
|
drop_weak_references();
|
||||||
|
else
|
||||||
|
delete this;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool refcounted_inner::unref_weak()
|
||||||
|
{
|
||||||
|
m_weak_ref --;
|
||||||
|
if(m_weak_ref == 0 && m_ref == 0) {
|
||||||
|
delete this;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void fsblk_t::set_block_size(u32 block_size)
|
||||||
|
{
|
||||||
|
m_block_size = block_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 *fsblk_t::iblock_t::offset(const char *function, u32 off, u32 size)
|
||||||
|
{
|
||||||
|
if(off + size > m_size)
|
||||||
|
throw std::out_of_range(util::string_format("block_t::%s out-of-block access, offset=%d, size=%d, block size=%d", function, off, size, m_size));
|
||||||
|
return data() + off;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8 *fsblk_t::iblock_t::rooffset(const char *function, u32 off, u32 size)
|
||||||
|
{
|
||||||
|
if(off + size > m_size)
|
||||||
|
throw std::out_of_range(util::string_format("block_t::%s out-of-block read access, offset=%d, size=%d, block size=%d\n", function, off, size, m_size));
|
||||||
|
return rodata() + off;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsblk_t::block_t::copy(u32 offset, const u8 *src, u32 size)
|
||||||
|
{
|
||||||
|
memcpy(m_object->offset("copy", offset, size), src, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsblk_t::block_t::fill(u32 offset, u8 data, u32 size)
|
||||||
|
{
|
||||||
|
memset(m_object->offset("fill", offset, size), data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsblk_t::block_t::fill(u8 data)
|
||||||
|
{
|
||||||
|
memset(m_object->data(), data, m_object->size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsblk_t::block_t::wstr(u32 offset, std::string_view str)
|
||||||
|
{
|
||||||
|
memcpy(m_object->offset("wstr", offset, str.size()), str.data(), str.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsblk_t::block_t::w8(u32 offset, u8 data)
|
||||||
|
{
|
||||||
|
m_object->offset("w8", offset, 1)[0] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsblk_t::block_t::w16b(u32 offset, u16 data)
|
||||||
|
{
|
||||||
|
put_u16be(m_object->offset("w16b", offset, 2), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsblk_t::block_t::w24b(u32 offset, u32 data)
|
||||||
|
{
|
||||||
|
put_u24be(m_object->offset("w24b", offset, 3), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsblk_t::block_t::w32b(u32 offset, u32 data)
|
||||||
|
{
|
||||||
|
put_u32be(m_object->offset("w32b", offset, 4), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsblk_t::block_t::w16l(u32 offset, u16 data)
|
||||||
|
{
|
||||||
|
put_u16le(m_object->offset("w16l", offset, 2), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsblk_t::block_t::w24l(u32 offset, u32 data)
|
||||||
|
{
|
||||||
|
put_u24le(m_object->offset("w24l", offset, 3), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsblk_t::block_t::w32l(u32 offset, u32 data)
|
||||||
|
{
|
||||||
|
put_u32le(m_object->offset("w32l", offset, 4), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view fsblk_t::block_t::rstr(u32 offset, u32 size) const
|
||||||
|
{
|
||||||
|
const u8 *d = m_object->rooffset("rstr", offset, size);
|
||||||
|
return std::string_view(reinterpret_cast<const char *>(d), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 fsblk_t::block_t::r8(u32 offset) const
|
||||||
|
{
|
||||||
|
return m_object->offset("r8", offset, 1)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 fsblk_t::block_t::r16b(u32 offset) const
|
||||||
|
{
|
||||||
|
return get_u16be(m_object->offset("r16b", offset, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 fsblk_t::block_t::r24b(u32 offset) const
|
||||||
|
{
|
||||||
|
return get_u24be(m_object->offset("r24b", offset, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 fsblk_t::block_t::r32b(u32 offset) const
|
||||||
|
{
|
||||||
|
return get_u32be(m_object->offset("r32b", offset, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 fsblk_t::block_t::r16l(u32 offset) const
|
||||||
|
{
|
||||||
|
return get_u16le(m_object->offset("r16l", offset, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 fsblk_t::block_t::r24l(u32 offset) const
|
||||||
|
{
|
||||||
|
return get_u24le(m_object->offset("r24l", offset, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 fsblk_t::block_t::r32l(u32 offset) const
|
||||||
|
{
|
||||||
|
return get_u32le(m_object->offset("r32l", offset, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void filesystem_t::wstr(u8 *p, std::string_view str)
|
||||||
|
{
|
||||||
|
memcpy(p, str.data(), str.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view filesystem_t::rstr(const u8 *p, u32 size)
|
||||||
|
{
|
||||||
|
return std::string_view(reinterpret_cast<const char *>(p), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view filesystem_t::trim_end_spaces(std::string_view str)
|
||||||
|
{
|
||||||
|
const auto i = str.find_last_not_of(' ');
|
||||||
|
return str.substr(0, (std::string::npos != i) ? (i + 1) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_data filesystem_t::volume_metadata()
|
||||||
|
{
|
||||||
|
return meta_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t filesystem_t::volume_metadata_change(const meta_data &meta)
|
||||||
|
{
|
||||||
|
return ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<err_t, meta_data> filesystem_t::metadata(const std::vector<std::string> &path)
|
||||||
|
{
|
||||||
|
return std::make_pair(ERR_UNSUPPORTED, meta_data());
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t filesystem_t::metadata_change(const std::vector<std::string> &path, const meta_data &meta)
|
||||||
|
{
|
||||||
|
return ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<err_t, std::vector<dir_entry>> filesystem_t::directory_contents(const std::vector<std::string> &path)
|
||||||
|
{
|
||||||
|
return std::make_pair(ERR_UNSUPPORTED, std::vector<dir_entry>());
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t filesystem_t::rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath)
|
||||||
|
{
|
||||||
|
return ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t filesystem_t::remove(const std::vector<std::string> &path)
|
||||||
|
{
|
||||||
|
return ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t filesystem_t::dir_create(const std::vector<std::string> &path, const meta_data &meta)
|
||||||
|
{
|
||||||
|
return ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t filesystem_t::file_create(const std::vector<std::string> &path, const meta_data &meta)
|
||||||
|
{
|
||||||
|
return ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<err_t, std::vector<u8>> filesystem_t::file_read(const std::vector<std::string> &path)
|
||||||
|
{
|
||||||
|
return std::make_pair(ERR_UNSUPPORTED, std::vector<u8>());
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t filesystem_t::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
|
||||||
|
{
|
||||||
|
return ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<err_t, std::vector<u8>> filesystem_t::file_rsrc_read(const std::vector<std::string> &path)
|
||||||
|
{
|
||||||
|
return std::make_pair(ERR_UNSUPPORTED, std::vector<u8>());
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t filesystem_t::file_rsrc_write(const std::vector<std::string> &path, const std::vector<u8> &data)
|
||||||
|
{
|
||||||
|
return ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t filesystem_t::format(const meta_data &meta)
|
||||||
|
{
|
||||||
|
return ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace fs
|
276
src/lib/formats/fsblk.h
Normal file
276
src/lib/formats/fsblk.h
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
// Filesystem operations on mounted image blocks
|
||||||
|
|
||||||
|
#ifndef MAME_FORMATS_FSBLK_H
|
||||||
|
#define MAME_FORMATS_FSBLK_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fsmeta.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace fs {
|
||||||
|
|
||||||
|
using u8 = uint8_t;
|
||||||
|
using u16 = uint16_t;
|
||||||
|
using u32 = uint32_t;
|
||||||
|
using u64 = uint64_t;
|
||||||
|
|
||||||
|
enum err_t {
|
||||||
|
ERR_OK = 0,
|
||||||
|
ERR_UNSUPPORTED,
|
||||||
|
ERR_INVALID,
|
||||||
|
ERR_NOT_FOUND,
|
||||||
|
ERR_NOT_EMPTY,
|
||||||
|
ERR_NO_SPACE,
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> class refcounted_outer {
|
||||||
|
public:
|
||||||
|
refcounted_outer(bool weak) : m_object(nullptr), m_is_weak_ref(weak) {}
|
||||||
|
refcounted_outer(T *object, bool weak) : m_object(object), m_is_weak_ref(weak) {
|
||||||
|
ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
refcounted_outer(const refcounted_outer &cref) {
|
||||||
|
m_object = cref.m_object;
|
||||||
|
m_is_weak_ref = cref.m_is_weak_ref;
|
||||||
|
ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
refcounted_outer(refcounted_outer &&cref) {
|
||||||
|
m_object = cref.m_object;
|
||||||
|
m_is_weak_ref = cref.m_is_weak_ref;
|
||||||
|
cref.m_object = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
~refcounted_outer() {
|
||||||
|
unref();
|
||||||
|
}
|
||||||
|
|
||||||
|
refcounted_outer<T> &operator =(T *dir) {
|
||||||
|
if(m_object != dir) {
|
||||||
|
unref();
|
||||||
|
m_object = dir;
|
||||||
|
ref();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
refcounted_outer<T> &operator =(const refcounted_outer<T> &cref) {
|
||||||
|
if(m_object != cref.m_object) {
|
||||||
|
unref();
|
||||||
|
m_object = cref.m_object;
|
||||||
|
ref();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
refcounted_outer<T> &operator =(refcounted_outer<T> &&cref) {
|
||||||
|
if(m_object != cref.m_object) {
|
||||||
|
unref();
|
||||||
|
m_object = cref.m_object;
|
||||||
|
ref();
|
||||||
|
} else if(m_is_weak_ref != cref.m_is_weak_ref) {
|
||||||
|
ref();
|
||||||
|
cref.unref();
|
||||||
|
m_object = cref.m_object; // In case the object got deleted (when going from strong ref to weak on the last strong)
|
||||||
|
}
|
||||||
|
cref.m_object = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool() const { return m_object != nullptr; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
T *m_object;
|
||||||
|
bool m_is_weak_ref;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ref() {
|
||||||
|
if(m_object) {
|
||||||
|
if(m_is_weak_ref)
|
||||||
|
m_object->ref_weak();
|
||||||
|
else
|
||||||
|
m_object->ref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unref() {
|
||||||
|
if(m_object) {
|
||||||
|
bool del = m_is_weak_ref ? m_object->unref_weak() : m_object->unref();
|
||||||
|
if(del)
|
||||||
|
m_object = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class refcounted_inner {
|
||||||
|
public:
|
||||||
|
refcounted_inner() : m_ref(0), m_weak_ref(0) {}
|
||||||
|
virtual ~refcounted_inner() = default;
|
||||||
|
|
||||||
|
void ref();
|
||||||
|
void ref_weak();
|
||||||
|
bool unref();
|
||||||
|
bool unref_weak();
|
||||||
|
|
||||||
|
virtual void drop_weak_references() = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
u32 m_ref, m_weak_ref;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class dir_entry_type {
|
||||||
|
dir,
|
||||||
|
file,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dir_entry {
|
||||||
|
std::string m_name;
|
||||||
|
dir_entry_type m_type;
|
||||||
|
meta_data m_meta;
|
||||||
|
|
||||||
|
dir_entry(dir_entry_type type, const meta_data &meta) : m_name(meta.get_string(meta_name::name)), m_type(type), m_meta(std::move(meta)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class fsblk_t {
|
||||||
|
protected:
|
||||||
|
class iblock_t : public refcounted_inner {
|
||||||
|
public:
|
||||||
|
iblock_t(u32 size) : refcounted_inner(), m_size(size) {}
|
||||||
|
virtual ~iblock_t() = default;
|
||||||
|
|
||||||
|
u32 size() const { return m_size; }
|
||||||
|
|
||||||
|
virtual const u8 *rodata() = 0;
|
||||||
|
virtual u8 *data() = 0;
|
||||||
|
u8 *offset(const char *function, u32 off, u32 size);
|
||||||
|
const u8 *rooffset(const char *function, u32 off, u32 size);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
u32 m_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
class block_t : public refcounted_outer<iblock_t> {
|
||||||
|
public:
|
||||||
|
block_t(bool weak = false) : refcounted_outer<iblock_t>(weak) {}
|
||||||
|
block_t(iblock_t *block, bool weak = true) : refcounted_outer(block, weak) {}
|
||||||
|
virtual ~block_t() = default;
|
||||||
|
|
||||||
|
block_t strong() { return block_t(m_object, false); }
|
||||||
|
block_t weak() { return block_t(m_object, true); }
|
||||||
|
|
||||||
|
u32 size() const { return m_object->size(); }
|
||||||
|
|
||||||
|
const u8 *rodata() const { return m_object->rodata(); }
|
||||||
|
u8 *data() { return m_object->data(); }
|
||||||
|
|
||||||
|
void copy(u32 offset, const u8 *src, u32 size);
|
||||||
|
void fill( u8 data);
|
||||||
|
void fill(u32 offset, u8 data, u32 size);
|
||||||
|
void wstr(u32 offset, std::string_view str);
|
||||||
|
void w8( u32 offset, u8 data);
|
||||||
|
void w16b(u32 offset, u16 data);
|
||||||
|
void w24b(u32 offset, u32 data);
|
||||||
|
void w32b(u32 offset, u32 data);
|
||||||
|
void w16l(u32 offset, u16 data);
|
||||||
|
void w24l(u32 offset, u32 data);
|
||||||
|
void w32l(u32 offset, u32 data);
|
||||||
|
|
||||||
|
std::string_view rstr(u32 offset, u32 size) const;
|
||||||
|
u8 r8( u32 offset) const;
|
||||||
|
u16 r16b(u32 offset) const;
|
||||||
|
u32 r24b(u32 offset) const;
|
||||||
|
u32 r32b(u32 offset) const;
|
||||||
|
u16 r16l(u32 offset) const;
|
||||||
|
u32 r24l(u32 offset) const;
|
||||||
|
u32 r32l(u32 offset) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
fsblk_t() : m_block_size(0) {}
|
||||||
|
virtual ~fsblk_t() = default;
|
||||||
|
|
||||||
|
virtual void set_block_size(u32 block_size);
|
||||||
|
virtual u32 block_count() const = 0;
|
||||||
|
virtual block_t get(u32 id) = 0;
|
||||||
|
virtual void fill(u8 data) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
u32 m_block_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class filesystem_t {
|
||||||
|
public:
|
||||||
|
virtual ~filesystem_t() = default;
|
||||||
|
|
||||||
|
// Get the metadata for the volume
|
||||||
|
virtual meta_data volume_metadata();
|
||||||
|
|
||||||
|
// Change the metadata for the volume
|
||||||
|
virtual err_t volume_metadata_change(const meta_data &meta);
|
||||||
|
|
||||||
|
// Get the metadata for a file or a directory. Empty path targets the root directory
|
||||||
|
virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path);
|
||||||
|
|
||||||
|
// Change the metadata for a file or a directory. Empty path targets the root directory
|
||||||
|
virtual err_t metadata_change(const std::vector<std::string> &path, const meta_data &meta);
|
||||||
|
|
||||||
|
// Get the contents of a directory, empty path targets the root directory
|
||||||
|
virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path);
|
||||||
|
|
||||||
|
// Rename a file or a directory. In contrast to metadata_change, this can move the object
|
||||||
|
// between directories
|
||||||
|
virtual err_t rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath);
|
||||||
|
|
||||||
|
// Remove a file or a directory. Directories must be empty (e.g. it's not recursive)
|
||||||
|
virtual err_t remove(const std::vector<std::string> &path);
|
||||||
|
|
||||||
|
// Create a directory, path designates where the directory must be, directory name is in meta
|
||||||
|
virtual err_t dir_create(const std::vector<std::string> &path, const meta_data &meta);
|
||||||
|
|
||||||
|
// Create an empty file, path designates where the file must be, file name is in meta
|
||||||
|
virtual err_t file_create(const std::vector<std::string> &path, const meta_data &meta);
|
||||||
|
|
||||||
|
// Read the contents of a file
|
||||||
|
virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path);
|
||||||
|
|
||||||
|
// Replace the contents of a file, the file must already exist
|
||||||
|
virtual err_t file_write(const std::vector<std::string> &path, const std::vector<u8> &data);
|
||||||
|
|
||||||
|
// Read the resource fork of a file on systems that handle those
|
||||||
|
virtual std::pair<err_t, std::vector<u8>> file_rsrc_read(const std::vector<std::string> &path);
|
||||||
|
|
||||||
|
// Replace the resource fork of a file, the file must already exist
|
||||||
|
virtual err_t file_rsrc_write(const std::vector<std::string> &path, const std::vector<u8> &data);
|
||||||
|
|
||||||
|
// Format an image, provide the volume metadata
|
||||||
|
virtual err_t format(const meta_data &meta);
|
||||||
|
|
||||||
|
static void wstr(u8 *p, std::string_view str);
|
||||||
|
|
||||||
|
static std::string_view rstr(const u8 *p, u32 size);
|
||||||
|
|
||||||
|
static std::string_view trim_end_spaces(std::string_view str);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
filesystem_t(fsblk_t &blockdev, u32 size) : m_blockdev(blockdev) {
|
||||||
|
m_blockdev.set_block_size(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
fsblk_t &m_blockdev;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace fs
|
||||||
|
|
||||||
|
#endif
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
// Block device on vector<uint8_t>
|
// Block device on vector<uint8_t>
|
||||||
|
|
||||||
#include "fsmgr.h"
|
#include "fsblk.h"
|
||||||
|
|
||||||
namespace fs {
|
namespace fs {
|
||||||
|
|
||||||
|
@ -6,49 +6,10 @@
|
|||||||
// Currently limited to floppies and creation of preformatted images
|
// Currently limited to floppies and creation of preformatted images
|
||||||
|
|
||||||
#include "fsmgr.h"
|
#include "fsmgr.h"
|
||||||
|
#include "flopimg.h"
|
||||||
#include "multibyte.h"
|
|
||||||
#include "strformat.h"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
namespace fs {
|
namespace fs {
|
||||||
|
|
||||||
void refcounted_inner::ref()
|
|
||||||
{
|
|
||||||
m_ref ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void refcounted_inner::ref_weak()
|
|
||||||
{
|
|
||||||
m_weak_ref ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool refcounted_inner::unref()
|
|
||||||
{
|
|
||||||
m_ref --;
|
|
||||||
if(m_ref == 0) {
|
|
||||||
if(m_weak_ref)
|
|
||||||
drop_weak_references();
|
|
||||||
else
|
|
||||||
delete this;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool refcounted_inner::unref_weak()
|
|
||||||
{
|
|
||||||
m_weak_ref --;
|
|
||||||
if(m_weak_ref == 0 && m_ref == 0) {
|
|
||||||
delete this;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void manager_t::enumerate_f(floppy_enumerator &fe) const
|
void manager_t::enumerate_f(floppy_enumerator &fe) const
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -104,209 +65,6 @@ char manager_t::directory_separator() const
|
|||||||
return 0; // Subdirectories not supported by default
|
return 0; // Subdirectories not supported by default
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsblk_t::set_block_size(u32 block_size)
|
|
||||||
{
|
|
||||||
m_block_size = block_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 *fsblk_t::iblock_t::offset(const char *function, u32 off, u32 size)
|
|
||||||
{
|
|
||||||
if(off + size > m_size)
|
|
||||||
throw std::out_of_range(util::string_format("block_t::%s out-of-block access, offset=%d, size=%d, block size=%d", function, off, size, m_size));
|
|
||||||
return data() + off;
|
|
||||||
}
|
|
||||||
|
|
||||||
const u8 *fsblk_t::iblock_t::rooffset(const char *function, u32 off, u32 size)
|
|
||||||
{
|
|
||||||
if(off + size > m_size)
|
|
||||||
throw std::out_of_range(util::string_format("block_t::%s out-of-block read access, offset=%d, size=%d, block size=%d\n", function, off, size, m_size));
|
|
||||||
return rodata() + off;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsblk_t::block_t::copy(u32 offset, const u8 *src, u32 size)
|
|
||||||
{
|
|
||||||
memcpy(m_object->offset("copy", offset, size), src, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsblk_t::block_t::fill(u32 offset, u8 data, u32 size)
|
|
||||||
{
|
|
||||||
memset(m_object->offset("fill", offset, size), data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsblk_t::block_t::fill(u8 data)
|
|
||||||
{
|
|
||||||
memset(m_object->data(), data, m_object->size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsblk_t::block_t::wstr(u32 offset, std::string_view str)
|
|
||||||
{
|
|
||||||
memcpy(m_object->offset("wstr", offset, str.size()), str.data(), str.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsblk_t::block_t::w8(u32 offset, u8 data)
|
|
||||||
{
|
|
||||||
m_object->offset("w8", offset, 1)[0] = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsblk_t::block_t::w16b(u32 offset, u16 data)
|
|
||||||
{
|
|
||||||
put_u16be(m_object->offset("w16b", offset, 2), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsblk_t::block_t::w24b(u32 offset, u32 data)
|
|
||||||
{
|
|
||||||
put_u24be(m_object->offset("w24b", offset, 3), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsblk_t::block_t::w32b(u32 offset, u32 data)
|
|
||||||
{
|
|
||||||
put_u32be(m_object->offset("w32b", offset, 4), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsblk_t::block_t::w16l(u32 offset, u16 data)
|
|
||||||
{
|
|
||||||
put_u16le(m_object->offset("w16l", offset, 2), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsblk_t::block_t::w24l(u32 offset, u32 data)
|
|
||||||
{
|
|
||||||
put_u24le(m_object->offset("w24l", offset, 3), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fsblk_t::block_t::w32l(u32 offset, u32 data)
|
|
||||||
{
|
|
||||||
put_u32le(m_object->offset("w32l", offset, 4), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view fsblk_t::block_t::rstr(u32 offset, u32 size) const
|
|
||||||
{
|
|
||||||
const u8 *d = m_object->rooffset("rstr", offset, size);
|
|
||||||
return std::string_view(reinterpret_cast<const char *>(d), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 fsblk_t::block_t::r8(u32 offset) const
|
|
||||||
{
|
|
||||||
return m_object->offset("r8", offset, 1)[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 fsblk_t::block_t::r16b(u32 offset) const
|
|
||||||
{
|
|
||||||
return get_u16be(m_object->offset("r16b", offset, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 fsblk_t::block_t::r24b(u32 offset) const
|
|
||||||
{
|
|
||||||
return get_u24be(m_object->offset("r24b", offset, 3));
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 fsblk_t::block_t::r32b(u32 offset) const
|
|
||||||
{
|
|
||||||
return get_u32be(m_object->offset("r32b", offset, 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 fsblk_t::block_t::r16l(u32 offset) const
|
|
||||||
{
|
|
||||||
return get_u16le(m_object->offset("r16l", offset, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 fsblk_t::block_t::r24l(u32 offset) const
|
|
||||||
{
|
|
||||||
return get_u24le(m_object->offset("r24l", offset, 3));
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 fsblk_t::block_t::r32l(u32 offset) const
|
|
||||||
{
|
|
||||||
return get_u32le(m_object->offset("r32l", offset, 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void filesystem_t::wstr(u8 *p, std::string_view str)
|
|
||||||
{
|
|
||||||
memcpy(p, str.data(), str.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view filesystem_t::rstr(const u8 *p, u32 size)
|
|
||||||
{
|
|
||||||
return std::string_view(reinterpret_cast<const char *>(p), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view filesystem_t::trim_end_spaces(std::string_view str)
|
|
||||||
{
|
|
||||||
const auto i = str.find_last_not_of(' ');
|
|
||||||
return str.substr(0, (std::string::npos != i) ? (i + 1) : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
meta_data filesystem_t::volume_metadata()
|
|
||||||
{
|
|
||||||
return meta_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
err_t filesystem_t::volume_metadata_change(const meta_data &meta)
|
|
||||||
{
|
|
||||||
return ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<err_t, meta_data> filesystem_t::metadata(const std::vector<std::string> &path)
|
|
||||||
{
|
|
||||||
return std::make_pair(ERR_UNSUPPORTED, meta_data());
|
|
||||||
}
|
|
||||||
|
|
||||||
err_t filesystem_t::metadata_change(const std::vector<std::string> &path, const meta_data &meta)
|
|
||||||
{
|
|
||||||
return ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<err_t, std::vector<dir_entry>> filesystem_t::directory_contents(const std::vector<std::string> &path)
|
|
||||||
{
|
|
||||||
return std::make_pair(ERR_UNSUPPORTED, std::vector<dir_entry>());
|
|
||||||
}
|
|
||||||
|
|
||||||
err_t filesystem_t::rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath)
|
|
||||||
{
|
|
||||||
return ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
err_t filesystem_t::remove(const std::vector<std::string> &path)
|
|
||||||
{
|
|
||||||
return ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
err_t filesystem_t::dir_create(const std::vector<std::string> &path, const meta_data &meta)
|
|
||||||
{
|
|
||||||
return ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
err_t filesystem_t::file_create(const std::vector<std::string> &path, const meta_data &meta)
|
|
||||||
{
|
|
||||||
return ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<err_t, std::vector<u8>> filesystem_t::file_read(const std::vector<std::string> &path)
|
|
||||||
{
|
|
||||||
return std::make_pair(ERR_UNSUPPORTED, std::vector<u8>());
|
|
||||||
}
|
|
||||||
|
|
||||||
err_t filesystem_t::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
|
|
||||||
{
|
|
||||||
return ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<err_t, std::vector<u8>> filesystem_t::file_rsrc_read(const std::vector<std::string> &path)
|
|
||||||
{
|
|
||||||
return std::make_pair(ERR_UNSUPPORTED, std::vector<u8>());
|
|
||||||
}
|
|
||||||
|
|
||||||
err_t filesystem_t::file_rsrc_write(const std::vector<std::string> &path, const std::vector<u8> &data)
|
|
||||||
{
|
|
||||||
return ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
err_t filesystem_t::format(const meta_data &meta)
|
|
||||||
{
|
|
||||||
return ERR_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_t::floppy_enumerator::floppy_enumerator(u32 form_factor, const std::vector<u32> &variants)
|
manager_t::floppy_enumerator::floppy_enumerator(u32 form_factor, const std::vector<u32> &variants)
|
||||||
: m_form_factor(form_factor)
|
: m_form_factor(form_factor)
|
||||||
, m_variants(variants)
|
, m_variants(variants)
|
||||||
|
@ -8,266 +8,20 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "flopimg.h"
|
|
||||||
#include "fsmeta.h"
|
#include "fsmeta.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class floppy_image_format_t;
|
||||||
|
|
||||||
namespace fs {
|
namespace fs {
|
||||||
|
|
||||||
using u8 = uint8_t;
|
// declared in fsblk.h
|
||||||
using u16 = uint16_t;
|
class filesystem_t;
|
||||||
|
class fsblk_t;
|
||||||
|
|
||||||
using u32 = uint32_t;
|
using u32 = uint32_t;
|
||||||
using u64 = uint64_t;
|
|
||||||
|
|
||||||
enum err_t {
|
|
||||||
ERR_OK = 0,
|
|
||||||
ERR_UNSUPPORTED,
|
|
||||||
ERR_INVALID,
|
|
||||||
ERR_NOT_FOUND,
|
|
||||||
ERR_NOT_EMPTY,
|
|
||||||
ERR_NO_SPACE,
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T> class refcounted_outer {
|
|
||||||
public:
|
|
||||||
refcounted_outer(bool weak) : m_object(nullptr), m_is_weak_ref(weak) {}
|
|
||||||
refcounted_outer(T *object, bool weak) : m_object(object), m_is_weak_ref(weak) {
|
|
||||||
ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
refcounted_outer(const refcounted_outer &cref) {
|
|
||||||
m_object = cref.m_object;
|
|
||||||
m_is_weak_ref = cref.m_is_weak_ref;
|
|
||||||
ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
refcounted_outer(refcounted_outer &&cref) {
|
|
||||||
m_object = cref.m_object;
|
|
||||||
m_is_weak_ref = cref.m_is_weak_ref;
|
|
||||||
cref.m_object = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
~refcounted_outer() {
|
|
||||||
unref();
|
|
||||||
}
|
|
||||||
|
|
||||||
refcounted_outer<T> &operator =(T *dir) {
|
|
||||||
if(m_object != dir) {
|
|
||||||
unref();
|
|
||||||
m_object = dir;
|
|
||||||
ref();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
refcounted_outer<T> &operator =(const refcounted_outer<T> &cref) {
|
|
||||||
if(m_object != cref.m_object) {
|
|
||||||
unref();
|
|
||||||
m_object = cref.m_object;
|
|
||||||
ref();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
refcounted_outer<T> &operator =(refcounted_outer<T> &&cref) {
|
|
||||||
if(m_object != cref.m_object) {
|
|
||||||
unref();
|
|
||||||
m_object = cref.m_object;
|
|
||||||
ref();
|
|
||||||
} else if(m_is_weak_ref != cref.m_is_weak_ref) {
|
|
||||||
ref();
|
|
||||||
cref.unref();
|
|
||||||
m_object = cref.m_object; // In case the object got deleted (when going from strong ref to weak on the last strong)
|
|
||||||
}
|
|
||||||
cref.m_object = nullptr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator bool() const { return m_object != nullptr; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
T *m_object;
|
|
||||||
bool m_is_weak_ref;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void ref() {
|
|
||||||
if(m_object) {
|
|
||||||
if(m_is_weak_ref)
|
|
||||||
m_object->ref_weak();
|
|
||||||
else
|
|
||||||
m_object->ref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void unref() {
|
|
||||||
if(m_object) {
|
|
||||||
bool del = m_is_weak_ref ? m_object->unref_weak() : m_object->unref();
|
|
||||||
if(del)
|
|
||||||
m_object = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class refcounted_inner {
|
|
||||||
public:
|
|
||||||
refcounted_inner() : m_ref(0), m_weak_ref(0) {}
|
|
||||||
virtual ~refcounted_inner() = default;
|
|
||||||
|
|
||||||
void ref();
|
|
||||||
void ref_weak();
|
|
||||||
bool unref();
|
|
||||||
bool unref_weak();
|
|
||||||
|
|
||||||
virtual void drop_weak_references() = 0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
u32 m_ref, m_weak_ref;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class dir_entry_type {
|
|
||||||
dir,
|
|
||||||
file,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct dir_entry {
|
|
||||||
std::string m_name;
|
|
||||||
dir_entry_type m_type;
|
|
||||||
meta_data m_meta;
|
|
||||||
|
|
||||||
dir_entry(dir_entry_type type, const meta_data &meta) : m_name(meta.get_string(meta_name::name)), m_type(type), m_meta(std::move(meta)) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class fsblk_t {
|
|
||||||
protected:
|
|
||||||
class iblock_t : public refcounted_inner {
|
|
||||||
public:
|
|
||||||
iblock_t(u32 size) : refcounted_inner(), m_size(size) {}
|
|
||||||
virtual ~iblock_t() = default;
|
|
||||||
|
|
||||||
u32 size() const { return m_size; }
|
|
||||||
|
|
||||||
virtual const u8 *rodata() = 0;
|
|
||||||
virtual u8 *data() = 0;
|
|
||||||
u8 *offset(const char *function, u32 off, u32 size);
|
|
||||||
const u8 *rooffset(const char *function, u32 off, u32 size);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
u32 m_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
class block_t : public refcounted_outer<iblock_t> {
|
|
||||||
public:
|
|
||||||
block_t(bool weak = false) : refcounted_outer<iblock_t>(weak) {}
|
|
||||||
block_t(iblock_t *block, bool weak = true) : refcounted_outer(block, weak) {}
|
|
||||||
virtual ~block_t() = default;
|
|
||||||
|
|
||||||
block_t strong() { return block_t(m_object, false); }
|
|
||||||
block_t weak() { return block_t(m_object, true); }
|
|
||||||
|
|
||||||
u32 size() const { return m_object->size(); }
|
|
||||||
|
|
||||||
const u8 *rodata() const { return m_object->rodata(); }
|
|
||||||
u8 *data() { return m_object->data(); }
|
|
||||||
|
|
||||||
void copy(u32 offset, const u8 *src, u32 size);
|
|
||||||
void fill( u8 data);
|
|
||||||
void fill(u32 offset, u8 data, u32 size);
|
|
||||||
void wstr(u32 offset, std::string_view str);
|
|
||||||
void w8( u32 offset, u8 data);
|
|
||||||
void w16b(u32 offset, u16 data);
|
|
||||||
void w24b(u32 offset, u32 data);
|
|
||||||
void w32b(u32 offset, u32 data);
|
|
||||||
void w16l(u32 offset, u16 data);
|
|
||||||
void w24l(u32 offset, u32 data);
|
|
||||||
void w32l(u32 offset, u32 data);
|
|
||||||
|
|
||||||
std::string_view rstr(u32 offset, u32 size) const;
|
|
||||||
u8 r8( u32 offset) const;
|
|
||||||
u16 r16b(u32 offset) const;
|
|
||||||
u32 r24b(u32 offset) const;
|
|
||||||
u32 r32b(u32 offset) const;
|
|
||||||
u16 r16l(u32 offset) const;
|
|
||||||
u32 r24l(u32 offset) const;
|
|
||||||
u32 r32l(u32 offset) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
fsblk_t() : m_block_size(0) {}
|
|
||||||
virtual ~fsblk_t() = default;
|
|
||||||
|
|
||||||
virtual void set_block_size(u32 block_size);
|
|
||||||
virtual u32 block_count() const = 0;
|
|
||||||
virtual block_t get(u32 id) = 0;
|
|
||||||
virtual void fill(u8 data) = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
u32 m_block_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class filesystem_t {
|
|
||||||
public:
|
|
||||||
virtual ~filesystem_t() = default;
|
|
||||||
|
|
||||||
// Get the metadata for the volume
|
|
||||||
virtual meta_data volume_metadata();
|
|
||||||
|
|
||||||
// Change the metadata for the volume
|
|
||||||
virtual err_t volume_metadata_change(const meta_data &meta);
|
|
||||||
|
|
||||||
// Get the metadata for a file or a directory. Empty path targets the root directory
|
|
||||||
virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path);
|
|
||||||
|
|
||||||
// Change the metadata for a file or a directory. Empty path targets the root directory
|
|
||||||
virtual err_t metadata_change(const std::vector<std::string> &path, const meta_data &meta);
|
|
||||||
|
|
||||||
// Get the contents of a directory, empty path targets the root directory
|
|
||||||
virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path);
|
|
||||||
|
|
||||||
// Rename a file or a directory. In contrast to metadata_change, this can move the object
|
|
||||||
// between directories
|
|
||||||
virtual err_t rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath);
|
|
||||||
|
|
||||||
// Remove a file or a directory. Directories must be empty (e.g. it's not recursive)
|
|
||||||
virtual err_t remove(const std::vector<std::string> &path);
|
|
||||||
|
|
||||||
// Create a directory, path designates where the directory must be, directory name is in meta
|
|
||||||
virtual err_t dir_create(const std::vector<std::string> &path, const meta_data &meta);
|
|
||||||
|
|
||||||
// Create an empty file, path designates where the file must be, file name is in meta
|
|
||||||
virtual err_t file_create(const std::vector<std::string> &path, const meta_data &meta);
|
|
||||||
|
|
||||||
// Read the contents of a file
|
|
||||||
virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path);
|
|
||||||
|
|
||||||
// Replace the contents of a file, the file must already exist
|
|
||||||
virtual err_t file_write(const std::vector<std::string> &path, const std::vector<u8> &data);
|
|
||||||
|
|
||||||
// Read the resource fork of a file on systems that handle those
|
|
||||||
virtual std::pair<err_t, std::vector<u8>> file_rsrc_read(const std::vector<std::string> &path);
|
|
||||||
|
|
||||||
// Replace the resource fork of a file, the file must already exist
|
|
||||||
virtual err_t file_rsrc_write(const std::vector<std::string> &path, const std::vector<u8> &data);
|
|
||||||
|
|
||||||
// Format an image, provide the volume metadata
|
|
||||||
virtual err_t format(const meta_data &meta);
|
|
||||||
|
|
||||||
static void wstr(u8 *p, std::string_view str);
|
|
||||||
|
|
||||||
static std::string_view rstr(const u8 *p, u32 size);
|
|
||||||
|
|
||||||
static std::string_view trim_end_spaces(std::string_view str);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
filesystem_t(fsblk_t &blockdev, u32 size) : m_blockdev(blockdev) {
|
|
||||||
m_blockdev.set_block_size(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
fsblk_t &m_blockdev;
|
|
||||||
};
|
|
||||||
|
|
||||||
class unformatted_floppy_creator;
|
|
||||||
|
|
||||||
class manager_t {
|
class manager_t {
|
||||||
public:
|
public:
|
||||||
@ -301,7 +55,6 @@ public:
|
|||||||
virtual void add(const manager_t *manager, const char *name, const char *description) = 0;
|
virtual void add(const manager_t *manager, const char *name, const char *description) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
virtual ~manager_t() = default;
|
virtual ~manager_t() = default;
|
||||||
|
|
||||||
virtual const char *name() const = 0;
|
virtual const char *name() const = 0;
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "image_handler.h"
|
#include "image_handler.h"
|
||||||
|
|
||||||
|
#include "formats/fsblk.h"
|
||||||
|
|
||||||
#include "corestr.h"
|
#include "corestr.h"
|
||||||
#include "ioprocs.h"
|
#include "ioprocs.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "formats/flopimg.h"
|
||||||
#include "formats/fsmgr.h"
|
#include "formats/fsmgr.h"
|
||||||
#include "harddisk.h"
|
#include "harddisk.h"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user