summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/formats/acorn_dsk.cpp216
-rw-r--r--src/lib/formats/acorn_dsk.h30
-rw-r--r--src/lib/formats/afs_dsk.cpp3
-rw-r--r--src/lib/formats/afs_dsk.h2
-rw-r--r--src/lib/formats/aim_dsk.cpp19
-rw-r--r--src/lib/formats/aim_dsk.h11
-rw-r--r--src/lib/formats/ami_dsk.cpp80
-rw-r--r--src/lib/formats/ami_dsk.h6
-rw-r--r--src/lib/formats/ap2_dsk.cpp141
-rw-r--r--src/lib/formats/ap2_dsk.h26
-rw-r--r--src/lib/formats/ap_dsk35.cpp83
-rw-r--r--src/lib/formats/ap_dsk35.h18
-rw-r--r--src/lib/formats/apd_dsk.cpp26
-rw-r--r--src/lib/formats/apd_dsk.h4
-rw-r--r--src/lib/formats/apollo_dsk.cpp14
-rw-r--r--src/lib/formats/apollo_dsk.h2
-rw-r--r--src/lib/formats/apridisk.cpp24
-rw-r--r--src/lib/formats/apridisk.h6
-rw-r--r--src/lib/formats/cassimg.cpp79
-rw-r--r--src/lib/formats/cassimg.h22
-rw-r--r--src/lib/formats/ccvf_dsk.cpp19
-rw-r--r--src/lib/formats/ccvf_dsk.h4
-rw-r--r--src/lib/formats/concept_dsk.cpp49
-rw-r--r--src/lib/formats/concept_dsk.h8
-rw-r--r--src/lib/formats/coupedsk.cpp28
-rw-r--r--src/lib/formats/coupedsk.h6
-rw-r--r--src/lib/formats/cqm_dsk.cpp36
-rw-r--r--src/lib/formats/cqm_dsk.h6
-rw-r--r--src/lib/formats/d64_dsk.cpp33
-rw-r--r--src/lib/formats/d64_dsk.h10
-rw-r--r--src/lib/formats/d80_dsk.cpp5
-rw-r--r--src/lib/formats/d88_dsk.cpp35
-rw-r--r--src/lib/formats/d88_dsk.h6
-rw-r--r--src/lib/formats/dcp_dsk.cpp28
-rw-r--r--src/lib/formats/dcp_dsk.h4
-rw-r--r--src/lib/formats/dfi_dsk.cpp25
-rw-r--r--src/lib/formats/dfi_dsk.h6
-rw-r--r--src/lib/formats/dim_dsk.cpp22
-rw-r--r--src/lib/formats/dim_dsk.h6
-rw-r--r--src/lib/formats/dip_dsk.cpp16
-rw-r--r--src/lib/formats/dip_dsk.h4
-rw-r--r--src/lib/formats/dmk_dsk.cpp27
-rw-r--r--src/lib/formats/dmk_dsk.h6
-rw-r--r--src/lib/formats/ds9_dsk.cpp24
-rw-r--r--src/lib/formats/ds9_dsk.h13
-rw-r--r--src/lib/formats/dsk_dsk.cpp35
-rw-r--r--src/lib/formats/dsk_dsk.h4
-rw-r--r--src/lib/formats/dvk_mx_dsk.cpp25
-rw-r--r--src/lib/formats/dvk_mx_dsk.h13
-rw-r--r--src/lib/formats/esq16_dsk.cpp40
-rw-r--r--src/lib/formats/esq16_dsk.h8
-rw-r--r--src/lib/formats/esq8_dsk.cpp38
-rw-r--r--src/lib/formats/esq8_dsk.h8
-rw-r--r--src/lib/formats/fdd_dsk.cpp18
-rw-r--r--src/lib/formats/fdd_dsk.h4
-rw-r--r--src/lib/formats/flex_dsk.cpp22
-rw-r--r--src/lib/formats/flex_dsk.h4
-rw-r--r--src/lib/formats/flopimg.cpp77
-rw-r--r--src/lib/formats/flopimg.h24
-rw-r--r--src/lib/formats/fsd_dsk.cpp16
-rw-r--r--src/lib/formats/fsd_dsk.h4
-rw-r--r--src/lib/formats/g64_dsk.cpp45
-rw-r--r--src/lib/formats/g64_dsk.h6
-rw-r--r--src/lib/formats/hpi_dsk.cpp23
-rw-r--r--src/lib/formats/hpi_dsk.h6
-rw-r--r--src/lib/formats/hti_tape.cpp52
-rw-r--r--src/lib/formats/hti_tape.h12
-rw-r--r--src/lib/formats/hxchfe_dsk.cpp26
-rw-r--r--src/lib/formats/hxchfe_dsk.h6
-rw-r--r--src/lib/formats/hxcmfm_dsk.cpp28
-rw-r--r--src/lib/formats/hxcmfm_dsk.h6
-rw-r--r--src/lib/formats/ibmxdf_dsk.cpp17
-rw-r--r--src/lib/formats/ibmxdf_dsk.h6
-rw-r--r--src/lib/formats/imd_dsk.cpp76
-rw-r--r--src/lib/formats/imd_dsk.h6
-rw-r--r--src/lib/formats/img_dsk.cpp22
-rw-r--r--src/lib/formats/img_dsk.h6
-rw-r--r--src/lib/formats/ioprocs.cpp214
-rw-r--r--src/lib/formats/ioprocs.h70
-rw-r--r--src/lib/formats/ipf_dsk.cpp21
-rw-r--r--src/lib/formats/ipf_dsk.h4
-rw-r--r--src/lib/formats/jfd_dsk.cpp25
-rw-r--r--src/lib/formats/jfd_dsk.h4
-rw-r--r--src/lib/formats/jvc_dsk.cpp26
-rw-r--r--src/lib/formats/jvc_dsk.h8
-rw-r--r--src/lib/formats/m20_dsk.cpp42
-rw-r--r--src/lib/formats/m20_dsk.h6
-rw-r--r--src/lib/formats/mdos_dsk.cpp22
-rw-r--r--src/lib/formats/mdos_dsk.h4
-rw-r--r--src/lib/formats/mfi_dsk.cpp29
-rw-r--r--src/lib/formats/mfi_dsk.h6
-rw-r--r--src/lib/formats/mfm_hd.cpp17
-rw-r--r--src/lib/formats/mfm_hd.h8
-rw-r--r--src/lib/formats/nfd_dsk.cpp31
-rw-r--r--src/lib/formats/nfd_dsk.h4
-rw-r--r--src/lib/formats/opd_dsk.cpp5
-rw-r--r--src/lib/formats/opd_dsk.h2
-rw-r--r--src/lib/formats/oric_dsk.cpp53
-rw-r--r--src/lib/formats/oric_dsk.h12
-rw-r--r--src/lib/formats/os9_dsk.cpp15
-rw-r--r--src/lib/formats/os9_dsk.h4
-rw-r--r--src/lib/formats/pasti_dsk.cpp16
-rw-r--r--src/lib/formats/pasti_dsk.h4
-rw-r--r--src/lib/formats/pc98fdi_dsk.cpp54
-rw-r--r--src/lib/formats/pc98fdi_dsk.h4
-rw-r--r--src/lib/formats/pc_dsk.cpp13
-rw-r--r--src/lib/formats/pc_dsk.h2
-rw-r--r--src/lib/formats/poly_dsk.cpp31
-rw-r--r--src/lib/formats/poly_dsk.h4
-rw-r--r--src/lib/formats/rx50_dsk.cpp27
-rw-r--r--src/lib/formats/rx50_dsk.h8
-rw-r--r--src/lib/formats/sdd_dsk.cpp5
-rw-r--r--src/lib/formats/sdf_dsk.cpp23
-rw-r--r--src/lib/formats/sdf_dsk.h6
-rw-r--r--src/lib/formats/st_dsk.cpp66
-rw-r--r--src/lib/formats/st_dsk.h16
-rw-r--r--src/lib/formats/svi_dsk.cpp37
-rw-r--r--src/lib/formats/svi_dsk.h6
-rw-r--r--src/lib/formats/td0_dsk.cpp73
-rw-r--r--src/lib/formats/td0_dsk.h6
-rw-r--r--src/lib/formats/ti99_dsk.cpp75
-rw-r--r--src/lib/formats/ti99_dsk.h26
-rw-r--r--src/lib/formats/trd_dsk.cpp17
-rw-r--r--src/lib/formats/trd_dsk.h2
-rw-r--r--src/lib/formats/trs80_dsk.cpp58
-rw-r--r--src/lib/formats/trs80_dsk.h6
-rw-r--r--src/lib/formats/uniflex_dsk.cpp21
-rw-r--r--src/lib/formats/uniflex_dsk.h4
-rw-r--r--src/lib/formats/upd765_dsk.cpp21
-rw-r--r--src/lib/formats/upd765_dsk.h8
-rw-r--r--src/lib/formats/vdk_dsk.cpp42
-rw-r--r--src/lib/formats/vdk_dsk.h6
-rw-r--r--src/lib/formats/victor9k_dsk.cpp32
-rw-r--r--src/lib/formats/victor9k_dsk.h8
-rw-r--r--src/lib/formats/vt_dsk.cpp47
-rw-r--r--src/lib/formats/vt_dsk.h12
-rw-r--r--src/lib/formats/wd177x_dsk.cpp27
-rw-r--r--src/lib/formats/wd177x_dsk.h8
-rw-r--r--src/lib/util/avhuff.cpp4
-rw-r--r--src/lib/util/aviio.cpp84
-rw-r--r--src/lib/util/cdrom.cpp91
-rw-r--r--src/lib/util/cdrom.h14
-rw-r--r--src/lib/util/chd.cpp711
-rw-r--r--src/lib/util/chd.h274
-rw-r--r--src/lib/util/chdcd.cpp186
-rw-r--r--src/lib/util/chdcd.h12
-rw-r--r--src/lib/util/chdcodec.cpp260
-rw-r--r--src/lib/util/chdcodec.h95
-rw-r--r--src/lib/util/corefile.cpp441
-rw-r--r--src/lib/util/corefile.h49
-rw-r--r--src/lib/util/harddisk.cpp18
-rw-r--r--src/lib/util/harddisk.h10
-rw-r--r--src/lib/util/ioprocs.cpp1248
-rw-r--r--src/lib/util/ioprocs.h130
-rw-r--r--src/lib/util/ioprocsfill.h163
-rw-r--r--src/lib/util/ioprocsfilter.cpp598
-rw-r--r--src/lib/util/ioprocsfilter.h31
-rw-r--r--src/lib/util/ioprocsvec.h211
-rw-r--r--src/lib/util/path.cpp0
-rw-r--r--src/lib/util/path.h65
-rw-r--r--src/lib/util/strformat.h54
-rw-r--r--src/lib/util/timeconv.cpp69
-rw-r--r--src/lib/util/timeconv.h39
-rw-r--r--src/lib/util/un7z.cpp467
-rw-r--r--src/lib/util/unzip.cpp1050
-rw-r--r--src/lib/util/unzip.h58
-rw-r--r--src/lib/util/utilfwd.h45
-rw-r--r--src/lib/util/zippath.cpp149
-rw-r--r--src/lib/util/zippath.h5
169 files changed, 6360 insertions, 3645 deletions
diff --git a/src/lib/formats/acorn_dsk.cpp b/src/lib/formats/acorn_dsk.cpp
index c4668478b05..40ab6eb1029 100644
--- a/src/lib/formats/acorn_dsk.cpp
+++ b/src/lib/formats/acorn_dsk.cpp
@@ -10,6 +10,9 @@
#include "acorn_dsk.h"
+#include "ioprocs.h"
+
+
acorn_ssd_format::acorn_ssd_format() : wd177x_format(formats)
{
}
@@ -29,29 +32,36 @@ const char *acorn_ssd_format::extensions() const
return "ssd,bbc,img";
}
-int acorn_ssd_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int acorn_ssd_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t cat[8];
uint32_t sectors0, sectors2;
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ {
+ LOG_FORMATS("ssd: error getting image size\n");
+ return -1;
+ }
- for(int i=0; formats[i].form_factor; i++) {
+ for (int i=0; formats[i].form_factor; i++)
+ {
+ size_t actual;
const format &f = formats[i];
- if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
+ if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
continue;
// test for Torch CPN - test pattern at sector &0018
- io_generic_read(io, cat, 0x32800, 8);
+ io.read_at(0x32800, cat, 8, actual);
if (memcmp(cat, "\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd", 4) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
return i;
// test for HADFS - test pattern at sector 70
- io_generic_read(io, cat, 0x04610, 8);
+ io.read_at(0x04610, cat, 8, actual);
if (memcmp(cat, "\x00\x28\x43\x29\x4a\x47\x48\x00", 4) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
return i;
// test for Kenda SD - offset &0962 = 0 SD/1 DD, offset &0963 = disk size blocks / 4 (block size = 1K, ie. 0x400 bytes), reserved tracks = 3, ie. 0x1e00 bytes, soft stagger = 2 sectors, ie. 0x200 bytes
- io_generic_read(io, cat, 0x0960, 8);
+ io.read_at(0x0960, cat, 8, actual);
if (cat[2] == 0 && ((uint64_t)cat[3] * 4 * 0x400 + 0x2000) == size && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
{
// valid blocks for single sided
@@ -63,20 +73,22 @@ int acorn_ssd_format::find_size(io_generic *io, uint32_t form_factor, const std:
}
// read sector count from side 0 catalogue
- io_generic_read(io, cat, 0x100, 8);
+ io.read_at(0x100, cat, 8, actual);
sectors0 = ((cat[6] & 3) << 8) + cat[7];
LOG_FORMATS("ssd: sector count 0: %d %s\n", sectors0, sectors0 % 10 != 0 ? "invalid" : "");
- if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) {
+ if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count))
+ {
if (f.head_count == 2)
{
// read sector count from side 2 catalogue
- io_generic_read(io, cat, (uint64_t)compute_track_size(f) * f.track_count + 0x100, 8); // sequential
+ io.read_at((uint64_t)compute_track_size(f) * f.track_count + 0x100, cat, 8, actual); // sequential
sectors2 = ((cat[6] & 3) << 8) + cat[7];
// exception case for Acorn CP/M System Disc 1
- io_generic_read(io, cat, 0x367ec, 8);
- if (memcmp(cat, "/M ", 4) == 0) sectors2 = ((cat[6] & 3) << 8) + cat[7];
+ io.read_at(0x367ec, cat, 8, actual);
+ if (memcmp(cat, "/M ", 4) == 0)
+ sectors2 = ((cat[6] & 3) << 8) + cat[7];
LOG_FORMATS("ssd: sector count 2: %d %s\n", sectors2, sectors2 % 10 != 0 ? "invalid" : "");
}
@@ -93,12 +105,13 @@ int acorn_ssd_format::find_size(io_generic *io, uint32_t form_factor, const std:
return -1;
}
-int acorn_ssd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int acorn_ssd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int type = find_size(io, form_factor, variants);
- if(type != -1)
+ if (type != -1)
return 90;
+
return 0;
}
@@ -171,40 +184,49 @@ const char *acorn_dsd_format::extensions() const
return "dsd";
}
-int acorn_dsd_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int acorn_dsd_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t cat[8];
uint32_t sectors0, sectors2;
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ {
+ LOG_FORMATS("dsd: error getting image size\n");
+ return -1;
+ }
- for (int i = 0; formats[i].form_factor; i++) {
+ for (int i = 0; formats[i].form_factor; i++)
+ {
+ size_t actual;
const format &f = formats[i];
if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
continue;
// test for Torch CPN - test pattern at sector &0018
- io_generic_read(io, cat, 0x1200, 8);
+ io.read_at(0x1200, cat, 8, actual);
if (memcmp(cat, "\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd", 4) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
return i;
// test for HADFS - test pattern at sector 70
- io_generic_read(io, cat, 0x08c10, 8);
+ io.read_at(0x08c10, cat, 8, actual);
if (memcmp(cat, "\x00\x28\x43\x29\x4a\x47\x48\x00", 4) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
return i;
// read sector count from side 0 catalogue
- io_generic_read(io, cat, 0x100, 8);
+ io.read_at(0x100, cat, 8, actual);
sectors0 = ((cat[6] & 3) << 8) + cat[7];
LOG_FORMATS("dsd: sector count 0: %d %s\n", sectors0, sectors0 % 10 != 0 ? "invalid" : "");
- if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) {
+ if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count))
+ {
// read sector count from side 2 catalogue
- io_generic_read(io, cat, 0xb00, 8); // interleaved
+ io.read_at(0xb00, cat, 8, actual); // interleaved
sectors2 = ((cat[6] & 3) << 8) + cat[7];
// exception case for Acorn CP/M System Disc 1
- io_generic_read(io, cat, 0x97ec, 8);
- if (memcmp(cat, "/M ", 4) == 0) sectors2 = ((cat[6] & 3) << 8) + cat[7];
+ io.read_at(0x97ec, cat, 8, actual);
+ if (memcmp(cat, "/M ", 4) == 0)
+ sectors2 = ((cat[6] & 3) << 8) + cat[7];
LOG_FORMATS("dsd: sector count 2: %d %s\n", sectors2, sectors2 % 10 != 0 ? "invalid" : "");
@@ -216,12 +238,13 @@ int acorn_dsd_format::find_size(io_generic *io, uint32_t form_factor, const std:
return -1;
}
-int acorn_dsd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int acorn_dsd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int type = find_size(io, form_factor, variants);
if (type != -1)
return 90;
+
return 0;
}
@@ -274,27 +297,36 @@ const char *opus_ddos_format::extensions() const
return "dds";
}
-int opus_ddos_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int opus_ddos_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
+ size_t actual;
uint8_t cat[8];
uint32_t sectors0, sectors2;
// read sector count from side 0 catalogue
- io_generic_read(io, cat, 0x1000, 8);
+ io.read_at(0x1000, cat, 8, actual);
sectors0 = (cat[1] << 8) + cat[2];
LOG_FORMATS("ddos: sector count 0: %d %s\n", sectors0, sectors0 % 18 != 0 ? "invalid" : "");
- uint64_t size = io_generic_size(io);
- for (int i = 0; formats[i].form_factor; i++) {
+ uint64_t size;
+ if (io.length(size))
+ {
+ LOG_FORMATS("ddos: error getting image size\n");
+ return -1;
+ }
+
+ for (int i = 0; formats[i].form_factor; i++)
+ {
const format &f = formats[i];
if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
continue;
- if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) {
+ if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count))
+ {
if (f.head_count == 2)
{
// read sector count from side 2 catalogue
- io_generic_read(io, cat, (uint64_t)compute_track_size(f) * f.track_count + 0x1000, 8); // sequential
+ io.read_at((uint64_t)compute_track_size(f) * f.track_count + 0x1000, cat, 8, actual); // sequential
sectors2 = (cat[1] << 8) + cat[2];
LOG_FORMATS("ddos: sector count 2: %d %s\n", sectors2, sectors2 % 18 != 0 ? "invalid" : "");
}
@@ -311,12 +343,13 @@ int opus_ddos_format::find_size(io_generic *io, uint32_t form_factor, const std:
return -1;
}
-int opus_ddos_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int opus_ddos_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int type = find_size(io, form_factor, variants);
if (type != -1)
return 90;
+
return 0;
}
@@ -369,25 +402,33 @@ const char *acorn_adfs_old_format::extensions() const
return "adf,ads,adm,adl";
}
-int acorn_adfs_old_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int acorn_adfs_old_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
+ size_t actual;
uint8_t map[3];
uint32_t sectors;
uint8_t oldmap[4];
// read sector count from free space map
- io_generic_read(io, map, 0xfc, 3);
+ io.read_at(0xfc, map, 3, actual);
sectors = map[0] + (map[1] << 8) + (map[2] << 16);
LOG_FORMATS("adfs_o: sector count %d %s\n", sectors, sectors % 16 != 0 ? "invalid" : "");
// read map identifier
- io_generic_read(io, oldmap, 0x201, 4);
+ io.read_at(0x201, oldmap, 4, actual);
LOG_FORMATS("adfs_o: map identifier %s %s\n", oldmap, memcmp(oldmap, "Hugo", 4) != 0 ? "invalid" : "");
- uint64_t size = io_generic_size(io);
- for(int i=0; formats[i].form_factor; i++) {
+ uint64_t size;
+ if (io.length(size))
+ {
+ LOG_FORMATS("adfs_o: error getting image size\n");
+ return -1;
+ }
+
+ for (int i=0; formats[i].form_factor; i++)
+ {
const format &f = formats[i];
- if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
+ if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
continue;
// valid images will have map identifier 'Hugo' and sector counts adfs-s = 0x280; adfs-m = 0x500; adfs-l = 0xa00; adfs-dos = 0xaa0; though many adfs-s images are incorrect
@@ -399,12 +440,13 @@ int acorn_adfs_old_format::find_size(io_generic *io, uint32_t form_factor, const
return -1;
}
-int acorn_adfs_old_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int acorn_adfs_old_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int type = find_size(io, form_factor, variants);
if(type != -1)
return 100;
+
return 0;
}
@@ -465,43 +507,50 @@ const char *acorn_adfs_new_format::extensions() const
return "adf";
}
-int acorn_adfs_new_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int acorn_adfs_new_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
+ size_t actual;
uint8_t dform[4];
uint8_t eform[4];
// read map identifiers for D and E formats
- io_generic_read(io, dform, 0x401, 4);
+ io.read_at(0x401, dform, 4, actual);
LOG_FORMATS("adfs_n: map identifier (D format) %s %s\n", dform, (memcmp(dform, "Hugo", 4) != 0 && memcmp(dform, "Nick", 4) != 0) ? "invalid" : "");
- io_generic_read(io, eform, 0x801, 4);
+ io.read_at(0x801, eform, 4, actual);
LOG_FORMATS("adfs_n: map identifier (E format) %s %s\n", eform, memcmp(eform, "Nick", 4) != 0 ? "invalid" : "");
- uint64_t size = io_generic_size(io);
- for (int i = 0; formats[i].form_factor; i++) {
+ uint64_t size;
+ if (io.length(size))
+ {
+ LOG_FORMATS("adfs_n: error getting image size\n");
+ return -1;
+ }
+
+ for (int i = 0; formats[i].form_factor; i++)
+ {
const format &f = formats[i];
if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
continue;
// no further checks for 1600K images
- if ((size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && size == 0x190000) {
+ if ((size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && size == 0x190000)
return i;
- }
// valid 800K images will have map identifier Nick, Arthur D format still use Hugo
- if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (memcmp(dform, "Hugo", 4) == 0 || memcmp(dform, "Nick", 4) == 0 || memcmp(eform, "Nick", 4) == 0)) {
+ if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (memcmp(dform, "Hugo", 4) == 0 || memcmp(dform, "Nick", 4) == 0 || memcmp(eform, "Nick", 4) == 0))
return i;
- }
}
LOG_FORMATS("adfs_n: no match\n");
return -1;
}
-int acorn_adfs_new_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int acorn_adfs_new_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int type = find_size(io, form_factor, variants);
if (type != -1)
return 100;
+
return 0;
}
@@ -546,33 +595,43 @@ const char *acorn_dos_format::extensions() const
return "img";
}
-int acorn_dos_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int acorn_dos_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint8_t type;
+ uint64_t size;
+ if (io.length(size))
+ {
+ LOG_FORMATS("dos: error getting image size\n");
+ return -1;
+ }
- uint64_t size = io_generic_size(io);
- for(int i=0; formats[i].form_factor; i++) {
+ for (int i=0; formats[i].form_factor; i++)
+ {
const format &f = formats[i];
- if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
+ if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
continue;
- if (size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) {
+ if (size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
+ {
// read media type ID from FAT - Acorn DOS = 0xfd
- io_generic_read(io, &type, 0, 1);
+ size_t actual;
+ uint8_t type;
+ io.read_at(0, &type, 1, actual);
LOG_FORMATS("dos: 800k media type id %02X %s\n", type, type != 0xfd ? "invalid" : "");
- if (type == 0xfd) return i;
+ if (type == 0xfd)
+ return i;
}
}
LOG_FORMATS("dos: no match\n");
return -1;
}
-int acorn_dos_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int acorn_dos_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int type = find_size(io, form_factor, variants);
- if(type != -1)
+ if (type != -1)
return 90;
+
return 0;
}
@@ -618,19 +677,28 @@ bool opus_ddcpm_format::supports_save() const
return false;
}
-int opus_ddcpm_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int opus_ddcpm_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
+ size_t actual;
uint8_t h[8];
- io_generic_read(io, h, 0, 8);
+ io.read_at(0, h, 8, actual);
+
+ uint64_t size;
+ if (io.length(size))
+ {
+ LOG_FORMATS("ddcpm: error getting image size\n");
+ return -1;
+ }
- if (io_generic_size(io) == 819200 && memcmp(h, "Slogger ", 8) == 0)
+ if (size == 819200 && memcmp(h, "Slogger ", 8) == 0)
return 100;
+
LOG_FORMATS("ddcpm: no match\n");
return 0;
}
-bool opus_ddcpm_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool opus_ddcpm_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
// Double density discs formatted with DDCPM :
//
@@ -644,19 +712,21 @@ bool opus_ddcpm_format::load(io_generic *io, uint32_t form_factor, const std::ve
// Sector skew of 1
// Sector interleave of 2
//
- int spt, bps;
-
- for (int head = 0; head < 2; head++) {
- for (int track = 0; track < 80; track++) {
- bool mfm = track > 2 || head;
- bps = mfm ? 512 : 256;
- spt = 10;
+ for (int head = 0; head < 2; head++)
+ {
+ for (int track = 0; track < 80; track++)
+ {
+ bool const mfm = track > 2 || head;
+ int const bps = mfm ? 512 : 256;
+ int const spt = 10;
desc_pc_sector sects[10];
uint8_t sectdata[10*512];
- io_generic_read(io, sectdata, head * 80 * spt * 512 + track * spt * 512, spt * 512);
+ size_t actual;
+ io.read_at(head * 80 * spt * 512 + track * spt * 512, sectdata, spt * 512, actual);
- for (int i = 0; i < spt; i++) {
+ for (int i = 0; i < spt; i++)
+ {
sects[i].track = track;
sects[i].head = head;
sects[i].sector = i;
@@ -677,7 +747,7 @@ bool opus_ddcpm_format::load(io_generic *io, uint32_t form_factor, const std::ve
return true;
}
-bool opus_ddcpm_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool opus_ddcpm_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
return false;
}
diff --git a/src/lib/formats/acorn_dsk.h b/src/lib/formats/acorn_dsk.h
index 1428212cfaa..de07e8b9fed 100644
--- a/src/lib/formats/acorn_dsk.h
+++ b/src/lib/formats/acorn_dsk.h
@@ -20,8 +20,8 @@ class acorn_ssd_format : public wd177x_format
public:
acorn_ssd_format();
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual int get_image_offset(const format &f, int head, int track) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -36,8 +36,8 @@ class acorn_dsd_format : public wd177x_format
public:
acorn_dsd_format();
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual int get_image_offset(const format &f, int head, int track) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -52,8 +52,8 @@ class opus_ddos_format : public wd177x_format
public:
opus_ddos_format();
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual int get_image_offset(const format &f, int head, int track) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -68,8 +68,8 @@ class acorn_adfs_old_format : public wd177x_format
public:
acorn_adfs_old_format();
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual int get_image_offset(const format &f, int head, int track) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -84,8 +84,8 @@ class acorn_adfs_new_format : public wd177x_format
public:
acorn_adfs_new_format();
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual int get_image_offset(const format &f, int head, int track) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -100,8 +100,8 @@ class acorn_dos_format : public wd177x_format
public:
acorn_dos_format();
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual int get_image_offset(const format &f, int head, int track) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -116,9 +116,9 @@ class opus_ddcpm_format : public floppy_image_format_t
public:
opus_ddcpm_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/afs_dsk.cpp b/src/lib/formats/afs_dsk.cpp
index d6b275240de..000daf62df7 100644
--- a/src/lib/formats/afs_dsk.cpp
+++ b/src/lib/formats/afs_dsk.cpp
@@ -30,12 +30,13 @@ const char *afs_format::extensions() const
return "adl,img";
}
-int afs_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int afs_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int type = find_size(io, form_factor, variants);
if (type != -1)
return 50;
+
return 0;
}
diff --git a/src/lib/formats/afs_dsk.h b/src/lib/formats/afs_dsk.h
index 1a15e54d90d..f56b2dcb1f4 100644
--- a/src/lib/formats/afs_dsk.h
+++ b/src/lib/formats/afs_dsk.h
@@ -20,7 +20,7 @@ class afs_format : public wd177x_format
public:
afs_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual int get_image_offset(const format &f, int head, int track) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/aim_dsk.cpp b/src/lib/formats/aim_dsk.cpp
index 489ec1752e4..6ad49b22969 100644
--- a/src/lib/formats/aim_dsk.cpp
+++ b/src/lib/formats/aim_dsk.cpp
@@ -12,10 +12,10 @@
*********************************************************************/
-#include <cassert>
-
#include "aim_dsk.h"
+#include "ioprocs.h"
+
aim_format::aim_format()
{
@@ -40,18 +40,20 @@ const char *aim_format::extensions() const
}
-int aim_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int aim_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- if (io_generic_size(io) == 2068480)
- {
+ uint64_t size;
+ if (io.length(size))
+ return 0;
+
+ if (size == 2068480)
return 100;
- }
return 0;
}
-bool aim_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool aim_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
image->set_variant(floppy_image::DSQD);
@@ -70,7 +72,8 @@ bool aim_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
bool header = false;
// Read track
- io_generic_read(io, &track_data[0], ( heads * track + head ) * track_size, track_size);
+ size_t actual;
+ io.read_at((heads * track + head) * track_size, &track_data[0], track_size, actual);
// Find first sector header or index mark
for (int offset = 0; offset < track_size; offset += 2)
diff --git a/src/lib/formats/aim_dsk.h b/src/lib/formats/aim_dsk.h
index c4737efc7e6..560943be30c 100644
--- a/src/lib/formats/aim_dsk.h
+++ b/src/lib/formats/aim_dsk.h
@@ -7,9 +7,10 @@
AIM disk images
*********************************************************************/
+#ifndef MAME_FORMATS_AIM_DSK_H
+#define MAME_FORMATS_AIM_DSK_H
-#ifndef AIM_DSK_H
-#define AIM_DSK_H
+#pragma once
#include "flopimg.h"
@@ -20,8 +21,8 @@ class aim_format : public floppy_image_format_t
public:
aim_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -31,4 +32,4 @@ public:
extern const floppy_format_type FLOPPY_AIM_FORMAT;
-#endif /* AIM_DSK_H */
+#endif // MAME_FORMATS_AIM_DSK_H
diff --git a/src/lib/formats/ami_dsk.cpp b/src/lib/formats/ami_dsk.cpp
index 5973bc69dab..eb96b01377d 100644
--- a/src/lib/formats/ami_dsk.cpp
+++ b/src/lib/formats/ami_dsk.cpp
@@ -8,10 +8,11 @@
*********************************************************************/
-#include <cassert>
-
#include "formats/ami_dsk.h"
+#include "ioprocs.h"
+
+
adf_format::adf_format() : floppy_image_format_t()
{
}
@@ -36,59 +37,61 @@ bool adf_format::supports_save() const
return true;
}
-int adf_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int adf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return 0;
+
if ((size == 901120) || (size == 912384) || (size == 1802240))
- {
return 50;
- }
+
return 0;
}
-bool adf_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool adf_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
desc_s sectors[22];
uint8_t sectdata[512*22];
bool is_hd = false;
int tracks = 80;
- for(int i=0; i<22; i++) {
+ for (int i=0; i<22; i++) {
sectors[i].data = sectdata + 512*i;
sectors[i].size = 512;
sectors[i].sector_id = i;
}
- uint64_t size = io_generic_size(io);
- if(size == 901120)
- {
+ uint64_t size;
+ if (io.length(size))
+ return false;
+
+ if (size == 901120) {
is_hd = false;
tracks = 80;
- }
- else if (size == 912384)
- {
+ } else if (size == 912384) {
is_hd = false;
tracks = 81;
- }
- else
- {
+ } else {
is_hd = true;
tracks = 80;
}
if (!is_hd) {
image->set_variant(floppy_image::DSDD);
- for(int track=0; track < tracks; track++) {
- for(int side=0; side < 2; side++) {
- io_generic_read(io, sectdata, (track*2 + side)*512*11, 512*11);
+ for (int track=0; track < tracks; track++) {
+ for (int side=0; side < 2; side++) {
+ size_t actual;
+ io.read_at((track*2 + side)*512*11, sectdata, 512*11, actual);
generate_track(amiga_11, track, side, sectors, 11, 100000, image);
}
}
} else {
image->set_variant(floppy_image::DSHD);
- for(int track=0; track < tracks; track++) {
- for(int side=0; side < 2; side++) {
- io_generic_read(io, sectdata, (track*2 + side)*512*22, 512*22);
+ for (int track=0; track < tracks; track++) {
+ for (int side=0; side < 2; side++) {
+ size_t actual;
+ io.read_at((track*2 + side)*512*22, sectdata, 512*22, actual);
generate_track(amiga_22, track, side, sectors, 22, 200000, image);
}
}
@@ -100,11 +103,11 @@ bool adf_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
uint32_t adf_format::g32(const std::vector<bool> &trackbuf, uint32_t pos)
{
uint32_t res = 0;
- for(int i=0; i != 32; i++) {
- if(trackbuf[pos])
+ for (int i=0; i != 32; i++) {
+ if (trackbuf[pos])
res |= 0x80000000 >> i;
- pos ++;
- if(pos == trackbuf.size())
+ pos++;
+ if (pos == trackbuf.size())
pos = 0;
}
return res;
@@ -113,34 +116,34 @@ uint32_t adf_format::g32(const std::vector<bool> &trackbuf, uint32_t pos)
uint32_t adf_format::checksum(const std::vector<bool> &trackbuf, uint32_t pos, int long_count)
{
uint32_t check = 0;
- for(int i=0; i<long_count; i++)
+ for (int i=0; i<long_count; i++)
check ^= g32(trackbuf, pos+32*i);
return check & 0x55555555;
}
-bool adf_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool adf_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint8_t sectdata[512*22];
- bool hd = image->get_variant() == floppy_image::DSHD;
+ bool const hd = image->get_variant() == floppy_image::DSHD;
- int data_track_size = hd ? 512*22 : 512*11;
+ int const data_track_size = hd ? 512*22 : 512*11;
- for(int track=0; track < 80; track++) {
- for(int side=0; side < 2; side++) {
+ for (int track=0; track < 80; track++) {
+ for (int side=0; side < 2; side++) {
auto trackbuf = generate_bitstream_from_track(track, side, hd ? 1000 : 2000, image);
- for(uint32_t i=0; i<trackbuf.size(); i++)
- if(g32(trackbuf, i) == 0x44894489 &&
+ for (uint32_t i=0; i<trackbuf.size(); i++)
+ if (g32(trackbuf, i) == 0x44894489 &&
(g32(trackbuf, i+384) & 0x55555555) == checksum(trackbuf, i+32, 10) &&
(g32(trackbuf, i+448) & 0x55555555) == checksum(trackbuf, i+480, 256)) {
uint32_t head = ((g32(trackbuf, i+32) & 0x55555555) << 1) | (g32(trackbuf, i+64) & 0x55555555);
int sect = (head >> 8) & 0xff;
- if(sect > (hd ? 22 : 11))
+ if (sect > (hd ? 22 : 11))
continue;
uint8_t *dest = sectdata + 512*sect;
- for(int j=0; j<128; j++) {
+ for (int j=0; j<128; j++) {
uint32_t val = ((g32(trackbuf, i+480+32*j) & 0x55555555) << 1) | (g32(trackbuf, i+4576+32*j) & 0x55555555);
*dest++ = val >> 24;
*dest++ = val >> 16;
@@ -148,7 +151,8 @@ bool adf_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
*dest++ = val;
}
- io_generic_write(io, sectdata, (track*2 + side)*data_track_size, data_track_size);
+ size_t actual;
+ io.write_at((track*2 + side) * data_track_size, sectdata, data_track_size, actual);
}
}
}
diff --git a/src/lib/formats/ami_dsk.h b/src/lib/formats/ami_dsk.h
index d25fd45a210..595beb1bcd3 100644
--- a/src/lib/formats/ami_dsk.h
+++ b/src/lib/formats/ami_dsk.h
@@ -19,9 +19,9 @@ class adf_format : public floppy_image_format_t
public:
adf_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/ap2_dsk.cpp b/src/lib/formats/ap2_dsk.cpp
index 50b071d6432..8adc13d69d3 100644
--- a/src/lib/formats/ap2_dsk.cpp
+++ b/src/lib/formats/ap2_dsk.cpp
@@ -8,13 +8,15 @@
*********************************************************************/
-#include <cstdlib>
-#include <cstring>
-#include <cassert>
-
#include "ap2_dsk.h"
#include "basicdsk.h"
+#include "ioprocs.h"
+
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+
#define APPLE2_IMAGE_DO 0
#define APPLE2_IMAGE_PO 1
@@ -559,9 +561,12 @@ bool a2_16sect_format::supports_save() const
return true;
}
-int a2_16sect_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int a2_16sect_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return 0;
+
//uint32_t expected_size = 35 * 16 * 256;
uint32_t expected_size = APPLE2_TRACK_COUNT * 16 * 256;
@@ -574,9 +579,11 @@ int a2_16sect_format::identify(io_generic *io, uint32_t form_factor, const std::
return 0;
}
-bool a2_16sect_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool a2_16sect_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return false;
image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD);
@@ -595,7 +602,8 @@ bool a2_16sect_format::load(io_generic *io, uint32_t form_factor, const std::vec
static const unsigned char cpm22_block1[8] = { 0xa2, 0x55, 0xa9, 0x00, 0x9d, 0x00, 0x0d, 0xca };
static const unsigned char subnod_block1[8] = { 0x63, 0xaa, 0xf0, 0x76, 0x8d, 0x63, 0xaa, 0x8e };
- io_generic_read(io, sector_data, fpos, 256*16);
+ size_t actual;
+ io.read_at(fpos, sector_data, 256*16, actual);
if (track == 0 && fpos == 0)
{
@@ -740,7 +748,7 @@ void a2_16sect_format::update_chk(const uint8_t *data, int size, uint32_t &chk)
//#define VERBOSE_SAVE
-bool a2_16sect_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool a2_16sect_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int g_tracks, g_heads;
int visualgrid[16][APPLE2_TRACK_COUNT]; // visualizer grid, cleared/initialized below
@@ -938,8 +946,9 @@ bool a2_16sect_format::save(io_generic *io, const std::vector<uint32_t> &variant
}
for(int i=0; i<nsect; i++) {
//if(nsect>0) printf("t%d,", track);
- uint8_t *data = sectdata + (256)*i;
- io_generic_write(io, data, pos_data, 256);
+ uint8_t const *const data = sectdata + (256)*i;
+ size_t actual;
+ io.write_at(pos_data, data, 256, actual);
pos_data += 256;
}
//printf("\n");
@@ -952,11 +961,11 @@ bool a2_16sect_format::save(io_generic *io, const std::vector<uint32_t> &variant
for (int i = 0; i < 16; i++) {
if (visualgrid[i][j] == NOTFOUND) printf("-NF- ");
else {
- if (visualgrid[i][j] & ADDRFOUND) printf("a"); else printf(" ");
- if (visualgrid[i][j] & ADDRGOOD) printf("A"); else printf(" ");
- if (visualgrid[i][j] & DATAFOUND) printf("d"); else printf(" ");
- if (visualgrid[i][j] & DATAGOOD) { printf("D"); total_good++; } else printf(" ");
- if (visualgrid[i][j] & DATAPOST) printf("."); else printf(" ");
+ if (visualgrid[i][j] & ADDRFOUND) printf("a"); else printf(" ");
+ if (visualgrid[i][j] & ADDRGOOD) printf("A"); else printf(" ");
+ if (visualgrid[i][j] & DATAFOUND) printf("d"); else printf(" ");
+ if (visualgrid[i][j] & DATAGOOD) { printf("D"); total_good++; } else printf(" ");
+ if (visualgrid[i][j] & DATAPOST) printf("."); else printf(" ");
}
}
printf("\n");
@@ -1019,14 +1028,16 @@ bool a2_rwts18_format::supports_save() const
return true;
}
-int a2_rwts18_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int a2_rwts18_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
- uint32_t expected_size = APPLE2_TRACK_COUNT * 16 * 256;
+ uint64_t size;
+ if(io.length(size))
+ return 0;
+ uint32_t const expected_size = APPLE2_TRACK_COUNT * 16 * 256;
return size == expected_size;
}
-bool a2_rwts18_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool a2_rwts18_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
/* TODO: rewrite me properly
uint8_t sector_data[(256)*16];
@@ -1046,7 +1057,8 @@ bool a2_rwts18_format::load(io_generic *io, uint32_t form_factor, const std::vec
sectors[si].size = 256;
sectors[si].sector_id = si;
sectors[si].sector_info = format;
- io_generic_read(io, data, pos_data, 256);
+ size_t actual;
+ io.read_at(pos_data, data, 256, actual);
pos_data += 256;
}
generate_track(mac_gcr, track, head, sectors, 16, 3104*16, image);
@@ -1075,7 +1087,7 @@ void a2_rwts18_format::update_chk(const uint8_t *data, int size, uint32_t &chk)
{
}
-bool a2_rwts18_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool a2_rwts18_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int g_tracks, g_heads;
int visualgrid[18][APPLE2_TRACK_COUNT]; // visualizer grid, cleared/initialized below
@@ -1266,8 +1278,9 @@ bool a2_rwts18_format::save(io_generic *io, const std::vector<uint32_t> &variant
}
for(int i=0; i<nsect; i++) {
//if(nsect>0) printf("t%d,", track);
- uint8_t *data = sectdata + (256)*i;
- io_generic_write(io, data, pos_data, 256);
+ uint8_t const *const data = sectdata + (256)*i;
+ size_t actual;
+ io.write_at(pos_data, data, 256, actual);
pos_data += 256;
}
@@ -1447,8 +1460,9 @@ bool a2_rwts18_format::save(io_generic *io, const std::vector<uint32_t> &variant
}
for(int i=0; i<nsect; i++) {
//if(nsect>0) printf("t%d,", track);
- uint8_t *data = sectdata + (256)*i;
- io_generic_write(io, data, pos_data, 256);
+ uint8_t const *const data = sectdata + (256)*i;
+ size_t actual;
+ io.write_at(pos_data, data, 256, actual);
pos_data += 256;
}
//printf("\n");
@@ -1500,9 +1514,12 @@ bool a2_edd_format::supports_save() const
return false;
}
-int a2_edd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int a2_edd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- return ((io_generic_size(io) == 2244608) || (io_generic_size(io) == 2310144)) ? 50 : 0;
+ uint64_t size;
+ if (io.length(size))
+ return 0;
+ return ((size == 2244608) || (size == 2310144)) ? 50 : 0;
}
uint8_t a2_edd_format::pick(const uint8_t *data, int pos)
@@ -1510,23 +1527,20 @@ uint8_t a2_edd_format::pick(const uint8_t *data, int pos)
return ((data[pos>>3] << 8) | data[(pos>>3)+1]) >> (8-(pos & 7));
}
-bool a2_edd_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool a2_edd_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint8_t *img;
uint8_t nibble[16384], stream[16384];
int npos[16384];
- img = (uint8_t *) malloc(2244608);
-
+ std::unique_ptr<uint8_t []> img(new (std::nothrow) uint8_t[2244608]);
if (!img)
- {
return false;
- }
- io_generic_read(io, img, 0, 2244608);
+ size_t actual;
+ io.read_at(0, img.get(), 2244608, actual);
for(int i=0; i<137; i++) {
- const uint8_t *trk = img + 16384*i;
+ uint8_t const *const trk = &img[16384*i];
int pos = 0;
int wpos = 0;
while(pos < 16383*8) {
@@ -1590,7 +1604,7 @@ bool a2_edd_format::load(io_generic *io, uint32_t form_factor, const std::vector
generate_track_from_bitstream(i >> 2, 0, stream, len, image, i & 3);
image->set_write_splice_position(i >> 2, 0, uint32_t(uint64_t(200'000'000)*splice/len), i & 3);
}
- free(img);
+ img.reset();
image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD);
@@ -1627,26 +1641,31 @@ bool a2_woz_format::supports_save() const
const uint8_t a2_woz_format::signature[8] = { 0x57, 0x4f, 0x5a, 0x31, 0xff, 0x0a, 0x0d, 0x0a };
const uint8_t a2_woz_format::signature2[8] = { 0x57, 0x4f, 0x5a, 0x32, 0xff, 0x0a, 0x0d, 0x0a };
-int a2_woz_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int a2_woz_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t header[8];
- io_generic_read(io, header, 0, 8);
+ size_t actual;
+ io.read_at(0, header, 8, actual);
if (!memcmp(header, signature, 8)) return 100;
if (!memcmp(header, signature2, 8)) return 100;
return 0;
}
-bool a2_woz_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool a2_woz_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- std::vector<uint8_t> img(io_generic_size(io));
- io_generic_read(io, &img[0], 0, img.size());
+ uint64_t image_size;
+ if(io.length(image_size))
+ return false;
+ std::vector<uint8_t> img(image_size);
+ size_t actual;
+ io.read_at(0, &img[0], img.size(), actual);
// Check signature
- if ((memcmp(&img[0], signature, 8)) && (memcmp(&img[0], signature2, 8)))
+ if((memcmp(&img[0], signature, 8)) && (memcmp(&img[0], signature2, 8)))
return false;
uint32_t woz_vers = 1;
- if (!memcmp(&img[0], signature2, 8)) woz_vers = 2;
+ if(!memcmp(&img[0], signature2, 8)) woz_vers = 2;
// Check integrity
uint32_t crc = crc32r(&img[12], img.size() - 12);
@@ -1663,7 +1682,7 @@ bool a2_woz_format::load(io_generic *io, uint32_t form_factor, const std::vector
uint32_t info_vers = r8(img, off_info + 0);
- if ((info_vers != 1) && (info_vers != 2))
+ if((info_vers != 1) && (info_vers != 2))
return false;
bool is_35 = r8(img, off_info + 1) == 2;
@@ -1721,7 +1740,7 @@ bool a2_woz_format::load(io_generic *io, uint32_t form_factor, const std::vector
return true;
}
-bool a2_woz_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool a2_woz_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
std::vector<std::vector<bool>> tracks(160);
bool twosided = false;
@@ -1823,7 +1842,8 @@ bool a2_woz_format::save(io_generic *io, const std::vector<uint32_t> &variants,
w32(data, 8, crc32r(&data[12], data.size() - 12));
- io_generic_write(io, data.data(), 0, data.size());
+ size_t actual;
+ io.write_at(0, data.data(), data.size(), actual);
return true;
}
@@ -1911,12 +1931,15 @@ bool a2_nib_format::supports_save() const
return false;
}
-int a2_nib_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int a2_nib_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- const auto size = io_generic_size(io);
- if (size == expected_size_35t || size == expected_size_40t) {
+ uint64_t size;
+ if (io.length(size))
+ return 0;
+
+ if (size == expected_size_35t || size == expected_size_40t)
return 50;
- }
+
return 0;
}
@@ -2031,18 +2054,20 @@ std::vector<uint32_t> a2_nib_format::generate_levels_from_nibbles(const std::vec
return levels;
}
-bool a2_nib_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool a2_nib_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- auto size = io_generic_size(io);
- if (size != expected_size_35t && size != expected_size_40t) {
+ uint64_t size;
+ if (io.length(size))
return false;
- }
+ if (size != expected_size_35t && size != expected_size_40t)
+ return false;
+
const auto nr_tracks = size == expected_size_35t? 35 : 40;
std::vector<uint8_t> nibbles(nibbles_per_track);
for (unsigned track = 0; track < nr_tracks; ++track) {
- io_generic_read(io, &nibbles[0],
- track * nibbles_per_track, nibbles_per_track);
+ size_t actual;
+ io.read_at(track * nibbles_per_track, &nibbles[0], nibbles_per_track, actual);
auto levels = generate_levels_from_nibbles(nibbles);
generate_track_from_levels(track, 0,
levels,
diff --git a/src/lib/formats/ap2_dsk.h b/src/lib/formats/ap2_dsk.h
index 7420d72d818..bab61cf96b8 100644
--- a/src/lib/formats/ap2_dsk.h
+++ b/src/lib/formats/ap2_dsk.h
@@ -41,9 +41,9 @@ class a2_16sect_format : public floppy_image_format_t
public:
a2_16sect_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -68,9 +68,9 @@ class a2_rwts18_format : public floppy_image_format_t
public:
a2_rwts18_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -92,8 +92,8 @@ class a2_edd_format : public floppy_image_format_t
public:
a2_edd_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
virtual const char *name() const override;
@@ -111,9 +111,9 @@ class a2_woz_format : public floppy_image_format_t
public:
a2_woz_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
virtual const char *name() const override;
@@ -141,8 +141,8 @@ class a2_nib_format : public floppy_image_format_t
public:
a2_nib_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
virtual const char *name() const override;
diff --git a/src/lib/formats/ap_dsk35.cpp b/src/lib/formats/ap_dsk35.cpp
index 9819406183c..6a3fa5d742b 100644
--- a/src/lib/formats/ap_dsk35.cpp
+++ b/src/lib/formats/ap_dsk35.cpp
@@ -100,6 +100,8 @@
#include "ap_dsk35.h"
+#include "ioprocs.h"
+
#include <cassert>
#include <cstdio>
@@ -1233,14 +1235,15 @@ bool dc42_format::supports_save() const
return true;
}
-int dc42_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int dc42_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint8_t h[0x54];
- uint64_t size = io_generic_size(io);
- if(size < 0x54)
+ uint64_t size;
+ if(io.length(size) || (size < 0x54))
return 0;
- io_generic_read(io, h, 0, 0x54);
+ uint8_t h[0x54];
+ size_t actual;
+ io.read_at(0, h, 0x54, actual);
uint32_t dsize = (h[0x40] << 24) | (h[0x41] << 16) | (h[0x42] << 8) | h[0x43];
uint32_t tsize = (h[0x44] << 24) | (h[0x45] << 16) | (h[0x46] << 8) | h[0x47];
@@ -1252,13 +1255,14 @@ int dc42_format::identify(io_generic *io, uint32_t form_factor, const std::vecto
return 0;
}
- return size == 0x54+tsize+dsize && h[0] < 64 && h[0x52] == 1 && h[0x53] == 0 ? 100 : 0;
+ return (size == 0x54+tsize+dsize && h[0] < 64 && h[0x52] == 1 && h[0x53] == 0) ? 100 : 0;
}
-bool dc42_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool dc42_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
uint8_t h[0x54];
- io_generic_read(io, h, 0, 0x54);
+ io.read_at(0, h, 0x54, actual);
int dsize = (h[0x40] << 24) | (h[0x41] << 16) | (h[0x42] << 8) | h[0x43];
int tsize = (h[0x44] << 24) | (h[0x45] << 16) | (h[0x46] << 8) | h[0x47];
@@ -1270,8 +1274,7 @@ bool dc42_format::load(io_generic *io, uint32_t form_factor, const std::vector<u
return false;
}
- switch (dsize)
- {
+ switch(dsize) {
case 409600: // Mac 400K
image->set_form_variant(floppy_image::FF_35, floppy_image::SSDD);
break;
@@ -1315,13 +1318,14 @@ bool dc42_format::load(io_generic *io, uint32_t form_factor, const std::vector<u
sectors[si].sector = i;
sectors[si].info = format;
if(tsize) {
- io_generic_read(io, data, pos_tag, 12);
+ io.read_at(pos_tag, data, 12, actual);
sectors[si].tag = data;
pos_tag += 12;
- } else
+ } else {
sectors[si].tag = nullptr;
+ }
sectors[si].data = data+12;
- io_generic_read(io, data+12, pos_data, 512);
+ io.read_at(pos_data, data+12, 512, actual);
pos_data += 512;
si = (si + 2) % ns;
if(si == 0)
@@ -1341,7 +1345,7 @@ void dc42_format::update_chk(const uint8_t *data, int size, uint32_t &chk)
}
}
-bool dc42_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool dc42_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int g_tracks, g_heads;
image->get_actual_geometry(g_tracks, g_heads);
@@ -1381,8 +1385,9 @@ bool dc42_format::save(io_generic *io, const std::vector<uint32_t> &variants, fl
for(unsigned int i=0; i < sectors.size(); i++) {
auto &sdata = sectors[i];
sdata.resize(512+12);
- io_generic_write(io, &sdata[0], pos_tag, 12);
- io_generic_write(io, &sdata[12], pos_data, 512);
+ size_t actual;
+ io.write_at(pos_tag, &sdata[0], 12, actual);
+ io.write_at(pos_data, &sdata[12], 512, actual);
pos_tag += 12;
pos_data += 512;
if(track || head || i)
@@ -1401,7 +1406,8 @@ bool dc42_format::save(io_generic *io, const std::vector<uint32_t> &variants, fl
h[0x4e] = tchk >> 8;
h[0x4f] = tchk;
- io_generic_write(io, h, 0, 0x54);
+ size_t actual;
+ io.write_at(0, h, 0x54, actual);
return true;
}
@@ -1432,26 +1438,32 @@ bool apple_gcr_format::supports_save() const
return true;
}
-int apple_gcr_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int apple_gcr_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return 0;
+
if(size == 409600 || (size == 819200 && (variants.empty() || has_variant(variants, floppy_image::DSDD))))
return 50;
return 0;
}
-bool apple_gcr_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool apple_gcr_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
desc_gcr_sector sectors[12];
uint8_t sdata[512*12];
int pos_data = 0;
uint8_t header[64];
- io_generic_read(io, header, 0, 64);
+ io.read_at(0, header, 64, actual);
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return false;
int head_count = size == 409600 ? 1 : size == 819200 ? 2 : 0;
image->set_form_variant(floppy_image::FF_35, head_count == 2 ? floppy_image::DSDD : floppy_image::SSDD);
@@ -1461,7 +1473,7 @@ bool apple_gcr_format::load(io_generic *io, uint32_t form_factor, const std::vec
for(int track=0; track < 80; track++) {
for(int head=0; head < head_count; head++) {
int ns = 12 - (track/16);
- io_generic_read(io, sdata, pos_data, 512*ns);
+ io.read_at(pos_data, sdata, 512*ns, actual);
pos_data += 512*ns;
int si = 0;
@@ -1482,7 +1494,7 @@ bool apple_gcr_format::load(io_generic *io, uint32_t form_factor, const std::vec
return true;
}
-bool apple_gcr_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool apple_gcr_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int g_tracks, g_heads;
image->get_actual_geometry(g_tracks, g_heads);
@@ -1498,7 +1510,8 @@ bool apple_gcr_format::save(io_generic *io, const std::vector<uint32_t> &variant
for(unsigned int i=0; i < sectors.size(); i++) {
auto &sdata = sectors[i];
sdata.resize(512+12);
- io_generic_write(io, &sdata[12], pos_data, 512);
+ size_t actual;
+ io.write_at(pos_data, &sdata[12], 512, actual);
pos_data += 512;
}
}
@@ -1534,10 +1547,11 @@ bool apple_2mg_format::supports_save() const
return true;
}
-int apple_2mg_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int apple_2mg_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t signature[4];
- io_generic_read(io, signature, 0, 4);
+ size_t actual;
+ io.read_at(0, signature, 4, actual);
if (!strncmp(reinterpret_cast<char *>(signature), "2IMG", 4))
{
return 100;
@@ -1552,11 +1566,12 @@ int apple_2mg_format::identify(io_generic *io, uint32_t form_factor, const std::
return 0;
}
-bool apple_2mg_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool apple_2mg_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
desc_gcr_sector sectors[12];
uint8_t sdata[512*12], header[64];
- io_generic_read(io, header, 0, 64);
+ io.read_at(0, header, 64, actual);
uint32_t blocks = header[0x14] | (header[0x15] << 8) | (header[0x16] << 16) | (header[0x17] << 24);
uint32_t pos_data = header[0x18] | (header[0x19] << 8) | (header[0x1a] << 16) | (header[0x1b] << 24);
@@ -1568,7 +1583,7 @@ bool apple_2mg_format::load(io_generic *io, uint32_t form_factor, const std::vec
for(int track=0; track < 80; track++) {
for(int head=0; head < 2; head++) {
int ns = 12 - (track/16);
- io_generic_read(io, sdata, pos_data, 512*ns);
+ io.read_at(pos_data, sdata, 512*ns, actual);
pos_data += 512*ns;
int si = 0;
@@ -1589,8 +1604,10 @@ bool apple_2mg_format::load(io_generic *io, uint32_t form_factor, const std::vec
return true;
}
-bool apple_2mg_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool apple_2mg_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
+
uint8_t header[0x40];
int pos_data = 0x40;
@@ -1611,7 +1628,7 @@ bool apple_2mg_format::save(io_generic *io, const std::vector<uint32_t> &variant
header[0x18] = 0x40;
// bytes of disk data
header[0x1c] = 0x00; header[0x1d] = 0x80; header[0x1e] = 0x0c; // 0xC8000 (819200)
- io_generic_write(io, header, 0, 0x40);
+ io.write_at(0, header, 0x40, actual);
for(int track=0; track < 80; track++) {
for(int head=0; head < 2; head++) {
@@ -1619,7 +1636,7 @@ bool apple_2mg_format::save(io_generic *io, const std::vector<uint32_t> &variant
for(unsigned int i=0; i < sectors.size(); i++) {
auto &sdata = sectors[i];
sdata.resize(512+12);
- io_generic_write(io, &sdata[12], pos_data, 512);
+ io.write_at(pos_data, &sdata[12], 512, actual);
pos_data += 512;
}
}
diff --git a/src/lib/formats/ap_dsk35.h b/src/lib/formats/ap_dsk35.h
index def1cb86856..f4a8ec7bff8 100644
--- a/src/lib/formats/ap_dsk35.h
+++ b/src/lib/formats/ap_dsk35.h
@@ -29,9 +29,9 @@ class dc42_format : public floppy_image_format_t
public:
dc42_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -49,9 +49,9 @@ class apple_gcr_format : public floppy_image_format_t
public:
apple_gcr_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -66,9 +66,9 @@ class apple_2mg_format : public floppy_image_format_t
public:
apple_2mg_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/apd_dsk.cpp b/src/lib/formats/apd_dsk.cpp
index 45d385a0800..f882d90fe23 100644
--- a/src/lib/formats/apd_dsk.cpp
+++ b/src/lib/formats/apd_dsk.cpp
@@ -60,9 +60,13 @@
*********************************************************************/
-#include <zlib.h>
#include "formats/apd_dsk.h"
+#include "ioprocs.h"
+
+#include <zlib.h>
+
+
static const uint8_t APD_HEADER[8] = { 'A', 'P', 'D', 'X', '0', '0', '0', '1' };
static const uint8_t GZ_HEADER[2] = { 0x1f, 0x8b };
@@ -85,11 +89,15 @@ const char *apd_format::extensions() const
return "apd";
}
-int apd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int apd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return 0;
+
std::vector<uint8_t> img(size);
- io_generic_read(io, &img[0], 0, size);
+ size_t actual;
+ io.read_at(0, &img[0], size, actual);
int err;
std::vector<uint8_t> gz_ptr(8);
@@ -123,11 +131,15 @@ int apd_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool apd_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool apd_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return false;
+
std::vector<uint8_t> img(size);
- io_generic_read(io, &img[0], 0, size);
+ size_t actual;
+ io.read_at(0, &img[0], size, actual);
int err;
std::vector<uint8_t> gz_ptr;
diff --git a/src/lib/formats/apd_dsk.h b/src/lib/formats/apd_dsk.h
index bc551973c4a..8c3ac6f0d42 100644
--- a/src/lib/formats/apd_dsk.h
+++ b/src/lib/formats/apd_dsk.h
@@ -23,8 +23,8 @@ public:
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
};
diff --git a/src/lib/formats/apollo_dsk.cpp b/src/lib/formats/apollo_dsk.cpp
index 75c31cfe7f8..a1159ac68c8 100644
--- a/src/lib/formats/apollo_dsk.cpp
+++ b/src/lib/formats/apollo_dsk.cpp
@@ -8,10 +8,11 @@
*********************************************************************/
-#include <cassert>
-
#include "formats/apollo_dsk.h"
+#include "ioprocs.h"
+
+
apollo_format::apollo_format() : upd765_format(formats)
{
}
@@ -46,10 +47,13 @@ const apollo_format::format apollo_format::formats[] = {
const floppy_format_type FLOPPY_APOLLO_FORMAT = &floppy_image_format_creator<apollo_format>;
-int apollo_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int apollo_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
- uint32_t expected_size = 77*2*8*1024;
+ uint64_t size;
+ if (io.length(size))
+ return 0;
+
+ constexpr uint32_t expected_size = 77*2*8*1024;
return ((size == expected_size) || (size == 0)) ? 1 : 0;
}
diff --git a/src/lib/formats/apollo_dsk.h b/src/lib/formats/apollo_dsk.h
index 6376c77b067..1c2c6d81030 100644
--- a/src/lib/formats/apollo_dsk.h
+++ b/src/lib/formats/apollo_dsk.h
@@ -19,7 +19,7 @@ class apollo_format : public upd765_format
public:
apollo_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual const char *name() const override;
virtual const char *description() const override;
virtual const char *extensions() const override;
diff --git a/src/lib/formats/apridisk.cpp b/src/lib/formats/apridisk.cpp
index 388d358f6f8..1560c199149 100644
--- a/src/lib/formats/apridisk.cpp
+++ b/src/lib/formats/apridisk.cpp
@@ -12,6 +12,8 @@
#include "imageutl.h"
+#include "ioprocs.h"
+
apridisk_format::apridisk_format()
{
@@ -32,10 +34,11 @@ const char *apridisk_format::extensions() const
return "dsk";
}
-int apridisk_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int apridisk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t header[APR_HEADER_SIZE];
- io_generic_read(io, header, 0, APR_HEADER_SIZE);
+ size_t actual;
+ io.read_at(0, header, APR_HEADER_SIZE, actual);
const char magic[] = "ACT Apricot disk image\x1a\x04";
@@ -45,21 +48,26 @@ int apridisk_format::identify(io_generic *io, uint32_t form_factor, const std::v
return 0;
}
-bool apridisk_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool apridisk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
desc_pc_sector sectors[80][2][18];
std::unique_ptr<uint8_t []> sector_data(new uint8_t [MAX_SECTORS * SECTOR_SIZE]);
uint8_t *data_ptr = sector_data.get();
int track_count = 0, head_count = 0, sector_count = 0;
- uint64_t file_size = io_generic_size(io);
+ uint64_t file_size;
+ if (io.length(file_size))
+ return false;
+
uint64_t file_offset = APR_HEADER_SIZE;
while (file_offset < file_size)
{
+ size_t actual;
+
// read sector header
uint8_t sector_header[16];
- io_generic_read(io, sector_header, file_offset, 16);
+ io.read_at(file_offset, sector_header, 16, actual);
uint32_t type = pick_integer_le(&sector_header, 0, 4);
uint16_t compression = pick_integer_le(&sector_header, 4, 2);
@@ -94,7 +102,7 @@ bool apridisk_format::load(io_generic *io, uint32_t form_factor, const std::vect
case APR_COMPRESSED:
{
uint8_t comp[3];
- io_generic_read(io, comp, file_offset, 3);
+ io.read_at(file_offset, comp, 3, actual);
uint16_t length = pick_integer_le(comp, 0, 2);
if (length != SECTOR_SIZE)
@@ -108,7 +116,7 @@ bool apridisk_format::load(io_generic *io, uint32_t form_factor, const std::vect
break;
case APR_UNCOMPRESSED:
- io_generic_read(io, data_ptr, file_offset, SECTOR_SIZE);
+ io.read_at(file_offset, data_ptr, SECTOR_SIZE, actual);
break;
default:
@@ -140,7 +148,7 @@ bool apridisk_format::load(io_generic *io, uint32_t form_factor, const std::vect
return true;
}
-bool apridisk_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool apridisk_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
return false;
}
diff --git a/src/lib/formats/apridisk.h b/src/lib/formats/apridisk.h
index 3e751f8d6ec..5cc8a1403fb 100644
--- a/src/lib/formats/apridisk.h
+++ b/src/lib/formats/apridisk.h
@@ -23,9 +23,9 @@ public:
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
private:
diff --git a/src/lib/formats/cassimg.cpp b/src/lib/formats/cassimg.cpp
index cf5812c67c1..2fab4a1ec8b 100644
--- a/src/lib/formats/cassimg.cpp
+++ b/src/lib/formats/cassimg.cpp
@@ -199,12 +199,15 @@ cassette_image::error cassette_image::lookup_sample(int channel, size_t sample,
-cassette_image::cassette_image(const Format *format, void *file, const io_procs *procs, int flags)
+cassette_image::cassette_image(const Format *format, util::random_read_write::ptr &&io, int flags) :
+ m_format(format),
+ m_io(std::move(io)),
+ m_channels(0),
+ m_flags(flags),
+ m_sample_frequency(0),
+ m_blocks(),
+ m_sample_count(0)
{
- m_format = format;
- m_io.file = file;
- m_io.procs = procs;
- m_flags = flags;
}
@@ -217,17 +220,24 @@ cassette_image::~cassette_image()
-cassette_image::error cassette_image::open(void *file, const io_procs *procs,
- const Format *format, int flags, ptr &outcassette)
+cassette_image::error cassette_image::open(
+ util::random_read_write::ptr &&io,
+ const Format *format,
+ int flags,
+ ptr &outcassette)
{
const Format *const formats[2] = { format, nullptr };
- return open_choices(file, procs, {}, formats, flags, outcassette);
+ return open_choices(std::move(io), { }, formats, flags, outcassette);
}
-cassette_image::error cassette_image::open_choices(void *file, const io_procs *procs, const std::string &extension,
- const Format *const *formats, int flags, ptr &outcassette)
+cassette_image::error cassette_image::open_choices(
+ util::random_read_write::ptr &&io,
+ const std::string &extension,
+ const Format *const *formats,
+ int flags,
+ ptr &outcassette)
{
// if not specified, use the dummy arguments
if (!formats)
@@ -235,7 +245,7 @@ cassette_image::error cassette_image::open_choices(void *file, const io_procs *p
// create the cassette object
ptr cassette;
- try { cassette.reset(new cassette_image(nullptr, file, procs, flags)); }
+ try { cassette.reset(new cassette_image(nullptr, std::move(io), flags)); }
catch (std::bad_alloc const &) { return error::OUT_OF_MEMORY; }
// identify the image
@@ -275,8 +285,12 @@ cassette_image::error cassette_image::open_choices(void *file, const io_procs *p
-cassette_image::error cassette_image::create(void *file, const io_procs *procs, const Format *format,
- const Options *opts, int flags, ptr &outcassette)
+cassette_image::error cassette_image::create(
+ util::random_read_write::ptr &&io,
+ const Format *format,
+ const Options *opts,
+ int flags,
+ ptr &outcassette)
{
static const Options default_options = { 1, 16, 44100 };
@@ -294,7 +308,7 @@ cassette_image::error cassette_image::create(void *file, const io_procs *procs,
// create the cassette object
ptr cassette;
- try { cassette.reset(new cassette_image(format, file, procs, flags)); }
+ try { cassette.reset(new cassette_image(format, std::move(io), flags)); }
catch (std::bad_alloc const &) { return error::OUT_OF_MEMORY; }
// read the options
@@ -334,13 +348,13 @@ cassette_image::Info cassette_image::get_info() const
-void cassette_image::change(void *file, const io_procs *procs, const Format *format, int flags)
+void cassette_image::change(util::random_read_write::ptr &&io, const Format *format, int flags)
{
- if ((flags & FLAG_READONLY) == 0)
+ if (!(flags & FLAG_READONLY))
flags |= CASSETTE_FLAG_DIRTY;
- m_io.file = file;
- m_io.procs = procs;
+
m_format = format;
+ m_io = std::move(io);
m_flags = flags;
}
@@ -352,7 +366,8 @@ void cassette_image::change(void *file, const io_procs *procs, const Format *for
void cassette_image::image_read(void *buffer, uint64_t offset, size_t length)
{
- io_generic_read(&m_io, buffer, offset, length);
+ size_t actual;
+ m_io->read_at(offset, buffer, length, actual);
}
@@ -360,7 +375,7 @@ void cassette_image::image_read(void *buffer, uint64_t offset, size_t length)
uint8_t cassette_image::image_read_byte(uint64_t offset)
{
uint8_t data;
- io_generic_read(&m_io, &data, offset, 1);
+ image_read(&data, offset, 1);
return data;
}
@@ -368,14 +383,17 @@ uint8_t cassette_image::image_read_byte(uint64_t offset)
void cassette_image::image_write(const void *buffer, uint64_t offset, size_t length)
{
- io_generic_write(&m_io, buffer, offset, length);
+ size_t actual;
+ m_io->write_at(offset, buffer, length, actual);
}
uint64_t cassette_image::image_size()
{
- return io_generic_size(&m_io);
+ uint64_t size = 0;
+ m_io->length(size);
+ return size;
}
@@ -900,20 +918,19 @@ done:
void cassette_image::dump(const char *filename)
{
- FILE *f = fopen(filename, "wb");
- if (!f)
+ util::random_read_write::ptr saved_io = util::stdio_read_write(fopen(filename, "wb"), 0);
+ if (!saved_io)
return;
- io_generic saved_io = m_io;
- const Format *saved_format = m_format;
+ Format const *const saved_format = m_format;
- m_io.file = f;
- m_io.procs = &stdio_ioprocs_noclose;
+ using std::swap;
+
+ swap(m_io, saved_io);
m_format = &wavfile_format;
+
perform_save();
- m_io = saved_io;
+ swap(m_io, saved_io);
m_format = saved_format;
-
- fclose(f);
}
diff --git a/src/lib/formats/cassimg.h b/src/lib/formats/cassimg.h
index 3a59870571a..765b860b659 100644
--- a/src/lib/formats/cassimg.h
+++ b/src/lib/formats/cassimg.h
@@ -185,14 +185,14 @@ public:
void dump(const char *filename);
error save();
- void change(void *file, const io_procs *procs, const Format *format, int flags);
+ void change(util::random_read_write::ptr &&io, const Format *format, int flags);
Info get_info() const;
- static error open(void *file, const io_procs *procs,
+ static error open(util::random_read_write::ptr &&io,
const Format *format, int flags, ptr &outcassette);
- static error open_choices(void *file, const io_procs *procs, const std::string &extension,
+ static error open_choices(util::random_read_write::ptr &&io, const std::string &extension,
const Format *const *formats, int flags, ptr &outcassette);
- static error create(void *file, const io_procs *procs, const cassette_image::Format *format,
+ static error create(util::random_read_write::ptr &&io, const cassette_image::Format *format,
const cassette_image::Options *opts, int flags, ptr &outcassette);
// builtin formats
@@ -201,7 +201,7 @@ public:
private:
struct manipulation_ranges;
- cassette_image(const Format *format, void *file, const io_procs *procs, int flags);
+ cassette_image(const Format *format, util::random_read_write::ptr &&io, int flags);
cassette_image(const cassette_image &) = delete;
cassette_image(cassette_image &&) = delete;
cassette_image &operator=(const cassette_image &) = delete;
@@ -212,15 +212,15 @@ private:
error compute_manipulation_ranges(int channel, double time_index, double sample_period, manipulation_ranges &ranges) const;
error lookup_sample(int channel, size_t sample, int32_t *&ptr);
- const Format *m_format = nullptr;
- io_generic m_io;
+ const Format *m_format;
+ util::random_read_write::ptr m_io;
- int m_channels = 0;
- int m_flags = 0;
- uint32_t m_sample_frequency = 0;
+ int m_channels;
+ int m_flags;
+ uint32_t m_sample_frequency;
std::vector<std::unique_ptr<int32_t []> > m_blocks;
- size_t m_sample_count = 0;
+ size_t m_sample_count;
};
/* macros for specifying format lists */
diff --git a/src/lib/formats/ccvf_dsk.cpp b/src/lib/formats/ccvf_dsk.cpp
index bba52d3922a..6ed0c14038a 100644
--- a/src/lib/formats/ccvf_dsk.cpp
+++ b/src/lib/formats/ccvf_dsk.cpp
@@ -11,6 +11,7 @@
#include "formats/ccvf_dsk.h"
#include "coretmpl.h" // BIT
+#include "ioprocs.h"
ccvf_format::ccvf_format()
@@ -46,12 +47,12 @@ const ccvf_format::format ccvf_format::file_formats[] = {
{}
};
-int ccvf_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int ccvf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
char h[36];
-
- io_generic_read(io, h, 0, 36);
- if(!memcmp(h, "Compucolor Virtual Floppy Disk Image", 36))
+ size_t actual;
+ io.read_at(0, h, 36, actual);
+ if (!memcmp(h, "Compucolor Virtual Floppy Disk Image", 36))
return 100;
return 0;
@@ -87,13 +88,17 @@ floppy_image_format_t::desc_e* ccvf_format::get_desc_8n1(const format &f, int &c
return desc;
}
-bool ccvf_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool ccvf_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
const format &f = formats[0];
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return false;
+
std::vector<uint8_t> img(size);
- io_generic_read(io, &img[0], 0, size);
+ size_t actual;
+ io.read_at(0, &img[0], size, actual);
std::string ccvf = std::string((const char *)&img[0], size);
std::vector<uint8_t> bytes(78720);
diff --git a/src/lib/formats/ccvf_dsk.h b/src/lib/formats/ccvf_dsk.h
index 5895a882550..92f04e03ddd 100644
--- a/src/lib/formats/ccvf_dsk.h
+++ b/src/lib/formats/ccvf_dsk.h
@@ -39,8 +39,8 @@ public:
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
protected:
diff --git a/src/lib/formats/concept_dsk.cpp b/src/lib/formats/concept_dsk.cpp
index 67c8562e1c3..7f5edce3363 100644
--- a/src/lib/formats/concept_dsk.cpp
+++ b/src/lib/formats/concept_dsk.cpp
@@ -10,11 +10,11 @@
*********************************************************************/
-#include <cassert>
-
-#include "flopimg.h"
#include "formats/concept_dsk.h"
+#include "ioprocs.h"
+
+
/* 9 sectors / track, 512 bytes per sector */
const floppy_image_format_t::desc_e cc525dsdd_format::cc_9_desc[] = {
{ MFM, 0x4e, 80 },
@@ -72,50 +72,50 @@ bool cc525dsdd_format::supports_save() const
return true;
}
-void cc525dsdd_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
+void cc525dsdd_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
{
- uint64_t size = io_generic_size(io);
-
track_count = 77;
head_count = 2;
sector_count = 9;
- uint32_t expected_size = 512 * track_count*head_count*sector_count;
- if (size == expected_size)
- {
+ uint32_t const expected_size = 512 * track_count*head_count*sector_count;
+
+ uint64_t size;
+ if (!io.length(size) && (size == expected_size))
return;
- }
track_count = head_count = sector_count = 0;
}
-int cc525dsdd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int cc525dsdd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
- if(track_count)
+ if (track_count)
return 50;
+
return 0;
}
-bool cc525dsdd_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool cc525dsdd_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint8_t track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
uint8_t sectdata[10*512];
desc_s sectors[10];
- for(int i=0; i<sector_count; i++) {
+ for (int i=0; i<sector_count; i++) {
sectors[i+1].data = sectdata + 512*i;
sectors[i+1].size = 512;
sectors[i+1].sector_id = i+1;
}
int track_size = sector_count*512;
- for(int track=0; track < track_count; track++) {
- for(int head=0; head < head_count; head++) {
- io_generic_read(io, sectdata, (track*head_count + head)*track_size, track_size);
+ for (int track=0; track < track_count; track++) {
+ for (int head=0; head < head_count; head++) {
+ size_t actual;
+ io.read_at((track*head_count + head) * track_size, sectdata, track_size, actual);
generate_track(cc_9_desc, track, head, sectors, sector_count, 100000, image);
}
}
@@ -125,28 +125,29 @@ bool cc525dsdd_format::load(io_generic *io, uint32_t form_factor, const std::vec
return true;
}
-bool cc525dsdd_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool cc525dsdd_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int track_count, head_count, sector_count;
get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count);
- if(track_count != 77)
+ if (track_count != 77)
track_count = 77;
// Happens for a fully unformatted floppy
- if(!head_count)
+ if (!head_count)
head_count = 2;
- if(sector_count != 9)
+ if (sector_count != 9)
sector_count = 9;
uint8_t sectdata[9*512];
int track_size = sector_count*512;
- for(int track=0; track < track_count; track++) {
- for(int head=0; head < head_count; head++) {
+ for (int track=0; track < track_count; track++) {
+ for (int head=0; head < head_count; head++) {
get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
- io_generic_write(io, sectdata, (track*head_count + head)*track_size, track_size);
+ size_t actual;
+ io.write_at((track*head_count + head)*track_size, sectdata, track_size, actual);
}
}
diff --git a/src/lib/formats/concept_dsk.h b/src/lib/formats/concept_dsk.h
index 58d4e1c52b3..36e3f790a84 100644
--- a/src/lib/formats/concept_dsk.h
+++ b/src/lib/formats/concept_dsk.h
@@ -17,9 +17,9 @@ class cc525dsdd_format : public floppy_image_format_t
public:
cc525dsdd_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -29,7 +29,7 @@ public:
static const desc_e cc_9_desc[];
private:
- void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
+ void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
};
extern const floppy_format_type FLOPPY_CONCEPT_525DSDD_FORMAT;
diff --git a/src/lib/formats/coupedsk.cpp b/src/lib/formats/coupedsk.cpp
index 16842583855..9400cd41bb6 100644
--- a/src/lib/formats/coupedsk.cpp
+++ b/src/lib/formats/coupedsk.cpp
@@ -8,10 +8,10 @@
**************************************************************************/
-#include <cassert>
+#include "coupedsk.h"
+
+#include "ioprocs.h"
-#include "formats/coupedsk.h"
-#include "flopimg.h"
const floppy_image_format_t::desc_e mgt_format::desc_10[] = {
{ MFM, 0x4e, 60 },
@@ -64,9 +64,11 @@ bool mgt_format::supports_save() const
return true;
}
-int mgt_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int mgt_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return 0;
if(/*size == 737280 || */ size == 819200)
return 50;
@@ -74,10 +76,12 @@ int mgt_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool mgt_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool mgt_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint64_t size = io_generic_size(io);
- int sector_count = size == 737280 ? 9 : 10;
+ uint64_t size;
+ if(io.length(size))
+ return false;
+ int const sector_count = (size == 737280) ? 9 : 10;
uint8_t sectdata[10*512];
desc_s sectors[10];
@@ -90,7 +94,8 @@ bool mgt_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
int track_size = sector_count*512;
for(int head=0; head < 2; head++) {
for(int track=0; track < 80; track++) {
- io_generic_read(io, sectdata, (track*2+head)*track_size, track_size);
+ size_t actual;
+ io.read_at((track*2+head)*track_size, sectdata, track_size, actual);
generate_track(desc_10, track, head, sectors, sector_count+1, 100000, image);
}
}
@@ -99,7 +104,7 @@ bool mgt_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
}
-bool mgt_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool mgt_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int track_count, head_count, sector_count;
get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count);
@@ -115,7 +120,8 @@ bool mgt_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
for(int head=0; head < 2; head++) {
for(int track=0; track < 80; track++) {
get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
- io_generic_write(io, sectdata, (track*2+head)*track_size, track_size);
+ size_t actual;
+ io.write_at((track*2+head)*track_size, sectdata, track_size, actual);
}
}
diff --git a/src/lib/formats/coupedsk.h b/src/lib/formats/coupedsk.h
index 3700d3e9974..e9ef4b118ca 100644
--- a/src/lib/formats/coupedsk.h
+++ b/src/lib/formats/coupedsk.h
@@ -19,9 +19,9 @@ class mgt_format : public floppy_image_format_t
public:
mgt_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/cqm_dsk.cpp b/src/lib/formats/cqm_dsk.cpp
index 5f79a4d3694..6639e50f801 100644
--- a/src/lib/formats/cqm_dsk.cpp
+++ b/src/lib/formats/cqm_dsk.cpp
@@ -8,9 +8,12 @@
*********************************************************************/
+#include "cqm_dsk.h"
+
+#include "ioprocs.h"
+
#include <cstring>
-#include <cassert>
-#include "flopimg.h"
+
#define CQM_HEADER_SIZE 133
@@ -231,17 +234,6 @@ FLOPPY_CONSTRUCT( cqm_dsk_construct )
-
-/*********************************************************************
-
- formats/cqm_dsk.c
-
- CopyQM disk images
-
-*********************************************************************/
-
-#include "cqm_dsk.h"
-
cqm_format::cqm_format()
{
}
@@ -261,10 +253,11 @@ const char *cqm_format::extensions() const
return "cqm,cqi,dsk";
}
-int cqm_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int cqm_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t h[3];
- io_generic_read(io, h, 0, 3);
+ size_t actual;
+ io.read_at(0, h, 3, actual);
if (h[0] == 'C' && h[1] == 'Q' && h[2] == 0x14)
return 100;
@@ -272,12 +265,13 @@ int cqm_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool cqm_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool cqm_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
const int max_size = 4*1024*1024; // 4MB ought to be large enough for any floppy
std::vector<uint8_t> imagebuf(max_size);
uint8_t header[CQM_HEADER_SIZE];
- io_generic_read(io, header, 0, CQM_HEADER_SIZE);
+ io.read_at(0, header, CQM_HEADER_SIZE, actual);
int sector_size = (header[0x04] << 8) | header[0x03];
int sector_per_track = (header[0x11] << 8) | header[0x10];
@@ -318,9 +312,11 @@ bool cqm_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
int rpm = form_factor == floppy_image::FF_8 || (form_factor == floppy_image::FF_525 && rate >= 300000) ? 360 : 300;
int base_cell_count = rate*60/rpm;
- int cqm_size = io_generic_size(io);
+ uint64_t cqm_size;
+ if (io.length(cqm_size))
+ return false;
std::vector<uint8_t> cqmbuf(cqm_size);
- io_generic_read(io, &cqmbuf[0], 0, cqm_size);
+ io.read_at(0, &cqmbuf[0], cqm_size, actual);
// decode the RLE data
for (int s = 0, pos = CQM_HEADER_SIZE + comment_size; pos < cqm_size; )
@@ -369,7 +365,7 @@ bool cqm_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
}
-bool cqm_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool cqm_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
return false;
}
diff --git a/src/lib/formats/cqm_dsk.h b/src/lib/formats/cqm_dsk.h
index 183c0b83e68..fc8376a2b85 100644
--- a/src/lib/formats/cqm_dsk.h
+++ b/src/lib/formats/cqm_dsk.h
@@ -19,9 +19,9 @@ class cqm_format : public floppy_image_format_t
public:
cqm_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/d64_dsk.cpp b/src/lib/formats/d64_dsk.cpp
index 4819ecc68d2..149130f0b3c 100644
--- a/src/lib/formats/d64_dsk.cpp
+++ b/src/lib/formats/d64_dsk.cpp
@@ -12,6 +12,8 @@
#include "formats/d64_dsk.h"
+#include "ioprocs.h"
+
d64_format::d64_format()
{
@@ -79,9 +81,12 @@ const int d64_format::speed_zone[] =
0, 0 // 41-42
};
-int d64_format::find_size(io_generic *io, uint32_t form_factor) const
+int d64_format::find_size(util::random_read &io, uint32_t form_factor) const
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return 0;
+
for(int i=0; formats[i].sector_count; i++) {
const format &f = formats[i];
if(size == (uint32_t) f.sector_count*f.sector_base_size*f.head_count)
@@ -89,12 +94,13 @@ int d64_format::find_size(io_generic *io, uint32_t form_factor) const
if(size == (uint32_t) (f.sector_count*f.sector_base_size*f.head_count) + f.sector_count)
return i;
}
+
return -1;
}
-int d64_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int d64_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- int type = find_size(io, form_factor);
+ const int type = find_size(io, form_factor);
if (type != -1)
return 50;
@@ -114,10 +120,11 @@ int d64_format::get_disk_id_offset(const format &f)
return 0x165a2;
}
-void d64_format::get_disk_id(const format &f, io_generic *io, uint8_t &id1, uint8_t &id2)
+void d64_format::get_disk_id(const format &f, util::random_read &io, uint8_t &id1, uint8_t &id2)
{
uint8_t id[2];
- io_generic_read(io, id, get_disk_id_offset(f), 2);
+ size_t actual;
+ io.read_at(get_disk_id_offset(f), id, 2, actual);
id1 = id[0];
id2 = id[1];
}
@@ -206,7 +213,7 @@ void d64_format::fix_end_gap(floppy_image_format_t::desc_e* desc, int remaining_
desc[22].p1 >>= remaining_size & 0x01;
}
-bool d64_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool d64_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
int type = find_size(io, form_factor);
if(type == -1)
@@ -214,7 +221,9 @@ bool d64_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
const format &f = formats[type];
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return false;
std::vector<uint8_t> img;
if(size == (uint32_t)f.sector_count*f.sector_base_size) {
@@ -225,7 +234,8 @@ bool d64_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
img.resize(size);
}
- io_generic_read(io, &img[0], 0, size);
+ size_t actual;
+ io.read_at(0, &img[0], size, actual);
int track_offset = 0, error_offset = f.sector_count*f.sector_base_size;
@@ -266,7 +276,7 @@ bool d64_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
}
-bool d64_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool d64_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
const format &f = formats[0];
@@ -280,7 +290,8 @@ bool d64_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
build_sector_description(f, sectdata, 0, 0, sectors, sector_count);
extract_sectors(image, f, sectors, track, head, sector_count);
- io_generic_write(io, sectdata, offset, track_size);
+ size_t actual;
+ io.write_at(offset, sectdata, track_size, actual);
}
}
diff --git a/src/lib/formats/d64_dsk.h b/src/lib/formats/d64_dsk.h
index 665f6489a81..13f1bd4e91c 100644
--- a/src/lib/formats/d64_dsk.h
+++ b/src/lib/formats/d64_dsk.h
@@ -37,9 +37,9 @@ public:
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override { return true; }
protected:
@@ -61,12 +61,12 @@ protected:
const format *formats;
- int find_size(io_generic *io, uint32_t form_factor) const;
+ int find_size(util::random_read &io, uint32_t form_factor) const;
virtual int get_physical_track(const format &f, int head, int track);
virtual uint32_t get_cell_size(const format &f, int track);
virtual int get_sectors_per_track(const format &f, int track);
virtual int get_disk_id_offset(const format &f);
- void get_disk_id(const format &f, io_generic *io, uint8_t &id1, uint8_t &id2);
+ void get_disk_id(const format &f, util::random_read &io, uint8_t &id1, uint8_t &id2);
virtual int get_image_offset(const format &f, int head, int track);
int compute_track_size(const format &f, int track);
virtual int get_gap2(const format &f, int head, int track) { return f.gap_2; }
diff --git a/src/lib/formats/d80_dsk.cpp b/src/lib/formats/d80_dsk.cpp
index d350411b159..338f00292a9 100644
--- a/src/lib/formats/d80_dsk.cpp
+++ b/src/lib/formats/d80_dsk.cpp
@@ -8,10 +8,11 @@
*********************************************************************/
-#include <cassert>
-
#include "formats/d80_dsk.h"
+#include "ioprocs.h"
+
+
d80_format::d80_format() : d64_format(file_formats), formats(nullptr)
{
}
diff --git a/src/lib/formats/d88_dsk.cpp b/src/lib/formats/d88_dsk.cpp
index 7c4eaa079dc..6e29f10df6a 100644
--- a/src/lib/formats/d88_dsk.cpp
+++ b/src/lib/formats/d88_dsk.cpp
@@ -29,11 +29,12 @@
*
*/
- #include <cassert>
-
#include "flopimg.h"
#include "imageutl.h"
+#include "ioprocs.h"
+
+
#define D88_HEADER_LEN 0x2b0
struct d88_tag
@@ -414,12 +415,15 @@ const char *d88_format::extensions() const
return "d77,d88,1dd";
}
-int d88_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int d88_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
- uint8_t h[32];
+ uint64_t size;
+ if(io.length(size))
+ return 0;
- io_generic_read(io, h, 0, 32);
+ uint8_t h[32];
+ size_t actual;
+ io.read_at(0, h, 32, actual);
if((little_endianize_int32(*(uint32_t *)(h+0x1c)) == size) &&
(h[0x1b] == 0x00 || h[0x1b] == 0x10 || h[0x1b] == 0x20 || h[0x1b] == 0x30 || h[0x1b] == 0x40))
return 100;
@@ -427,11 +431,12 @@ int d88_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool d88_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool d88_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint8_t h[32];
+ size_t actual;
- io_generic_read(io, h, 0, 32);
+ uint8_t h[32];
+ io.read_at(0, h, 32, actual);
int cell_count = 0;
int track_count = 0;
@@ -477,9 +482,11 @@ bool d88_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return false;
uint32_t track_pos[164];
- io_generic_read(io, track_pos, 32, 164*4);
+ io.read_at(32, track_pos, 164*4, actual);
- uint64_t file_size = io_generic_size(io);
+ uint64_t file_size;
+ if(io.length(file_size))
+ return false;
for(int track=0; track < track_count; track++)
for(int head=0; head < head_count; head++) {
@@ -496,7 +503,7 @@ bool d88_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
uint8_t hs[16];
- io_generic_read(io, hs, pos, 16);
+ io.read_at(pos, hs, 16, actual);
pos += 16;
uint16_t size = little_endianize_int16(*(uint16_t *)(hs+14));
@@ -521,7 +528,7 @@ bool d88_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
if(size) {
sects[i].data = sect_data + sdatapos;
- io_generic_read(io, sects[i].data, pos, size);
+ io.read_at(pos, sects[i].data, size, actual);
pos += size;
sdatapos += size;
@@ -536,7 +543,7 @@ bool d88_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
}
-bool d88_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool d88_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
return false;
}
diff --git a/src/lib/formats/d88_dsk.h b/src/lib/formats/d88_dsk.h
index c7c85fc1949..aeed5ed16e8 100644
--- a/src/lib/formats/d88_dsk.h
+++ b/src/lib/formats/d88_dsk.h
@@ -20,9 +20,9 @@ class d88_format : public floppy_image_format_t
public:
d88_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/dcp_dsk.cpp b/src/lib/formats/dcp_dsk.cpp
index b3beb40404f..7d419628bdc 100644
--- a/src/lib/formats/dcp_dsk.cpp
+++ b/src/lib/formats/dcp_dsk.cpp
@@ -20,10 +20,11 @@
*********************************************************************/
-#include <cassert>
-
#include "dcp_dsk.h"
+#include "ioprocs.h"
+
+
dcp_format::dcp_format()
{
}
@@ -43,14 +44,18 @@ const char *dcp_format::extensions() const
return "dcp,dcu";
}
-int dcp_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int dcp_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return 0;
+
uint8_t h[0xa2];
int heads, tracks, spt, bps, count_tracks = 0;
bool is_hdb = false;
- io_generic_read(io, h, 0, 0xa2);
+ size_t actual;
+ io.read_at(0, h, 0xa2, actual);
// First byte is the disk format (see below in load() for details)
switch (h[0])
@@ -112,13 +117,14 @@ int dcp_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool dcp_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool dcp_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
uint8_t h[0xa2];
int heads, tracks, spt, bps;
bool is_hdb = false;
- io_generic_read(io, h, 0, 0xa2);
+ io.read_at(0, h, 0xa2, actual);
// First byte is the disk format:
switch (h[0])
@@ -215,7 +221,7 @@ bool dcp_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
for (int track = 0; track < tracks; track++)
for (int head = 0; head < heads; head++)
{
- io_generic_read(io, sect_data, 0xa2 + bps * spt * (track * heads + head), bps * spt);
+ io.read_at(0xa2 + bps * spt * (track * heads + head), sect_data, bps * spt, actual);
for (int i = 0; i < spt; i++)
{
@@ -235,7 +241,7 @@ bool dcp_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
else // FIXME: the code below is untested, because no image was found... there might be some silly mistake in the disk geometry!
{
// Read Head 0 Track 0 is FM with 26 sectors of 128bytes instead of 256
- io_generic_read(io, sect_data, 0xa2, 128 * spt);
+ io.read_at(0xa2, sect_data, 128 * spt, actual);
for (int i = 0; i < spt; i++)
{
@@ -252,7 +258,7 @@ bool dcp_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
build_pc_track_fm(0, 0, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, 128));
// Read Head 1 Track 0 is MFM with 26 sectors of 256bytes
- io_generic_read(io, sect_data, 0xa2 + 128 * spt, bps * spt);
+ io.read_at(0xa2 + 128 * spt, sect_data, bps * spt, actual);
for (int i = 0; i < spt; i++)
{
@@ -273,7 +279,7 @@ bool dcp_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
for (int track = 1; track < tracks; track++)
for (int head = 0; head < heads; head++)
{
- io_generic_read(io, sect_data, data_offs + bps * spt * ((track - 1) * heads + head), bps * spt);
+ io.read_at(data_offs + bps * spt * ((track - 1) * heads + head), sect_data, bps * spt, actual);
for (int i = 0; i < spt; i++)
{
diff --git a/src/lib/formats/dcp_dsk.h b/src/lib/formats/dcp_dsk.h
index c06396d527e..716814ffd48 100644
--- a/src/lib/formats/dcp_dsk.h
+++ b/src/lib/formats/dcp_dsk.h
@@ -20,8 +20,8 @@ class dcp_format : public floppy_image_format_t
public:
dcp_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/dfi_dsk.cpp b/src/lib/formats/dfi_dsk.cpp
index 409797e9583..607be56f741 100644
--- a/src/lib/formats/dfi_dsk.cpp
+++ b/src/lib/formats/dfi_dsk.cpp
@@ -13,7 +13,8 @@
#include "dfi_dsk.h"
-#include <zlib.h>
+#include "ioprocs.h"
+
#define NUMBER_OF_MULTIREADS 3
// thresholds for brickwall windowing
@@ -56,24 +57,28 @@ bool dfi_format::supports_save() const
return false;
}
-int dfi_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int dfi_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
char sign[4];
- io_generic_read(io, sign, 0, 4);
+ size_t actual;
+ io.read_at(0, sign, 4, actual);
return memcmp(sign, "DFE2", 4) ? 0 : 100;
}
-bool dfi_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool dfi_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
char sign[4];
- io_generic_read(io, sign, 0, 4);
- if (memcmp(sign, "DFER", 4) == 0)
- {
+ io.read_at(0, sign, 4, actual);
+ if(memcmp(sign, "DFER", 4) == 0) {
osd_printf_error("dfi_dsk: Old type Discferret image detected; the mess Discferret decoder will not handle this properly, bailing out!\n");
return false;
}
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return false;
+
uint64_t pos = 4;
std::vector<uint8_t> data;
int onerev_time = 0; // time for one revolution, used to guess clock and rpm for DFE2 files
@@ -81,7 +86,7 @@ bool dfi_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
int rpm=360; // drive rpm
while(pos < size) {
uint8_t h[10];
- io_generic_read(io, h, pos, 10);
+ io.read_at(pos, h, 10, actual);
uint16_t track = (h[0] << 8) | h[1];
uint16_t head = (h[2] << 8) | h[3];
// Ignore sector
@@ -97,7 +102,7 @@ bool dfi_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
data.resize(tsize);
pos += 10; // skip the header, we already read it
- io_generic_read(io, &data[0], pos, tsize);
+ io.read_at(pos, &data[0], tsize, actual);
pos += tsize; // for next time we read, increment to the beginning of next header
int index_time = 0; // what point the last index happened
diff --git a/src/lib/formats/dfi_dsk.h b/src/lib/formats/dfi_dsk.h
index d727f1d3c06..71b69c43d70 100644
--- a/src/lib/formats/dfi_dsk.h
+++ b/src/lib/formats/dfi_dsk.h
@@ -12,9 +12,9 @@ class dfi_format : public floppy_image_format_t
public:
dfi_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- // virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image);
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ // virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image);
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/dim_dsk.cpp b/src/lib/formats/dim_dsk.cpp
index 964f19ce028..04f6e3b8995 100644
--- a/src/lib/formats/dim_dsk.cpp
+++ b/src/lib/formats/dim_dsk.cpp
@@ -8,12 +8,14 @@
*********************************************************************/
-#include <cstring>
-#include <cassert>
-
#include "dim_dsk.h"
#include "basicdsk.h"
+#include "ioprocs.h"
+
+#include <cstring>
+
+
FLOPPY_IDENTIFY(dim_dsk_identify)
{
uint8_t dim_header[16];
@@ -132,11 +134,12 @@ const char *dim_format::extensions() const
return "dim";
}
-int dim_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int dim_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t h[16];
- io_generic_read(io, h, 0xab, 16);
+ size_t actual;
+ io.read_at(0xab, h, 16, actual);
if(strncmp((const char *)h, "DIFC HEADER", 11) == 0)
return 100;
@@ -144,14 +147,15 @@ int dim_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool dim_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool dim_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
int offset = 0x100;
uint8_t h;
uint8_t track_total = 77;
int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
- io_generic_read(io, &h, 0, 1);
+ io.read_at(0, &h, 1, actual);
int spt, gap3, bps, size;
switch(h) {
@@ -211,7 +215,7 @@ bool dim_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
sects[i].deleted = false;
sects[i].bad_crc = false;
sects[i].data = &sect_data[sdatapos];
- io_generic_read(io, sects[i].data, offset, bps);
+ io.read_at(offset, sects[i].data, bps, actual);
offset += bps;
sdatapos += bps;
}
@@ -223,7 +227,7 @@ bool dim_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
}
-bool dim_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool dim_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
return false;
}
diff --git a/src/lib/formats/dim_dsk.h b/src/lib/formats/dim_dsk.h
index e0227e2e221..5c84f329cb6 100644
--- a/src/lib/formats/dim_dsk.h
+++ b/src/lib/formats/dim_dsk.h
@@ -25,9 +25,9 @@ class dim_format : public floppy_image_format_t
public:
dim_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/dip_dsk.cpp b/src/lib/formats/dip_dsk.cpp
index a33d6fe35d6..17a7f856efe 100644
--- a/src/lib/formats/dip_dsk.cpp
+++ b/src/lib/formats/dip_dsk.cpp
@@ -14,10 +14,11 @@
*********************************************************************/
-#include <cassert>
-
#include "dip_dsk.h"
+#include "ioprocs.h"
+
+
dip_format::dip_format()
{
}
@@ -37,9 +38,11 @@ const char *dip_format::extensions() const
return "dip";
}
-int dip_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int dip_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return 0;
if (size == 0x134000 + 0x100)
return 100;
@@ -47,7 +50,7 @@ int dip_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool dip_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool dip_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
int heads, tracks, spt, bps;
@@ -69,7 +72,8 @@ bool dip_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
for (int track = 0; track < tracks; track++)
for (int head = 0; head < heads; head++)
{
- io_generic_read(io, sect_data, 0x100 + bps * spt * (track * heads + head), bps * spt);
+ size_t actual;
+ io.read_at(0x100 + bps * spt * (track * heads + head), sect_data, bps * spt, actual);
for (int i = 0; i < spt; i++)
{
diff --git a/src/lib/formats/dip_dsk.h b/src/lib/formats/dip_dsk.h
index 255e4e6c8a1..e310ef3f655 100644
--- a/src/lib/formats/dip_dsk.h
+++ b/src/lib/formats/dip_dsk.h
@@ -20,8 +20,8 @@ class dip_format : public floppy_image_format_t
public:
dip_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/dmk_dsk.cpp b/src/lib/formats/dmk_dsk.cpp
index 39c23223ec5..6a9e1dc0f0b 100644
--- a/src/lib/formats/dmk_dsk.cpp
+++ b/src/lib/formats/dmk_dsk.cpp
@@ -13,10 +13,10 @@ TODO:
*********************************************************************/
-#include <cassert>
-
#include "dmk_dsk.h"
+#include "ioprocs.h"
+
dmk_format::dmk_format()
{
@@ -41,14 +41,16 @@ const char *dmk_format::extensions() const
}
-int dmk_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int dmk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
+ uint64_t size;
+ if (io.length(size))
+ return 0;
+
const int header_size = 16;
uint8_t header[header_size];
-
- uint64_t size = io_generic_size(io);
-
- io_generic_read(io, header, 0, header_size);
+ size_t actual;
+ io.read_at(0, header, header_size, actual);
int tracks = header[1];
int track_size = ( header[3] << 8 ) | header[2];
@@ -81,12 +83,13 @@ int dmk_format::identify(io_generic *io, uint32_t form_factor, const std::vector
}
-bool dmk_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool dmk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
+
const int header_size = 16;
uint8_t header[header_size];
-
- io_generic_read(io, header, 0, header_size);
+ io.read_at(0, header, header_size, actual);
const int tracks = header[1];
const int track_size = ( header[3] << 8 ) | header[2];
@@ -128,7 +131,7 @@ bool dmk_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
int dam_location[64];
// Read track
- io_generic_read(io, &track_data[0], header_size + ( heads * track + head ) * track_size, track_size);
+ io.read_at(header_size + (heads * track + head) * track_size, &track_data[0], track_size, actual);
for (int i = 0; i < 64; i++)
{
@@ -213,7 +216,7 @@ bool dmk_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
}
-bool dmk_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool dmk_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
return false;
}
diff --git a/src/lib/formats/dmk_dsk.h b/src/lib/formats/dmk_dsk.h
index a2e7898dece..5485869b5b6 100644
--- a/src/lib/formats/dmk_dsk.h
+++ b/src/lib/formats/dmk_dsk.h
@@ -21,9 +21,9 @@ class dmk_format : public floppy_image_format_t
public:
dmk_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/ds9_dsk.cpp b/src/lib/formats/ds9_dsk.cpp
index fdf4f5e2299..c97a2cced51 100644
--- a/src/lib/formats/ds9_dsk.cpp
+++ b/src/lib/formats/ds9_dsk.cpp
@@ -14,10 +14,10 @@
************************************************************************/
-#include <cassert>
-
#include "formats/ds9_dsk.h"
+#include "ioprocs.h"
+
static FLOPPY_IDENTIFY(ds9_dsk_identify)
{
@@ -97,33 +97,32 @@ const char *ds9_format::extensions() const
return "ds9";
}
-void ds9_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
+void ds9_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
{
- uint32_t expected_size = 0;
- uint64_t size = io_generic_size(io);
-
head_count = 2;
track_count = 80;
sector_count = 21;
- expected_size = 256 * track_count * head_count * sector_count;
+ uint32_t const expected_size = 256 * track_count * head_count * sector_count;
- if (size >= expected_size) // standard format has 860160 bytes
+ uint64_t size;
+ if (!io.length(size) && (size >= expected_size)) // standard format has 860160 bytes
return;
track_count = head_count = sector_count = 0;
}
-int ds9_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int ds9_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
- if (track_count) return 50;
+ if (track_count)
+ return 50;
return 0;
}
-bool ds9_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool ds9_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint8_t track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
@@ -143,7 +142,8 @@ bool ds9_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
{
for (int head = 0; head < head_count; head++)
{
- io_generic_read(io, sectdata, (track * head_count + head) * track_size, track_size);
+ size_t actual;
+ io.read_at((track * head_count + head) * track_size, sectdata, track_size, actual);
generate_track(ds9_desc, track, head, sectors, sector_count, 104000, image);
}
}
diff --git a/src/lib/formats/ds9_dsk.h b/src/lib/formats/ds9_dsk.h
index 317134eab87..abdf152b2b3 100644
--- a/src/lib/formats/ds9_dsk.h
+++ b/src/lib/formats/ds9_dsk.h
@@ -5,9 +5,10 @@
formats/ds9_dsk.h
*********************************************************************/
+#ifndef MAME_FORMATS_DS9_DSK_H
+#define MAME_FORMATS_DS9_DSK_H
-#ifndef DS9_DSK_H_
-#define DS9_DSK_H_
+#pragma once
#include "flopimg.h"
#include "formats/basicdsk.h"
@@ -19,8 +20,8 @@ class ds9_format : public floppy_image_format_t
public:
ds9_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -30,9 +31,9 @@ public:
static const desc_e ds9_desc[];
private:
- void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
+ void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
};
extern const floppy_format_type FLOPPY_DS9_FORMAT;
-#endif /* DS9_DSK_H_ */
+#endif // MAME_FORMATS_DS9_DSK_H
diff --git a/src/lib/formats/dsk_dsk.cpp b/src/lib/formats/dsk_dsk.cpp
index dba11347887..fcf967edcb1 100644
--- a/src/lib/formats/dsk_dsk.cpp
+++ b/src/lib/formats/dsk_dsk.cpp
@@ -8,11 +8,12 @@
*********************************************************************/
-#include <cstring>
-#include <cassert>
-
+#include "dsk_dsk.h"
#include "imageutl.h"
-#include "flopimg.h"
+
+#include "ioprocs.h"
+
+#include <cstring>
#define MV_CPC "MV - CPC"
#define EXTENDED "EXTENDED"
@@ -270,7 +271,8 @@ FLOPPY_CONSTRUCT( dsk_dsk_construct )
return FLOPPY_ERROR_SUCCESS;
}
-#include "dsk_dsk.h"
+
+
#define DSK_FORMAT_HEADER "MV - CPC"
#define EXT_FORMAT_HEADER "EXTENDED CPC DSK"
@@ -299,11 +301,12 @@ bool dsk_format::supports_save() const
return false;
}
-int dsk_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int dsk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t header[16];
- io_generic_read(io, &header, 0, sizeof(header));
+ size_t actual;
+ io.read_at(0, &header, sizeof(header), actual);
if ( memcmp( header, DSK_FORMAT_HEADER, 8 ) ==0) {
return 100;
}
@@ -344,14 +347,18 @@ struct sector_header
#pragma pack()
-bool dsk_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool dsk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
+
uint8_t header[0x100];
bool extendformat = false;
- uint64_t image_size = io_generic_size(io);
+ uint64_t image_size;
+ if (io.length(image_size))
+ return false;
- io_generic_read(io, &header, 0, sizeof(header));
+ io.read_at(0, &header, sizeof(header), actual);
if ( memcmp( header, EXT_FORMAT_HEADER, 16 ) ==0) {
extendformat = true;
}
@@ -418,7 +425,7 @@ bool dsk_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
if(track_offsets[(track<<1)+side] >= image_size)
continue;
track_header tr;
- io_generic_read(io, &tr,track_offsets[(track<<1)+side],sizeof(tr));
+ io.read_at(track_offsets[(track<<1)+side], &tr, sizeof(tr), actual);
// skip if there are no sectors in this track
if (tr.number_of_sector == 0)
@@ -428,7 +435,7 @@ bool dsk_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
int first_sector_code = -1;
for(int j=0;j<tr.number_of_sector;j++) {
sector_header sector;
- io_generic_read(io, &sector,track_offsets[(track<<1)+side]+sizeof(tr)+(sizeof(sector)*j),sizeof(sector));
+ io.read_at(track_offsets[(track<<1)+side]+sizeof(tr)+(sizeof(sector)*j), &sector, sizeof(sector), actual);
if (j == 0)
first_sector_code = sector.sector_size_code;
@@ -447,7 +454,7 @@ bool dsk_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
for(int j=0;j<tr.number_of_sector;j++) {
sector_header sector;
- io_generic_read(io, &sector,track_offsets[(track<<1)+side]+sizeof(tr)+(sizeof(sector)*j),sizeof(sector));
+ io.read_at(track_offsets[(track<<1)+side]+sizeof(tr)+(sizeof(sector)*j), &sector, sizeof(sector), actual);
sects[j].track = sector.track;
sects[j].head = sector.side;
@@ -470,7 +477,7 @@ bool dsk_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
if(!(sector.fdc_status_reg1 & 0x04)) {
sects[j].data = sect_data + sdatapos;
- io_generic_read(io, sects[j].data, pos, sects[j].actual_size);
+ io.read_at(pos, sects[j].data, sects[j].actual_size, actual);
sdatapos += sects[j].actual_size;
} else
diff --git a/src/lib/formats/dsk_dsk.h b/src/lib/formats/dsk_dsk.h
index a08e3955888..7d6b3bc43dc 100644
--- a/src/lib/formats/dsk_dsk.h
+++ b/src/lib/formats/dsk_dsk.h
@@ -19,8 +19,8 @@ class dsk_format : public floppy_image_format_t
public:
dsk_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/dvk_mx_dsk.cpp b/src/lib/formats/dvk_mx_dsk.cpp
index 07d7a38cf95..08156d29e9c 100644
--- a/src/lib/formats/dvk_mx_dsk.cpp
+++ b/src/lib/formats/dvk_mx_dsk.cpp
@@ -18,11 +18,11 @@
************************************************************************/
-#include <cassert>
-
-#include "flopimg.h"
#include "formats/dvk_mx_dsk.h"
+#include "ioprocs.h"
+
+
const floppy_image_format_t::desc_e dvk_mx_format::dvk_mx_new_desc[] = {
/* 01 */ { FM, 0x00, 8*2 }, // eight 0x0000 words
/* 03 */ { FM, 0x00, 1 },
@@ -81,9 +81,14 @@ bool dvk_mx_format::supports_save() const
return false;
}
-void dvk_mx_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
+void dvk_mx_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ {
+ track_count = head_count = sector_count = 0;
+ return;
+ }
switch (size)
{
@@ -108,7 +113,7 @@ void dvk_mx_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &hea
}
}
-int dvk_mx_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int dvk_mx_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t track_count, head_count, sector_count;
@@ -117,7 +122,8 @@ int dvk_mx_format::identify(io_generic *io, uint32_t form_factor, const std::vec
if (track_count)
{
uint8_t sectdata[512];
- io_generic_read(io, sectdata, 512, 512);
+ size_t actual;
+ io.read_at(512, sectdata, 512, actual);
// check value in RT-11 home block. see src/tools/imgtool/modules/rt11.cpp
if (pick_integer_le(sectdata, 0724, 2) == 6)
return 100;
@@ -129,7 +135,7 @@ int dvk_mx_format::identify(io_generic *io, uint32_t form_factor, const std::vec
return 0;
}
-bool dvk_mx_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool dvk_mx_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint8_t track_count, head_count, sector_count;
@@ -150,7 +156,8 @@ bool dvk_mx_format::load(io_generic *io, uint32_t form_factor, const std::vector
{
for (int head = 0; head < head_count; head++)
{
- io_generic_read(io, sectdata, (track * head_count + head) * track_size, track_size);
+ size_t actual;
+ io.read_at((track * head_count + head) * track_size, sectdata, track_size, actual);
generate_track(dvk_mx_new_desc, track, head, sectors, sector_count, 45824, image);
}
}
diff --git a/src/lib/formats/dvk_mx_dsk.h b/src/lib/formats/dvk_mx_dsk.h
index 38fd895d154..e20066fc3ec 100644
--- a/src/lib/formats/dvk_mx_dsk.h
+++ b/src/lib/formats/dvk_mx_dsk.h
@@ -5,9 +5,8 @@
formats/dvk_mx_dsk.h
*********************************************************************/
-
-#ifndef DVK_MX_DSK_H_
-#define DVK_MX_DSK_H_
+#ifndef MAME_FORMATS_DVK_MX_DSK_H
+#define MAME_FORMATS_DVK_MX_DSK_H
#pragma once
@@ -19,8 +18,8 @@ class dvk_mx_format : public floppy_image_format_t
public:
dvk_mx_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -31,9 +30,9 @@ public:
static const desc_e dvk_mx_new_desc[];
private:
- void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
+ void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
};
extern const floppy_format_type FLOPPY_DVK_MX_FORMAT;
-#endif /* DVK_MX_DSK_H_ */
+#endif // MAME_FORMATS_DVK_MX_DSK_H
diff --git a/src/lib/formats/esq16_dsk.cpp b/src/lib/formats/esq16_dsk.cpp
index 10802d26495..b33e529fef2 100644
--- a/src/lib/formats/esq16_dsk.cpp
+++ b/src/lib/formats/esq16_dsk.cpp
@@ -10,10 +10,10 @@
*********************************************************************/
-#include <cassert>
+#include "esq16_dsk.h"
+
+#include "ioprocs.h"
-#include "flopimg.h"
-#include "formats/esq16_dsk.h"
const floppy_image_format_t::desc_e esqimg_format::esq_10_desc[] = {
{ MFM, 0x4e, 80 },
@@ -71,23 +71,23 @@ bool esqimg_format::supports_save() const
return true;
}
-void esqimg_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
+void esqimg_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
{
- uint64_t size = io_generic_size(io);
- track_count = 80;
- head_count = 2;
- sector_count = 10;
-
- uint32_t expected_size = 512 * track_count*head_count*sector_count;
- if (size == expected_size)
- {
- return;
- }
+ uint64_t size;
+ if(!io.length(size)) {
+ track_count = 80;
+ head_count = 2;
+ sector_count = 10;
+ uint32_t expected_size = 512 * track_count*head_count*sector_count;
+ if(size == expected_size) {
+ return;
+ }
+ }
track_count = head_count = sector_count = 0;
}
-int esqimg_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int esqimg_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
@@ -97,7 +97,7 @@ int esqimg_format::identify(io_generic *io, uint32_t form_factor, const std::vec
return 0;
}
-bool esqimg_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool esqimg_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint8_t track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
@@ -113,7 +113,8 @@ bool esqimg_format::load(io_generic *io, uint32_t form_factor, const std::vector
int track_size = sector_count*512;
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
- io_generic_read(io, sectdata, (track*head_count + head)*track_size, track_size);
+ size_t actual;
+ io.read_at((track*head_count + head)*track_size, sectdata, track_size, actual);
generate_track(esq_10_desc, track, head, sectors, sector_count, 110528, image);
}
}
@@ -123,7 +124,7 @@ bool esqimg_format::load(io_generic *io, uint32_t form_factor, const std::vector
return true;
}
-bool esqimg_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool esqimg_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int track_count, head_count, sector_count;
get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count);
@@ -144,7 +145,8 @@ bool esqimg_format::save(io_generic *io, const std::vector<uint32_t> &variants,
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
- io_generic_write(io, sectdata, (track*head_count + head)*track_size, track_size);
+ size_t actual;
+ io.write_at((track*head_count + head)*track_size, sectdata, track_size, actual);
}
}
diff --git a/src/lib/formats/esq16_dsk.h b/src/lib/formats/esq16_dsk.h
index 8cc49150d2c..2347d64f59c 100644
--- a/src/lib/formats/esq16_dsk.h
+++ b/src/lib/formats/esq16_dsk.h
@@ -21,9 +21,9 @@ class esqimg_format : public floppy_image_format_t
public:
esqimg_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -33,7 +33,7 @@ public:
static const desc_e esq_10_desc[];
private:
- void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
+ void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
};
extern const floppy_format_type FLOPPY_ESQIMG_FORMAT;
diff --git a/src/lib/formats/esq8_dsk.cpp b/src/lib/formats/esq8_dsk.cpp
index f9dcb3d0727..952dd16edbd 100644
--- a/src/lib/formats/esq8_dsk.cpp
+++ b/src/lib/formats/esq8_dsk.cpp
@@ -12,10 +12,10 @@
*********************************************************************/
-#include <cassert>
+#include "esq8_dsk.h"
+
+#include "ioprocs.h"
-#include "flopimg.h"
-#include "formats/esq8_dsk.h"
const floppy_image_format_t::desc_e esq8img_format::esq_6_desc[] = {
{ MFM, 0x4e, 80 },
@@ -73,22 +73,24 @@ bool esq8img_format::supports_save() const
return true;
}
-void esq8img_format::find_size(io_generic *io, int &track_count, int &head_count, int &sector_count)
+void esq8img_format::find_size(util::random_read &io, int &track_count, int &head_count, int &sector_count)
{
- uint64_t size = io_generic_size(io);
- track_count = 80;
- head_count = 1;
- sector_count = 6;
-
- if(size == 5632 * 80)
+ uint64_t size;
+ if(!io.length(size))
{
- return;
- }
+ track_count = 80;
+ head_count = 1;
+ sector_count = 6;
+ if(size == 5632 * 80)
+ {
+ return;
+ }
+ }
track_count = head_count = sector_count = 0;
}
-int esq8img_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int esq8img_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
@@ -99,7 +101,7 @@ int esq8img_format::identify(io_generic *io, uint32_t form_factor, const std::ve
return 0;
}
-bool esq8img_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool esq8img_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
int track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
@@ -128,7 +130,8 @@ bool esq8img_format::load(io_generic *io, uint32_t form_factor, const std::vecto
{
for(int head=0; head < head_count; head++)
{
- io_generic_read(io, sectdata, (track*head_count + head)*track_size, track_size);
+ size_t actual;
+ io.read_at((track*head_count + head)*track_size, sectdata, track_size, actual);
generate_track(esq_6_desc, track, head, sectors, sector_count, 109376, image);
}
}
@@ -138,7 +141,7 @@ bool esq8img_format::load(io_generic *io, uint32_t form_factor, const std::vecto
return true;
}
-bool esq8img_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool esq8img_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint64_t file_offset = 0;
int track_count, head_count, sector_count;
@@ -175,7 +178,8 @@ bool esq8img_format::save(io_generic *io, const std::vector<uint32_t> &variants,
return false;
}
- io_generic_write(io, sectors[sector].data(), file_offset, sector_expected_size);
+ size_t actual;
+ io.write_at(file_offset, sectors[sector].data(), sector_expected_size, actual);
file_offset += sector_expected_size;
}
}
diff --git a/src/lib/formats/esq8_dsk.h b/src/lib/formats/esq8_dsk.h
index c4fe5a74f1b..aa09fd278a7 100644
--- a/src/lib/formats/esq8_dsk.h
+++ b/src/lib/formats/esq8_dsk.h
@@ -23,9 +23,9 @@ class esq8img_format : public floppy_image_format_t
public:
esq8img_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -35,7 +35,7 @@ public:
static const desc_e esq_6_desc[];
private:
- void find_size(io_generic *io, int &track_count, int &head_count, int &sector_count);
+ void find_size(util::random_read &io, int &track_count, int &head_count, int &sector_count);
};
extern const floppy_format_type FLOPPY_ESQ8IMG_FORMAT;
diff --git a/src/lib/formats/fdd_dsk.cpp b/src/lib/formats/fdd_dsk.cpp
index df5fd3caa8c..8c8249c9452 100644
--- a/src/lib/formats/fdd_dsk.cpp
+++ b/src/lib/formats/fdd_dsk.cpp
@@ -31,10 +31,11 @@
*********************************************************************/
-#include <cassert>
-
#include "fdd_dsk.h"
+#include "ioprocs.h"
+
+
fdd_format::fdd_format()
{
}
@@ -54,10 +55,11 @@ const char *fdd_format::extensions() const
return "fdd";
}
-int fdd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int fdd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t h[7];
- io_generic_read(io, h, 0, 7);
+ size_t actual;
+ io.read_at(0, h, 7, actual);
if (strncmp((const char *)h, "VFD1.0", 6) == 0)
return 100;
@@ -65,7 +67,7 @@ int fdd_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool fdd_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool fdd_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint8_t hsec[0x0c];
@@ -86,7 +88,8 @@ bool fdd_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
for (int sect = 0; sect < 26; sect++)
{
// read sector map for this sector
- io_generic_read(io, hsec, pos, 0x0c);
+ size_t actual;
+ io.read_at(pos, hsec, 0x0c, actual);
pos += 0x0c;
if (hsec[0] == 0xff) // unformatted/unused sector
@@ -118,10 +121,11 @@ bool fdd_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
cur_sec_map = track * 26 + i;
sector_size = 128 << sec_sizes[cur_sec_map];
+ size_t actual;
if (sec_offs[cur_sec_map] == 0xffffffff)
memset(sect_data + cur_pos, fill_vals[cur_sec_map], sector_size);
else
- io_generic_read(io, sect_data + cur_pos, sec_offs[cur_sec_map], sector_size);
+ io.read_at(sec_offs[cur_sec_map], sect_data + cur_pos, sector_size, actual);
sects[i].track = tracks[cur_sec_map];
sects[i].head = heads[cur_sec_map];
diff --git a/src/lib/formats/fdd_dsk.h b/src/lib/formats/fdd_dsk.h
index ec013c58571..c1a3ae8a29b 100644
--- a/src/lib/formats/fdd_dsk.h
+++ b/src/lib/formats/fdd_dsk.h
@@ -20,8 +20,8 @@ class fdd_format : public floppy_image_format_t
public:
fdd_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/flex_dsk.cpp b/src/lib/formats/flex_dsk.cpp
index 692cc4bdc9d..4989a25e707 100644
--- a/src/lib/formats/flex_dsk.cpp
+++ b/src/lib/formats/flex_dsk.cpp
@@ -50,7 +50,11 @@
*/
#include "flex_dsk.h"
-#include "formats/imageutl.h"
+
+#include "imageutl.h"
+
+#include "ioprocs.h"
+
flex_format::flex_format() : wd177x_format(formats)
{
@@ -71,7 +75,7 @@ const char *flex_format::extensions() const
return "dsk";
}
-int flex_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int flex_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int type = find_size(io, form_factor, variants);
@@ -80,17 +84,21 @@ int flex_format::identify(io_generic *io, uint32_t form_factor, const std::vecto
return 0;
}
-int flex_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int flex_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return -1;
+
uint8_t boot0[256], boot1[256];
+ size_t actual;
// Look at the boot sector.
// Density, sides, link??
- io_generic_read(io, &boot0, 256 * 0, sizeof(boot0));
- io_generic_read(io, &boot1, 256 * 1, sizeof(boot1));
+ io.read_at(256 * 0, &boot0, sizeof(boot0), actual);
+ io.read_at(256 * 1, &boot1, sizeof(boot1), actual);
// Look at the system information sector.
- io_generic_read(io, &info, 256 * 2, sizeof(struct sysinfo_sector));
+ io.read_at(256 * 2, &info, sizeof(struct sysinfo_sector), actual);
LOG_FORMATS("FLEX floppy dsk: size %d bytes, %d total sectors, %d remaining bytes, expected form factor %x\n", (uint32_t)size, (uint32_t)size / 256, (uint32_t)size % 256, form_factor);
diff --git a/src/lib/formats/flex_dsk.h b/src/lib/formats/flex_dsk.h
index 094c6854b24..0048e4e088f 100644
--- a/src/lib/formats/flex_dsk.h
+++ b/src/lib/formats/flex_dsk.h
@@ -21,8 +21,8 @@ public:
virtual const char *name() const override;
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual const wd177x_format::format &get_track_format(const format &f, int head, int track) override;
private:
diff --git a/src/lib/formats/flopimg.cpp b/src/lib/formats/flopimg.cpp
index 48c2fa1b610..55d00d1bb83 100644
--- a/src/lib/formats/flopimg.cpp
+++ b/src/lib/formats/flopimg.cpp
@@ -11,9 +11,10 @@
#include "flopimg.h"
#include "imageutl.h"
-#include "osdcore.h"
#include "ioprocs.h"
+#include "osdcore.h"
+
#include <cassert>
#include <cctype>
#include <climits>
@@ -30,7 +31,7 @@ using util::BIT;
struct floppy_image_legacy
{
- struct io_generic io = { 0 };
+ util::random_read_write::ptr io = nullptr;
const struct FloppyFormat *floppy_option = nullptr;
struct FloppyCallbacks format = { 0 };
@@ -69,22 +70,20 @@ OPTION_GUIDE_START(floppy_option_guide)
OPTION_GUIDE_END
-static void floppy_close_internal(floppy_image_legacy *floppy, bool close_file);
+static void floppy_close_internal(floppy_image_legacy *floppy);
/*********************************************************************
opening, closing and creating of floppy images
*********************************************************************/
/* basic floppy_image_legacy initialization common to floppy_open() and floppy_create() */
-static floppy_image_legacy *floppy_init(void *fp, const struct io_procs *procs, int flags)
+static floppy_image_legacy *floppy_init(util::random_read_write::ptr &&io, int flags)
{
floppy_image_legacy *floppy;
floppy = new floppy_image_legacy;
- floppy->io.file = fp;
- floppy->io.procs = procs;
- floppy->io.filler = 0xFF;
+ floppy->io = std::move(io);
floppy->flags = (uint8_t) flags;
return floppy;
}
@@ -93,7 +92,7 @@ static floppy_image_legacy *floppy_init(void *fp, const struct io_procs *procs,
/* main code for identifying and maybe opening a disk image; not exposed
* directly because this function is big and hideous */
-static floperr_t floppy_open_internal(void *fp, const struct io_procs *procs, const std::string &extension,
+static floperr_t floppy_open_internal(util::random_read_write::ptr &&io, const std::string &extension,
const struct FloppyFormat *floppy_options, int max_options, int flags, floppy_image_legacy **outfloppy,
int *outoption)
{
@@ -104,7 +103,7 @@ static floperr_t floppy_open_internal(void *fp, const struct io_procs *procs, co
int vote;
size_t i;
- floppy = floppy_init(fp, procs, flags);
+ floppy = floppy_init(std::move(io), flags);
if (!floppy)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
@@ -163,7 +162,7 @@ done:
/* if we have a floppy disk and we either errored or are not keeping it, close it */
if (floppy && (!outfloppy || err))
{
- floppy_close_internal(floppy, false);
+ floppy_close_internal(floppy);
floppy = nullptr;
}
@@ -176,31 +175,31 @@ done:
-floperr_t floppy_identify(void *fp, const struct io_procs *procs, const char *extension,
+floperr_t floppy_identify(util::random_read_write::ptr &&io, const char *extension,
const struct FloppyFormat *formats, int *identified_format)
{
- return floppy_open_internal(fp, procs, extension, formats, INT_MAX, FLOPPY_FLAGS_READONLY, nullptr, identified_format);
+ return floppy_open_internal(std::move(io), extension, formats, INT_MAX, FLOPPY_FLAGS_READONLY, nullptr, identified_format);
}
-floperr_t floppy_open(void *fp, const struct io_procs *procs, const std::string &extension,
+floperr_t floppy_open(util::random_read_write::ptr &&io, const std::string &extension,
const struct FloppyFormat *format, int flags, floppy_image_legacy **outfloppy)
{
- return floppy_open_internal(fp, procs, extension, format, 1, flags, outfloppy, nullptr);
+ return floppy_open_internal(std::move(io), extension, format, 1, flags, outfloppy, nullptr);
}
-floperr_t floppy_open_choices(void *fp, const struct io_procs *procs, const std::string &extension,
+floperr_t floppy_open_choices(util::random_read_write::ptr &&io, const std::string &extension,
const struct FloppyFormat *formats, int flags, floppy_image_legacy **outfloppy)
{
- return floppy_open_internal(fp, procs, extension, formats, INT_MAX, flags, outfloppy, nullptr);
+ return floppy_open_internal(std::move(io), extension, formats, INT_MAX, flags, outfloppy, nullptr);
}
-floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy)
+floperr_t floppy_create(util::random_read_write::ptr &&io, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy)
{
floppy_image_legacy *floppy = nullptr;
floperr_t err;
@@ -210,7 +209,7 @@ floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct Flo
assert(format);
/* create the new image */
- floppy = floppy_init(fp, procs, 0);
+ floppy = floppy_init(std::move(io), 0);
if (!floppy)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
@@ -266,28 +265,26 @@ floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct Flo
done:
if (err && floppy)
{
- floppy_close_internal(floppy, false);
+ floppy_close_internal(floppy);
floppy = nullptr;
}
if (outfloppy)
*outfloppy = floppy;
else if (floppy)
- floppy_close_internal(floppy, false);
+ floppy_close_internal(floppy);
return err;
}
-static void floppy_close_internal(floppy_image_legacy *floppy, bool close_file)
+static void floppy_close_internal(floppy_image_legacy *floppy)
{
if (floppy) {
floppy_track_unload(floppy);
if(floppy->floppy_option && floppy->floppy_option->destruct)
floppy->floppy_option->destruct(floppy, floppy->floppy_option);
- if (close_file)
- io_generic_close(&floppy->io);
delete floppy;
}
@@ -297,7 +294,7 @@ static void floppy_close_internal(floppy_image_legacy *floppy, bool close_file)
void floppy_close(floppy_image_legacy *floppy)
{
- floppy_close_internal(floppy, true);
+ floppy_close_internal(floppy);
}
@@ -332,14 +329,16 @@ void *floppy_create_tag(floppy_image_legacy *floppy, size_t tagsize)
uint8_t floppy_get_filler(floppy_image_legacy *floppy)
{
- return floppy->io.filler;
+ // FIXME: remove this function, it's here for legacy reasons
+ // the caller actually sets the filler byte - in practice it's always 0xff but there's no actual guarantee
+ return 0xff;
}
-void floppy_set_filler(floppy_image_legacy *floppy, uint8_t filler)
+util::random_read_write &floppy_get_io(floppy_image_legacy *floppy)
{
- floppy->io.filler = filler;
+ return *floppy->io;
}
@@ -350,28 +349,42 @@ void floppy_set_filler(floppy_image_legacy *floppy, uint8_t filler)
void floppy_image_read(floppy_image_legacy *floppy, void *buffer, uint64_t offset, size_t length)
{
- io_generic_read(&floppy->io, buffer, offset, length);
+ size_t actual;
+ floppy->io->read_at(offset, buffer, length, actual);
}
void floppy_image_write(floppy_image_legacy *floppy, const void *buffer, uint64_t offset, size_t length)
{
- io_generic_write(&floppy->io, buffer, offset, length);
+ size_t actual;
+ floppy->io->write_at(offset, buffer, length, actual);
}
void floppy_image_write_filler(floppy_image_legacy *floppy, uint8_t filler, uint64_t offset, size_t length)
{
- io_generic_write_filler(&floppy->io, filler, offset, length);
+ uint8_t buffer[512];
+ memset(buffer, filler, std::min(sizeof(buffer), length));
+
+ while (length)
+ {
+ size_t const block = std::min(sizeof(buffer), length);
+ size_t actual;
+ floppy->io->write_at(offset, buffer, block, actual);
+ offset += block;
+ length -= block;
+ }
}
uint64_t floppy_image_size(floppy_image_legacy *floppy)
{
- return io_generic_size(&floppy->io);
+ uint64_t result;
+ floppy->io->length(result);
+ return result;
}
@@ -976,7 +989,7 @@ bool floppy_image_format_t::has_variant(const std::vector<uint32_t> &variants, u
return false;
}
-bool floppy_image_format_t::save(io_generic *, const std::vector<uint32_t> &, floppy_image *)
+bool floppy_image_format_t::save(util::random_read_write &io, const std::vector<uint32_t> &, floppy_image *)
{
return false;
}
diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h
index 101d9bd86bd..6279def82f8 100644
--- a/src/lib/formats/flopimg.h
+++ b/src/lib/formats/flopimg.h
@@ -12,11 +12,13 @@
#pragma once
-#include "osdcore.h"
-#include "ioprocs.h"
-#include "opresolv.h"
#include "coretmpl.h"
+#include "opresolv.h"
+#include "utilfwd.h"
+
+#include "osdcore.h"
+#include <memory>
#include <vector>
#ifndef LOG_FORMATS
@@ -166,20 +168,20 @@ LEGACY_FLOPPY_OPTIONS_EXTERN(default);
OPTION_GUIDE_EXTERN(floppy_option_guide);
/* opening, closing and creating of floppy images */
-floperr_t floppy_open(void *fp, const struct io_procs *procs, const std::string &extension, const struct FloppyFormat *format, int flags, floppy_image_legacy **outfloppy);
-floperr_t floppy_open_choices(void *fp, const struct io_procs *procs, const std::string &extension, const struct FloppyFormat *formats, int flags, floppy_image_legacy **outfloppy);
-floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy);
+floperr_t floppy_open(std::unique_ptr<util::random_read_write> &&io, const std::string &extension, const struct FloppyFormat *format, int flags, floppy_image_legacy **outfloppy);
+floperr_t floppy_open_choices(std::unique_ptr<util::random_read_write> &&io, const std::string &extension, const struct FloppyFormat *formats, int flags, floppy_image_legacy **outfloppy);
+floperr_t floppy_create(std::unique_ptr<util::random_read_write> &&io, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy);
void floppy_close(floppy_image_legacy *floppy);
/* useful for identifying a floppy image */
-floperr_t floppy_identify(void *fp, const struct io_procs *procs, const char *extension, const struct FloppyFormat *formats, int *identified_format);
+floperr_t floppy_identify(std::unique_ptr<util::random_read_write> &&io, const char *extension, const struct FloppyFormat *formats, int *identified_format);
/* functions useful within format constructors */
void *floppy_tag(floppy_image_legacy *floppy);
void *floppy_create_tag(floppy_image_legacy *floppy, size_t tagsize);
struct FloppyCallbacks *floppy_callbacks(floppy_image_legacy *floppy);
uint8_t floppy_get_filler(floppy_image_legacy *floppy);
-void floppy_set_filler(floppy_image_legacy *floppy, uint8_t filler);
+util::random_read_write &floppy_get_io(floppy_image_legacy *floppy);
/* calls for accessing disk image data */
floperr_t floppy_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, void *buffer, size_t buffer_len);
@@ -235,7 +237,7 @@ public:
@param variants the variants from floppy_image the drive can handle
@return 1 if image valid, 0 otherwise.
*/
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) = 0;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) = 0;
/*! @brief Load an image.
The load function opens an image file and converts it to the
@@ -247,7 +249,7 @@ public:
@param image output buffer for data in MESS internal format.
@return true on success, false otherwise.
*/
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) = 0;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) = 0;
/*! @brief Save an image.
The save function writes back an image from the MESS internal
@@ -257,7 +259,7 @@ public:
@param image source buffer containing data in MESS internal format.
@return true on success, false otherwise.
*/
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image);
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image);
//! @returns string containing name of format.
virtual const char *name() const = 0;
diff --git a/src/lib/formats/fsd_dsk.cpp b/src/lib/formats/fsd_dsk.cpp
index c5ebd243875..ffb23035420 100644
--- a/src/lib/formats/fsd_dsk.cpp
+++ b/src/lib/formats/fsd_dsk.cpp
@@ -10,6 +10,8 @@
#include "fsd_dsk.h"
+#include "ioprocs.h"
+
/*********************************************************************
@@ -83,11 +85,12 @@ bool fsd_format::supports_save() const
return false;
}
-int fsd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int fsd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t h[3];
- io_generic_read(io, h, 0, 3);
+ size_t actual;
+ io.read_at(0, h, 3, actual);
if (memcmp(h, "FSD", 3) == 0) {
return 100;
}
@@ -95,16 +98,19 @@ int fsd_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool fsd_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool fsd_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
const char* result[255];
result[0x00] = "OK";
result[0x0e] = "Data CRC Error";
result[0x20] = "Deleted Data";
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return false;
std::vector<uint8_t> img(size);
- io_generic_read(io, &img[0], 0, size);
+ size_t actual;
+ io.read_at(0, &img[0], size, actual);
uint64_t pos;
std::string title;
diff --git a/src/lib/formats/fsd_dsk.h b/src/lib/formats/fsd_dsk.h
index ee2c4aa466c..779ee28ec02 100644
--- a/src/lib/formats/fsd_dsk.h
+++ b/src/lib/formats/fsd_dsk.h
@@ -33,8 +33,8 @@ public:
virtual const char *extensions() const override;
virtual bool supports_save() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
};
extern const floppy_format_type FLOPPY_FSD_FORMAT;
diff --git a/src/lib/formats/g64_dsk.cpp b/src/lib/formats/g64_dsk.cpp
index 02098db88e0..8e6b9c75e44 100644
--- a/src/lib/formats/g64_dsk.cpp
+++ b/src/lib/formats/g64_dsk.cpp
@@ -12,6 +12,8 @@
#include "formats/g64_dsk.h"
+#include "ioprocs.h"
+
#define G64_FORMAT_HEADER "GCR-1541"
@@ -27,22 +29,27 @@ const uint32_t g64_format::c1541_cell_size[] =
3250 // 16MHz/13/4
};
-int g64_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int g64_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
char h[8];
- io_generic_read(io, h, 0, 8);
+ size_t actual;
+ io.read_at(0, h, 8, actual);
if (!memcmp(h, G64_FORMAT_HEADER, 8))
return 100;
return 0;
}
-bool g64_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool g64_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return false;
+
std::vector<uint8_t> img(size);
- io_generic_read(io, &img[0], 0, size);
+ size_t actual;
+ io.read_at(0, &img[0], size, actual);
if (img[POS_VERSION])
{
@@ -109,15 +116,19 @@ int g64_format::generate_bitstream(int track, int head, int speed_zone, std::vec
return ((actual_cell_size >= cell_size-10) && (actual_cell_size <= cell_size+10)) ? speed_zone : -1;
}
-bool g64_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool g64_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ uint8_t const zerofill[] = { 0x00, 0x00, 0x00, 0x00 };
+ std::vector<uint8_t> const prefill(TRACK_LENGTH, 0xff);
+ size_t actual;
+
int tracks, heads;
image->get_actual_geometry(tracks, heads);
tracks = TRACK_COUNT * heads;
// write header
uint8_t header[] = { 'G', 'C', 'R', '-', '1', '5', '4', '1', 0x00, static_cast<uint8_t>(tracks), TRACK_LENGTH & 0xff, TRACK_LENGTH >> 8 };
- io_generic_write(io, header, POS_SIGNATURE, sizeof(header));
+ io.write_at(POS_SIGNATURE, header, sizeof(header), actual);
// write tracks
for (int head = 0; head < heads; head++) {
@@ -126,12 +137,12 @@ bool g64_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
std::vector<bool> trackbuf;
for (int track = 0; track < TRACK_COUNT; track++) {
- uint32_t tpos = POS_TRACK_OFFSET + (track * 4);
- uint32_t spos = tpos + (tracks * 4);
- uint32_t dpos = POS_TRACK_OFFSET + (tracks * 4 * 2) + (tracks_written * TRACK_LENGTH);
+ uint32_t const tpos = POS_TRACK_OFFSET + (track * 4);
+ uint32_t const spos = tpos + (tracks * 4);
+ uint32_t const dpos = POS_TRACK_OFFSET + (tracks * 4 * 2) + (tracks_written * TRACK_LENGTH);
- io_generic_write_filler(io, 0x00, tpos, 4);
- io_generic_write_filler(io, 0x00, spos, 4);
+ io.write_at(tpos, zerofill, 4, actual);
+ io.write_at(spos, zerofill, 4, actual);
if (image->get_buffer(track, head).size() <= 1)
continue;
@@ -163,11 +174,11 @@ bool g64_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
place_integer_le(speed_offset, 0, 4, speed_zone);
place_integer_le(track_length, 0, 2, packed.size());
- io_generic_write(io, track_offset, tpos, 4);
- io_generic_write(io, speed_offset, spos, 4);
- io_generic_write_filler(io, 0xff, dpos, TRACK_LENGTH);
- io_generic_write(io, track_length, dpos, 2);
- io_generic_write(io, packed.data(), dpos + 2, packed.size());
+ io.write_at(tpos, track_offset, 4, actual);
+ io.write_at(spos, speed_offset, 4, actual);
+ io.write_at(dpos, prefill.data(), TRACK_LENGTH, actual);
+ io.write_at(dpos, track_length, 2, actual);
+ io.write_at(dpos + 2, packed.data(), packed.size(), actual);
tracks_written++;
}
diff --git a/src/lib/formats/g64_dsk.h b/src/lib/formats/g64_dsk.h
index 6691146c70e..fcd48d96796 100644
--- a/src/lib/formats/g64_dsk.h
+++ b/src/lib/formats/g64_dsk.h
@@ -20,9 +20,9 @@ class g64_format : public floppy_image_format_t
public:
g64_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/hpi_dsk.cpp b/src/lib/formats/hpi_dsk.cpp
index d9fc788fd45..bdccc66803d 100644
--- a/src/lib/formats/hpi_dsk.cpp
+++ b/src/lib/formats/hpi_dsk.cpp
@@ -48,6 +48,7 @@
#include "hpi_dsk.h"
#include "coretmpl.h" // BIT
+#include "ioprocs.h"
// Debugging
@@ -78,9 +79,12 @@ hpi_format::hpi_format()
(void)HPI_RED_IMAGE_SIZE;
}
-int hpi_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int hpi_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size)) {
+ return 0;
+ }
// we try to stay back and give only 50 points, since another image
// format may also have images of the same size (there is no header and no
@@ -142,12 +146,15 @@ bool hpi_format::geometry_from_size(uint64_t image_size , unsigned& heads , unsi
}
}
-bool hpi_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool hpi_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
unsigned heads;
unsigned cylinders;
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size)) {
+ return false;
+ }
if (!geometry_from_size(size, heads, cylinders)) {
return false;
}
@@ -161,7 +168,8 @@ bool hpi_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
// Suck in the whole image
std::vector<uint8_t> image_data(size);
- io_generic_read(io, (void *)image_data.data(), 0, size);
+ size_t actual;
+ io.read_at(0, image_data.data(), size, actual);
// Get interleave factor from image
unsigned il = (unsigned)image_data[ IL_OFFSET ] * 256 + image_data[ IL_OFFSET + 1 ];
@@ -191,7 +199,7 @@ bool hpi_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
}
-bool hpi_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool hpi_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int tracks;
int heads;
@@ -206,7 +214,8 @@ bool hpi_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
while (get_next_sector(bitstream , pos , track_no , head_no , sector_no , sector_data)) {
if (track_no == cyl && head_no == head && sector_no < HPI_SECTORS) {
unsigned offset_in_image = chs_to_lba(cyl, head, sector_no, heads) * HPI_SECTOR_SIZE;
- io_generic_write(io, sector_data, offset_in_image, HPI_SECTOR_SIZE);
+ size_t actual;
+ io.write_at(offset_in_image, sector_data, HPI_SECTOR_SIZE, actual);
}
}
}
diff --git a/src/lib/formats/hpi_dsk.h b/src/lib/formats/hpi_dsk.h
index 38c70e91c33..ca8aa1ffe11 100644
--- a/src/lib/formats/hpi_dsk.h
+++ b/src/lib/formats/hpi_dsk.h
@@ -28,9 +28,9 @@ class hpi_format : public floppy_image_format_t
public:
hpi_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
virtual const char *extensions() const override;
diff --git a/src/lib/formats/hti_tape.cpp b/src/lib/formats/hti_tape.cpp
index 7f77e3f99df..8fbaeef91cc 100644
--- a/src/lib/formats/hti_tape.cpp
+++ b/src/lib/formats/hti_tape.cpp
@@ -10,6 +10,8 @@
#include "imageutl.h"
+#include "ioprocs.h"
+
static constexpr uint32_t OLD_FILE_MAGIC = 0x5441434f; // Magic value at start of old-format image file: "TACO"
static constexpr uint32_t FILE_MAGIC_DELTA = 0x48544930; // Magic value at start of delta-modulation image file: "HTI0"
@@ -47,22 +49,25 @@ hti_format_t::hti_format_t()
clear_tape();
}
-bool hti_format_t::load_tape(io_generic *io)
+bool hti_format_t::load_tape(util::random_read &io)
{
+ if (io.seek(0, SEEK_SET)) {
+ return false;
+ }
+
+ size_t actual;
uint8_t tmp[ 4 ];
- io_generic_read(io, tmp, 0, 4);
+ io.read(tmp, 4, actual);
auto magic = pick_integer_be(tmp , 0 , 4);
if (((m_img_format == HTI_DELTA_MOD_16_BITS || m_img_format == HTI_DELTA_MOD_17_BITS) && magic != FILE_MAGIC_DELTA && magic != OLD_FILE_MAGIC) ||
(m_img_format == HTI_MANCHESTER_MOD && magic != FILE_MAGIC_MANCHESTER)) {
return false;
}
- uint64_t offset = 4;
-
for (unsigned i = 0; i < no_of_tracks(); i++) {
tape_track_t& track = m_tracks[ i ];
- if (!load_track(io , offset , track , magic == OLD_FILE_MAGIC)) {
+ if (!load_track(io, track, magic == OLD_FILE_MAGIC)) {
clear_tape();
return false;
}
@@ -71,14 +76,15 @@ bool hti_format_t::load_tape(io_generic *io)
return true;
}
-void hti_format_t::save_tape(io_generic *io)
+void hti_format_t::save_tape(util::random_read_write &io)
{
+ io.seek(0, SEEK_SET);
+
+ size_t actual;
uint8_t tmp[ 4 ];
place_integer_be(tmp, 0, 4, m_img_format == HTI_MANCHESTER_MOD ? FILE_MAGIC_MANCHESTER : FILE_MAGIC_DELTA);
- io_generic_write(io, tmp, 0, 4);
-
- uint64_t offset = 4;
+ io.write(tmp, 4, actual);
for (unsigned i = 0; i < no_of_tracks(); i++) {
const tape_track_t& track = m_tracks[ i ];
@@ -87,18 +93,17 @@ void hti_format_t::save_tape(io_generic *io)
tape_track_t::const_iterator it_start;
for (tape_track_t::const_iterator it = track.cbegin(); it != track.cend(); ++it) {
if (it->first != next_pos) {
- dump_sequence(io , offset , it_start , n_words);
+ dump_sequence(io, it_start, n_words);
it_start = it;
n_words = 0;
}
next_pos = it->first + word_length(it->second);
n_words++;
}
- dump_sequence(io , offset , it_start , n_words);
+ dump_sequence(io, it_start, n_words);
// End of track
place_integer_le(tmp, 0, 4, (uint32_t)-1);
- io_generic_write(io, tmp, offset, 4);
- offset += 4;
+ io.write(tmp, 4, actual);
}
}
@@ -374,8 +379,9 @@ bool hti_format_t::next_gap(unsigned track_no , tape_pos_t& pos , bool forward ,
return n_gaps == 0;
}
-bool hti_format_t::load_track(io_generic *io , uint64_t& offset , tape_track_t& track , bool old_format)
+bool hti_format_t::load_track(util::random_read &io , tape_track_t& track , bool old_format)
{
+ size_t actual;
uint8_t tmp[ 4 ];
uint32_t tmp32;
tape_pos_t delta_pos = 0;
@@ -385,8 +391,7 @@ bool hti_format_t::load_track(io_generic *io , uint64_t& offset , tape_track_t&
while (1) {
// Read no. of words to follow
- io_generic_read(io, tmp, offset, 4);
- offset += 4;
+ io.read(tmp, 4, actual);
tmp32 = pick_integer_le(tmp, 0, 4);
@@ -398,8 +403,7 @@ bool hti_format_t::load_track(io_generic *io , uint64_t& offset , tape_track_t&
unsigned n_words = tmp32;
// Read tape position of block
- io_generic_read(io, tmp, offset, 4);
- offset += 4;
+ io.read(tmp, 4, actual);
tmp32 = pick_integer_le(tmp, 0, 4);
@@ -411,8 +415,7 @@ bool hti_format_t::load_track(io_generic *io , uint64_t& offset , tape_track_t&
for (unsigned i = 0; i < n_words; i++) {
uint16_t tmp16;
- io_generic_read(io, tmp, offset, 2);
- offset += 2;
+ io.read(tmp, 2, actual);
tmp16 = pick_integer_le(tmp, 0, 2);
if (!old_format) {
@@ -469,19 +472,18 @@ bool hti_format_t::load_track(io_generic *io , uint64_t& offset , tape_track_t&
}
}
-void hti_format_t::dump_sequence(io_generic *io , uint64_t& offset , tape_track_t::const_iterator it_start , unsigned n_words)
+void hti_format_t::dump_sequence(util::random_read_write &io , tape_track_t::const_iterator it_start , unsigned n_words)
{
if (n_words) {
+ size_t actual;
uint8_t tmp[ 8 ];
place_integer_le(tmp, 0, 4, n_words);
place_integer_le(tmp, 4, 4, it_start->first);
- io_generic_write(io, tmp, offset, 8);
- offset += 8;
+ io.write(tmp, 8, actual);
for (unsigned i = 0; i < n_words; i++) {
place_integer_le(tmp, 0, 2, it_start->second);
- io_generic_write(io, tmp, offset, 2);
- offset += 2;
+ io.write(tmp, 2, actual);
++it_start;
}
}
diff --git a/src/lib/formats/hti_tape.h b/src/lib/formats/hti_tape.h
index 7725b87fa2a..373c971d174 100644
--- a/src/lib/formats/hti_tape.h
+++ b/src/lib/formats/hti_tape.h
@@ -13,10 +13,12 @@
#pragma once
-#include "ioprocs.h"
+#include "utilfwd.h"
+#include <cstdint>
#include <map>
+
class hti_format_t
{
public:
@@ -71,8 +73,8 @@ public:
// Return number of tracks
unsigned no_of_tracks() const { return m_img_format == HTI_MANCHESTER_MOD ? 1 : 2; }
- bool load_tape(io_generic *io);
- void save_tape(io_generic *io);
+ bool load_tape(util::random_read &io);
+ void save_tape(util::random_read_write &io);
void clear_tape();
// Return physical length of a bit on tape
@@ -127,8 +129,8 @@ private:
// Image format
image_format_t m_img_format;
- bool load_track(io_generic *io , uint64_t& offset , tape_track_t& track , bool old_format);
- static void dump_sequence(io_generic *io , uint64_t& offset , tape_track_t::const_iterator it_start , unsigned n_words);
+ bool load_track(util::random_read &io , tape_track_t& track , bool old_format);
+ static void dump_sequence(util::random_read_write &io , tape_track_t::const_iterator it_start , unsigned n_words);
tape_pos_t word_end_pos(const track_iterator_t& it) const;
void adjust_it(tape_track_t& track , track_iterator_t& it , tape_pos_t pos) const;
diff --git a/src/lib/formats/hxchfe_dsk.cpp b/src/lib/formats/hxchfe_dsk.cpp
index 68360f4e9bb..15598bbd746 100644
--- a/src/lib/formats/hxchfe_dsk.cpp
+++ b/src/lib/formats/hxchfe_dsk.cpp
@@ -101,6 +101,9 @@
#include "hxchfe_dsk.h"
+#include "ioprocs.h"
+
+
#define HFE_FORMAT_HEADER "HXCPICFE"
#define HEADER_LENGTH 512
@@ -144,19 +147,21 @@ bool hfe_format::supports_save() const
return true;
}
-int hfe_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int hfe_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t header[8];
- io_generic_read(io, &header, 0, sizeof(header));
+ size_t actual;
+ io.read_at(0, &header, sizeof(header), actual);
if ( memcmp( header, HFE_FORMAT_HEADER, 8 ) ==0) {
return 100;
}
return 0;
}
-bool hfe_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool hfe_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
uint8_t header[HEADER_LENGTH];
uint8_t track_table[TRACK_TABLE_LENGTH];
@@ -164,7 +169,7 @@ bool hfe_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
image->get_maximal_geometry(drivecyl, driveheads);
// read header
- io_generic_read(io, header, 0, HEADER_LENGTH);
+ io.read_at(0, header, HEADER_LENGTH, actual);
// get values
// Format revision must be 0
@@ -236,7 +241,7 @@ bool hfe_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
// read track lookup table (multiple of 512)
int table_offset = (header[18] & 0xff) | ((header[19] & 0xff)<<8);
- io_generic_read(io, track_table, table_offset<<9, TRACK_TABLE_LENGTH);
+ io.read_at(table_offset<<9, track_table, TRACK_TABLE_LENGTH, actual);
for (int i=0; i < m_cylinders; i++)
{
@@ -252,7 +257,7 @@ bool hfe_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
// The HFE format defines an interleave of the two sides per cylinder
// at every 256 bytes
cylinder_buffer.resize(m_cyl_length[cyl]);
- io_generic_read(io, &cylinder_buffer[0], m_cyl_offset[cyl]<<9, m_cyl_length[cyl]);
+ io.read_at(m_cyl_offset[cyl]<<9, &cylinder_buffer[0], m_cyl_length[cyl], actual);
generate_track_from_hfe_bitstream(cyl, 0, samplelength, &cylinder_buffer[0], m_cyl_length[cyl], image);
if (m_heads == 2)
@@ -412,8 +417,9 @@ void hfe_format::generate_track_from_hfe_bitstream(int cyl, int head, int sample
image->set_write_splice_position(cyl, head, 0, 0);
}
-bool hfe_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool hfe_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
std::vector<uint8_t> cylbuf;
// Create a buffer that is big enough to handle HD formats. We don't
@@ -484,7 +490,7 @@ bool hfe_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
header[13] = (m_bit_rate >> 8) & 0xff;
// Now write the header
- io_generic_write(io, header, 0, HEADER_LENGTH);
+ io.write_at(0, header, HEADER_LENGTH, actual);
// Set up the track lookup table
// We need the encoding value to be sure about the track length
@@ -505,10 +511,10 @@ bool hfe_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
for (int i=m_cylinders*4; i < TRACK_TABLE_LENGTH; i++)
track_table[i] = 0xff;
- io_generic_write(io, track_table, 0x200, TRACK_TABLE_LENGTH);
+ io.write_at(0x200, track_table, TRACK_TABLE_LENGTH, actual);
}
// Write the current cylinder
- io_generic_write(io, &cylbuf[0], m_cyl_offset[cyl]<<9, (m_cyl_length[cyl] + 0x1ff) & 0xfe00);
+ io.write_at(m_cyl_offset[cyl]<<9, &cylbuf[0], (m_cyl_length[cyl] + 0x1ff) & 0xfe00, actual);
}
return true;
}
diff --git a/src/lib/formats/hxchfe_dsk.h b/src/lib/formats/hxchfe_dsk.h
index 9d2dbdeae77..4ea98ed861c 100644
--- a/src/lib/formats/hxchfe_dsk.h
+++ b/src/lib/formats/hxchfe_dsk.h
@@ -47,9 +47,9 @@ public:
hfe_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/hxcmfm_dsk.cpp b/src/lib/formats/hxcmfm_dsk.cpp
index b6845b28e4a..e7bf03acd2f 100644
--- a/src/lib/formats/hxcmfm_dsk.cpp
+++ b/src/lib/formats/hxcmfm_dsk.cpp
@@ -1,10 +1,11 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
-#include <cassert>
-
#include "hxcmfm_dsk.h"
+#include "ioprocs.h"
+
+
#define MFM_FORMAT_HEADER "HXCMFM"
#pragma pack(1)
@@ -57,24 +58,26 @@ bool mfm_format::supports_save() const
return true;
}
-int mfm_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int mfm_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t header[7];
- io_generic_read(io, &header, 0, sizeof(header));
+ size_t actual;
+ io.read_at(0, &header, sizeof(header), actual);
if ( memcmp( header, MFM_FORMAT_HEADER, 6 ) ==0) {
return 100;
}
return 0;
}
-bool mfm_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool mfm_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
MFMIMG header;
MFMTRACKIMG trackdesc;
// read header
- io_generic_read(io, &header, 0, sizeof(header));
+ io.read_at(0, &header, sizeof(header), actual);
int drivecyl, driveheads;
image->get_maximal_geometry(drivecyl, driveheads);
@@ -86,12 +89,12 @@ bool mfm_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
for(int side=0; side < header.number_of_side; side++) {
if (!skip_odd || track%2 == 0) {
// read location of
- io_generic_read(io, &trackdesc,(header.mfmtracklistoffset)+( counter *sizeof(trackdesc)),sizeof(trackdesc));
+ io.read_at((header.mfmtracklistoffset)+( counter *sizeof(trackdesc)), &trackdesc, sizeof(trackdesc), actual);
trackbuf.resize(trackdesc.mfmtracksize);
// actual data read
- io_generic_read(io, &trackbuf[0], trackdesc.mfmtrackoffset, trackdesc.mfmtracksize);
+ io.read_at(trackdesc.mfmtrackoffset, &trackbuf[0], trackdesc.mfmtracksize, actual);
if (skip_odd) {
generate_track_from_bitstream(track/2, side, &trackbuf[0], trackdesc.mfmtracksize*8, image);
@@ -109,9 +112,10 @@ bool mfm_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
}
-bool mfm_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool mfm_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
// TODO: HD support
+ size_t actual;
MFMIMG header;
int track_count, head_count;
image->get_actual_geometry(track_count, head_count);
@@ -124,7 +128,7 @@ bool mfm_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
header.floppyiftype = 4;
header.mfmtracklistoffset = sizeof(MFMIMG);
- io_generic_write(io, &header, 0, sizeof(MFMIMG));
+ io.write_at(0, &header, sizeof(MFMIMG), actual);
int tpos = sizeof(MFMIMG);
int dpos = tpos + track_count*head_count*sizeof(MFMTRACKIMG);
@@ -143,8 +147,8 @@ bool mfm_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
trackdesc.mfmtracksize = packed.size();
trackdesc.mfmtrackoffset = dpos;
- io_generic_write(io, &trackdesc, tpos, sizeof(MFMTRACKIMG));
- io_generic_write(io, packed.data(), dpos, packed.size());
+ io.write_at(tpos, &trackdesc, sizeof(MFMTRACKIMG), actual);
+ io.write_at(dpos, packed.data(), packed.size(), actual);
tpos += sizeof(MFMTRACKIMG);
dpos += packed.size();
diff --git a/src/lib/formats/hxcmfm_dsk.h b/src/lib/formats/hxcmfm_dsk.h
index a6f884ab03e..c42190f3aae 100644
--- a/src/lib/formats/hxcmfm_dsk.h
+++ b/src/lib/formats/hxcmfm_dsk.h
@@ -19,9 +19,9 @@ class mfm_format : public floppy_image_format_t
public:
mfm_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/ibmxdf_dsk.cpp b/src/lib/formats/ibmxdf_dsk.cpp
index b18ffad63dc..5a44290a337 100644
--- a/src/lib/formats/ibmxdf_dsk.cpp
+++ b/src/lib/formats/ibmxdf_dsk.cpp
@@ -32,6 +32,8 @@
#include "ibmxdf_dsk.h"
+#include "ioprocs.h"
+
ibmxdf_format::ibmxdf_format() : wd177x_format(formats)
{
@@ -52,7 +54,7 @@ const char *ibmxdf_format::extensions() const
return "xdf,img";
}
-int ibmxdf_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int ibmxdf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int type = find_size(io, form_factor, variants);
@@ -61,9 +63,11 @@ int ibmxdf_format::identify(io_generic *io, uint32_t form_factor, const std::vec
return 0;
}
-int ibmxdf_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int ibmxdf_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return -1;
if (size != 1884160)
return -1;
@@ -173,7 +177,7 @@ const ibmxdf_format::format ibmxdf_format::formats_head1_track0[] = {
{}
};
-bool ibmxdf_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool ibmxdf_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
int type = find_size(io, form_factor, variants);
if(type == -1)
@@ -207,8 +211,9 @@ bool ibmxdf_format::load(io_generic *io, uint32_t form_factor, const std::vector
desc[16].p1 = get_track_dam_mfm(tf, head, track);
build_sector_description(tf, sectdata, sectors, track, head);
- int track_size = compute_track_size(f) * 2; // read both sides at once
- io_generic_read(io, sectdata, get_image_offset(f, head, track), track_size);
+ int const track_size = compute_track_size(f) * 2; // read both sides at once
+ size_t actual;
+ io.read_at(get_image_offset(f, head, track), sectdata, track_size, actual);
generate_track(desc, track, head, sectors, tf.sector_count, total_size, image);
}
diff --git a/src/lib/formats/ibmxdf_dsk.h b/src/lib/formats/ibmxdf_dsk.h
index 6d37142ac30..dbb448f8ad3 100644
--- a/src/lib/formats/ibmxdf_dsk.h
+++ b/src/lib/formats/ibmxdf_dsk.h
@@ -23,11 +23,11 @@ public:
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override { return false; }
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual int get_image_offset(const format &f, int head, int track) override;
virtual const wd177x_format::format &get_track_format(const format &f, int head, int track) override;
diff --git a/src/lib/formats/imd_dsk.cpp b/src/lib/formats/imd_dsk.cpp
index b3d4eac8229..b0e9a4159d9 100644
--- a/src/lib/formats/imd_dsk.cpp
+++ b/src/lib/formats/imd_dsk.cpp
@@ -10,7 +10,8 @@
#include "imd_dsk.h"
-#include <cassert>
+#include "ioprocs.h"
+
#include <cstring>
@@ -409,25 +410,29 @@ void imd_format::fixnum(char *start, char *end) const
};
}
-int imd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int imd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
char h[4];
- io_generic_read(io, h, 0, 4);
+ size_t actual;
+ io.read_at(0, h, 4, actual);
if(!memcmp(h, "IMD ", 4))
return 100;
return 0;
}
-bool imd_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool imd_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return false;
std::vector<uint8_t> img(size);
- io_generic_read(io, &img[0], 0, size);
+ size_t actual;
+ io.read_at(0, &img[0], size, actual);
uint64_t pos, savepos;
- for(pos=0; pos < size && img[pos] != 0x1a; pos++) {};
+ for(pos=0; pos < size && img[pos] != 0x1a; pos++) { }
pos++;
m_comment.resize(pos);
@@ -627,39 +632,34 @@ bool can_compress(const uint8_t* buffer, uint8_t ptrn, uint64_t size)
return true;
}
-bool imd_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool imd_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint64_t pos = 0;
- io_generic_write(io, &m_comment[0], pos, m_comment.size());
- pos += m_comment.size();
+ if(io.seek(0, SEEK_SET))
+ return false;
+
+ size_t written;
+ io.write(&m_comment[0], m_comment.size(), written);
for (int i = 0; i < m_mode.size(); i++)
{
- io_generic_write(io, &m_mode[i], pos++, 1);
- io_generic_write(io, &m_track[i], pos++, 1);
- io_generic_write(io, &m_head[i], pos++, 1);
- io_generic_write(io, &m_sector_count[i], pos++, 1);
- io_generic_write(io, &m_ssize[i], pos++, 1);
+ io.write(&m_mode[i], 1, written);
+ io.write(&m_track[i], 1, written);
+ io.write(&m_head[i], 1, written);
+ io.write(&m_sector_count[i], 1, written);
+ io.write(&m_ssize[i], 1, written);
- io_generic_write(io, &m_snum[i][0], pos, m_sector_count[i]);
- pos += m_sector_count[i];
+ io.write(&m_snum[i][0], m_sector_count[i], written);
if (m_tnum[i].size())
- {
- io_generic_write(io, &m_tnum[i][0], pos, m_sector_count[i]);
- pos += m_sector_count[i];
- }
+ io.write(&m_tnum[i][0], m_sector_count[i], written);
if (m_hnum[i].size())
- {
- io_generic_write(io, &m_hnum[i][0], pos, m_sector_count[i]);
- pos += m_sector_count[i];
- }
+ io.write(&m_hnum[i][0], m_sector_count[i], written);
- uint32_t actual_size = m_ssize[i] < 7 ? 128 << m_ssize[i] : 8192;
- uint8_t head = m_head[i] & 0x3f;
+ uint32_t const actual_size = m_ssize[i] < 7 ? 128 << m_ssize[i] : 8192;
+ uint8_t const head = m_head[i] & 0x3f;
- bool fm = m_mode[i]< 3;
+ bool const fm = m_mode[i]< 3;
auto bitstream = generate_bitstream_from_track(m_track[i]*m_trackmult, head, fm ? 4000 : 2000, image);
std::vector<std::vector<uint8_t>> sectors;
@@ -674,11 +674,10 @@ bool imd_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
const auto &data = sectors[m_snum[i][j]];
- uint8_t mode;
if (data.empty())
{
- mode = 0;
- io_generic_write(io, &mode, pos++, 1);
+ uint8_t const mode = 0;
+ io.write(&mode, 1, written);
continue;
}
else if (data.size() < actual_size) {
@@ -690,16 +689,15 @@ bool imd_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
if (can_compress(sdata, sdata[0], actual_size))
{
- mode = 2;
- io_generic_write(io, &mode, pos++, 1);
- io_generic_write(io, &sdata[0], pos++, 1);
+ uint8_t const mode = 2;
+ io.write(&mode, 1, written);
+ io.write(&sdata[0], 1, written);
}
else
{
- mode = 1;
- io_generic_write(io, &mode, pos++, 1);
- io_generic_write(io, &sdata, pos, actual_size);
- pos += actual_size;
+ uint8_t const mode = 1;
+ io.write(&mode, 1, written);
+ io.write(&sdata, actual_size, written);
}
}
}
diff --git a/src/lib/formats/imd_dsk.h b/src/lib/formats/imd_dsk.h
index ba04a0c09e7..acf7da9b892 100644
--- a/src/lib/formats/imd_dsk.h
+++ b/src/lib/formats/imd_dsk.h
@@ -17,9 +17,9 @@ class imd_format : public floppy_image_format_t
public:
imd_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image* image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image* image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/img_dsk.cpp b/src/lib/formats/img_dsk.cpp
index 757f695d923..73ae499c764 100644
--- a/src/lib/formats/img_dsk.cpp
+++ b/src/lib/formats/img_dsk.cpp
@@ -17,6 +17,7 @@
#include "img_dsk.h"
#include "coretmpl.h" // BIT
+#include "ioprocs.h"
// Debugging
@@ -40,9 +41,12 @@ img_format::img_format()
{
}
-int img_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int img_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size)) {
+ return 0;
+ }
if (((form_factor == floppy_image::FF_8) || (form_factor == floppy_image::FF_UNKNOWN)) &&
size == IMG_IMAGE_SIZE) {
@@ -52,17 +56,18 @@ int img_format::identify(io_generic *io, uint32_t form_factor, const std::vector
}
}
-bool img_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool img_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint64_t size = io_generic_size(io);
- if (size != IMG_IMAGE_SIZE) {
+ uint64_t size;
+ if (io.length(size) || (size != IMG_IMAGE_SIZE)) {
return false;
}
image->set_variant(floppy_image::SSDD);
// Suck in the whole image
std::vector<uint8_t> image_data(size);
- io_generic_read(io, (void *)image_data.data(), 0, size);
+ size_t actual;
+ io.read_at(0, image_data.data(), size, actual);
for (unsigned cyl = 0; cyl < TRACKS; cyl++) {
std::vector<uint32_t> track_data;
@@ -96,7 +101,7 @@ bool img_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
}
-bool img_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool img_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
for (int cyl = 0; cyl < TRACKS; cyl++) {
auto bitstream = generate_bitstream_from_track(cyl , 0 , CELL_SIZE , image , 0);
@@ -106,7 +111,8 @@ bool img_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
while (get_next_sector(bitstream , pos , track_no , sector_no , sector_data)) {
if (track_no == cyl && sector_no >= 1 && sector_no <= SECTORS) {
unsigned offset_in_image = (cyl * SECTORS + sector_no - 1) * SECTOR_SIZE;
- io_generic_write(io, sector_data, offset_in_image, SECTOR_SIZE);
+ size_t actual;
+ io.write_at(offset_in_image, sector_data, SECTOR_SIZE, actual);
}
}
}
diff --git a/src/lib/formats/img_dsk.h b/src/lib/formats/img_dsk.h
index af9a2d62466..bbd7a0fc03e 100644
--- a/src/lib/formats/img_dsk.h
+++ b/src/lib/formats/img_dsk.h
@@ -27,9 +27,9 @@ public:
img_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
virtual const char *extensions() const override;
diff --git a/src/lib/formats/ioprocs.cpp b/src/lib/formats/ioprocs.cpp
deleted file mode 100644
index 78e009aa112..00000000000
--- a/src/lib/formats/ioprocs.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-#include <cstdio>
-#include <cstring>
-#include <cassert>
-#include "ioprocs.h"
-#include "corefile.h"
-
-
-/*********************************************************************
- ioprocs implementation on stdio
-*********************************************************************/
-
-static void stdio_closeproc(void *file)
-{
- fclose((FILE*)file);
-}
-
-static int stdio_seekproc(void *file, int64_t offset, int whence)
-{
- return fseek((FILE*)file, (long) offset, whence);
-}
-
-static size_t stdio_readproc(void *file, void *buffer, size_t length)
-{
- return fread(buffer, 1, length, (FILE*)file);
-}
-
-static size_t stdio_writeproc(void *file, const void *buffer, size_t length)
-{
- return fwrite(buffer, 1, length, (FILE*)file);
-}
-
-static uint64_t stdio_filesizeproc(void *file)
-{
- long l, sz;
- l = ftell((FILE*)file);
- if (fseek((FILE*)file, 0, SEEK_END))
- return (size_t) -1;
- sz = ftell((FILE*)file);
- if (fseek((FILE*)file, l, SEEK_SET))
- return (size_t) -1;
- return (size_t) sz;
-}
-
-const struct io_procs stdio_ioprocs =
-{
- stdio_closeproc,
- stdio_seekproc,
- stdio_readproc,
- stdio_writeproc,
- stdio_filesizeproc
-};
-
-const struct io_procs stdio_ioprocs_noclose =
-{
- nullptr,
- stdio_seekproc,
- stdio_readproc,
- stdio_writeproc,
- stdio_filesizeproc
-};
-
-/*********************************************************************
- ioprocs implementation on corefile
-*********************************************************************/
-
-static void corefile_closeproc(void *file)
-{
- delete (util::core_file*)file;
-}
-
-static int corefile_seekproc(void *file, int64_t offset, int whence)
-{
- return ((util::core_file*)file)->seek(offset, whence);
-}
-
-static size_t corefile_readproc(void *file, void *buffer, size_t length)
-{
- return ((util::core_file*)file)->read(buffer, length);
-}
-
-static size_t corefile_writeproc(void *file, const void *buffer, size_t length)
-{
- return ((util::core_file*)file)->write(buffer, length);
-}
-
-static uint64_t corefile_filesizeproc(void *file)
-{
- const auto l = ((util::core_file*)file)->tell();
- if (((util::core_file*)file)->seek(0, SEEK_END))
- return (size_t) -1;
- const auto sz = ((util::core_file*)file)->tell();
- if (((util::core_file*)file)->seek(l, SEEK_SET))
- return uint64_t(-1);
- return uint64_t(sz);
-}
-
-const struct io_procs corefile_ioprocs =
-{
- corefile_closeproc,
- corefile_seekproc,
- corefile_readproc,
- corefile_writeproc,
- corefile_filesizeproc
-};
-
-const struct io_procs corefile_ioprocs_noclose =
-{
- nullptr,
- corefile_seekproc,
- corefile_readproc,
- corefile_writeproc,
- corefile_filesizeproc
-};
-
-
-
-/*********************************************************************
- calls for accessing generic IO
-*********************************************************************/
-
-static void io_generic_seek(struct io_generic *genio, uint64_t offset)
-{
- genio->procs->seekproc(genio->file, offset, SEEK_SET);
-}
-
-
-
-void io_generic_close(struct io_generic *genio)
-{
- if (genio->procs->closeproc)
- genio->procs->closeproc(genio->file);
-}
-
-
-
-void io_generic_read(struct io_generic *genio, void *buffer, uint64_t offset, size_t length)
-{
- uint64_t size;
- size_t bytes_read;
-
- size = io_generic_size(genio);
- if (size <= offset)
- {
- bytes_read = 0;
- }
- else
- {
- io_generic_seek(genio, offset);
- bytes_read = genio->procs->readproc(genio->file, buffer, length);
- }
- memset(((uint8_t *) buffer) + bytes_read, genio->filler, length - bytes_read);
-}
-
-
-
-void io_generic_write(struct io_generic *genio, const void *buffer, uint64_t offset, size_t length)
-{
- uint64_t filler_size = 0;
- char filler_buffer[1024];
- size_t bytes_to_write;
- uint64_t size;
-
- size = io_generic_size(genio);
-
- if (size < offset)
- {
- filler_size = offset - size;
- offset = size;
- }
-
- io_generic_seek(genio, offset);
-
- if (filler_size)
- {
- memset(filler_buffer, genio->filler, sizeof(filler_buffer));
- do
- {
- bytes_to_write = (filler_size > sizeof(filler_buffer)) ? sizeof(filler_buffer) : (size_t) filler_size;
- genio->procs->writeproc(genio->file, filler_buffer, bytes_to_write);
- filler_size -= bytes_to_write;
- }
- while(filler_size > 0);
- }
-
- if (length > 0)
- genio->procs->writeproc(genio->file, buffer, length);
-}
-
-
-
-void io_generic_write_filler(struct io_generic *genio, uint8_t filler, uint64_t offset, size_t length)
-{
- uint8_t buffer[512];
- size_t this_length;
-
- memset(buffer, filler, std::min(length, sizeof(buffer)));
-
- while(length > 0)
- {
- this_length = std::min(length, sizeof(buffer));
- io_generic_write(genio, buffer, offset, this_length);
- offset += this_length;
- length -= this_length;
- }
-}
-
-
-
-uint64_t io_generic_size(struct io_generic *genio)
-{
- return genio->procs->filesizeproc(genio->file);
-}
diff --git a/src/lib/formats/ioprocs.h b/src/lib/formats/ioprocs.h
deleted file mode 100644
index 1244873f14c..00000000000
--- a/src/lib/formats/ioprocs.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
-/*********************************************************************
-
- ioprocs.h
-
- File IO abstraction layer
-
-*********************************************************************/
-#ifndef MAME_FORMATS_IOPROCS_H
-#define MAME_FORMATS_IOPROCS_H
-
-#pragma once
-
-#include <cstdint>
-#include <cstdlib>
-
-
-
-/***************************************************************************
-
- Type definitions
-
-***************************************************************************/
-
-struct io_procs
-{
- void (*closeproc)(void *file) = nullptr;
- int (*seekproc)(void *file, int64_t offset, int whence) = nullptr;
- size_t (*readproc)(void *file, void *buffer, size_t length) = nullptr;
- size_t (*writeproc)(void *file, const void *buffer, size_t length) = nullptr;
- uint64_t (*filesizeproc)(void *file) = nullptr;
-};
-
-
-
-struct io_generic
-{
- const struct io_procs *procs = nullptr;
- void *file = nullptr;
- uint8_t filler = 0;
-};
-
-
-/***************************************************************************
-
- Globals
-
-***************************************************************************/
-
-extern const io_procs stdio_ioprocs;
-extern const io_procs stdio_ioprocs_noclose;
-extern const io_procs corefile_ioprocs;
-extern const io_procs corefile_ioprocs_noclose;
-
-
-
-/***************************************************************************
-
- Prototypes
-
-***************************************************************************/
-
-void io_generic_close(struct io_generic *genio);
-void io_generic_read(struct io_generic *genio, void *buffer, uint64_t offset, size_t length);
-void io_generic_write(struct io_generic *genio, const void *buffer, uint64_t offset, size_t length);
-void io_generic_write_filler(struct io_generic *genio, uint8_t filler, uint64_t offset, size_t length);
-uint64_t io_generic_size(struct io_generic *genio);
-
-#endif // MAME_FORMATS_IOPROCS_H
diff --git a/src/lib/formats/ipf_dsk.cpp b/src/lib/formats/ipf_dsk.cpp
index 0f1725f5c14..10c9ba2c4a9 100644
--- a/src/lib/formats/ipf_dsk.cpp
+++ b/src/lib/formats/ipf_dsk.cpp
@@ -2,6 +2,8 @@
// copyright-holders:Olivier Galibert
#include "ipf_dsk.h"
+#include "ioprocs.h"
+
#include <cassert>
@@ -27,11 +29,12 @@ bool ipf_format::supports_save() const
return false;
}
-int ipf_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int ipf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
static const uint8_t refh[12] = { 0x43, 0x41, 0x50, 0x53, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0xd5, 0x73, 0xba };
uint8_t h[12];
- io_generic_read(io, h, 0, 12);
+ size_t actual;
+ io.read_at(0, h, 12, actual);
if(!memcmp(h, refh, 12))
return 100;
@@ -39,14 +42,16 @@ int ipf_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool ipf_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool ipf_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- ipf_decode dec;
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return false;
std::vector<uint8_t> data(size);
- io_generic_read(io, &data[0], 0, size);
- bool res = dec.parse(data, image);
- return res;
+ size_t actual;
+ io.read_at(0, &data[0], size, actual);
+ ipf_decode dec;
+ return dec.parse(data, image);
}
uint32_t ipf_format::ipf_decode::r32(const uint8_t *p)
diff --git a/src/lib/formats/ipf_dsk.h b/src/lib/formats/ipf_dsk.h
index d848a5bb3a0..28d552d5812 100644
--- a/src/lib/formats/ipf_dsk.h
+++ b/src/lib/formats/ipf_dsk.h
@@ -12,8 +12,8 @@
class ipf_format : public floppy_image_format_t
{
public:
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/jfd_dsk.cpp b/src/lib/formats/jfd_dsk.cpp
index 947d6ba4022..7a1da472356 100644
--- a/src/lib/formats/jfd_dsk.cpp
+++ b/src/lib/formats/jfd_dsk.cpp
@@ -158,9 +158,13 @@
*********************************************************************/
-#include <zlib.h>
#include "formats/jfd_dsk.h"
+#include "ioprocs.h"
+
+#include <zlib.h>
+
+
static const uint8_t JFD_HEADER[4] = { 'J', 'F', 'D', 'I' };
static const uint8_t GZ_HEADER[2] = { 0x1f, 0x8b };
@@ -183,11 +187,14 @@ const char *jfd_format::extensions() const
return "jfd";
}
-int jfd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int jfd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return 0;
std::vector<uint8_t> img(size);
- io_generic_read(io, &img[0], 0, size);
+ size_t actual;
+ io.read_at(0, &img[0], size, actual);
int err;
std::vector<uint8_t> gz_ptr(4);
@@ -221,11 +228,15 @@ int jfd_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool jfd_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool jfd_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return false;
+
std::vector<uint8_t> img(size);
- io_generic_read(io, &img[0], 0, size);
+ size_t actual;
+ io.read_at(0, &img[0], size, actual);
int err;
std::vector<uint8_t> gz_ptr;
diff --git a/src/lib/formats/jfd_dsk.h b/src/lib/formats/jfd_dsk.h
index 75b9910c426..7231ccf3460 100644
--- a/src/lib/formats/jfd_dsk.h
+++ b/src/lib/formats/jfd_dsk.h
@@ -23,8 +23,8 @@ public:
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
};
diff --git a/src/lib/formats/jvc_dsk.cpp b/src/lib/formats/jvc_dsk.cpp
index 8332f86bace..c71f2c3be06 100644
--- a/src/lib/formats/jvc_dsk.cpp
+++ b/src/lib/formats/jvc_dsk.cpp
@@ -106,6 +106,8 @@
#include "jvc_dsk.h"
+#include "ioprocs.h"
+
jvc_format::jvc_format()
{
@@ -126,19 +128,22 @@ const char *jvc_format::extensions() const
return "jvc,dsk";
}
-bool jvc_format::parse_header(io_generic *io, int &header_size, int &tracks, int &heads, int &sectors, int &sector_size, int &base_sector_id)
+bool jvc_format::parse_header(util::random_read &io, int &header_size, int &tracks, int &heads, int &sectors, int &sector_size, int &base_sector_id)
{
// The JVC format has a header whose size is the size of the image modulo 256. Currently, we only
// handle up to five header bytes
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return false;
header_size = size % 256;
uint8_t header[5];
// if we know that this is a header of a bad size, we can fail immediately; otherwise read the header
+ size_t actual;
if (header_size >= sizeof(header))
return false;
if (header_size > 0)
- io_generic_read(io, header, 0, header_size);
+ io.read_at(0, header, header_size, actual);
// default values
heads = 1;
@@ -168,13 +173,13 @@ bool jvc_format::parse_header(io_generic *io, int &header_size, int &tracks, int
return tracks * heads * sectors * sector_size == (size - header_size);
}
-int jvc_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int jvc_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int header_size, tracks, heads, sectors, sector_size, sector_base_id;
return parse_header(io, header_size, tracks, heads, sectors, sector_size, sector_base_id) ? 50 : 0;
}
-bool jvc_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool jvc_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
int header_size, track_count, head_count, sector_count, sector_size, sector_base_id;
@@ -210,7 +215,8 @@ bool jvc_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
sectors[interleave[i]].bad_crc = false;
sectors[interleave[i]].data = &sector_data[sector_offset];
- io_generic_read(io, sectors[interleave[i]].data, file_offset, sector_size);
+ size_t actual;
+ io.read_at(file_offset, sectors[interleave[i]].data, sector_size, actual);
sector_offset += sector_size;
file_offset += sector_size;
@@ -223,7 +229,7 @@ bool jvc_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
}
-bool jvc_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool jvc_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint64_t file_offset = 0;
@@ -236,7 +242,8 @@ bool jvc_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
uint8_t header[2];
header[0] = 18;
header[1] = 2;
- io_generic_write(io, header, file_offset, sizeof(header));
+ size_t actual;
+ io.write_at(file_offset, header, sizeof(header), actual);
file_offset += sizeof(header);
}
@@ -256,7 +263,8 @@ bool jvc_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
return false;
}
- io_generic_write(io, sectors[1 + i].data(), file_offset, 256);
+ size_t actual;
+ io.write_at(file_offset, sectors[1 + i].data(), 256, actual);
file_offset += 256;
}
}
diff --git a/src/lib/formats/jvc_dsk.h b/src/lib/formats/jvc_dsk.h
index 7c744a0acb5..1b8b59c725f 100644
--- a/src/lib/formats/jvc_dsk.h
+++ b/src/lib/formats/jvc_dsk.h
@@ -35,13 +35,13 @@ public:
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
private:
- bool parse_header(io_generic *io, int &header_size, int &tracks, int &heads, int &sectors, int &sector_size, int &base_sector_id);
+ bool parse_header(util::random_read &io, int &header_size, int &tracks, int &heads, int &sectors, int &sector_size, int &base_sector_id);
};
extern const floppy_format_type FLOPPY_JVC_FORMAT;
diff --git a/src/lib/formats/m20_dsk.cpp b/src/lib/formats/m20_dsk.cpp
index 60b2ae58176..05c52c2f211 100644
--- a/src/lib/formats/m20_dsk.cpp
+++ b/src/lib/formats/m20_dsk.cpp
@@ -16,6 +16,9 @@
#include "m20_dsk.h"
+#include "ioprocs.h"
+
+
m20_format::m20_format()
{
}
@@ -40,21 +43,27 @@ bool m20_format::supports_save() const
return true;
}
-int m20_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int m20_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- if(io_generic_size(io) == 286720)
+ uint64_t size;
+ if (io.length(size))
+ return 0;
+
+ if (size == 286720)
return 50;
+
return 0;
}
-bool m20_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool m20_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
for (int track = 0; track < 35; track++)
for (int head = 0; head < 2; head ++) {
bool mfm = track || head;
desc_pc_sector sects[16];
uint8_t sectdata[16*256];
- io_generic_read(io, sectdata, 16*256*(track*2+head), 16*256);
+ size_t actual;
+ io.read_at(16*256*(track*2+head), sectdata, 16*256, actual);
for (int i = 0; i < 16; i++) {
int j = i/2 + (i & 1 ? 0 : 8);
sects[i].track = track;
@@ -76,7 +85,7 @@ bool m20_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
}
-bool m20_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool m20_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint64_t file_offset = 0;
@@ -87,26 +96,27 @@ bool m20_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
auto bitstream = generate_bitstream_from_track(0, 0, 4000, image);
auto sectors = extract_sectors_from_bitstream_fm_pc(bitstream);
- for (int i = 0; i < 16; i++)
- {
- io_generic_write(io, sectors[i + 1].data(), file_offset, 128);
+ for (int i = 0; i < 16; i++) {
+ size_t actual;
+ io.write_at(file_offset, sectors[i + 1].data(), 128, actual);
file_offset += 256; //128;
}
// rest are mfm tracks
- for (int track = 0; track < track_count; track++)
- {
- for (int head = 0; head < head_count; head++)
- {
+ for (int track = 0; track < track_count; track++) {
+ for (int head = 0; head < head_count; head++) {
// skip track 0, head 0
- if (track == 0) { if (head_count == 1) break; else head++; }
+ if (track == 0) {
+ if (head_count == 1) break;
+ else head++;
+ }
bitstream = generate_bitstream_from_track(track, head, 2000, image);
sectors = extract_sectors_from_bitstream_mfm_pc(bitstream);
- for (int i = 0; i < 16; i++)
- {
- io_generic_write(io, sectors[i + 1].data(), file_offset, 256);
+ for (int i = 0; i < 16; i++) {
+ size_t actual;
+ io.write_at(file_offset, sectors[i + 1].data(), 256, actual);
file_offset += 256;
}
}
diff --git a/src/lib/formats/m20_dsk.h b/src/lib/formats/m20_dsk.h
index ed8a7bc4517..d9bd7a45425 100644
--- a/src/lib/formats/m20_dsk.h
+++ b/src/lib/formats/m20_dsk.h
@@ -18,9 +18,9 @@ class m20_format : public floppy_image_format_t {
public:
m20_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/mdos_dsk.cpp b/src/lib/formats/mdos_dsk.cpp
index b96be2f327e..e49d825ea9a 100644
--- a/src/lib/formats/mdos_dsk.cpp
+++ b/src/lib/formats/mdos_dsk.cpp
@@ -50,7 +50,9 @@
*/
#include "mdos_dsk.h"
-#include "formats/imageutl.h"
+#include "imageutl.h"
+
+#include "ioprocs.h"
mdos_format::mdos_format() : wd177x_format(formats)
@@ -72,12 +74,13 @@ const char *mdos_format::extensions() const
return "dsk";
}
-int mdos_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int mdos_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- int type = find_size(io, form_factor, variants);
+ int type = find_size(io, form_factor, variants);
if (type != -1)
return 75;
+
return 0;
}
@@ -109,12 +112,15 @@ int mdos_format::parse_date_field(uint8_t *str)
return (high - 0x30) * 10 + (low - 0x30);
}
-int mdos_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int mdos_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ size_t actual;
+ uint64_t size;
+ if (io.length(size))
+ return -1;
// Look at the disk id sector.
- io_generic_read(io, &info, 0, sizeof(struct disk_id_sector));
+ io.read_at(0, &info, sizeof(struct disk_id_sector), actual);
LOG_FORMATS("MDOS floppy dsk: size %d bytes, %d total sectors, %d remaining bytes, expected form factor %x\n", (uint32_t)size, (uint32_t)size / 128, (uint32_t)size % 128, form_factor);
@@ -176,8 +182,8 @@ int mdos_format::find_size(io_generic *io, uint32_t form_factor, const std::vect
// the extent of the disk are free or available.
uint8_t cluster_allocation[128], cluster_available[128];
- io_generic_read(io, &cluster_allocation, 1 * 128, sizeof(cluster_allocation));
- io_generic_read(io, &cluster_available, 2 * 128, sizeof(cluster_available));
+ io.read_at(1 * 128, &cluster_allocation, sizeof(cluster_allocation), actual);
+ io.read_at(2 * 128, &cluster_available, sizeof(cluster_available), actual);
for (int cluster = 0; cluster < sizeof(cluster_allocation) * 8; cluster++) {
if (cluster * 4 * 128 + 4 * 128 > size) {
diff --git a/src/lib/formats/mdos_dsk.h b/src/lib/formats/mdos_dsk.h
index 65e7bca9f14..56dd29c9954 100644
--- a/src/lib/formats/mdos_dsk.h
+++ b/src/lib/formats/mdos_dsk.h
@@ -19,8 +19,8 @@ public:
virtual const char *name() const override;
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual const wd177x_format::format &get_track_format(const format &f, int head, int track) override;
private:
diff --git a/src/lib/formats/mfi_dsk.cpp b/src/lib/formats/mfi_dsk.cpp
index 7670bf6bfb9..8272253c36a 100644
--- a/src/lib/formats/mfi_dsk.cpp
+++ b/src/lib/formats/mfi_dsk.cpp
@@ -1,10 +1,12 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
-#include <cassert>
-
#include "mfi_dsk.h"
+
+#include "ioprocs.h"
+
#include <zlib.h>
+
/*
Mess floppy image structure:
@@ -94,11 +96,12 @@ bool mfi_format::supports_save() const
return true;
}
-int mfi_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int mfi_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
header h;
- io_generic_read(io, &h, 0, sizeof(header));
+ size_t actual;
+ io.read_at(0, &h, sizeof(header), actual);
if(memcmp( h.sign, sign, 16 ) == 0 &&
(h.cyl_count & CYLINDER_MASK) <= 84 &&
(h.cyl_count >> RESOLUTION_SHIFT) < 3 &&
@@ -108,15 +111,16 @@ int mfi_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool mfi_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool mfi_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
header h;
entry entries[84*2*4];
- io_generic_read(io, &h, 0, sizeof(header));
+ io.read_at(0, &h, sizeof(header), actual);
int resolution = h.cyl_count >> RESOLUTION_SHIFT;
h.cyl_count &= CYLINDER_MASK;
- io_generic_read(io, &entries, sizeof(header), (h.cyl_count << resolution)*h.head_count*sizeof(entry));
+ io.read_at(sizeof(header), &entries, (h.cyl_count << resolution)*h.head_count*sizeof(entry), actual);
image->set_form_variant(h.form_factor, h.variant);
@@ -139,7 +143,7 @@ bool mfi_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
compressed.resize(ent->compressed_size);
- io_generic_read(io, &compressed[0], ent->offset, ent->compressed_size);
+ io.read_at(ent->offset, &compressed[0], ent->compressed_size, actual);
unsigned int cell_count = ent->uncompressed_size/4;
std::vector<uint32_t> &trackbuf = image->get_buffer(cyl >> 2, head, cyl & 3);;
@@ -169,8 +173,9 @@ bool mfi_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
}
-bool mfi_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool mfi_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
int tracks, heads;
image->get_actual_geometry(tracks, heads);
int resolution = image->get_resolution();
@@ -190,7 +195,7 @@ bool mfi_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
h.form_factor = image->get_form_factor();
h.variant = image->get_variant();
- io_generic_write(io, &h, 0, sizeof(header));
+ io.write_at(0, &h, sizeof(header), actual);
memset(entries, 0, sizeof(entries));
@@ -226,11 +231,11 @@ bool mfi_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
entries[epos].write_splice = image->get_write_splice_position(track >> 2, head, track & 3);
epos++;
- io_generic_write(io, postcomp.get(), pos, csize);
+ io.write_at(pos, postcomp.get(), csize, actual);
pos += csize;
}
- io_generic_write(io, entries, sizeof(header), (tracks << resolution)*heads*sizeof(entry));
+ io.write_at(sizeof(header), entries, (tracks << resolution)*heads*sizeof(entry), actual);
return true;
}
diff --git a/src/lib/formats/mfi_dsk.h b/src/lib/formats/mfi_dsk.h
index 129a9ee599e..d0dd36c3d68 100644
--- a/src/lib/formats/mfi_dsk.h
+++ b/src/lib/formats/mfi_dsk.h
@@ -12,9 +12,9 @@ class mfi_format : public floppy_image_format_t
public:
mfi_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/mfm_hd.cpp b/src/lib/formats/mfm_hd.cpp
index 98d8079443c..738f0999863 100644
--- a/src/lib/formats/mfm_hd.cpp
+++ b/src/lib/formats/mfm_hd.cpp
@@ -294,9 +294,9 @@ int mfmhd_generic_format::chs_to_lba(int cylinder, int head, int sector)
else return -1;
}
-chd_error mfmhd_generic_format::load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head)
+std::error_condition mfmhd_generic_format::load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head)
{
- chd_error state = CHDERR_NONE;
+ std::error_condition state;
uint8_t sector_content[16384];
int sectorcount = m_param.sectors_per_track;
@@ -382,8 +382,9 @@ chd_error mfmhd_generic_format::load(chd_file* chdfile, uint16_t* trackimage, in
int lbaposition = chs_to_lba(cylinder, head, sec_number);
if (lbaposition>=0)
{
- chd_error state = chdfile->read_units(lbaposition, sector_content);
- if (state != CHDERR_NONE) break;
+ state = chdfile->read_units(lbaposition, sector_content);
+ if (state)
+ break;
}
else
{
@@ -413,7 +414,7 @@ chd_error mfmhd_generic_format::load(chd_file* chdfile, uint16_t* trackimage, in
if (TRACE_LAYOUT) osd_printf_verbose("\n");
// Gap 4
- if (state == CHDERR_NONE)
+ if (!state)
{
// Fill the rest with 0x4e
mfm_encode(trackimage, position, 0x4e, tracksize-position);
@@ -433,7 +434,7 @@ enum
CHECK_CRC
};
-chd_error mfmhd_generic_format::save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int current_cylinder, int current_head)
+std::error_condition mfmhd_generic_format::save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int current_cylinder, int current_head)
{
if (TRACE_RWTRACK) osd_printf_verbose("%s: write back (c=%d,h=%d) to CHD\n", tag(), current_cylinder, current_head);
@@ -490,7 +491,7 @@ chd_error mfmhd_generic_format::save(chd_file* chdfile, uint16_t* trackimage, in
bool countgap3 = false;
bool countsync = false;
- chd_error chdstate = CHDERR_NONE;
+ std::error_condition chdstate;
if (TRACE_IMAGE)
{
@@ -643,7 +644,7 @@ chd_error mfmhd_generic_format::save(chd_file* chdfile, uint16_t* trackimage, in
if (TRACE_DETAIL) osd_printf_verbose("%s: Writing sector chs=(%d,%d,%d) to CHD\n", tag(), current_cylinder, current_head, sector);
chdstate = chdfile->write_units(chs_to_lba(current_cylinder, current_head, sector), buffer);
- if (chdstate != CHDERR_NONE)
+ if (chdstate)
{
osd_printf_verbose("%s: Write error while writing sector chs=(%d,%d,%d)\n", tag(), cylinder, head, sector);
}
diff --git a/src/lib/formats/mfm_hd.h b/src/lib/formats/mfm_hd.h
index 7d28adc518d..472062d1440 100644
--- a/src/lib/formats/mfm_hd.h
+++ b/src/lib/formats/mfm_hd.h
@@ -151,10 +151,10 @@ public:
virtual ~mfmhd_image_format_t() {};
// Load the image.
- virtual chd_error load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) = 0;
+ virtual std::error_condition load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) = 0;
// Save the image.
- virtual chd_error save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) = 0;
+ virtual std::error_condition save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) = 0;
// Return the original parameters of the image
mfmhd_layout_params* get_initial_params() { return &m_param_old; }
@@ -196,8 +196,8 @@ class mfmhd_generic_format : public mfmhd_image_format_t
{
public:
mfmhd_generic_format() { m_devtag = std::string("mfmhd_generic_format"); };
- chd_error load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) override;
- chd_error save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) override;
+ std::error_condition load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) override;
+ std::error_condition save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) override;
// Yes, we want to save all parameters
virtual bool save_param(mfmhd_param_t type) override { return true; }
diff --git a/src/lib/formats/nfd_dsk.cpp b/src/lib/formats/nfd_dsk.cpp
index 1a0430f9af1..4a51e0db54c 100644
--- a/src/lib/formats/nfd_dsk.cpp
+++ b/src/lib/formats/nfd_dsk.cpp
@@ -77,10 +77,11 @@
*********************************************************************/
- #include <cassert>
-
#include "nfd_dsk.h"
+#include "ioprocs.h"
+
+
nfd_format::nfd_format()
{
}
@@ -100,10 +101,11 @@ const char *nfd_format::extensions() const
return "nfd";
}
-int nfd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int nfd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t h[16];
- io_generic_read(io, h, 0, 16);
+ size_t actual;
+ io.read_at(0, h, 16, actual);
if (strncmp((const char *)h, "T98FDDIMAGE.R0", 14) == 0 || strncmp((const char *)h, "T98FDDIMAGE.R1", 14) == 0)
return 100;
@@ -111,11 +113,14 @@ int nfd_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool nfd_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool nfd_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint64_t size = io_generic_size(io);
+ size_t actual;
+ uint64_t size;
+ if (io.length(size))
+ return false;
uint8_t h[0x120], hsec[0x10];
- io_generic_read(io, h, 0, 0x120);
+ io.read_at(0, h, 0x120, actual);
int format_version = !strncmp((const char *)h, "T98FDDIMAGE.R0", 14) ? 0 : 1;
// sector map (the 164th entry is only used by rev.1 format, loops with track < 163 are correct for rev.0)
@@ -140,7 +145,7 @@ bool nfd_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
{
int curr_track_size = 0;
// read sector map absolute location
- io_generic_read(io, hsec, pos, 4);
+ io.read_at(pos, hsec, 4, actual);
pos += 4;
uint32_t secmap_addr = little_endianize_int32(*(uint32_t *)(hsec));
@@ -149,14 +154,14 @@ bool nfd_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
// read actual sector map for the sectors of this track
// for rev.1 format the first 0x10 are a track summary:
// first WORD is # of sectors, second WORD is # of special data sectors
- io_generic_read(io, hsec, secmap_addr, 0x10);
+ io.read_at(secmap_addr, hsec, 0x10, actual);
secmap_addr += 0x10;
num_secs[track] = little_endianize_int16(*(uint16_t *)(hsec));
num_specials[track] = little_endianize_int16(*(uint16_t *)(hsec + 0x2));
for (int sect = 0; sect < num_secs[track]; sect++)
{
- io_generic_read(io, hsec, secmap_addr, 0x10);
+ io.read_at(secmap_addr, hsec, 0x10, actual);
if (track == 0 && sect == 0)
disk_type = hsec[0xb]; // can this change across the disk? I don't think so...
@@ -175,7 +180,7 @@ bool nfd_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
{
for (int sect = 0; sect < num_specials[track]; sect++)
{
- io_generic_read(io, hsec, secmap_addr, 0x10);
+ io.read_at(secmap_addr, hsec, 0x10, actual);
secmap_addr += 0x10;
curr_track_size += (hsec[9] + 1) * little_endianize_int32(*(uint32_t *)(hsec + 0x0a));
}
@@ -198,7 +203,7 @@ bool nfd_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
{
// read sector map for this sector
// for rev.0 format each sector uses 0x10 bytes
- io_generic_read(io, hsec, pos, 0x10);
+ io.read_at(pos, hsec, 0x10, actual);
if (track == 0 && sect == 0)
disk_type = hsec[0xa]; // can this change across the disk? I don't think so...
@@ -245,7 +250,7 @@ bool nfd_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
for (int track = 0; track < 163 && pos < size; track++)
{
- io_generic_read(io, sect_data, pos, track_sizes[track]);
+ io.read_at(pos, sect_data, track_sizes[track], actual);
for (int i = 0; i < num_secs[track]; i++)
{
diff --git a/src/lib/formats/nfd_dsk.h b/src/lib/formats/nfd_dsk.h
index 5eb41893c5f..c0030b073a5 100644
--- a/src/lib/formats/nfd_dsk.h
+++ b/src/lib/formats/nfd_dsk.h
@@ -20,8 +20,8 @@ class nfd_format : public floppy_image_format_t
public:
nfd_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/opd_dsk.cpp b/src/lib/formats/opd_dsk.cpp
index e105d53d678..964b30b75a0 100644
--- a/src/lib/formats/opd_dsk.cpp
+++ b/src/lib/formats/opd_dsk.cpp
@@ -30,12 +30,13 @@ const char *opd_format::extensions() const
return "opd,opu";
}
-int opd_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int opd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- int type = find_size(io, form_factor, variants);
+ int const type = find_size(io, form_factor, variants);
if (type != -1)
return 90;
+
return 0;
}
diff --git a/src/lib/formats/opd_dsk.h b/src/lib/formats/opd_dsk.h
index 9a4205314ec..9236320f154 100644
--- a/src/lib/formats/opd_dsk.h
+++ b/src/lib/formats/opd_dsk.h
@@ -21,7 +21,7 @@ class opd_format : public wd177x_format
public:
opd_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual int get_image_offset(const format &f, int head, int track) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/oric_dsk.cpp b/src/lib/formats/oric_dsk.cpp
index 22d70124572..f5b0783a112 100644
--- a/src/lib/formats/oric_dsk.cpp
+++ b/src/lib/formats/oric_dsk.cpp
@@ -8,7 +8,9 @@
*********************************************************************/
-#include "formats/oric_dsk.h"
+#include "oric_dsk.h"
+
+#include "ioprocs.h"
const char *oric_dsk_format::name() const
@@ -31,10 +33,11 @@ bool oric_dsk_format::supports_save() const
return true;
}
-int oric_dsk_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int oric_dsk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t h[256];
- io_generic_read(io, h, 0, 256);
+ size_t actual;
+ io.read_at(0, h, 256, actual);
if(memcmp(h, "MFM_DISK", 8))
return 0;
@@ -43,27 +46,30 @@ int oric_dsk_format::identify(io_generic *io, uint32_t form_factor, const std::v
int tracks = (h[15] << 24) | (h[14] << 16) | (h[13] << 8) | h[12];
int geom = (h[19] << 24) | (h[18] << 16) | (h[17] << 8) | h[16];
- int size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return 0;
if(sides < 0 || sides > 2 || geom != 1 || size != 256+6400*sides*tracks)
return 0;
return 100;
}
-bool oric_dsk_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool oric_dsk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
uint8_t h[256];
uint8_t t[6250+3];
t[6250] = t[6251] = t[6252] = 0;
- io_generic_read(io, h, 0, 256);
+ io.read_at(0, h, 256, actual);
int sides = (h[11] << 24) | (h[10] << 16) | (h[ 9] << 8) | h[ 8];
int tracks = (h[15] << 24) | (h[14] << 16) | (h[13] << 8) | h[12];
for(int side=0; side<sides; side++)
for(int track=0; track<tracks; track++) {
- io_generic_read(io, t, 256+6400*(tracks*side + track), 6250);
+ io.read_at(256+6400*(tracks*side + track), t, 6250, actual);
std::vector<uint32_t> stream;
int sector_size = 128;
for(int i=0; i<6250; i++) {
@@ -99,8 +105,9 @@ bool oric_dsk_format::load(io_generic *io, uint32_t form_factor, const std::vect
return true;
}
-bool oric_dsk_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool oric_dsk_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ // FIXME: surely this should return false, since it does't actually save anything?
return true;
}
@@ -127,28 +134,35 @@ bool oric_jasmin_format::supports_save() const
return true;
}
-int oric_jasmin_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int oric_jasmin_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- int size = io_generic_size(io);
- bool can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD);
+ uint64_t size;
+ if(io.length(size))
+ return 0;
+
+ bool const can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD);
if(size == 41*17*256 || (can_ds && size == 41*17*256*2))
return 50;
return 0;
}
-bool oric_jasmin_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool oric_jasmin_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- int size = io_generic_size(io);
- bool can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD);
+ uint64_t size;
+ if(io.length(size))
+ return false;
+
+ bool const can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD);
if(size != 41*17*256 && (!can_ds || size != 41*17*256*2))
return false;
- int heads = size == 41*17*256 ? 1 : 2;
+ int const heads = size == 41*17*256 ? 1 : 2;
std::vector<uint8_t> data(size);
- io_generic_read(io, data.data(), 0, size);
+ size_t actual;
+ io.read_at(0, data.data(), size, actual);
for(int head = 0; head != heads; head++)
for(int track = 0; track != 41; track++) {
@@ -173,7 +187,7 @@ bool oric_jasmin_format::load(io_generic *io, uint32_t form_factor, const std::v
return true;
}
-bool oric_jasmin_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool oric_jasmin_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int tracks, heads;
image->get_actual_geometry(tracks, heads);
@@ -191,8 +205,9 @@ bool oric_jasmin_format::save(io_generic *io, const std::vector<uint32_t> &varia
for(int track = 0; track != 41; track++) {
auto sectors = extract_sectors_from_bitstream_mfm_pc(generate_bitstream_from_track(track, head, 2000, image));
for(unsigned int sector = 0; sector != 17; sector ++) {
- const uint8_t *data = sector+1 < sectors.size() && !sectors[sector+1].empty() ? sectors[sector+1].data() : zero;
- io_generic_write(io, data, 256 * (sector + track*17 + head*17*41), 256);
+ uint8_t const *const data = (sector+1 < sectors.size() && !sectors[sector+1].empty()) ? sectors[sector+1].data() : zero;
+ size_t actual;
+ io.write_at(256 * (sector + track*17 + head*17*41), data, 256, actual);
}
}
return true;
diff --git a/src/lib/formats/oric_dsk.h b/src/lib/formats/oric_dsk.h
index e42b876e52f..6fd1021384b 100644
--- a/src/lib/formats/oric_dsk.h
+++ b/src/lib/formats/oric_dsk.h
@@ -18,9 +18,9 @@ class oric_dsk_format : public floppy_image_format_t
{
public:
oric_dsk_format() = default;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -35,9 +35,9 @@ class oric_jasmin_format : public floppy_image_format_t
public:
oric_jasmin_format() = default;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/os9_dsk.cpp b/src/lib/formats/os9_dsk.cpp
index b28e4f8d293..ba1b2427811 100644
--- a/src/lib/formats/os9_dsk.cpp
+++ b/src/lib/formats/os9_dsk.cpp
@@ -48,6 +48,7 @@
#include "imageutl.h"
#include "coretmpl.h" // BIT
+#include "ioprocs.h"
os9_format::os9_format() : wd177x_format(formats)
@@ -69,21 +70,25 @@ const char *os9_format::extensions() const
return "dsk,os9";
}
-int os9_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int os9_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- int type = find_size(io, form_factor, variants);
+ int const type = find_size(io, form_factor, variants);
if (type != -1)
return 75;
+
return 0;
}
-int os9_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int os9_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return -1;
uint8_t os9_header[0x60];
- io_generic_read(io, os9_header, 0, sizeof(os9_header));
+ size_t actual;
+ io.read_at(0, os9_header, sizeof(os9_header), actual);
int os9_total_sectors = pick_integer_be(os9_header, 0x00, 3);
int os9_heads = util::BIT(os9_header[0x10], 0) ? 2 : 1;
diff --git a/src/lib/formats/os9_dsk.h b/src/lib/formats/os9_dsk.h
index 57dfbfc9ab5..124c019d155 100644
--- a/src/lib/formats/os9_dsk.h
+++ b/src/lib/formats/os9_dsk.h
@@ -21,8 +21,8 @@ public:
virtual const char *name() const override;
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual const wd177x_format::format &get_track_format(const format &f, int head, int track) override;
private:
diff --git a/src/lib/formats/pasti_dsk.cpp b/src/lib/formats/pasti_dsk.cpp
index 0ab6dc2f064..1a418096cd3 100644
--- a/src/lib/formats/pasti_dsk.cpp
+++ b/src/lib/formats/pasti_dsk.cpp
@@ -2,6 +2,8 @@
// copyright-holders:Olivier Galibert
#include "pasti_dsk.h"
+#include "ioprocs.h"
+
// Pasti format supported using the documentation at
// http://www.sarnau.info/atari:pasti_file_format
@@ -36,10 +38,11 @@ bool pasti_format::supports_save() const
return false;
}
-int pasti_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int pasti_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t h[16];
- io_generic_read(io, h, 0, 16);
+ size_t actual;
+ io.read_at(0, h, 16, actual);
if(!memcmp(h, "RSY\0\3\0", 6) &&
(1 || (h[10] >= 80 && h[10] <= 82) || (h[10] >= 160 && h[10] <= 164)))
@@ -58,10 +61,11 @@ static void hexdump(const uint8_t *d, int s)
}
}
-bool pasti_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool pasti_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
uint8_t fh[16];
- io_generic_read(io, fh, 0, 16);
+ io.read_at(0, fh, 16, actual);
std::vector<uint8_t> raw_track;
@@ -76,7 +80,7 @@ bool pasti_format::load(io_generic *io, uint32_t form_factor, const std::vector<
for(int track=0; track < tracks; track++) {
for(int head=0; head < heads; head++) {
uint8_t th[16];
- io_generic_read(io, th, pos, 16);
+ io.read_at(pos, th, 16, actual);
int entry_len = th[0] | (th[1] << 8) | (th[2] << 16) | (th[3] << 24);
int fuzz_len = th[4] | (th[5] << 8) | (th[6] << 16) | (th[7] << 24);
int sect = th[8] | (th[9] << 8);
@@ -87,7 +91,7 @@ bool pasti_format::load(io_generic *io, uint32_t form_factor, const std::vector<
raw_track.resize(entry_len-16);
- io_generic_read(io, &raw_track[0], pos+16, entry_len-16);
+ io.read_at(pos+16, &raw_track[0], entry_len-16, actual);
uint8_t *fuzz = fuzz_len ? &raw_track[16*sect] : nullptr;
uint8_t *bdata = fuzz ? fuzz+fuzz_len : &raw_track[16*sect];
diff --git a/src/lib/formats/pasti_dsk.h b/src/lib/formats/pasti_dsk.h
index b3fc869da4d..2575c12eeb4 100644
--- a/src/lib/formats/pasti_dsk.h
+++ b/src/lib/formats/pasti_dsk.h
@@ -12,8 +12,8 @@ class pasti_format : public floppy_image_format_t
public:
pasti_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/pc98fdi_dsk.cpp b/src/lib/formats/pc98fdi_dsk.cpp
index 2d503acebe4..61fb8fb8fe3 100644
--- a/src/lib/formats/pc98fdi_dsk.cpp
+++ b/src/lib/formats/pc98fdi_dsk.cpp
@@ -8,9 +8,11 @@
*********************************************************************/
-#include <cassert>
#include "pc98fdi_dsk.h"
+#include "ioprocs.h"
+
+
pc98fdi_format::pc98fdi_format()
{
}
@@ -30,47 +32,53 @@ const char *pc98fdi_format::extensions() const
return "fdi";
}
-int pc98fdi_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int pc98fdi_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
- uint8_t h[32];
+ uint64_t size;
+ if(io.length(size))
+ return 0;
- io_generic_read(io, h, 0, 32);
- uint32_t hsize = little_endianize_int32(*(uint32_t *) (h + 0x8));
- uint32_t psize = little_endianize_int32(*(uint32_t *) (h + 0xc));
- uint32_t ssize = little_endianize_int32(*(uint32_t *) (h + 0x10));
- uint32_t scnt = little_endianize_int32(*(uint32_t *) (h + 0x14));
- uint32_t sides = little_endianize_int32(*(uint32_t *) (h + 0x18));
- uint32_t ntrk = little_endianize_int32(*(uint32_t *) (h + 0x1c));
+ uint8_t h[32];
+ size_t actual;
+ io.read_at(0, h, 32, actual);
+
+ uint32_t const hsize = little_endianize_int32(*(uint32_t *) (h + 0x8));
+ uint32_t const psize = little_endianize_int32(*(uint32_t *) (h + 0xc));
+ uint32_t const ssize = little_endianize_int32(*(uint32_t *) (h + 0x10));
+ uint32_t const scnt = little_endianize_int32(*(uint32_t *) (h + 0x14));
+ uint32_t const sides = little_endianize_int32(*(uint32_t *) (h + 0x18));
+ uint32_t const ntrk = little_endianize_int32(*(uint32_t *) (h + 0x1c));
if(size == hsize + psize && psize == ssize*scnt*sides*ntrk)
return 100;
return 0;
}
-bool pc98fdi_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool pc98fdi_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint8_t h[32];
+ size_t actual;
- io_generic_read(io, h, 0, 32);
+ uint8_t h[32];
+ io.read_at(0, h, 32, actual);
- uint32_t hsize = little_endianize_int32(*(uint32_t *)(h+0x8));
- uint32_t sector_size = little_endianize_int32(*(uint32_t *)(h+0x10));
- uint32_t sector_count = little_endianize_int32(*(uint32_t *)(h+0x14));
- uint32_t head_count = little_endianize_int32(*(uint32_t *)(h+0x18));
- uint32_t track_count = little_endianize_int32(*(uint32_t *)(h+0x1c));
+ uint32_t const hsize = little_endianize_int32(*(uint32_t *)(h+0x8));
+ uint32_t const sector_size = little_endianize_int32(*(uint32_t *)(h+0x10));
+ uint32_t const sector_count = little_endianize_int32(*(uint32_t *)(h+0x14));
+ uint32_t const head_count = little_endianize_int32(*(uint32_t *)(h+0x18));
+ uint32_t const track_count = little_endianize_int32(*(uint32_t *)(h+0x1c));
- int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
+ int const cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
- int ssize;
- for(ssize=0; (128 << ssize) < sector_size; ssize++) {};
+ int ssize = 0;
+ while ((128 << ssize) < sector_size)
+ ssize++;
desc_pc_sector sects[256];
uint8_t sect_data[65536];
for(int track=0; track < track_count; track++)
for(int head=0; head < head_count; head++) {
- io_generic_read(io, sect_data, hsize + sector_size*sector_count*(track*head_count + head), sector_size*sector_count);
+ io.read_at(hsize + sector_size*sector_count*(track*head_count + head), sect_data, sector_size*sector_count, actual);
for(int i=0; i<sector_count; i++) {
sects[i].track = track;
diff --git a/src/lib/formats/pc98fdi_dsk.h b/src/lib/formats/pc98fdi_dsk.h
index 1c60f059cbe..1c539f06094 100644
--- a/src/lib/formats/pc98fdi_dsk.h
+++ b/src/lib/formats/pc98fdi_dsk.h
@@ -20,8 +20,8 @@ class pc98fdi_format : public floppy_image_format_t
public:
pc98fdi_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/pc_dsk.cpp b/src/lib/formats/pc_dsk.cpp
index c814afbe6dc..6fe2a82196a 100644
--- a/src/lib/formats/pc_dsk.cpp
+++ b/src/lib/formats/pc_dsk.cpp
@@ -8,10 +8,12 @@
*********************************************************************/
+#include "formats/pc_dsk.h"
+
+#include "ioprocs.h"
+
#include <cstring>
-#include <cassert>
-#include "formats/pc_dsk.h"
pc_format::pc_format() : upd765_format(formats)
{
@@ -32,9 +34,12 @@ const char *pc_format::extensions() const
return "dsk,ima,img,ufi,360";
}
-int pc_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int pc_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size)) {
+ return 0;
+ }
/* some 360K images have a 512-byte header */
if (size == 368640 + 0x200) {
diff --git a/src/lib/formats/pc_dsk.h b/src/lib/formats/pc_dsk.h
index d53879611b9..8c99a35457f 100644
--- a/src/lib/formats/pc_dsk.h
+++ b/src/lib/formats/pc_dsk.h
@@ -20,7 +20,7 @@ class pc_format : public upd765_format
public:
pc_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/poly_dsk.cpp b/src/lib/formats/poly_dsk.cpp
index a865729864e..8845643eb72 100644
--- a/src/lib/formats/poly_dsk.cpp
+++ b/src/lib/formats/poly_dsk.cpp
@@ -10,6 +10,9 @@
#include "poly_dsk.h"
+#include "ioprocs.h"
+
+
poly_cpm_format::poly_cpm_format()
{
}
@@ -34,30 +37,35 @@ bool poly_cpm_format::supports_save() const
return true;
}
-int poly_cpm_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int poly_cpm_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint8_t boot[16];
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return 0;
// check for valid sizes
if (size == 630784 || size == 622592 || size == 256256)
{
// check for Poly CP/M boot sector
- io_generic_read(io, boot, 0, 16);
+ uint8_t boot[16];
+ size_t actual;
+ io.read_at(0, boot, 16, actual);
if (memcmp(boot, "\x86\xc3\xb7\x00\x00\x8e\x10\xc0\xbf\x00\x01\xbf\xe0\x60\x00\x00", 16) == 0)
{
return 100;
}
}
+
return 0;
}
-bool poly_cpm_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool poly_cpm_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- int total_tracks, spt, bps, head_num;
-
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size) || io.seek(0, SEEK_SET))
+ return false;
+ int total_tracks, spt, bps, head_num;
switch (size)
{
case 622592:
@@ -83,8 +91,7 @@ bool poly_cpm_format::load(io_generic *io, uint32_t form_factor, const std::vect
break;
}
- int cell_count = (form_factor == floppy_image::FF_525) ? 50000 : 100000;
- int offset = 0;
+ int const cell_count = (form_factor == floppy_image::FF_525) ? 50000 : 100000;
for (int track = 0; track < total_tracks; track++)
for (int head = 0; head < head_num; head++)
@@ -105,8 +112,8 @@ bool poly_cpm_format::load(io_generic *io, uint32_t form_factor, const std::vect
sects[i].deleted = false;
sects[i].bad_crc = false;
sects[i].data = &sect_data[sdatapos];
- io_generic_read(io, sects[i].data, offset, bps);
- offset += bps;
+ size_t actual;
+ io.read(sects[i].data, bps, actual);
sdatapos += bps;
}
// gap sizes unverified
diff --git a/src/lib/formats/poly_dsk.h b/src/lib/formats/poly_dsk.h
index 8fd3c9be4a5..8afb6836302 100644
--- a/src/lib/formats/poly_dsk.h
+++ b/src/lib/formats/poly_dsk.h
@@ -20,8 +20,8 @@ public:
virtual const char *name() const override;
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
};
diff --git a/src/lib/formats/rx50_dsk.cpp b/src/lib/formats/rx50_dsk.cpp
index d0d8f270c56..f81e2fa5b67 100644
--- a/src/lib/formats/rx50_dsk.cpp
+++ b/src/lib/formats/rx50_dsk.cpp
@@ -29,11 +29,11 @@
FORMAT A: /F:160 on DOS; turn MEDIACHK ON
************************************************************************/
-#include <cassert>
-
-#include "flopimg.h"
#include "formats/rx50_dsk.h"
+#include "ioprocs.h"
+
+
// Controller: WD1793
// TRACK LAYOUT IS UNVERIFED. SEE SOURCES:
// - 'esq_dsk16' (uses WD 1772)
@@ -95,12 +95,17 @@ bool rx50img_format::supports_save() const
return true;
}
-void rx50img_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
+void rx50img_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
{
head_count = 1;
uint32_t expected_size = 0;
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ {
+ track_count = head_count = sector_count = 0;
+ return;
+ }
track_count = 80;
sector_count = 10;
@@ -124,7 +129,7 @@ void rx50img_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &he
track_count = head_count = sector_count = 0;
}
-int rx50img_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int rx50img_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
@@ -135,7 +140,7 @@ int rx50img_format::identify(io_generic *io, uint32_t form_factor, const std::ve
}
// /* Sectors are numbered 1 to 10 */
-bool rx50img_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool rx50img_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint8_t track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
@@ -153,7 +158,8 @@ bool rx50img_format::load(io_generic *io, uint32_t form_factor, const std::vecto
int track_size = sector_count*512;
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
- io_generic_read(io, sectdata, (track*head_count + head)*track_size, track_size);
+ size_t actual;
+ io.read_at((track*head_count + head)*track_size, sectdata, track_size, actual);
generate_track(rx50_10_desc, track, head, sectors, sector_count, 102064, image); // 98480
}
}
@@ -163,7 +169,7 @@ bool rx50img_format::load(io_generic *io, uint32_t form_factor, const std::vecto
return true;
}
-bool rx50img_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool rx50img_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int track_count, head_count, sector_count;
get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count);
@@ -199,7 +205,8 @@ bool rx50img_format::save(io_generic *io, const std::vector<uint32_t> &variants,
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
- io_generic_write(io, sectdata, (track*head_count + head)*track_size, track_size);
+ size_t actual;
+ io.write_at((track*head_count + head)*track_size, sectdata, track_size, actual);
}
}
return true;
diff --git a/src/lib/formats/rx50_dsk.h b/src/lib/formats/rx50_dsk.h
index 9cac83bd67f..d28ea398d30 100644
--- a/src/lib/formats/rx50_dsk.h
+++ b/src/lib/formats/rx50_dsk.h
@@ -23,9 +23,9 @@ class rx50img_format : public floppy_image_format_t
public:
rx50img_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -35,7 +35,7 @@ public:
static const desc_e rx50_10_desc[];
private:
- void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
+ void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
};
extern const floppy_format_type FLOPPY_RX50IMG_FORMAT;
diff --git a/src/lib/formats/sdd_dsk.cpp b/src/lib/formats/sdd_dsk.cpp
index cac33948db0..f3e8df51bda 100644
--- a/src/lib/formats/sdd_dsk.cpp
+++ b/src/lib/formats/sdd_dsk.cpp
@@ -8,10 +8,11 @@
*********************************************************************/
-#include <cassert>
-
#include "formats/sdd_dsk.h"
+#include "ioprocs.h"
+
+
sdd_format::sdd_format() : wd177x_format(formats)
{
}
diff --git a/src/lib/formats/sdf_dsk.cpp b/src/lib/formats/sdf_dsk.cpp
index 223b6dc8d8a..f57540f3c35 100644
--- a/src/lib/formats/sdf_dsk.cpp
+++ b/src/lib/formats/sdf_dsk.cpp
@@ -12,7 +12,9 @@
*********************************************************************/
#include "sdf_dsk.h"
-#include <cassert>
+
+#include "ioprocs.h"
+
sdf_format::sdf_format()
{
@@ -37,18 +39,18 @@ const char *sdf_format::extensions() const
}
-int sdf_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int sdf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t header[HEADER_SIZE];
- uint64_t size = io_generic_size(io);
-
- if (size < HEADER_SIZE)
+ uint64_t size;
+ if (io.length(size) || (size < HEADER_SIZE))
{
return 0;
}
- io_generic_read(io, header, 0, HEADER_SIZE);
+ size_t actual;
+ io.read_at(0, header, HEADER_SIZE, actual);
int tracks = header[4];
int heads = header[5];
@@ -74,13 +76,14 @@ int sdf_format::identify(io_generic *io, uint32_t form_factor, const std::vector
}
-bool sdf_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool sdf_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
uint8_t header[HEADER_SIZE];
std::vector<uint8_t> track_data(TOTAL_TRACK_SIZE);
std::vector<uint32_t> raw_track_data;
- io_generic_read(io, header, 0, HEADER_SIZE);
+ io.read_at(0, header, HEADER_SIZE, actual);
const int tracks = header[4];
const int heads = header[5];
@@ -104,7 +107,7 @@ bool sdf_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
raw_track_data.clear();
// Read track
- io_generic_read(io, &track_data[0], HEADER_SIZE + ( heads * track + head ) * TOTAL_TRACK_SIZE, TOTAL_TRACK_SIZE);
+ io.read_at(HEADER_SIZE + (heads * track + head) * TOTAL_TRACK_SIZE, &track_data[0], TOTAL_TRACK_SIZE, actual);
int sector_count = track_data[0];
@@ -181,7 +184,7 @@ bool sdf_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
}
-bool sdf_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool sdf_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
return false;
}
diff --git a/src/lib/formats/sdf_dsk.h b/src/lib/formats/sdf_dsk.h
index fe3f6eb7a98..b86692f618a 100644
--- a/src/lib/formats/sdf_dsk.h
+++ b/src/lib/formats/sdf_dsk.h
@@ -22,9 +22,9 @@ class sdf_format : public floppy_image_format_t
public:
sdf_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/st_dsk.cpp b/src/lib/formats/st_dsk.cpp
index cb363cbe3e3..d044bc5bdac 100644
--- a/src/lib/formats/st_dsk.cpp
+++ b/src/lib/formats/st_dsk.cpp
@@ -8,10 +8,11 @@
*********************************************************************/
-#include <cassert>
-
#include "formats/st_dsk.h"
+#include "ioprocs.h"
+
+
st_format::st_format()
{
}
@@ -36,18 +37,20 @@ bool st_format::supports_save() const
return true;
}
-void st_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
+void st_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
{
- uint64_t size = io_generic_size(io);
- for(track_count=80; track_count <= 82; track_count++)
- for(head_count=1; head_count <= 2; head_count++)
- for(sector_count=9; sector_count <= 11; sector_count++)
- if(size == (uint32_t)512*track_count*head_count*sector_count)
- return;
+ uint64_t size;
+ if(!io.length(size)) {
+ for(track_count=80; track_count <= 82; track_count++)
+ for(head_count=1; head_count <= 2; head_count++)
+ for(sector_count=9; sector_count <= 11; sector_count++)
+ if(size == (uint32_t)512*track_count*head_count*sector_count)
+ return;
+ }
track_count = head_count = sector_count = 0;
}
-int st_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int st_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint8_t track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
@@ -57,7 +60,7 @@ int st_format::identify(io_generic *io, uint32_t form_factor, const std::vector<
return 0;
}
-bool st_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool st_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint8_t track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
@@ -73,7 +76,8 @@ bool st_format::load(io_generic *io, uint32_t form_factor, const std::vector<uin
int track_size = sector_count*512;
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
- io_generic_read(io, sectdata, (track*head_count + head)*track_size, track_size);
+ size_t actual;
+ io.read_at((track*head_count + head)*track_size, sectdata, track_size, actual);
generate_track(atari_st_fcp_get_desc(track, head, head_count, sector_count),
track, head, sectors, sector_count, 100000, image);
}
@@ -84,7 +88,7 @@ bool st_format::load(io_generic *io, uint32_t form_factor, const std::vector<uin
return true;
}
-bool st_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool st_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int track_count, head_count, sector_count;
get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count);
@@ -109,7 +113,8 @@ bool st_format::save(io_generic *io, const std::vector<uint32_t> &variants, flop
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
- io_generic_write(io, sectdata, (track*head_count + head)*track_size, track_size);
+ size_t actual;
+ io.write_at((track*head_count + head)*track_size, sectdata, track_size, actual);
}
}
@@ -141,10 +146,11 @@ bool msa_format::supports_save() const
return true;
}
-void msa_format::read_header(io_generic *io, uint16_t &sign, uint16_t &sect, uint16_t &head, uint16_t &strack, uint16_t &etrack)
+void msa_format::read_header(util::random_read &io, uint16_t &sign, uint16_t &sect, uint16_t &head, uint16_t &strack, uint16_t &etrack)
{
uint8_t h[10];
- io_generic_read(io, h, 0, 10);
+ size_t actual;
+ io.read_at(0, h, 10, actual);
sign = (h[0] << 8) | h[1];
sect = (h[2] << 8) | h[3];
head = (h[4] << 8) | h[5];
@@ -206,7 +212,7 @@ bool msa_format::compress(const uint8_t *buffer, int usize, uint8_t *dest, int &
return dst < usize;
}
-int msa_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int msa_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
uint16_t sign, sect, head, strack, etrack;
read_header(io, sign, sect, head, strack, etrack);
@@ -220,7 +226,7 @@ int msa_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool msa_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool msa_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint16_t sign, sect, heads, strack, etrack;
read_header(io, sign, sect, heads, strack, etrack);
@@ -238,11 +244,12 @@ bool msa_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
for(int track=strack; track <= etrack; track++) {
for(int head=0; head <= heads; head++) {
+ size_t actual;
uint8_t th[2];
- io_generic_read(io, th, pos, 2);
+ io.read_at(pos, th, 2, actual);
pos += 2;
int tsize = (th[0] << 8) | th[1];
- io_generic_read(io, sectdata, pos, tsize);
+ io.read_at(pos, sectdata, tsize, actual);
pos += tsize;
if(tsize < track_size) {
if(!uncompress(sectdata, tsize, track_size))
@@ -258,7 +265,7 @@ bool msa_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
}
-bool msa_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool msa_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int track_count, head_count, sector_count;
get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count);
@@ -289,9 +296,10 @@ bool msa_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
header[8] = 0;
header[9] = track_count-1;
- io_generic_write(io, header, 0, 10);
-
- int pos = 10;
+ if(io.seek(0, SEEK_SET))
+ return false;
+ size_t actual;
+ io.write(header, 10, actual);
uint8_t sectdata[11*512];
uint8_t compdata[11*512];
@@ -305,16 +313,14 @@ bool msa_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
uint8_t th[2];
th[0] = csize >> 8;
th[1] = csize;
- io_generic_write(io, th, pos, 2);
- io_generic_write(io, compdata, pos+2, csize);
- pos += 2+csize;
+ io.write(th, 2, actual);
+ io.write(compdata, csize, actual);
} else {
uint8_t th[2];
th[0] = track_size >> 8;
th[1] = track_size;
- io_generic_write(io, th, pos, 2);
- io_generic_write(io, sectdata, pos+2, track_size);
- pos += 2+track_size;
+ io.write(th, 2, actual);
+ io.write(sectdata, track_size, actual);
}
}
}
diff --git a/src/lib/formats/st_dsk.h b/src/lib/formats/st_dsk.h
index ce501a9f516..34f303bb1ae 100644
--- a/src/lib/formats/st_dsk.h
+++ b/src/lib/formats/st_dsk.h
@@ -19,9 +19,9 @@ class st_format : public floppy_image_format_t
public:
st_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -29,7 +29,7 @@ public:
virtual bool supports_save() const override;
private:
- void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
+ void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
};
class msa_format : public floppy_image_format_t
@@ -37,9 +37,9 @@ class msa_format : public floppy_image_format_t
public:
msa_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
@@ -49,7 +49,7 @@ public:
private:
bool uncompress(uint8_t *buffer, int csize, int usize);
bool compress(const uint8_t *src, int usize, uint8_t *dest, int &csize);
- void read_header(io_generic *io, uint16_t &sign, uint16_t &sect, uint16_t &head, uint16_t &strack, uint16_t &etrack);
+ void read_header(util::random_read &io, uint16_t &sign, uint16_t &sect, uint16_t &head, uint16_t &strack, uint16_t &etrack);
};
extern const floppy_format_type FLOPPY_ST_FORMAT;
diff --git a/src/lib/formats/svi_dsk.cpp b/src/lib/formats/svi_dsk.cpp
index e3cfa294fcb..0a05bd15c80 100644
--- a/src/lib/formats/svi_dsk.cpp
+++ b/src/lib/formats/svi_dsk.cpp
@@ -10,6 +10,9 @@
#include "svi_dsk.h"
+#include "ioprocs.h"
+
+
svi_format::svi_format()
{
}
@@ -29,9 +32,11 @@ const char *svi_format::extensions() const
return "dsk";
}
-int svi_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int svi_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if (io.length(size))
+ return 0;
if (size == 172032 || size == 346112)
return 50;
@@ -39,11 +44,13 @@ int svi_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool svi_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool svi_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint64_t size = io_generic_size(io);
- int head_count;
+ uint64_t size;
+ if (io.length(size))
+ return false;
+ int head_count;
switch (size)
{
case 172032: head_count = 1; break;
@@ -51,7 +58,8 @@ bool svi_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
default: return false;
}
- int file_offset = 0;
+ if (io.seek(0, SEEK_SET))
+ return false;
for (int track = 0; track < 40; track++)
{
@@ -75,10 +83,10 @@ bool svi_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
sectors[i].bad_crc = false;
sectors[i].data = &sector_data[sector_offset];
- io_generic_read(io, sectors[i].data, file_offset, sector_size);
+ size_t actual;
+ io.read(sectors[i].data, sector_size, actual);
sector_offset += sector_size;
- file_offset += sector_size;
}
if (track == 0 && head == 0)
@@ -91,9 +99,10 @@ bool svi_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
}
-bool svi_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool svi_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint64_t file_offset = 0;
+ if (io.seek(0, SEEK_SET))
+ return false;
int track_count, head_count;
image->get_actual_geometry(track_count, head_count);
@@ -104,8 +113,8 @@ bool svi_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
for (int i = 0; i < 18; i++)
{
- io_generic_write(io, sectors[i + 1].data(), file_offset, 128);
- file_offset += 128;
+ size_t actual;
+ io.write(sectors[i + 1].data(), 128, actual);
}
// rest are mfm tracks
@@ -121,8 +130,8 @@ bool svi_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
for (int i = 0; i < 17; i++)
{
- io_generic_write(io, sectors[i + 1].data(), file_offset, 256);
- file_offset += 256;
+ size_t actual;
+ io.write(sectors[i + 1].data(), 256, actual);
}
}
}
diff --git a/src/lib/formats/svi_dsk.h b/src/lib/formats/svi_dsk.h
index 57f4f89ccca..a631bdf498c 100644
--- a/src/lib/formats/svi_dsk.h
+++ b/src/lib/formats/svi_dsk.h
@@ -23,9 +23,9 @@ public:
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
};
diff --git a/src/lib/formats/td0_dsk.cpp b/src/lib/formats/td0_dsk.cpp
index edac0aae010..345a242c86b 100644
--- a/src/lib/formats/td0_dsk.cpp
+++ b/src/lib/formats/td0_dsk.cpp
@@ -16,9 +16,11 @@
#include "flopimg.h"
-#include <cassert>
+#include "ioprocs.h"
+
#include <cstring>
+
#define BUFSZ 512 // new input buffer
/* LZSS Parameters */
@@ -59,7 +61,16 @@ struct tdlzhuf {
struct td0dsk_t
{
- io_generic *floppy_file;
+public:
+ td0dsk_t(util::random_read &f) : floppy_file(f) { }
+
+ void set_floppy_file_offset(uint64_t o) { floppy_file_offset = o; }
+
+ void init_Decode();
+ int Decode(uint8_t *buf, int len);
+
+private:
+ util::random_read &floppy_file;
uint64_t floppy_file_offset;
struct tdlzhuf tdctl;
@@ -87,29 +98,10 @@ struct td0dsk_t
void update(int c);
int16_t DecodeChar();
int16_t DecodePosition();
- void init_Decode();
- int Decode(uint8_t *buf, int len);
};
//static td0dsk_t td0dsk;
-struct floppy_image_legacy
-{
- struct io_generic io;
-
- const struct FloppyFormat *floppy_option;
- struct FloppyCallbacks format;
-
- /* loaded track stuff */
- int loaded_track_head;
- int loaded_track_index;
- uint32_t loaded_track_size;
- void *loaded_track_data;
- uint8_t loaded_track_status;
- uint8_t flags;
-};
-
-
static struct td0dsk_tag *get_tag(floppy_image_legacy *floppy)
{
struct td0dsk_tag *tag;
@@ -332,11 +324,13 @@ static floperr_t td0_get_indexed_sector_info(floppy_image_legacy *floppy, int he
int td0dsk_t::data_read(uint8_t *buf, uint16_t size)
{
- uint64_t image_size = io_generic_size(floppy_file);
+ uint64_t image_size = 0;
+ floppy_file.length(image_size);
if (size > image_size - floppy_file_offset) {
size = image_size - floppy_file_offset;
}
- io_generic_read(floppy_file,buf,floppy_file_offset,size);
+ size_t actual;
+ floppy_file.read_at(floppy_file_offset, buf, size, actual);
floppy_file_offset += size;
return size;
}
@@ -675,7 +669,6 @@ int td0dsk_t::Decode(uint8_t *buf, int len) /* Decoding/Uncompressing */
FLOPPY_CONSTRUCT( td0_dsk_construct )
{
- td0dsk_t state;
struct FloppyCallbacks *callbacks;
struct td0dsk_tag *tag;
uint8_t *header;
@@ -706,9 +699,9 @@ FLOPPY_CONSTRUCT( td0_dsk_construct )
int rd;
int off = 12;
int size = 0;
- state.floppy_file = &(floppy->io);
+ td0dsk_t state(floppy_get_io(floppy));
state.init_Decode();
- state.floppy_file_offset = 12;
+ state.set_floppy_file_offset(12);
do
{
if((rd = state.Decode(obuf, BUFSZ)) > 0) size += rd;
@@ -720,7 +713,7 @@ FLOPPY_CONSTRUCT( td0_dsk_construct )
return FLOPPY_ERROR_OUTOFMEMORY;
}
memcpy(tag->data,obuf,12);
- state.floppy_file_offset = 12;
+ state.set_floppy_file_offset(12);
state.init_Decode();
do
{
@@ -815,20 +808,22 @@ const char *td0_format::extensions() const
return "td0";
}
-int td0_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int td0_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
+ size_t actual;
uint8_t h[7];
- io_generic_read(io, h, 0, 7);
+ io.read_at(0, h, 7, actual);
if(((h[0] == 'T') && (h[1] == 'D')) || ((h[0] == 't') && (h[1] == 'd')))
{
- return 100;
+ return 100;
}
return 0;
}
-bool td0_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool td0_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
int track_count = 0;
int head_count = 0;
int track_spt;
@@ -837,20 +832,24 @@ bool td0_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
std::vector<uint8_t> imagebuf(max_size);
uint8_t header[12];
- io_generic_read(io, header, 0, 12);
+ io.read_at(0, header, 12, actual);
head_count = header[9];
if(header[0] == 't')
{
- td0dsk_t disk_decode;
+ td0dsk_t disk_decode(io);
- disk_decode.floppy_file = io;
disk_decode.init_Decode();
- disk_decode.floppy_file_offset = 12;
+ disk_decode.set_floppy_file_offset(12);
disk_decode.Decode(&imagebuf[0], max_size);
}
else
- io_generic_read(io, &imagebuf[0], 12, io_generic_size(io));
+ {
+ uint64_t image_size;
+ if(io.length(image_size))
+ return false;
+ io.read_at(12, &imagebuf[0], image_size, actual);
+ }
if(header[7] & 0x80)
offset = 10 + imagebuf[2] + (imagebuf[3] << 8);
@@ -1024,7 +1023,7 @@ bool td0_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
}
-bool td0_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool td0_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
return false;
}
diff --git a/src/lib/formats/td0_dsk.h b/src/lib/formats/td0_dsk.h
index b4656305920..cf625374130 100644
--- a/src/lib/formats/td0_dsk.h
+++ b/src/lib/formats/td0_dsk.h
@@ -13,9 +13,9 @@ class td0_format : public floppy_image_format_t
public:
td0_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/ti99_dsk.cpp b/src/lib/formats/ti99_dsk.cpp
index 06ce98dfda0..507d7dc0ae0 100644
--- a/src/lib/formats/ti99_dsk.cpp
+++ b/src/lib/formats/ti99_dsk.cpp
@@ -43,6 +43,8 @@
#include "ti99_dsk.h"
#include "imageutl.h"
+#include "ioprocs.h"
+
#include "osdcore.h" // osd_printf_* (in osdcore.h)
#include <cstring>
@@ -80,13 +82,16 @@ int ti99_floppy_format::get_encoding(int cell_size)
/*
Load the image from disk and convert it into a sequence of flux levels.
*/
-bool ti99_floppy_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool ti99_floppy_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ uint64_t file_size;
+ if (io.length(file_size))
+ return false;
+
int cell_size = 0;
int sector_count = 0;
int heads = 0;
int log_track_count = 0;
- int file_size = io_generic_size(io);
bool img_high_tpi = false;
bool drive_high_tpi = false;
@@ -211,7 +216,7 @@ bool ti99_floppy_format::load(io_generic *io, uint32_t form_factor, const std::v
/*
Save all tracks to the image file.
*/
-bool ti99_floppy_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool ti99_floppy_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
uint8_t sectordata[9216]; // max size (36*256)
@@ -916,9 +921,12 @@ const char *ti99_sdf_format::extensions() const
return "dsk";
}
-int ti99_sdf_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int ti99_sdf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t file_size = io_generic_size(io);
+ uint64_t file_size;
+ if (io.length(file_size))
+ return 0;
+
int vote = 0;
// Adding support for another sector image format which adds 768 bytes
@@ -947,7 +955,8 @@ int ti99_sdf_format::identify(io_generic *io, uint32_t form_factor, const std::v
{
// Read first sector (Volume Information Block)
ti99vib vib;
- io_generic_read(io, &vib, 0, sizeof(ti99vib));
+ size_t actual;
+ io.read_at(0, &vib, sizeof(ti99vib), actual);
// Check from contents
if ((vib.id[0]=='D')&&(vib.id[1]=='S')&&(vib.id[2]=='K'))
@@ -964,10 +973,14 @@ int ti99_sdf_format::identify(io_generic *io, uint32_t form_factor, const std::v
return vote;
}
-void ti99_sdf_format::determine_sizes(io_generic *io, int& cell_size, int& sector_count, int& heads, int& tracks)
+void ti99_sdf_format::determine_sizes(util::random_read &io, int& cell_size, int& sector_count, int& heads, int& tracks)
{
- uint64_t file_size = io_generic_size(io);
- ti99vib vib;
+ uint64_t file_size;
+ if (io.length(file_size))
+ {
+ cell_size = sector_count = heads = tracks = 0;
+ return;
+ }
cell_size = 0;
sector_count = 0;
@@ -980,7 +993,9 @@ void ti99_sdf_format::determine_sizes(io_generic *io, int& cell_size, int& secto
file_size -= 768;
// Read first sector
- io_generic_read(io, &vib, 0, sizeof(ti99vib));
+ ti99vib vib;
+ size_t actual;
+ io.read_at(0, &vib, sizeof(ti99vib), actual);
// Check from contents
if ((vib.id[0]=='D')&&(vib.id[1]=='S')&&(vib.id[2]=='K'))
@@ -1059,13 +1074,14 @@ int ti99_sdf_format::get_track_size(int sector_count)
return sector_count * SECTOR_SIZE;
}
-void ti99_sdf_format::load_track(io_generic *io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount)
+void ti99_sdf_format::load_track(util::random_read &io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount)
{
// Calculate the track offset from the beginning of the image file
int logicaltrack = (head==0)? track : (2*trackcount - track - 1);
int position = logicaltrack * get_track_size(sectorcount);
- io_generic_read(io, sectordata, position, sectorcount*SECTOR_SIZE);
+ size_t actual;
+ io.read_at(position, sectordata, sectorcount*SECTOR_SIZE, actual);
// Interleave and skew
int interleave = 7;
@@ -1133,19 +1149,18 @@ std::string ti99_floppy_format::dumpline(uint8_t* line, int address) const
Write the data to the disk. We have a list of sector positions, so we
just need to go through that list and save each sector in the sector data.
*/
-void ti99_sdf_format::write_track(io_generic *io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count)
+void ti99_sdf_format::write_track(util::random_read_write &io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count)
{
- uint8_t* buf;
-
int logicaltrack = head * track_count;
logicaltrack += ((head&1)==0)? track : (track_count - 1 - track);
int trackoffset = logicaltrack * sector_count * SECTOR_SIZE;
for (int i=0; i < sector_count; i++)
{
- buf = sectordata + i * SECTOR_SIZE;
+ uint8_t const *const buf = sectordata + i * SECTOR_SIZE;
LOGMASKED(LOG_DETAIL, "[ti99_dsk] Writing sector %d (offset %06x)\n", sector[i], sector[i] * SECTOR_SIZE);
- io_generic_write(io, buf, trackoffset + sector[i] * SECTOR_SIZE, SECTOR_SIZE);
+ size_t actual;
+ io.write_at(trackoffset + sector[i] * SECTOR_SIZE, buf, SECTOR_SIZE, actual);
}
}
@@ -1209,7 +1224,7 @@ const char *ti99_tdf_format::extensions() const
/*
Determine whether the image file can be interpreted as a track dump
*/
-int ti99_tdf_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int ti99_tdf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int vote = 0;
uint8_t fulltrack[6872];
@@ -1232,7 +1247,8 @@ int ti99_tdf_format::identify(io_generic *io, uint32_t form_factor, const std::v
LOGMASKED(LOG_INFO, "[ti99_dsk] Image file length matches TDF\n");
// Fetch track 0
- io_generic_read(io, fulltrack, 0, get_track_size(sector_count));
+ size_t actual;
+ io.read_at(0, fulltrack, get_track_size(sector_count), actual);
if (sector_count == 9)
{
@@ -1279,9 +1295,14 @@ int ti99_tdf_format::identify(io_generic *io, uint32_t form_factor, const std::v
Find the proper format for a given image file. Tracks are counted per side.
Note that only two formats are actually compatible with the PC99 emulator.
*/
-void ti99_tdf_format::determine_sizes(io_generic *io, int& cell_size, int& sector_count, int& heads, int& tracks)
+void ti99_tdf_format::determine_sizes(util::random_read &io, int& cell_size, int& sector_count, int& heads, int& tracks)
{
- uint64_t file_size = io_generic_size(io);
+ uint64_t file_size;
+ if (io.length(file_size))
+ {
+ cell_size = sector_count = heads = tracks = 0;
+ return;
+ }
// LOGMASKED(LOG_INFO, "[ti99_dsk] Image size = %ld\n", file_size); // doesn't compile
switch (file_size)
@@ -1336,13 +1357,14 @@ void ti99_tdf_format::determine_sizes(io_generic *io, int& cell_size, int& secto
track from scratch. TDF is not as flexible as it suggests, it does not
allow different gap lengths and so on.
*/
-void ti99_tdf_format::load_track(io_generic *io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount)
+void ti99_tdf_format::load_track(util::random_read &io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount)
{
+ size_t actual;
uint8_t fulltrack[12544]; // space for a full TDF track
// Read beginning of track 0. We need this to get the first gap, according
// to the format
- io_generic_read(io, fulltrack, 0, 100);
+ io.read_at(0, fulltrack, 100, actual);
int offset = 0;
int tracksize = get_track_size(sectorcount);
@@ -1383,7 +1405,7 @@ void ti99_tdf_format::load_track(io_generic *io, uint8_t *sectordata, int *secto
int base = (head * trackcount + track) * tracksize;
int position = 0;
- io_generic_read(io, fulltrack, base, tracksize);
+ io.read_at(base, fulltrack, tracksize, actual);
for (int i=0; i < sectorcount; i++)
{
@@ -1431,7 +1453,7 @@ void ti99_tdf_format::load_track(io_generic *io, uint8_t *sectordata, int *secto
need the sector contents and the sector sequence, which are passed via
sectordata, sector, and sector_count.
*/
-void ti99_tdf_format::write_track(io_generic *io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count)
+void ti99_tdf_format::write_track(util::random_read_write &io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count)
{
uint8_t trackdata[12544];
int offset = ((track_count * head) + track) * get_track_size(sector_count);
@@ -1485,7 +1507,8 @@ void ti99_tdf_format::write_track(io_generic *io, uint8_t *sectordata, int *sect
for (int i=0; i < param[WGAP3]; i++) trackdata[pos++] = param[WGAPBYTE];
}
for (int i=0; i < param[WGAP4]; i++) trackdata[pos++] = param[WGAPBYTE];
- io_generic_write(io, trackdata, offset, get_track_size(sector_count));
+ size_t actual;
+ io.write_at(offset, trackdata, get_track_size(sector_count), actual);
}
int ti99_tdf_format::get_track_size(int sector_count)
diff --git a/src/lib/formats/ti99_dsk.h b/src/lib/formats/ti99_dsk.h
index 5b59b164344..6590d1e7dd2 100644
--- a/src/lib/formats/ti99_dsk.h
+++ b/src/lib/formats/ti99_dsk.h
@@ -23,8 +23,8 @@ class ti99_floppy_format : public floppy_image_format_t
{
public:
bool supports_save() const override { return true; }
- bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
protected:
uint8_t get_data_from_encoding(uint16_t raw);
@@ -32,10 +32,10 @@ protected:
virtual int min_heads() =0;
- virtual void determine_sizes(io_generic *io, int& cell_size, int& sector_count, int& heads, int& tracks) =0;
+ virtual void determine_sizes(util::random_read &io, int& cell_size, int& sector_count, int& heads, int& tracks) =0;
virtual int get_track_size(int sector_count) =0;
- virtual void load_track(io_generic *io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) =0;
- virtual void write_track(io_generic *io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) =0;
+ virtual void load_track(util::random_read &io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) =0;
+ virtual void write_track(util::random_read_write &io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) =0;
int get_encoding(int cell_size);
@@ -53,16 +53,16 @@ protected:
class ti99_sdf_format : public ti99_floppy_format
{
public:
- int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
const char *name() const override;
const char *description() const override;
const char *extensions() const override;
private:
- void determine_sizes(io_generic *io, int& cell_size, int& sector_count, int& heads, int& tracks) override;
+ void determine_sizes(util::random_read &io, int& cell_size, int& sector_count, int& heads, int& tracks) override;
int get_track_size(int sector_count) override;
- void write_track(io_generic *io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) override;
- void load_track(io_generic *io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sector_count, int track_count) override;
+ void write_track(util::random_read_write &io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) override;
+ void load_track(util::random_read &io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sector_count, int track_count) override;
// This format supports single-sided images
int min_heads() override { return 1; }
@@ -92,15 +92,15 @@ extern const floppy_format_type FLOPPY_TI99_SDF_FORMAT;
class ti99_tdf_format : public ti99_floppy_format
{
public:
- int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
const char *name() const override;
const char *description() const override;
const char *extensions() const override;
private:
- void determine_sizes(io_generic *io, int& cell_size, int& sector_count, int& heads, int& tracks) override;
- void load_track(io_generic *io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) override;
- void write_track(io_generic *io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) override;
+ void determine_sizes(util::random_read &io, int& cell_size, int& sector_count, int& heads, int& tracks) override;
+ void load_track(util::random_read &io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) override;
+ void write_track(util::random_read_write &io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) override;
int get_track_size(int sector_count) override;
// This format only supports double-sided images
diff --git a/src/lib/formats/trd_dsk.cpp b/src/lib/formats/trd_dsk.cpp
index 26b6ce5b6a5..4236259cca5 100644
--- a/src/lib/formats/trd_dsk.cpp
+++ b/src/lib/formats/trd_dsk.cpp
@@ -8,10 +8,11 @@
*********************************************************************/
-#include <cassert>
-
#include "formats/trd_dsk.h"
+#include "ioprocs.h"
+
+
trd_format::trd_format() : wd177x_format(formats)
{
}
@@ -31,10 +32,13 @@ const char *trd_format::extensions() const
return "trd";
}
-int trd_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int trd_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
+ uint64_t size;
+ if (io.length(size))
+ return -1;
+
int index = -1;
- uint64_t size = io_generic_size(io);
for (int i = 0; formats[i].form_factor; i++)
{
const format &f = formats[i];
@@ -47,12 +51,13 @@ int trd_format::find_size(io_generic *io, uint32_t form_factor, const std::vecto
{
index = i; // at least size match, save it for the case if there will be no exact matches
+ size_t actual;
uint8_t sectdata[0x100];
if (f.encoding == floppy_image::MFM)
- io_generic_read(io, sectdata, 0x800, 0x100);
+ io.read_at(0x800, sectdata, 0x100, actual);
else
{
- io_generic_read(io, sectdata, 0x100, 0x100);
+ io.read_at(0x100, sectdata, 0x100, actual);
for (int i = 0; i < 0x100; i++)
sectdata[i] ^= 0xff;
}
diff --git a/src/lib/formats/trd_dsk.h b/src/lib/formats/trd_dsk.h
index 6f19f9976a5..c5a411c60bb 100644
--- a/src/lib/formats/trd_dsk.h
+++ b/src/lib/formats/trd_dsk.h
@@ -24,7 +24,7 @@ public:
private:
static const format formats[];
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
};
extern const floppy_format_type FLOPPY_TRD_FORMAT;
diff --git a/src/lib/formats/trs80_dsk.cpp b/src/lib/formats/trs80_dsk.cpp
index f010a24e570..acd48368239 100644
--- a/src/lib/formats/trs80_dsk.cpp
+++ b/src/lib/formats/trs80_dsk.cpp
@@ -66,6 +66,9 @@ Description of JV3:
#include "trs80_dsk.h"
+#include "ioprocs.h"
+
+
jv1_format::jv1_format() : wd177x_format(formats)
{
}
@@ -132,15 +135,18 @@ const char *jv3_format::extensions() const
return "jv3,dsk";
}
-int jv3_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int jv3_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint32_t image_size = io_generic_size(io);
+ uint64_t image_size;
+ if (io.length(image_size))
+ return 0;
if (image_size < 0x2200)
return 0; // too small, silent return
std::vector<uint8_t> data(image_size);
- io_generic_read(io, data.data(), 0, image_size);
+ size_t actual;
+ io.read_at(0, data.data(), image_size, actual);
const uint32_t entries = 2901;
const uint32_t header_size = entries *3 +1;
@@ -181,20 +187,20 @@ int jv3_format::identify(io_generic *io, uint32_t form_factor, const std::vector
// validate so we don't overrun the array
if (track >= MAX_TRACKS)
{
- printf("jv3_format::identify - track %d exceeds maximum allowed (%d)\n",track,MAX_TRACKS-1);
+ osd_printf_info("jv3_format::identify - track %d exceeds maximum allowed (%d)\n",track,MAX_TRACKS-1);
return 0;
}
if (sector >= MAX_SECTORS)
{
- printf("jv3_format::identify - sector %d exceeds maximum allowed (%d)\n",sector,MAX_SECTORS-1);
+ osd_printf_info("jv3_format::identify - sector %d exceeds maximum allowed (%d)\n",sector,MAX_SECTORS-1);
return 0;
}
// check if sector already exists
if (sector_array[flag_side][track][sector])
{
- printf("jv3_format::identify - side %d track %d sector %d is duplicated\n",flag_side,track,sector);
+ osd_printf_info("jv3_format::identify - side %d track %d sector %d is duplicated\n",flag_side,track,sector);
return 0;
}
@@ -214,21 +220,25 @@ int jv3_format::identify(io_generic *io, uint32_t form_factor, const std::vector
// Is all data in the image? (unused tracks at the end are optional)
if (last_data > image_size)
{
- printf("jv3_format::identify - disk is missing some data. Expected 0x%X, Actual = 0x%X\n",last_data,image_size);
+ osd_printf_info("jv3_format::identify - disk is missing some data. Expected 0x%X, Actual = 0x%X\n",last_data,image_size);
return 0;
}
return 80;
}
-bool jv3_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool jv3_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
// disk has already been validated in every way except if it exceeds drive tracks, we do that below
- printf("Disk detected as JV3\n");fflush(stdout);
+ osd_printf_info("Disk detected as JV3\n");
int drive_tracks, drive_sides;
image->get_maximal_geometry(drive_tracks, drive_sides);
- std::vector<uint8_t> data(io_generic_size(io));
- io_generic_read(io, data.data(), 0, data.size());
+ uint64_t image_size;
+ if (io.length(image_size))
+ return false;
+ std::vector<uint8_t> data(image_size);
+ size_t actual;
+ io.read_at(0, data.data(), data.size(), actual);
const uint32_t entries = 2901;
const uint32_t header_size = entries *3 +1;
bool is_dd = false, is_ds = false;
@@ -313,7 +323,7 @@ bool jv3_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
data_ptr += sector_size;
}
- //printf("Side %d, Track %d, %s density\n",curr_side,curr_track,ddensity ? "Double" : "Single");
+ //osd_printf_verbose("Side %d, Track %d, %s density\n",curr_side,curr_track,ddensity ? "Double" : "Single");
if (ddensity)
{
is_dd = true;
@@ -344,7 +354,7 @@ bool jv3_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
}
-bool jv3_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool jv3_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int track_count, head_count;
image->get_actual_geometry(track_count, head_count);
@@ -352,10 +362,15 @@ bool jv3_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
if (track_count)
{
// If the disk already exists, find out if it's writable
- std::vector<uint8_t> data(io_generic_size(io));
- io_generic_read(io, data.data(), 0, data.size());
- if ((data.size() >= 0x2200) && (data[0x21ff] == 0))
- return false; // disk is readonly
+ uint64_t image_size;
+ if (!io.length(image_size))
+ {
+ std::vector<uint8_t> data(image_size);
+ size_t actual;
+ io.read_at(0, data.data(), data.size(), actual);
+ if ((data.size() >= 0x2200) && (data[0x21ff] == 0))
+ return false; // disk is readonly
+ }
}
uint32_t data_ptr = 0x2200, sect_ptr = 0;
@@ -396,7 +411,8 @@ bool jv3_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
header[sect_ptr++] = track;
header[sect_ptr++] = i;
header[sect_ptr++] = head ? 0x10 : 0;
- io_generic_write(io, &dummy[0], data_ptr, 256);
+ size_t actual;
+ io.write_at(data_ptr, &dummy[0], 256, actual);
data_ptr += 256;
}
}
@@ -417,14 +433,16 @@ bool jv3_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
flags |= (sectors[i].size() >> 8) ^1;
flags |= head ? 0x10 : 0;
header[sect_ptr++] = flags;
- io_generic_write(io, sectors[i].data(), data_ptr, sectors[i].size());
+ size_t actual;
+ io.write_at(data_ptr, sectors[i].data(), sectors[i].size(), actual);
data_ptr += sectors[i].size();
}
}
}
}
// Save the header
- io_generic_write(io, header, 0, 0x2200);
+ size_t actual;
+ io.write_at(0, header, 0x2200, actual);
return true;
}
diff --git a/src/lib/formats/trs80_dsk.h b/src/lib/formats/trs80_dsk.h
index 60618a93693..31955fe4a5e 100644
--- a/src/lib/formats/trs80_dsk.h
+++ b/src/lib/formats/trs80_dsk.h
@@ -35,9 +35,9 @@ class jv3_format : public floppy_image_format_t
public:
jv3_format();
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual const char *name() const override;
virtual const char *description() const override;
diff --git a/src/lib/formats/uniflex_dsk.cpp b/src/lib/formats/uniflex_dsk.cpp
index fa5d9b50acc..f85da09b75e 100644
--- a/src/lib/formats/uniflex_dsk.cpp
+++ b/src/lib/formats/uniflex_dsk.cpp
@@ -10,7 +10,10 @@
*/
#include "uniflex_dsk.h"
-#include "formats/imageutl.h"
+#include "imageutl.h"
+
+#include "ioprocs.h"
+
uniflex_format::uniflex_format() : wd177x_format(formats)
{
@@ -31,22 +34,26 @@ const char *uniflex_format::extensions() const
return "dsk";
}
-int uniflex_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int uniflex_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- int type = find_size(io, form_factor, variants);
+ int const type = find_size(io, form_factor, variants);
if (type != -1)
return 75;
+
return 0;
}
-int uniflex_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int uniflex_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
- uint8_t sir[192];
+ uint64_t size;
+ if (io.length(size))
+ return -1;
// Look at the SIR sector, the second sector.
- io_generic_read(io, sir, 1 * 512, sizeof(sir));
+ uint8_t sir[192];
+ size_t actual;
+ io.read_at(1 * 512, sir, sizeof(sir), actual);
uint16_t fdn_block_count = pick_integer_be(sir, 0x10, 2);
uint32_t last_block_number = pick_integer_be(sir, 0x12, 3);
diff --git a/src/lib/formats/uniflex_dsk.h b/src/lib/formats/uniflex_dsk.h
index fad6741f533..af39a09678e 100644
--- a/src/lib/formats/uniflex_dsk.h
+++ b/src/lib/formats/uniflex_dsk.h
@@ -19,8 +19,8 @@ public:
virtual const char *name() const override;
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
void build_sector_description(const format &f, uint8_t *sectdata, desc_s *sectors, int track, int head) const override;
private:
diff --git a/src/lib/formats/upd765_dsk.cpp b/src/lib/formats/upd765_dsk.cpp
index e7118dde236..d0afab39352 100644
--- a/src/lib/formats/upd765_dsk.cpp
+++ b/src/lib/formats/upd765_dsk.cpp
@@ -10,14 +10,19 @@
#include "formats/upd765_dsk.h"
+#include "ioprocs.h"
+
upd765_format::upd765_format(const format *_formats) : file_header_skip_bytes(0), file_footer_skip_bytes(0), formats(_formats)
{
}
-int upd765_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
+int upd765_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return -1;
+
for(int i=0; formats[i].form_factor; i++) {
const format &f = formats[i];
if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
@@ -31,7 +36,7 @@ int upd765_format::find_size(io_generic *io, uint32_t form_factor, const std::ve
return -1;
}
-int upd765_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int upd765_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int type = find_size(io, form_factor, variants);
@@ -175,7 +180,7 @@ floppy_image_format_t::desc_e* upd765_format::get_desc_mfm(const format &f, int
return desc;
}
-bool upd765_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool upd765_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
int type = find_size(io, form_factor, variants);
if(type == -1)
@@ -222,7 +227,8 @@ bool upd765_format::load(io_generic *io, uint32_t form_factor, const std::vector
for(int track=0; track < f.track_count; track++)
for(int head=0; head < f.head_count; head++) {
build_sector_description(f, sectdata, sectors, track, head);
- io_generic_read(io, sectdata, file_header_skip_bytes + (track*f.head_count + head)*track_size, track_size);
+ size_t actual;
+ io.read_at(file_header_skip_bytes + (track*f.head_count + head)*track_size, sectdata, track_size, actual);
generate_track(desc, track, head, sectors, f.sector_count, total_size, image);
}
@@ -236,7 +242,7 @@ bool upd765_format::supports_save() const
return true;
}
-bool upd765_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool upd765_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
// Count the number of formats
int formats_count;
@@ -346,7 +352,8 @@ bool upd765_format::save(io_generic *io, const std::vector<uint32_t> &variants,
for(int head=0; head < f.head_count; head++) {
build_sector_description(f, sectdata, sectors, track, head);
extract_sectors(image, f, sectors, track, head);
- io_generic_write(io, sectdata, (track*f.head_count + head)*track_size, track_size);
+ size_t actual;
+ io.write_at((track*f.head_count + head)*track_size, sectdata, track_size, actual);
}
return true;
diff --git a/src/lib/formats/upd765_dsk.h b/src/lib/formats/upd765_dsk.h
index e93a0f24326..48acfc02a88 100644
--- a/src/lib/formats/upd765_dsk.h
+++ b/src/lib/formats/upd765_dsk.h
@@ -39,9 +39,9 @@ public:
// End the array with {}
upd765_format(const format *formats);
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
protected:
@@ -50,7 +50,7 @@ protected:
floppy_image_format_t::desc_e* get_desc_fm(const format &f, int &current_size, int &end_gap_index);
floppy_image_format_t::desc_e* get_desc_mfm(const format &f, int &current_size, int &end_gap_index);
- int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) const;
+ int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const;
int compute_track_size(const format &f) const;
virtual void build_sector_description(const format &d, uint8_t *sectdata, desc_s *sectors, int track, int head) const;
void check_compatibility(floppy_image *image, std::vector<int> &candidates);
diff --git a/src/lib/formats/vdk_dsk.cpp b/src/lib/formats/vdk_dsk.cpp
index 57c44f8bb29..759697f852f 100644
--- a/src/lib/formats/vdk_dsk.cpp
+++ b/src/lib/formats/vdk_dsk.cpp
@@ -12,6 +12,9 @@
#include "vdk_dsk.h"
+#include "ioprocs.h"
+
+
vdk_format::vdk_format()
{
}
@@ -31,10 +34,11 @@ const char *vdk_format::extensions() const
return "vdk";
}
-int vdk_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int vdk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
+ size_t actual;
uint8_t id[2];
- io_generic_read(io, id, 0, 2);
+ io.read_at(0, id, 2, actual);
if (id[0] == 'd' && id[1] == 'k')
return 50;
@@ -42,16 +46,21 @@ int vdk_format::identify(io_generic *io, uint32_t form_factor, const std::vector
return 0;
}
-bool vdk_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool vdk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
+ size_t actual;
+ if (io.seek(0, SEEK_SET))
+ return false;
+
uint8_t header[0x100];
- io_generic_read(io, header, 0, 0x100);
+ io.read(header, 0x100, actual);
- int header_size = header[3] * 0x100 + header[2];
- int track_count = header[8];
- int head_count = header[9];
+ int const header_size = header[3] * 0x100 + header[2];
+ int const track_count = header[8];
+ int const head_count = header[9];
- int file_offset = header_size;
+ if (io.seek(header_size, SEEK_SET))
+ return false;
for (int track = 0; track < track_count; track++)
{
@@ -72,10 +81,9 @@ bool vdk_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
sectors[i].bad_crc = false;
sectors[i].data = &sector_data[sector_offset];
- io_generic_read(io, sectors[i].data, file_offset, SECTOR_SIZE);
+ io.read(sectors[i].data, SECTOR_SIZE, actual);
sector_offset += SECTOR_SIZE;
- file_offset += SECTOR_SIZE;
}
build_wd_track_mfm(track, head, image, 100000, SECTOR_COUNT, sectors, 22, 32, 24);
@@ -85,9 +93,11 @@ bool vdk_format::load(io_generic *io, uint32_t form_factor, const std::vector<ui
return true;
}
-bool vdk_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool vdk_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
- uint64_t file_offset = 0;
+ size_t actual;
+ if (io.seek(0, SEEK_SET))
+ return false;
int track_count, head_count;
image->get_actual_geometry(track_count, head_count);
@@ -108,8 +118,7 @@ bool vdk_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
header[10] = 0;
header[11] = 0;
- io_generic_write(io, header, file_offset, sizeof(header));
- file_offset += sizeof(header);
+ io.write(header, sizeof(header), actual);
// write disk data
for (int track = 0; track < track_count; track++)
@@ -120,10 +129,7 @@ bool vdk_format::save(io_generic *io, const std::vector<uint32_t> &variants, flo
auto sectors = extract_sectors_from_bitstream_mfm_pc(bitstream);
for (int i = 0; i < SECTOR_COUNT; i++)
- {
- io_generic_write(io, sectors[FIRST_SECTOR_ID + i].data(), file_offset, SECTOR_SIZE);
- file_offset += SECTOR_SIZE;
- }
+ io.write(sectors[FIRST_SECTOR_ID + i].data(), SECTOR_SIZE, actual);
}
}
diff --git a/src/lib/formats/vdk_dsk.h b/src/lib/formats/vdk_dsk.h
index 94347b326f6..797d2644972 100644
--- a/src/lib/formats/vdk_dsk.h
+++ b/src/lib/formats/vdk_dsk.h
@@ -25,9 +25,9 @@ public:
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
private:
diff --git a/src/lib/formats/victor9k_dsk.cpp b/src/lib/formats/victor9k_dsk.cpp
index ace1ec50933..3a142629726 100644
--- a/src/lib/formats/victor9k_dsk.cpp
+++ b/src/lib/formats/victor9k_dsk.cpp
@@ -99,6 +99,8 @@
#include "formats/victor9k_dsk.h"
+#include "ioprocs.h"
+
victor9k_format::victor9k_format()
{
@@ -119,18 +121,22 @@ const char *victor9k_format::extensions() const
return "img";
}
-int victor9k_format::find_size(io_generic *io, uint32_t form_factor)
+int victor9k_format::find_size(util::random_read &io, uint32_t form_factor)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return -1;
+
for(int i=0; formats[i].sector_count; i++) {
const format &f = formats[i];
if(size == (uint32_t) f.sector_count*f.sector_base_size*f.head_count)
return i;
}
+
return -1;
}
-int victor9k_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int victor9k_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
int type = find_size(io, form_factor);
@@ -248,19 +254,24 @@ void victor9k_format::build_sector_description(const format &f, uint8_t *sectdat
}
}
-bool victor9k_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool victor9k_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- int type = find_size(io, form_factor);
+ int const type = find_size(io, form_factor);
if(type == -1)
return false;
const format &f = formats[type];
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return false;
+
std::vector<uint8_t> img;
- img.resize(size);
+ try { img.resize(size); }
+ catch (...) { return false; }
- io_generic_read(io, &img[0], 0, size);
+ size_t actual;
+ io.read_at(0, &img[0], size, actual);
log_boot_sector(&img[0]);
@@ -392,7 +403,7 @@ const int victor9k_format::rpm[9] =
252, 267, 283, 300, 321, 342, 368, 401, 417
};
-bool victor9k_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool victor9k_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
const format &f = formats[0];
@@ -406,7 +417,8 @@ bool victor9k_format::save(io_generic *io, const std::vector<uint32_t> &variants
build_sector_description(f, sectdata, 0, sectors, sector_count);
extract_sectors(image, f, sectors, track, head, sector_count);
- io_generic_write(io, sectdata, offset, track_size);
+ size_t actual;
+ io.write_at(offset, sectdata, track_size, actual);
}
}
diff --git a/src/lib/formats/victor9k_dsk.h b/src/lib/formats/victor9k_dsk.h
index 92d1c664a5f..aafd8fdcb14 100644
--- a/src/lib/formats/victor9k_dsk.h
+++ b/src/lib/formats/victor9k_dsk.h
@@ -34,9 +34,9 @@ public:
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override { return true; }
static int get_rpm(int head, int track);
@@ -49,7 +49,7 @@ protected:
static const int speed_zone[2][80];
static const int rpm[9];
- int find_size(io_generic *io, uint32_t form_factor);
+ int find_size(util::random_read &io, uint32_t form_factor);
void log_boot_sector(uint8_t *data);
floppy_image_format_t::desc_e* get_sector_desc(const format &f, int &current_size, int sector_count);
void build_sector_description(const format &f, uint8_t *sectdata, uint32_t sect_offs, desc_s *sectors, int sector_count) const;
diff --git a/src/lib/formats/vt_dsk.cpp b/src/lib/formats/vt_dsk.cpp
index d6cc3da4521..15c6955bfcc 100644
--- a/src/lib/formats/vt_dsk.cpp
+++ b/src/lib/formats/vt_dsk.cpp
@@ -10,6 +10,9 @@
#include "formats/vt_dsk.h"
+#include "ioprocs.h"
+
+
// Zero = | 9187 |
// One = | 2237 | 6950 |
// 0.5us ~= 143
@@ -213,9 +216,11 @@ const char *vtech_dsk_format::extensions() const
return "dsk";
}
-int vtech_bin_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int vtech_bin_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- int size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return 0;
if(size == 40*16*256)
return 50;
@@ -223,14 +228,18 @@ int vtech_bin_format::identify(io_generic *io, uint32_t form_factor, const std::
return 0;
}
-int vtech_dsk_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int vtech_dsk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- int size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return 0;
+
if(size < 256)
return 0;
std::vector<uint8_t> bdata(size);
- io_generic_read(io, bdata.data(), 0, size);
+ size_t actual;
+ io.read_at(0, bdata.data(), size, actual);
// Structurally validate the presence of sector headers and data
int count_sh = 0, count_sd = 0;
@@ -246,25 +255,29 @@ int vtech_dsk_format::identify(io_generic *io, uint32_t form_factor, const std::
return count_sh >= 30*16 && count_sd >= 30*16 ? 100 : 0;
}
-bool vtech_bin_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool vtech_bin_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- int size = io_generic_size(io);
- if(size != 40*16*256)
+ uint64_t size;
+ if(io.length(size) || (size != 40*16*256))
return false;
std::vector<uint8_t> bdata(size);
- io_generic_read(io, bdata.data(), 0, size);
+ size_t actual;
+ io.read_at(0, bdata.data(), size, actual);
image_to_flux(bdata, image);
image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD);
return true;
}
-bool vtech_dsk_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool vtech_dsk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- int size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return false;
std::vector<uint8_t> bdata(size);
- io_generic_read(io, bdata.data(), 0, size);
+ size_t actual;
+ io.read_at(0, bdata.data(), size, actual);
std::vector<uint8_t> bdatax(128*16*40, 0);
@@ -327,7 +340,7 @@ bool vtech_dsk_format::load(io_generic *io, uint32_t form_factor, const std::vec
return true;
}
-bool vtech_bin_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool vtech_bin_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int tracks, heads;
image->get_maximal_geometry(tracks, heads);
@@ -335,11 +348,12 @@ bool vtech_bin_format::save(io_generic *io, const std::vector<uint32_t> &variant
return false;
auto bdata = flux_to_image(image);
- io_generic_write(io, bdata.data(), 0, bdata.size());
+ size_t actual;
+ io.write_at(0, bdata.data(), bdata.size(), actual);
return true;
}
-bool vtech_dsk_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool vtech_dsk_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
int tracks, heads;
image->get_maximal_geometry(tracks, heads);
@@ -387,7 +401,8 @@ bool vtech_dsk_format::save(io_generic *io, const std::vector<uint32_t> &variant
}
}
- io_generic_write(io, bdatax.data(), 0, bdatax.size());
+ size_t actual;
+ io.write_at(0, bdatax.data(), bdatax.size(), actual);
return true;
}
diff --git a/src/lib/formats/vt_dsk.h b/src/lib/formats/vt_dsk.h
index 739e5234a3f..4bc46871e7e 100644
--- a/src/lib/formats/vt_dsk.h
+++ b/src/lib/formats/vt_dsk.h
@@ -34,9 +34,9 @@ public:
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
};
class vtech_dsk_format : public vtech_common_format {
@@ -47,9 +47,9 @@ public:
virtual const char *description() const override;
virtual const char *extensions() const override;
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
};
extern const floppy_format_type FLOPPY_VTECH_BIN_FORMAT;
diff --git a/src/lib/formats/wd177x_dsk.cpp b/src/lib/formats/wd177x_dsk.cpp
index 22309f32a12..da900b03db5 100644
--- a/src/lib/formats/wd177x_dsk.cpp
+++ b/src/lib/formats/wd177x_dsk.cpp
@@ -10,6 +10,8 @@
#include "formats/wd177x_dsk.h"
+#include "ioprocs.h"
+
wd177x_format::wd177x_format(const format *_formats)
{
@@ -29,9 +31,12 @@ const wd177x_format::format &wd177x_format::get_track_format(const format &f, in
/*
Default implementation for find_size. May be overwritten by subclasses.
*/
-int wd177x_format::find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int wd177x_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- uint64_t size = io_generic_size(io);
+ uint64_t size;
+ if(io.length(size))
+ return -1;
+
for(int i=0; formats[i].form_factor; i++) {
const format &f = formats[i];
if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
@@ -49,15 +54,17 @@ int wd177x_format::find_size(io_generic *io, uint32_t form_factor, const std::ve
if(size == format_size)
return i;
}
+
return -1;
}
-int wd177x_format::identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants)
+int wd177x_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants)
{
- int type = find_size(io, form_factor, variants);
+ int const type = find_size(io, form_factor, variants);
if(type != -1)
return 50;
+
return 0;
}
@@ -197,9 +204,9 @@ floppy_image_format_t::desc_e* wd177x_format::get_desc_mfm(const format &f, int
return desc;
}
-bool wd177x_format::load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
+bool wd177x_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image)
{
- int type = find_size(io, form_factor, variants);
+ int const type = find_size(io, form_factor, variants);
if(type == -1)
return false;
@@ -251,7 +258,8 @@ bool wd177x_format::load(io_generic *io, uint32_t form_factor, const std::vector
build_sector_description(tf, sectdata, sectors, track, head);
int track_size = compute_track_size(tf);
- io_generic_read(io, sectdata, get_image_offset(f, head, track), track_size);
+ size_t actual;
+ io.read_at(get_image_offset(f, head, track), sectdata, track_size, actual);
generate_track(desc, track, head, sectors, tf.sector_count, total_size, image);
}
@@ -265,7 +273,7 @@ bool wd177x_format::supports_save() const
return true;
}
-bool wd177x_format::save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image)
+bool wd177x_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image)
{
// Count the number of formats
int formats_count;
@@ -377,7 +385,8 @@ bool wd177x_format::save(io_generic *io, const std::vector<uint32_t> &variants,
build_sector_description(tf, sectdata, sectors, track, head);
extract_sectors(image, tf, sectors, track, head);
int track_size = compute_track_size(tf);
- io_generic_write(io, sectdata, get_image_offset(f, head, track), track_size);
+ size_t actual;
+ io.write_at(get_image_offset(f, head, track), sectdata, track_size, actual);
}
}
diff --git a/src/lib/formats/wd177x_dsk.h b/src/lib/formats/wd177x_dsk.h
index 4cae9ffa754..a7bd92994e6 100644
--- a/src/lib/formats/wd177x_dsk.h
+++ b/src/lib/formats/wd177x_dsk.h
@@ -38,9 +38,9 @@ public:
// End the array with {}
wd177x_format(const format *formats);
- virtual int identify(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
- virtual bool load(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
- virtual bool save(io_generic *io, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image *image) override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, floppy_image *image) override;
virtual bool supports_save() const override;
protected:
@@ -51,7 +51,7 @@ protected:
virtual const wd177x_format::format &get_track_format(const format &f, int head, int track);
virtual floppy_image_format_t::desc_e* get_desc_fm(const format &f, int &current_size, int &end_gap_index);
virtual floppy_image_format_t::desc_e* get_desc_mfm(const format &f, int &current_size, int &end_gap_index);
- virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector<uint32_t> &variants);
+ virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants);
virtual int get_image_offset(const format &f, int head, int track);
virtual int get_track_dam_fm(const format &f, int head, int track);
virtual int get_track_dam_mfm(const format &f, int head, int track);
diff --git a/src/lib/util/avhuff.cpp b/src/lib/util/avhuff.cpp
index ac5cea71526..0689fe25b80 100644
--- a/src/lib/util/avhuff.cpp
+++ b/src/lib/util/avhuff.cpp
@@ -896,9 +896,9 @@ avhuff_error avhuff_decoder::decode_audio(int channels, int samples, const uint8
{
// reset and decode
if (!m_flac_decoder.reset(48000, 1, samples, source, size))
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
if (!m_flac_decoder.decode_interleaved(reinterpret_cast<int16_t *>(curdest), samples, swap_endian))
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// finish up
m_flac_decoder.finish();
diff --git a/src/lib/util/aviio.cpp b/src/lib/util/aviio.cpp
index 03014611873..3a3a1a412f6 100644
--- a/src/lib/util/aviio.cpp
+++ b/src/lib/util/aviio.cpp
@@ -1710,8 +1710,8 @@ avi_file::error avi_file_impl::read_uncompressed_video_frame(std::uint32_t frame
/* read in the data */
std::uint32_t bytes_read;
- osd_file::error const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(framenum).offset, stream->chunk(framenum).length, bytes_read);
- if (filerr != osd_file::error::NONE || bytes_read != stream->chunk(framenum).length)
+ std::error_condition const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(framenum).offset, stream->chunk(framenum).length, bytes_read);
+ if (filerr || bytes_read != stream->chunk(framenum).length)
return error::READ_ERROR;
/* validate this is good data */
@@ -1765,8 +1765,8 @@ avi_file::error avi_file_impl::read_video_frame(std::uint32_t framenum, bitmap_y
/* read in the data */
std::uint32_t bytes_read;
- osd_file::error const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(framenum).offset, stream->chunk(framenum).length, bytes_read);
- if (filerr != osd_file::error::NONE || bytes_read != stream->chunk(framenum).length)
+ std::error_condition const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(framenum).offset, stream->chunk(framenum).length, bytes_read);
+ if (filerr || bytes_read != stream->chunk(framenum).length)
return error::READ_ERROR;
/* validate this is good data */
@@ -1857,8 +1857,8 @@ avi_file::error avi_file_impl::read_sound_samples(int channel, std::uint32_t fir
return avierr;
/* read in the data */
- auto const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(chunknum).offset, stream->chunk(chunknum).length, bytes_read);
- if (filerr != osd_file::error::NONE || bytes_read != stream->chunk(chunknum).length)
+ std::error_condition const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(chunknum).offset, stream->chunk(chunknum).length, bytes_read);
+ if (filerr || bytes_read != stream->chunk(chunknum).length)
return error::READ_ERROR;
/* validate this is good data */
@@ -2085,14 +2085,15 @@ avi_file::error avi_file_impl::append_sound_samples(int channel, const std::int1
avi_file::error avi_file_impl::read_chunk_data(avi_chunk const &chunk, std::unique_ptr<std::uint8_t []> &buffer)
{
- /* allocate memory for the data */
- try { buffer.reset(new std::uint8_t[chunk.size]); }
- catch (...) { return error::NO_MEMORY; }
+ // allocate memory for the data
+ buffer.reset(new (std::nothrow) std::uint8_t[chunk.size]);
+ if (!buffer)
+ return error::NO_MEMORY;
- /* read from the file */
+ // read from the file
std::uint32_t bytes_read;
- osd_file::error const filerr = m_file->read(&buffer[0], chunk.offset + 8, chunk.size, bytes_read);
- if (filerr != osd_file::error::NONE || bytes_read != chunk.size)
+ std::error_condition const filerr = m_file->read(&buffer[0], chunk.offset + 8, chunk.size, bytes_read);
+ if (filerr || bytes_read != chunk.size)
{
buffer.reset();
return error::READ_ERROR;
@@ -2292,35 +2293,33 @@ avi_file::error avi_file_impl::find_next_list(std::uint32_t findme, const avi_ch
avi_file::error avi_file_impl::get_next_chunk_internal(const avi_chunk *parent, avi_chunk &newchunk, std::uint64_t offset)
{
- osd_file::error filerr;
- std::uint8_t buffer[12];
- std::uint32_t bytesread;
-
- /* nullptr parent implies the root */
- if (parent == nullptr)
+ // nullptr parent implies the root
+ if (!parent)
parent = &m_rootchunk;
- /* start at the current offset */
+ // start at the current offset
newchunk.offset = offset;
- /* if we're past the bounds of the parent, bail */
+ // if we're past the bounds of the parent, bail
if (newchunk.offset + 8 >= parent->offset + 8 + parent->size)
return error::END;
- /* read the header */
- filerr = m_file->read(buffer, newchunk.offset, 8, bytesread);
- if (filerr != osd_file::error::NONE || bytesread != 8)
+ // read the header
+ std::uint8_t buffer[12];
+ std::uint32_t bytesread;
+ std::error_condition filerr = m_file->read(buffer, newchunk.offset, 8, bytesread);
+ if (filerr || bytesread != 8)
return error::INVALID_DATA;
- /* fill in the new chunk */
+ // fill in the new chunk
newchunk.type = fetch_32bits(&buffer[0]);
newchunk.size = fetch_32bits(&buffer[4]);
- /* if we are a list, fetch the list type */
+ // if we are a list, fetch the list type
if (newchunk.type == CHUNKTYPE_LIST || newchunk.type == CHUNKTYPE_RIFF)
{
filerr = m_file->read(&buffer[8], newchunk.offset + 8, 4, bytesread);
- if (filerr != osd_file::error::NONE || bytesread != 4)
+ if (filerr || bytesread != 4)
return error::INVALID_DATA;
newchunk.listtype = fetch_32bits(&buffer[8]);
}
@@ -2643,16 +2642,15 @@ avi_file::error avi_file_impl::parse_indx_chunk(avi_stream &stream, avi_chunk co
/* loop over entries and create subchunks for each */
for (std::uint32_t entry = 0; entry < entries; entry++)
{
- const std::uint8_t *base = &chunkdata[24 + entry * 16];
- osd_file::error filerr;
+ std::uint8_t const *const base = &chunkdata[24 + entry * 16];
avi_chunk subchunk;
- std::uint32_t bytes_read;
- std::uint8_t buffer[8];
/* go read the subchunk */
subchunk.offset = fetch_64bits(&base[0]);
- filerr = m_file->read(buffer, subchunk.offset, sizeof(buffer), bytes_read);
- if (filerr != osd_file::error::NONE || bytes_read != sizeof(buffer))
+ std::uint32_t bytes_read;
+ std::uint8_t buffer[8];
+ std::error_condition const filerr = m_file->read(buffer, subchunk.offset, sizeof(buffer), bytes_read);
+ if (filerr || bytes_read != sizeof(buffer))
{
avierr = error::READ_ERROR;
break;
@@ -2788,8 +2786,8 @@ avi_file::error avi_file_impl::chunk_open(std::uint32_t type, std::uint32_t list
/* write the header */
std::uint32_t written;
- osd_file::error const filerr = m_file->write(buffer, m_writeoffs, sizeof(buffer), written);
- if (filerr != osd_file::error::NONE || written != sizeof(buffer))
+ std::error_condition const filerr = m_file->write(buffer, m_writeoffs, sizeof(buffer), written);
+ if (filerr || written != sizeof(buffer))
return error::WRITE_ERROR;
m_writeoffs += written;
}
@@ -2806,8 +2804,8 @@ avi_file::error avi_file_impl::chunk_open(std::uint32_t type, std::uint32_t list
/* write the header */
std::uint32_t written;
- osd_file::error const filerr = m_file->write(buffer, m_writeoffs, sizeof(buffer), written);
- if (filerr != osd_file::error::NONE || written != sizeof(buffer))
+ std::error_condition const filerr = m_file->write(buffer, m_writeoffs, sizeof(buffer), written);
+ if (filerr || written != sizeof(buffer))
return error::WRITE_ERROR;
m_writeoffs += written;
}
@@ -2846,8 +2844,8 @@ avi_file::error avi_file_impl::chunk_close()
put_32bits(&buffer[0], std::uint32_t(chunksize));
std::uint32_t written;
- osd_file::error const filerr = m_file->write(buffer, chunk.offset + 4, sizeof(buffer), written);
- if (filerr != osd_file::error::NONE || written != sizeof(buffer))
+ std::error_condition const filerr = m_file->write(buffer, chunk.offset + 4, sizeof(buffer), written);
+ if (filerr || written != sizeof(buffer))
return error::WRITE_ERROR;
}
@@ -2925,8 +2923,8 @@ avi_file::error avi_file_impl::chunk_write(std::uint32_t type, const void *data,
/* write the data */
std::uint32_t written;
- osd_file::error const filerr = m_file->write(data, m_writeoffs, length, written);
- if (filerr != osd_file::error::NONE || written != length)
+ std::error_condition const filerr = m_file->write(data, m_writeoffs, length, written);
+ if (filerr || written != length)
return error::WRITE_ERROR;
m_writeoffs += written;
@@ -3678,7 +3676,7 @@ avi_file::error avi_file::open(std::string const &filename, ptr &file)
/* open the file */
osd_file::ptr f;
std::uint64_t length;
- if (osd_file::open(filename, OPEN_FLAG_READ, f, length) != osd_file::error::NONE)
+ if (osd_file::open(filename, OPEN_FLAG_READ, f, length))
return error::CANT_OPEN_FILE;
/* allocate the file */
@@ -3731,8 +3729,8 @@ avi_file::error avi_file::create(std::string const &filename, movie_info const &
/* open the file */
osd_file::ptr f;
std::uint64_t length;
- osd_file::error const filerr = osd_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, f, length);
- if (filerr != osd_file::error::NONE)
+ std::error_condition const filerr = osd_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, f, length);
+ if (filerr)
return error::CANT_OPEN_FILE;
/* allocate the file */
diff --git a/src/lib/util/cdrom.cpp b/src/lib/util/cdrom.cpp
index 4ac1ab6e865..7510a1f9b47 100644
--- a/src/lib/util/cdrom.cpp
+++ b/src/lib/util/cdrom.cpp
@@ -19,6 +19,7 @@
#include "cdrom.h"
#include "chdcd.h"
+#include "corefile.h"
#include <cassert>
#include <cstdlib>
@@ -223,10 +224,10 @@ cdrom_file *cdrom_open(const char *inputfile)
return nullptr;
// set up the CD-ROM module and get the disc info
- chd_error err = chdcd_parse_toc(inputfile, file->cdtoc, file->track_info);
- if (err != CHDERR_NONE)
+ std::error_condition err = chdcd_parse_toc(inputfile, file->cdtoc, file->track_info);
+ if (err)
{
- fprintf(stderr, "Error reading input file: %s\n", chd_file::error_string(err));
+ fprintf(stderr, "Error reading input file: %s\n", err.message().c_str());
delete file;
return nullptr;
}
@@ -238,14 +239,15 @@ cdrom_file *cdrom_open(const char *inputfile)
for (i = 0; i < file->cdtoc.numtrks; i++)
{
- osd_file::error filerr = util::core_file::open(file->track_info.track[i].fname, OPEN_FLAG_READ, file->fhandle[i]);
- if (filerr != osd_file::error::NONE)
+ std::error_condition const filerr = util::core_file::open(file->track_info.track[i].fname, OPEN_FLAG_READ, file->fhandle[i]);
+ if (filerr)
{
fprintf(stderr, "Unable to open file: %s\n", file->track_info.track[i].fname.c_str());
cdrom_close(file);
return nullptr;
}
}
+
/* calculate the starting frame for each track, keeping in mind that CHDMAN
pads tracks out with extra frames to fit 4-frame size boundries
*/
@@ -336,8 +338,8 @@ cdrom_file *cdrom_open(chd_file *chd)
file->chd = chd;
/* read the CD-ROM metadata */
- chd_error err = cdrom_parse_metadata(chd, &file->cdtoc);
- if (err != CHDERR_NONE)
+ std::error_condition err = cdrom_parse_metadata(chd, &file->cdtoc);
+ if (err)
{
delete file;
return nullptr;
@@ -446,7 +448,7 @@ void cdrom_close(cdrom_file *file)
***************************************************************************/
/**
- * @fn chd_error read_partial_sector(cdrom_file *file, void *dest, uint32_t lbasector, uint32_t chdsector, uint32_t tracknum, uint32_t startoffs, uint32_t length)
+ * @fn std::error_condition read_partial_sector(cdrom_file *file, void *dest, uint32_t lbasector, uint32_t chdsector, uint32_t tracknum, uint32_t startoffs, uint32_t length)
*
* @brief Reads partial sector.
*
@@ -461,9 +463,9 @@ void cdrom_close(cdrom_file *file)
* @return The partial sector.
*/
-chd_error read_partial_sector(cdrom_file *file, void *dest, uint32_t lbasector, uint32_t chdsector, uint32_t tracknum, uint32_t startoffs, uint32_t length, bool phys=false)
+std::error_condition read_partial_sector(cdrom_file *file, void *dest, uint32_t lbasector, uint32_t chdsector, uint32_t tracknum, uint32_t startoffs, uint32_t length, bool phys=false)
{
- chd_error result = CHDERR_NONE;
+ std::error_condition result;
bool needswap = false;
// if this is pregap info that isn't actually in the file, just return blank data
@@ -570,14 +572,14 @@ uint32_t cdrom_read_data(cdrom_file *file, uint32_t lbasector, void *buffer, uin
if ((datatype == tracktype) || (datatype == CD_TRACK_RAW_DONTCARE))
{
- return (read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 0, file->cdtoc.tracks[tracknum].datasize, phys) == CHDERR_NONE);
+ return !read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 0, file->cdtoc.tracks[tracknum].datasize, phys);
}
else
{
// return 2048 bytes of mode 1 data from a 2352 byte mode 1 raw sector
if ((datatype == CD_TRACK_MODE1) && (tracktype == CD_TRACK_MODE1_RAW))
{
- return (read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 16, 2048, phys) == CHDERR_NONE);
+ return !read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 16, 2048, phys);
}
// return 2352 byte mode 1 raw sector from 2048 bytes of mode 1 data
@@ -593,25 +595,25 @@ uint32_t cdrom_read_data(cdrom_file *file, uint32_t lbasector, void *buffer, uin
bufptr[14] = msf&0xff;
bufptr[15] = 1; // mode 1
LOG(("CDROM: promotion of mode1/form1 sector to mode1 raw is not complete!\n"));
- return (read_partial_sector(file, bufptr+16, lbasector, chdsector, tracknum, 0, 2048, phys) == CHDERR_NONE);
+ return !read_partial_sector(file, bufptr+16, lbasector, chdsector, tracknum, 0, 2048, phys);
}
// return 2048 bytes of mode 1 data from a mode2 form1 or raw sector
if ((datatype == CD_TRACK_MODE1) && ((tracktype == CD_TRACK_MODE2_FORM1)||(tracktype == CD_TRACK_MODE2_RAW)))
{
- return (read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 24, 2048, phys) == CHDERR_NONE);
+ return !read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 24, 2048, phys);
}
// return 2048 bytes of mode 1 data from a mode2 form2 or XA sector
if ((datatype == CD_TRACK_MODE1) && (tracktype == CD_TRACK_MODE2_FORM_MIX))
{
- return (read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 8, 2048, phys) == CHDERR_NONE);
+ return !read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 8, 2048, phys);
}
// return mode 2 2336 byte data from a 2352 byte mode 1 or 2 raw sector (skip the header)
if ((datatype == CD_TRACK_MODE2) && ((tracktype == CD_TRACK_MODE1_RAW) || (tracktype == CD_TRACK_MODE2_RAW)))
{
- return (read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 16, 2336, phys) == CHDERR_NONE);
+ return !read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 16, 2336, phys);
}
LOG(("CDROM: Conversion from type %d to type %d not supported!\n", tracktype, datatype));
@@ -660,8 +662,8 @@ uint32_t cdrom_read_subcode(cdrom_file *file, uint32_t lbasector, void *buffer,
return 0;
// read the data
- chd_error err = read_partial_sector(file, buffer, lbasector, chdsector, tracknum, file->cdtoc.tracks[tracknum].datasize, file->cdtoc.tracks[tracknum].subsize);
- return (err == CHDERR_NONE);
+ std::error_condition err = read_partial_sector(file, buffer, lbasector, chdsector, tracknum, file->cdtoc.tracks[tracknum].datasize, file->cdtoc.tracks[tracknum].subsize);
+ return !err;
}
@@ -1139,21 +1141,20 @@ const char *cdrom_get_subtype_string(uint32_t subtype)
-------------------------------------------------*/
/**
- * @fn chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
+ * @fn std::error_condition cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
*
* @brief Cdrom parse metadata.
*
* @param [in,out] chd If non-null, the chd.
* @param [in,out] toc If non-null, the TOC.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
+std::error_condition cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
{
std::string metadata;
- chd_error err;
- int i;
+ std::error_condition err;
toc->flags = 0;
@@ -1168,49 +1169,49 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
/* fetch the metadata for this track */
err = chd->read_metadata(CDROM_TRACK_METADATA_TAG, toc->numtrks, metadata);
- if (err == CHDERR_NONE)
+ if (!err)
{
/* parse the metadata */
type[0] = subtype[0] = 0;
pgtype[0] = pgsub[0] = 0;
if (sscanf(metadata.c_str(), CDROM_TRACK_METADATA_FORMAT, &tracknum, type, subtype, &frames) != 4)
- return CHDERR_INVALID_DATA;
+ return chd_file::error::INVALID_DATA;
if (tracknum == 0 || tracknum > CD_MAX_TRACKS)
- return CHDERR_INVALID_DATA;
+ return chd_file::error::INVALID_DATA;
track = &toc->tracks[tracknum - 1];
}
else
{
err = chd->read_metadata(CDROM_TRACK_METADATA2_TAG, toc->numtrks, metadata);
- if (err == CHDERR_NONE)
+ if (!err)
{
/* parse the metadata */
type[0] = subtype[0] = 0;
pregap = postgap = 0;
if (sscanf(metadata.c_str(), CDROM_TRACK_METADATA2_FORMAT, &tracknum, type, subtype, &frames, &pregap, pgtype, pgsub, &postgap) != 8)
- return CHDERR_INVALID_DATA;
+ return chd_file::error::INVALID_DATA;
if (tracknum == 0 || tracknum > CD_MAX_TRACKS)
- return CHDERR_INVALID_DATA;
+ return chd_file::error::INVALID_DATA;
track = &toc->tracks[tracknum - 1];
}
else
{
err = chd->read_metadata(GDROM_OLD_METADATA_TAG, toc->numtrks, metadata);
- if (err == CHDERR_NONE)
+ if (!err)
/* legacy GDROM track was detected */
toc->flags |= CD_FLAG_GDROMLE;
else
err = chd->read_metadata(GDROM_TRACK_METADATA_TAG, toc->numtrks, metadata);
- if (err == CHDERR_NONE)
+ if (!err)
{
/* parse the metadata */
type[0] = subtype[0] = 0;
pregap = postgap = 0;
if (sscanf(metadata.c_str(), GDROM_TRACK_METADATA_FORMAT, &tracknum, type, subtype, &frames, &padframes, &pregap, pgtype, pgsub, &postgap) != 9)
- return CHDERR_INVALID_DATA;
+ return chd_file::error::INVALID_DATA;
if (tracknum == 0 || tracknum > CD_MAX_TRACKS)
- return CHDERR_INVALID_DATA;
+ return chd_file::error::INVALID_DATA;
track = &toc->tracks[tracknum - 1];
toc->flags |= CD_FLAG_GDROM;
}
@@ -1226,7 +1227,7 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
track->datasize = 0;
cdrom_convert_type_string_to_track_info(type, track);
if (track->datasize == 0)
- return CHDERR_INVALID_DATA;
+ return chd_file::error::INVALID_DATA;
/* extract the subtype and determine the subcode data size */
track->subtype = CD_SUB_NONE;
@@ -1261,21 +1262,21 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
/* if we got any tracks this way, we're done */
if (toc->numtrks > 0)
- return CHDERR_NONE;
+ return std::error_condition();
printf("toc->numtrks = %u?!\n", toc->numtrks);
/* look for old-style metadata */
std::vector<uint8_t> oldmetadata;
err = chd->read_metadata(CDROM_OLD_METADATA_TAG, 0, oldmetadata);
- if (err != CHDERR_NONE)
+ if (err)
return err;
/* reconstruct the TOC from it */
auto *mrp = reinterpret_cast<uint32_t *>(&oldmetadata[0]);
toc->numtrks = *mrp++;
- for (i = 0; i < CD_MAX_TRACKS; i++)
+ for (int i = 0; i < CD_MAX_TRACKS; i++)
{
toc->tracks[i].trktype = *mrp++;
toc->tracks[i].subtype = *mrp++;
@@ -1295,7 +1296,7 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
if (toc->numtrks > CD_MAX_TRACKS)
{
toc->numtrks = swapendian_int32(toc->numtrks);
- for (i = 0; i < CD_MAX_TRACKS; i++)
+ for (int i = 0; i < CD_MAX_TRACKS; i++)
{
toc->tracks[i].trktype = swapendian_int32(toc->tracks[i].trktype);
toc->tracks[i].subtype = swapendian_int32(toc->tracks[i].subtype);
@@ -1307,7 +1308,7 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
}
}
- return CHDERR_NONE;
+ return std::error_condition();
}
@@ -1316,19 +1317,19 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc)
-------------------------------------------------*/
/**
- * @fn chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc)
+ * @fn std::error_condition cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc)
*
* @brief Cdrom write metadata.
*
* @param [in,out] chd If non-null, the chd.
* @param toc The TOC.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc)
+std::error_condition cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc)
{
- chd_error err;
+ std::error_condition err;
/* write the metadata */
for (int i = 0; i < toc->numtrks; i++)
@@ -1363,10 +1364,10 @@ chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc)
err = chd->write_metadata(GDROM_TRACK_METADATA_TAG, i, metadata);
}
- if (err != CHDERR_NONE)
+ if (err)
return err;
}
- return CHDERR_NONE;
+ return std::error_condition();
}
/**
diff --git a/src/lib/util/cdrom.h b/src/lib/util/cdrom.h
index 27d41da845e..1847a1db83a 100644
--- a/src/lib/util/cdrom.h
+++ b/src/lib/util/cdrom.h
@@ -7,15 +7,15 @@
Generic MAME cd-rom implementation
***************************************************************************/
-
-#ifndef MAME_UTIL_CDROM_H
-#define MAME_UTIL_CDROM_H
+#ifndef MAME_LIB_UTIL_CDROM_H
+#define MAME_LIB_UTIL_CDROM_H
#pragma once
-#include "osdcore.h"
#include "chd.h"
+#include "osdcore.h"
+
/***************************************************************************
@@ -137,8 +137,8 @@ void cdrom_convert_subtype_string_to_track_info(const char *typestring, cdrom_tr
void cdrom_convert_subtype_string_to_pregap_info(const char *typestring, cdrom_track_info *info);
const char *cdrom_get_type_string(uint32_t trktype);
const char *cdrom_get_subtype_string(uint32_t subtype);
-chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc);
-chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc);
+std::error_condition cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc);
+std::error_condition cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc);
// ECC utilities
bool ecc_verify(const uint8_t *sector);
@@ -184,4 +184,4 @@ static inline uint32_t lba_to_msf_alt(int lba)
return ret;
}
-#endif // MAME_UTIL_CDROM_H
+#endif // MAME_LIB_UTIL_CDROM_H
diff --git a/src/lib/util/chd.cpp b/src/lib/util/chd.cpp
index 0de05849cdd..29792fc36df 100644
--- a/src/lib/util/chd.cpp
+++ b/src/lib/util/chd.cpp
@@ -8,20 +8,24 @@
***************************************************************************/
-#include <cassert>
-
#include "chd.h"
+
#include "avhuff.h"
-#include "hashing.h"
-#include "flac.h"
#include "cdrom.h"
+#include "corefile.h"
#include "coretmpl.h"
+#include "flac.h"
+#include "hashing.h"
+
+#include "eminline.h"
+
#include <zlib.h>
-#include <ctime>
+
+#include <cassert>
#include <cstddef>
#include <cstdlib>
+#include <ctime>
#include <new>
-#include "eminline.h"
//**************************************************************************
@@ -186,14 +190,17 @@ inline void chd_file::be_write_sha1(uint8_t *base, util::sha1_t value)
inline void chd_file::file_read(uint64_t offset, void *dest, uint32_t length)
{
// no file = failure
- if (m_file == nullptr)
- throw CHDERR_NOT_OPEN;
+ if (!m_file)
+ throw std::error_condition(error::NOT_OPEN);
// seek and read
m_file->seek(offset, SEEK_SET);
- uint32_t count = m_file->read(dest, length);
- if (count != length)
- throw CHDERR_READ_ERROR;
+ size_t count;
+ std::error_condition err = m_file->read(dest, length, count);
+ if (err)
+ throw err;
+ else if (count != length)
+ throw std::error_condition(std::errc::io_error); // TODO: revisit this error code (happens if file is cut off)
}
@@ -205,14 +212,17 @@ inline void chd_file::file_read(uint64_t offset, void *dest, uint32_t length)
inline void chd_file::file_write(uint64_t offset, const void *source, uint32_t length)
{
// no file = failure
- if (m_file == nullptr)
- throw CHDERR_NOT_OPEN;
+ if (!m_file)
+ throw std::error_condition(error::NOT_OPEN);
// seek and write
m_file->seek(offset, SEEK_SET);
- uint32_t count = m_file->write(source, length);
- if (count != length)
- throw CHDERR_WRITE_ERROR;
+ size_t count;
+ std::error_condition err = m_file->write(source, length, count);
+ if (err)
+ throw err;
+ else if (count != length)
+ throw std::error_condition(std::errc::interrupted); // can theoretically happen if write is inuterrupted by a signal
}
@@ -224,15 +234,22 @@ inline void chd_file::file_write(uint64_t offset, const void *source, uint32_t l
inline uint64_t chd_file::file_append(const void *source, uint32_t length, uint32_t alignment)
{
+ std::error_condition err;
+
// no file = failure
- if (m_file == nullptr)
- throw CHDERR_NOT_OPEN;
+ if (!m_file)
+ throw std::error_condition(error::NOT_OPEN);
// seek to the end and align if necessary
- m_file->seek(0, SEEK_END);
+ err = m_file->seek(0, SEEK_END);
+ if (err)
+ throw err;
if (alignment != 0)
{
- uint64_t offset = m_file->tell();
+ uint64_t offset;
+ err = m_file->tell(offset);
+ if (err)
+ throw err;
uint32_t delta = offset % alignment;
if (delta != 0)
{
@@ -242,20 +259,27 @@ inline uint64_t chd_file::file_append(const void *source, uint32_t length, uint3
delta = alignment - delta;
while (delta != 0)
{
- uint32_t bytes_to_write = (std::min<std::size_t>)(sizeof(buffer), delta);
- uint32_t count = m_file->write(buffer, bytes_to_write);
- if (count != bytes_to_write)
- throw CHDERR_WRITE_ERROR;
- delta -= bytes_to_write;
+ uint32_t bytes_to_write = std::min<std::size_t>(sizeof(buffer), delta);
+ size_t count;
+ err = m_file->write(buffer, bytes_to_write, count);
+ if (err)
+ throw err;
+ delta -= count;
}
}
}
// write the real data
- uint64_t offset = m_file->tell();
- uint32_t count = m_file->write(source, length);
- if (count != length)
- throw CHDERR_READ_ERROR;
+ uint64_t offset;
+ err = m_file->tell(offset);
+ if (err)
+ throw err;
+ size_t count;
+ err = m_file->write(source, length, count);
+ if (err)
+ throw err;
+ else if (count != length)
+ throw std::error_condition(std::errc::interrupted); // can theoretically happen if write is interrupted by a signal
return offset;
}
@@ -288,11 +312,8 @@ inline uint8_t chd_file::bits_for_value(uint64_t value)
*/
chd_file::chd_file()
- : m_file(nullptr),
- m_owns_file(false)
{
// reset state
- memset(m_decompressor, 0, sizeof(m_decompressor));
close();
}
@@ -311,6 +332,22 @@ chd_file::~chd_file()
}
/**
+ * @fn util::random_read chd_file::file()
+ *
+ * @brief -------------------------------------------------
+ * file - return our underlying file
+ * -------------------------------------------------.
+ *
+ * @return A random_read.
+ */
+
+util::random_read &chd_file::file()
+{
+ assert(m_file);
+ return *m_file;
+}
+
+/**
* @fn util::sha1_t chd_file::sha1()
*
* @brief -------------------------------------------------
@@ -329,7 +366,7 @@ util::sha1_t chd_file::sha1()
file_read(m_sha1_offset, rawbuf, sizeof(rawbuf));
return be_read_sha1(rawbuf);
}
- catch (chd_error &)
+ catch (std::error_condition const &)
{
// on failure, return nullptr
return util::sha1_t::null;
@@ -354,15 +391,15 @@ util::sha1_t chd_file::raw_sha1()
try
{
// determine offset within the file for data-only
- if (m_rawsha1_offset == 0)
- throw CHDERR_UNSUPPORTED_VERSION;
+ if (!m_rawsha1_offset)
+ throw std::error_condition(error::UNSUPPORTED_VERSION);
// read the big-endian version
uint8_t rawbuf[sizeof(util::sha1_t)];
file_read(m_rawsha1_offset, rawbuf, sizeof(rawbuf));
return be_read_sha1(rawbuf);
}
- catch (chd_error &)
+ catch (std::error_condition const &)
{
// on failure, return nullptr
return util::sha1_t::null;
@@ -387,15 +424,15 @@ util::sha1_t chd_file::parent_sha1()
try
{
// determine offset within the file
- if (m_parentsha1_offset == 0)
- throw CHDERR_UNSUPPORTED_VERSION;
+ if (!m_parentsha1_offset)
+ throw std::error_condition(error::UNSUPPORTED_VERSION);
// read the big-endian version
uint8_t rawbuf[sizeof(util::sha1_t)];
file_read(m_parentsha1_offset, rawbuf, sizeof(rawbuf));
return be_read_sha1(rawbuf);
}
- catch (chd_error &)
+ catch (std::error_condition const &)
{
// on failure, return nullptr
return util::sha1_t::null;
@@ -403,7 +440,7 @@ util::sha1_t chd_file::parent_sha1()
}
/**
- * @fn chd_error chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes)
+ * @fn std::error_condition chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes)
*
* @brief -------------------------------------------------
* hunk_info - return information about this hunk
@@ -413,14 +450,14 @@ util::sha1_t chd_file::parent_sha1()
* @param [in,out] compressor The compressor.
* @param [in,out] compbytes The compbytes.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes)
+std::error_condition chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes)
{
// error if invalid
if (hunknum >= m_hunkcount)
- return CHDERR_HUNK_OUT_OF_RANGE;
+ return std::error_condition(error::HUNK_OUT_OF_RANGE);
// get the map pointer
uint8_t *rawmap;
@@ -506,11 +543,11 @@ chd_error chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint
break;
default:
- return CHDERR_UNKNOWN_COMPRESSION;
+ return error::UNKNOWN_COMPRESSION;
}
break;
}
- return CHDERR_NONE;
+ return std::error_condition();
}
/**
@@ -554,8 +591,8 @@ void chd_file::set_raw_sha1(util::sha1_t rawdata)
void chd_file::set_parent_sha1(util::sha1_t parent)
{
// if no file, fail
- if (m_file == nullptr)
- throw CHDERR_INVALID_FILE;
+ if (!m_file)
+ throw std::error_condition(error::INVALID_FILE);
// create a big-endian version
uint8_t rawbuf[sizeof(util::sha1_t)];
@@ -567,7 +604,7 @@ void chd_file::set_parent_sha1(util::sha1_t parent)
}
/**
- * @fn chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4])
+ * @fn std::error_condition chd_file::create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4])
*
* @brief -------------------------------------------------
* create - create a new file with no parent using an existing opened file handle
@@ -579,14 +616,16 @@ void chd_file::set_parent_sha1(util::sha1_t parent)
* @param unitbytes The unitbytes.
* @param compression The compression.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4])
+std::error_condition chd_file::create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4])
{
// make sure we don't already have a file open
- if (m_file != nullptr)
- return CHDERR_ALREADY_OPEN;
+ if (m_file)
+ return error::ALREADY_OPEN;
+ else if (!file)
+ return std::errc::invalid_argument;
// set the header parameters
m_logicalbytes = logicalbytes;
@@ -596,13 +635,12 @@ chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_
m_parent = nullptr;
// take ownership of the file
- m_file = &file;
- m_owns_file = false;
+ m_file = std::move(file);
return create_common();
}
/**
- * @fn chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent)
+ * @fn std::error_condition chd_file::create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent)
*
* @brief -------------------------------------------------
* create - create a new file with a parent using an existing opened file handle
@@ -614,14 +652,16 @@ chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_
* @param compression The compression.
* @param [in,out] parent The parent.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent)
+std::error_condition chd_file::create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent)
{
// make sure we don't already have a file open
- if (m_file != nullptr)
- return CHDERR_ALREADY_OPEN;
+ if (m_file)
+ return error::ALREADY_OPEN;
+ else if (!file)
+ return std::errc::invalid_argument;
// set the header parameters
m_logicalbytes = logicalbytes;
@@ -631,13 +671,12 @@ chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_
m_parent = &parent;
// take ownership of the file
- m_file = &file;
- m_owns_file = false;
+ m_file = std::move(file);
return create_common();
}
/**
- * @fn chd_error chd_file::create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4])
+ * @fn std::error_condition chd_file::create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4])
*
* @brief -------------------------------------------------
* create - create a new file with no parent using a filename
@@ -649,40 +688,38 @@ chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_
* @param unitbytes The unitbytes.
* @param compression The compression.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4])
+std::error_condition chd_file::create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4])
{
// make sure we don't already have a file open
- if (m_file != nullptr)
- return CHDERR_ALREADY_OPEN;
+ if (m_file)
+ return error::ALREADY_OPEN;
// create the new file
util::core_file::ptr file;
- const osd_file::error filerr = util::core_file::open(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
- if (filerr != osd_file::error::NONE)
- return CHDERR_FILE_NOT_FOUND;
+ std::error_condition filerr = util::core_file::open(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
+ if (filerr)
+ return filerr;
+ util::random_read_write::ptr io = util::core_file_read_write(std::move(file));
+ if (!io)
+ return std::errc::not_enough_memory;
// create the file normally, then claim the file
- const chd_error chderr = create(*file, logicalbytes, hunkbytes, unitbytes, compression);
- m_owns_file = true;
+ std::error_condition chderr = create(std::move(io), logicalbytes, hunkbytes, unitbytes, compression);
// if an error happened, close and delete the file
- if (chderr != CHDERR_NONE)
+ if (chderr)
{
- file.reset();
- osd_file::remove(filename);
- }
- else
- {
- file.release();
+ io.reset();
+ osd_file::remove(std::string(filename)); // FIXME: allow osd_file to use std::string_view
}
return chderr;
}
/**
- * @fn chd_error chd_file::create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent)
+ * @fn std::error_condition chd_file::create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent)
*
* @brief -------------------------------------------------
* create - create a new file with a parent using a filename
@@ -694,40 +731,38 @@ chd_error chd_file::create(const char *filename, uint64_t logicalbytes, uint32_t
* @param compression The compression.
* @param [in,out] parent The parent.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent)
+std::error_condition chd_file::create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent)
{
// make sure we don't already have a file open
- if (m_file != nullptr)
- return CHDERR_ALREADY_OPEN;
+ if (m_file)
+ return error::ALREADY_OPEN;
// create the new file
util::core_file::ptr file;
- const osd_file::error filerr = util::core_file::open(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
- if (filerr != osd_file::error::NONE)
- return CHDERR_FILE_NOT_FOUND;
+ std::error_condition filerr = util::core_file::open(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
+ if (filerr)
+ return filerr;
+ util::random_read_write::ptr io = util::core_file_read_write(std::move(file));
+ if (!io)
+ return std::errc::not_enough_memory;
// create the file normally, then claim the file
- const chd_error chderr = create(*file, logicalbytes, hunkbytes, compression, parent);
- m_owns_file = true;
+ std::error_condition chderr = create(std::move(io), logicalbytes, hunkbytes, compression, parent);
// if an error happened, close and delete the file
- if (chderr != CHDERR_NONE)
- {
- file.reset();
- osd_file::remove(filename);
- }
- else
+ if (chderr)
{
- file.release();
+ io.reset();
+ osd_file::remove(std::string(filename)); // FIXME: allow osd_file to use std::string_view
}
return chderr;
}
/**
- * @fn chd_error chd_file::open(const char *filename, bool writeable, chd_file *parent)
+ * @fn std::error_condition chd_file::open(std::string_view filename, bool writeable, chd_file *parent)
*
* @brief -------------------------------------------------
* open - open an existing file for read or read/write
@@ -737,35 +772,36 @@ chd_error chd_file::create(const char *filename, uint64_t logicalbytes, uint32_t
* @param writeable true if writeable.
* @param [in,out] parent If non-null, the parent.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::open(const char *filename, bool writeable, chd_file *parent)
+std::error_condition chd_file::open(std::string_view filename, bool writeable, chd_file *parent)
{
// make sure we don't already have a file open
- if (m_file != nullptr)
- return CHDERR_ALREADY_OPEN;
+ if (m_file)
+ return error::ALREADY_OPEN;
// open the file
const uint32_t openflags = writeable ? (OPEN_FLAG_READ | OPEN_FLAG_WRITE) : OPEN_FLAG_READ;
util::core_file::ptr file;
- const osd_file::error filerr = util::core_file::open(filename, openflags, file);
- if (filerr != osd_file::error::NONE)
- return CHDERR_FILE_NOT_FOUND;
+ std::error_condition filerr = util::core_file::open(filename, openflags, file);
+ if (filerr)
+ return filerr;
+ util::random_read_write::ptr io = util::core_file_read_write(std::move(file));
+ if (!io)
+ return std::errc::not_enough_memory;
// now open the CHD
- chd_error err = open(*file, writeable, parent);
- if (err != CHDERR_NONE)
+ std::error_condition err = open(std::move(io), writeable, parent);
+ if (err)
return err;
// we now own this file
- file.release();
- m_owns_file = true;
return err;
}
/**
- * @fn chd_error chd_file::open(util::core_file &file, bool writeable, chd_file *parent)
+ * @fn std::error_condition chd_file::open(util::random_read_write::ptr &&file, bool writeable, chd_file *parent)
*
* @brief -------------------------------------------------
* open - open an existing file for read or read/write
@@ -775,18 +811,19 @@ chd_error chd_file::open(const char *filename, bool writeable, chd_file *parent)
* @param writeable true if writeable.
* @param [in,out] parent If non-null, the parent.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::open(util::core_file &file, bool writeable, chd_file *parent)
+std::error_condition chd_file::open(util::random_read_write::ptr &&file, bool writeable, chd_file *parent)
{
// make sure we don't already have a file open
- if (m_file != nullptr)
- return CHDERR_ALREADY_OPEN;
+ if (m_file)
+ return error::ALREADY_OPEN;
+ else if (!file)
+ return std::errc::invalid_argument;
// open the file
- m_file = &file;
- m_owns_file = false;
+ m_file = std::move(file);
m_parent = parent;
m_cachehunk = ~0;
return open_common(writeable);
@@ -803,10 +840,7 @@ chd_error chd_file::open(util::core_file &file, bool writeable, chd_file *parent
void chd_file::close()
{
// reset file characteristics
- if (m_owns_file && m_file)
- delete m_file;
- m_file = nullptr;
- m_owns_file = false;
+ m_file.reset();
m_allow_reads = false;
m_allow_writes = false;
@@ -836,10 +870,7 @@ void chd_file::close()
// reset compression management
for (auto & elem : m_decompressor)
- {
- delete elem;
- elem = nullptr;
- }
+ elem.reset();
m_compressed.clear();
// reset caching
@@ -848,7 +879,7 @@ void chd_file::close()
}
/**
- * @fn chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer)
+ * @fn std::error_condition chd_file::read_hunk(uint32_t hunknum, void *buffer)
*
* @brief -------------------------------------------------
* read - read a single hunk from the CHD file
@@ -870,18 +901,18 @@ void chd_file::close()
* @return The hunk.
*/
-chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer)
+std::error_condition chd_file::read_hunk(uint32_t hunknum, void *buffer)
{
// wrap this for clean reporting
try
{
// punt if no file
- if (m_file == nullptr)
- throw CHDERR_NOT_OPEN;
+ if (!m_file)
+ throw std::error_condition(error::NOT_OPEN);
// return an error if out of range
if (hunknum >= m_hunkcount)
- throw CHDERR_HUNK_OUT_OF_RANGE;
+ throw std::error_condition(error::HUNK_OUT_OF_RANGE);
// get a pointer to the map entry
uint64_t blockoffs;
@@ -904,29 +935,29 @@ chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer)
file_read(blockoffs, &m_compressed[0], blocklen);
m_decompressor[0]->decompress(&m_compressed[0], blocklen, dest, m_hunkbytes);
if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && dest != nullptr && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
- throw CHDERR_DECOMPRESSION_ERROR;
- return CHDERR_NONE;
+ throw std::error_condition(error::DECOMPRESSION_ERROR);
+ return std::error_condition();
case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
file_read(blockoffs, dest, m_hunkbytes);
if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
- throw CHDERR_DECOMPRESSION_ERROR;
- return CHDERR_NONE;
+ throw std::error_condition(error::DECOMPRESSION_ERROR);
+ return std::error_condition();
case V34_MAP_ENTRY_TYPE_MINI:
be_write(dest, blockoffs, 8);
for (uint32_t bytes = 8; bytes < m_hunkbytes; bytes++)
dest[bytes] = dest[bytes - 8];
if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
- throw CHDERR_DECOMPRESSION_ERROR;
- return CHDERR_NONE;
+ throw std::error_condition(error::DECOMPRESSION_ERROR);
+ return std::error_condition();
case V34_MAP_ENTRY_TYPE_SELF_HUNK:
return read_hunk(blockoffs, dest);
case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
if (m_parent_missing)
- throw CHDERR_REQUIRES_PARENT;
+ throw std::error_condition(error::REQUIRES_PARENT);
return m_parent->read_hunk(blockoffs, dest);
}
break;
@@ -942,12 +973,12 @@ chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer)
if (blockoffs != 0)
file_read(blockoffs, dest, m_hunkbytes);
else if (m_parent_missing)
- throw CHDERR_REQUIRES_PARENT;
+ throw std::error_condition(error::REQUIRES_PARENT);
else if (m_parent != nullptr)
m_parent->read_hunk(hunknum, dest);
else
memset(dest, 0, m_hunkbytes);
- return CHDERR_NONE;
+ return std::error_condition();
}
// compressed case
@@ -963,41 +994,40 @@ chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer)
file_read(blockoffs, &m_compressed[0], blocklen);
m_decompressor[rawmap[0]]->decompress(&m_compressed[0], blocklen, dest, m_hunkbytes);
if (!m_decompressor[rawmap[0]]->lossy() && dest != nullptr && util::crc16_creator::simple(dest, m_hunkbytes) != blockcrc)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(error::DECOMPRESSION_ERROR);
if (m_decompressor[rawmap[0]]->lossy() && util::crc16_creator::simple(&m_compressed[0], blocklen) != blockcrc)
- throw CHDERR_DECOMPRESSION_ERROR;
- return CHDERR_NONE;
+ throw std::error_condition(error::DECOMPRESSION_ERROR);
+ return std::error_condition();
case COMPRESSION_NONE:
file_read(blockoffs, dest, m_hunkbytes);
if (util::crc16_creator::simple(dest, m_hunkbytes) != blockcrc)
- throw CHDERR_DECOMPRESSION_ERROR;
- return CHDERR_NONE;
+ throw std::error_condition(error::DECOMPRESSION_ERROR);
+ return std::error_condition();
case COMPRESSION_SELF:
return read_hunk(blockoffs, dest);
case COMPRESSION_PARENT:
if (m_parent_missing)
- throw CHDERR_REQUIRES_PARENT;
+ throw std::error_condition(error::REQUIRES_PARENT);
return m_parent->read_bytes(uint64_t(blockoffs) * uint64_t(m_parent->unit_bytes()), dest, m_hunkbytes);
}
break;
}
// if we get here, something was wrong
- throw CHDERR_READ_ERROR;
+ throw std::error_condition(std::errc::io_error);
}
-
- // just return errors
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
+ // just return errors
return err;
}
}
/**
- * @fn chd_error chd_file::write_hunk(uint32_t hunknum, const void *buffer)
+ * @fn std::error_condition chd_file::write_hunk(uint32_t hunknum, const void *buffer)
*
* @brief -------------------------------------------------
* write - write a single hunk to the CHD file
@@ -1012,29 +1042,29 @@ chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer)
* @param hunknum The hunknum.
* @param buffer The buffer.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::write_hunk(uint32_t hunknum, const void *buffer)
+std::error_condition chd_file::write_hunk(uint32_t hunknum, const void *buffer)
{
// wrap this for clean reporting
try
{
// punt if no file
- if (m_file == nullptr)
- throw CHDERR_NOT_OPEN;
+ if (!m_file)
+ throw std::error_condition(error::NOT_OPEN);
// return an error if out of range
if (hunknum >= m_hunkcount)
- throw CHDERR_HUNK_OUT_OF_RANGE;
+ throw std::error_condition(error::HUNK_OUT_OF_RANGE);
// if not writeable, fail
if (!m_allow_writes)
- throw CHDERR_FILE_NOT_WRITEABLE;
+ throw std::error_condition(error::FILE_NOT_WRITEABLE);
// uncompressed writes only via this interface
if (compressed())
- throw CHDERR_FILE_NOT_WRITEABLE;
+ throw std::error_condition(error::FILE_NOT_WRITEABLE);
// see if we have allocated the space on disk for this hunk
uint8_t *rawmap = &m_rawmap[hunknum * 4];
@@ -1055,7 +1085,7 @@ chd_error chd_file::write_hunk(uint32_t hunknum, const void *buffer)
// if it's all zeros, do nothing more
if (all_zeros)
- return CHDERR_NONE;
+ return std::error_condition();
// append new data to the end of the file, aligning the first chunk
rawentry = file_append(buffer, m_hunkbytes, m_hunkbytes) / m_hunkbytes;
@@ -1068,22 +1098,22 @@ chd_error chd_file::write_hunk(uint32_t hunknum, const void *buffer)
if (hunknum == m_cachehunk && buffer != &m_cache[0])
memcpy(&m_cache[0], buffer, m_hunkbytes);
}
-
- // otherwise, just overwrite
else
+ {
+ // otherwise, just overwrite
file_write(uint64_t(rawentry) * uint64_t(m_hunkbytes), buffer, m_hunkbytes);
- return CHDERR_NONE;
+ }
+ return std::error_condition();
}
-
- // just return errors
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
+ // just return errors
return err;
}
}
/**
- * @fn chd_error chd_file::read_units(uint64_t unitnum, void *buffer, uint32_t count)
+ * @fn std::error_condition chd_file::read_units(uint64_t unitnum, void *buffer, uint32_t count)
*
* @brief -------------------------------------------------
* read_units - read the given number of units from the CHD
@@ -1096,13 +1126,13 @@ chd_error chd_file::write_hunk(uint32_t hunknum, const void *buffer)
* @return The units.
*/
-chd_error chd_file::read_units(uint64_t unitnum, void *buffer, uint32_t count)
+std::error_condition chd_file::read_units(uint64_t unitnum, void *buffer, uint32_t count)
{
return read_bytes(unitnum * uint64_t(m_unitbytes), buffer, count * m_unitbytes);
}
/**
- * @fn chd_error chd_file::write_units(uint64_t unitnum, const void *buffer, uint32_t count)
+ * @fn std::error_condition chd_file::write_units(uint64_t unitnum, const void *buffer, uint32_t count)
*
* @brief -------------------------------------------------
* write_units - write the given number of units to the CHD
@@ -1112,16 +1142,16 @@ chd_error chd_file::read_units(uint64_t unitnum, void *buffer, uint32_t count)
* @param buffer The buffer.
* @param count Number of.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::write_units(uint64_t unitnum, const void *buffer, uint32_t count)
+std::error_condition chd_file::write_units(uint64_t unitnum, const void *buffer, uint32_t count)
{
return write_bytes(unitnum * uint64_t(m_unitbytes), buffer, count * m_unitbytes);
}
/**
- * @fn chd_error chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes)
+ * @fn std::error_condition chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes)
*
* @brief -------------------------------------------------
* read_bytes - read from the CHD at a byte level, using the cache to handle partial
@@ -1135,7 +1165,7 @@ chd_error chd_file::write_units(uint64_t unitnum, const void *buffer, uint32_t c
* @return The bytes.
*/
-chd_error chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes)
+std::error_condition chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes)
{
// iterate over hunks
uint32_t first_hunk = offset / m_hunkbytes;
@@ -1148,7 +1178,7 @@ chd_error chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes)
uint32_t endoffs = (curhunk == last_hunk) ? ((offset + bytes - 1) % m_hunkbytes) : (m_hunkbytes - 1);
// if it's a full block, just read directly from disk unless it's the cached hunk
- chd_error err = CHDERR_NONE;
+ std::error_condition err;
if (startoffs == 0 && endoffs == m_hunkbytes - 1 && curhunk != m_cachehunk)
err = read_hunk(curhunk, dest);
@@ -1158,7 +1188,7 @@ chd_error chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes)
if (curhunk != m_cachehunk)
{
err = read_hunk(curhunk, &m_cache[0]);
- if (err != CHDERR_NONE)
+ if (err)
return err;
m_cachehunk = curhunk;
}
@@ -1166,15 +1196,15 @@ chd_error chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes)
}
// handle errors and advance
- if (err != CHDERR_NONE)
+ if (err)
return err;
dest += endoffs + 1 - startoffs;
}
- return CHDERR_NONE;
+ return std::error_condition();
}
/**
- * @fn chd_error chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t bytes)
+ * @fn std::error_condition chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t bytes)
*
* @brief -------------------------------------------------
* write_bytes - write to the CHD at a byte level, using the cache to handle partial
@@ -1185,10 +1215,10 @@ chd_error chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes)
* @param buffer The buffer.
* @param bytes The bytes.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t bytes)
+std::error_condition chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t bytes)
{
// iterate over hunks
uint32_t first_hunk = offset / m_hunkbytes;
@@ -1201,7 +1231,7 @@ chd_error chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t by
uint32_t endoffs = (curhunk == last_hunk) ? ((offset + bytes - 1) % m_hunkbytes) : (m_hunkbytes - 1);
// if it's a full block, just write directly to disk unless it's the cached hunk
- chd_error err = CHDERR_NONE;
+ std::error_condition err;
if (startoffs == 0 && endoffs == m_hunkbytes - 1 && curhunk != m_cachehunk)
err = write_hunk(curhunk, source);
@@ -1211,7 +1241,7 @@ chd_error chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t by
if (curhunk != m_cachehunk)
{
err = read_hunk(curhunk, &m_cache[0]);
- if (err != CHDERR_NONE)
+ if (err)
return err;
m_cachehunk = curhunk;
}
@@ -1220,15 +1250,15 @@ chd_error chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t by
}
// handle errors and advance
- if (err != CHDERR_NONE)
+ if (err)
return err;
source += endoffs + 1 - startoffs;
}
- return CHDERR_NONE;
+ return std::error_condition();
}
/**
- * @fn chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output)
+ * @fn std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output)
*
* @brief -------------------------------------------------
* read_metadata - read the indexed metadata of the given type
@@ -1244,7 +1274,7 @@ chd_error chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t by
* @return The metadata.
*/
-chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output)
+std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output)
{
// wrap this for clean reporting
try
@@ -1252,23 +1282,22 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind
// if we didn't find it, just return
metadata_entry metaentry;
if (!metadata_find(searchtag, searchindex, metaentry))
- throw CHDERR_METADATA_NOT_FOUND;
+ throw std::error_condition(error::METADATA_NOT_FOUND);
// read the metadata
output.assign(metaentry.length, '\0');
file_read(metaentry.offset + METADATA_HEADER_SIZE, &output[0], metaentry.length);
- return CHDERR_NONE;
+ return std::error_condition();
}
-
- // just return errors
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
+ // just return errors
return err;
}
}
/**
- * @fn chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output)
+ * @fn std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output)
*
* @brief Reads a metadata.
*
@@ -1282,7 +1311,7 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind
* @return The metadata.
*/
-chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output)
+std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output)
{
// wrap this for clean reporting
try
@@ -1290,23 +1319,22 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind
// if we didn't find it, just return
metadata_entry metaentry;
if (!metadata_find(searchtag, searchindex, metaentry))
- throw CHDERR_METADATA_NOT_FOUND;
+ throw std::error_condition(error::METADATA_NOT_FOUND);
// read the metadata
output.resize(metaentry.length);
file_read(metaentry.offset + METADATA_HEADER_SIZE, &output[0], metaentry.length);
- return CHDERR_NONE;
+ return std::error_condition();
}
-
- // just return errors
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
+ // just return errors
return err;
}
}
/**
- * @fn chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen)
+ * @fn std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen)
*
* @brief Reads a metadata.
*
@@ -1322,7 +1350,7 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind
* @return The metadata.
*/
-chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen)
+std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen)
{
// wrap this for clean reporting
try
@@ -1330,23 +1358,22 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind
// if we didn't find it, just return
metadata_entry metaentry;
if (!metadata_find(searchtag, searchindex, metaentry))
- throw CHDERR_METADATA_NOT_FOUND;
+ throw std::error_condition(error::METADATA_NOT_FOUND);
// read the metadata
resultlen = metaentry.length;
file_read(metaentry.offset + METADATA_HEADER_SIZE, output, std::min(outputlen, resultlen));
- return CHDERR_NONE;
+ return std::error_condition();
}
-
- // just return errors
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
+ // just return errors
return err;
}
}
/**
- * @fn chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output, chd_metadata_tag &resulttag, uint8_t &resultflags)
+ * @fn std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output, chd_metadata_tag &resulttag, uint8_t &resultflags)
*
* @brief Reads a metadata.
*
@@ -1362,7 +1389,7 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind
* @return The metadata.
*/
-chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output, chd_metadata_tag &resulttag, uint8_t &resultflags)
+std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output, chd_metadata_tag &resulttag, uint8_t &resultflags)
{
// wrap this for clean reporting
try
@@ -1370,25 +1397,24 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind
// if we didn't find it, just return
metadata_entry metaentry;
if (!metadata_find(searchtag, searchindex, metaentry))
- throw CHDERR_METADATA_NOT_FOUND;
+ throw std::error_condition(error::METADATA_NOT_FOUND);
// read the metadata
output.resize(metaentry.length);
file_read(metaentry.offset + METADATA_HEADER_SIZE, &output[0], metaentry.length);
resulttag = metaentry.metatag;
resultflags = metaentry.flags;
- return CHDERR_NONE;
+ return std::error_condition();
}
-
- // just return errors
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
+ // just return errors
return err;
}
}
/**
- * @fn chd_error chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags)
+ * @fn std::error_condition chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags)
*
* @brief -------------------------------------------------
* write_metadata - write the indexed metadata of the given type
@@ -1400,17 +1426,17 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind
* @param inputlen The inputlen.
* @param flags The flags.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags)
+std::error_condition chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags)
{
// wrap this for clean reporting
try
{
// must write at least 1 byte and no more than 16MB
if (inputlen < 1 || inputlen >= 16 * 1024 * 1024)
- return CHDERR_INVALID_PARAMETER;
+ return std::error_condition(std::errc::invalid_argument);
// find the entry if it already exists
metadata_entry metaentry;
@@ -1459,18 +1485,17 @@ chd_error chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex,
// update the hash
metadata_update_hash();
- return CHDERR_NONE;
+ return std::error_condition();
}
-
- // return any errors
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
+ // return any errors
return err;
}
}
/**
- * @fn chd_error chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex)
+ * @fn std::error_condition chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex)
*
* @brief -------------------------------------------------
* delete_metadata - remove the given metadata from the list
@@ -1482,10 +1507,10 @@ chd_error chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex,
* @param metatag The metatag.
* @param metaindex The metaindex.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex)
+std::error_condition chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex)
{
// wrap this for clean reporting
try
@@ -1493,22 +1518,21 @@ chd_error chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex
// find the entry
metadata_entry metaentry;
if (!metadata_find(metatag, metaindex, metaentry))
- throw CHDERR_METADATA_NOT_FOUND;
+ throw std::error_condition(error::METADATA_NOT_FOUND);
// point the previous to the next, unlinking us
metadata_set_previous_next(metaentry.prev, metaentry.next);
- return CHDERR_NONE;
+ return std::error_condition();
}
-
- // return any errors
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
+ // return any errors
return err;
}
}
/**
- * @fn chd_error chd_file::clone_all_metadata(chd_file &source)
+ * @fn std::error_condition chd_file::clone_all_metadata(chd_file &source)
*
* @brief -------------------------------------------------
* clone_all_metadata - clone the metadata from one CHD to a second
@@ -1518,10 +1542,10 @@ chd_error chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex
*
* @param [in,out] source Another instance to copy.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::clone_all_metadata(chd_file &source)
+std::error_condition chd_file::clone_all_metadata(chd_file &source)
{
// wrap this for clean reporting
try
@@ -1540,16 +1564,15 @@ chd_error chd_file::clone_all_metadata(chd_file &source)
source.file_read(metaentry.offset + METADATA_HEADER_SIZE, &filedata[0], metaentry.length);
// write it to the destination
- chd_error err = write_metadata(metaentry.metatag, (uint32_t)-1, &filedata[0], metaentry.length, metaentry.flags);
- if (err != CHDERR_NONE)
+ std::error_condition err = write_metadata(metaentry.metatag, (uint32_t)-1, &filedata[0], metaentry.length, metaentry.flags);
+ if (err)
throw err;
}
- return CHDERR_NONE;
+ return std::error_condition();
}
-
- // return any errors
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
+ // return any errors
return err;
}
}
@@ -1607,7 +1630,7 @@ util::sha1_t chd_file::compute_overall_sha1(util::sha1_t rawsha1)
}
/**
- * @fn chd_error chd_file::codec_configure(chd_codec_type codec, int param, void *config)
+ * @fn std::error_condition chd_file::codec_configure(chd_codec_type codec, int param, void *config)
*
* @brief -------------------------------------------------
* codec_config - set internal codec parameters
@@ -1617,10 +1640,10 @@ util::sha1_t chd_file::compute_overall_sha1(util::sha1_t rawsha1)
* @param param The parameter.
* @param [in,out] config If non-null, the configuration.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::codec_configure(chd_codec_type codec, int param, void *config)
+std::error_condition chd_file::codec_configure(chd_codec_type codec, int param, void *config)
{
// wrap this for clean reporting
try
@@ -1630,14 +1653,13 @@ chd_error chd_file::codec_configure(chd_codec_type codec, int param, void *confi
if (m_compression[codecnum] == codec)
{
m_decompressor[codecnum]->configure(param, config);
- return CHDERR_NONE;
+ return std::error_condition();
}
- return CHDERR_INVALID_PARAMETER;
+ return std::errc::invalid_argument;
}
-
- // return any errors
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
+ // return any errors
return err;
}
}
@@ -1654,44 +1676,49 @@ chd_error chd_file::codec_configure(chd_codec_type codec, int param, void *confi
* @return null if it fails, else a char*.
*/
-const char *chd_file::error_string(chd_error err)
+std::error_category const &chd_category() noexcept
{
- switch (err)
+ class chd_category_impl : public std::error_category
{
- case CHDERR_NONE: return "no error";
- case CHDERR_NO_INTERFACE: return "no drive interface";
- case CHDERR_OUT_OF_MEMORY: return "out of memory";
- case CHDERR_NOT_OPEN: return "file not open";
- case CHDERR_ALREADY_OPEN: return "file already open";
- case CHDERR_INVALID_FILE: return "invalid file";
- case CHDERR_INVALID_PARAMETER: return "invalid parameter";
- case CHDERR_INVALID_DATA: return "invalid data";
- case CHDERR_FILE_NOT_FOUND: return "file not found";
- case CHDERR_REQUIRES_PARENT: return "requires parent";
- case CHDERR_FILE_NOT_WRITEABLE: return "file not writeable";
- case CHDERR_READ_ERROR: return "read error";
- case CHDERR_WRITE_ERROR: return "write error";
- case CHDERR_CODEC_ERROR: return "codec error";
- case CHDERR_INVALID_PARENT: return "invalid parent";
- case CHDERR_HUNK_OUT_OF_RANGE: return "hunk out of range";
- case CHDERR_DECOMPRESSION_ERROR: return "decompression error";
- case CHDERR_COMPRESSION_ERROR: return "compression error";
- case CHDERR_CANT_CREATE_FILE: return "can't create file";
- case CHDERR_CANT_VERIFY: return "can't verify file";
- case CHDERR_NOT_SUPPORTED: return "operation not supported";
- case CHDERR_METADATA_NOT_FOUND: return "can't find metadata";
- case CHDERR_INVALID_METADATA_SIZE: return "invalid metadata size";
- case CHDERR_UNSUPPORTED_VERSION: return "mismatched DIFF and CHD or unsupported CHD version";
- case CHDERR_VERIFY_INCOMPLETE: return "incomplete verify";
- case CHDERR_INVALID_METADATA: return "invalid metadata";
- case CHDERR_INVALID_STATE: return "invalid state";
- case CHDERR_OPERATION_PENDING: return "operation pending";
- case CHDERR_UNSUPPORTED_FORMAT: return "unsupported format";
- case CHDERR_UNKNOWN_COMPRESSION: return "unknown compression type";
- case CHDERR_WALKING_PARENT: return "currently examining parent";
- case CHDERR_COMPRESSING: return "currently compressing";
- default: return "undocumented error";
- }
+ virtual char const *name() const noexcept override { return "chd"; }
+
+ virtual std::string message(int condition) const override
+ {
+ using namespace std::literals;
+ static std::string_view const s_messages[] = {
+ "No error"sv,
+ "No drive interface"sv,
+ "File not open"sv,
+ "File already open"sv,
+ "Invalid file"sv,
+ "Invalid data"sv,
+ "Requires parent"sv,
+ "File not writeable"sv,
+ "Codec error"sv,
+ "Invalid parent"sv,
+ "Hunk out of range"sv,
+ "Decompression error"sv,
+ "Compression error"sv,
+ "Can't verify file"sv,
+ "Can't find metadata"sv,
+ "Invalid metadata size"sv,
+ "Mismatched DIFF and CHD or unsupported CHD version"sv,
+ "Incomplete verify"sv,
+ "Invalid metadata"sv,
+ "Invalid state"sv,
+ "Operation pending"sv,
+ "Unsupported format"sv,
+ "Unknown compression type"sv,
+ "Currently examining parent"sv,
+ "Currently compressing"sv };
+ if ((0 <= condition) && (std::size(s_messages) > condition))
+ return std::string(s_messages[condition]);
+ else
+ return "Unknown error"s;
+ }
+ };
+ static chd_category_impl const s_chd_category_instance;
+ return s_chd_category_instance;
}
@@ -1716,15 +1743,15 @@ uint32_t chd_file::guess_unitbytes()
// look for hard disk metadata; if found, then the unit size == sector size
std::string metadata;
int i0, i1, i2, i3;
- if (read_metadata(HARD_DISK_METADATA_TAG, 0, metadata) == CHDERR_NONE && sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, &i0, &i1, &i2, &i3) == 4)
+ if (!read_metadata(HARD_DISK_METADATA_TAG, 0, metadata) && sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, &i0, &i1, &i2, &i3) == 4)
return i3;
// look for CD-ROM metadata; if found, then the unit size == CD frame size
- if (read_metadata(CDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
- read_metadata(CDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
- read_metadata(CDROM_TRACK_METADATA2_TAG, 0, metadata) == CHDERR_NONE ||
- read_metadata(GDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE ||
- read_metadata(GDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE)
+ if (!read_metadata(CDROM_OLD_METADATA_TAG, 0, metadata) ||
+ !read_metadata(CDROM_TRACK_METADATA_TAG, 0, metadata) ||
+ !read_metadata(CDROM_TRACK_METADATA2_TAG, 0, metadata) ||
+ !read_metadata(GDROM_OLD_METADATA_TAG, 0, metadata) ||
+ !read_metadata(GDROM_TRACK_METADATA_TAG, 0, metadata))
return CD_FRAME_SIZE;
// otherwise, just map 1:1 with the hunk size
@@ -1751,7 +1778,7 @@ void chd_file::parse_v3_header(uint8_t *rawheader, util::sha1_t &parentsha1)
{
// verify header length
if (be_read(&rawheader[8], 4) != V3_HEADER_SIZE)
- throw CHDERR_INVALID_FILE;
+ throw std::error_condition(error::INVALID_FILE);
// extract core info
m_logicalbytes = be_read(&rawheader[28], 8);
@@ -1771,7 +1798,7 @@ void chd_file::parse_v3_header(uint8_t *rawheader, util::sha1_t &parentsha1)
case 1: m_compression[0] = CHD_CODEC_ZLIB; break;
case 2: m_compression[0] = CHD_CODEC_ZLIB; break;
case 3: m_compression[0] = CHD_CODEC_AVHUFF; break;
- default: throw CHDERR_UNKNOWN_COMPRESSION;
+ default: throw std::error_condition(error::UNKNOWN_COMPRESSION);
}
m_compression[1] = m_compression[2] = m_compression[3] = CHD_CODEC_NONE;
@@ -1814,7 +1841,7 @@ void chd_file::parse_v4_header(uint8_t *rawheader, util::sha1_t &parentsha1)
{
// verify header length
if (be_read(&rawheader[8], 4) != V4_HEADER_SIZE)
- throw CHDERR_INVALID_FILE;
+ throw std::error_condition(error::INVALID_FILE);
// extract core info
m_logicalbytes = be_read(&rawheader[28], 8);
@@ -1834,7 +1861,7 @@ void chd_file::parse_v4_header(uint8_t *rawheader, util::sha1_t &parentsha1)
case 1: m_compression[0] = CHD_CODEC_ZLIB; break;
case 2: m_compression[0] = CHD_CODEC_ZLIB; break;
case 3: m_compression[0] = CHD_CODEC_AVHUFF; break;
- default: throw CHDERR_UNKNOWN_COMPRESSION;
+ default: throw std::error_condition(error::UNKNOWN_COMPRESSION);
}
m_compression[1] = m_compression[2] = m_compression[3] = CHD_CODEC_NONE;
@@ -1874,7 +1901,7 @@ void chd_file::parse_v5_header(uint8_t *rawheader, util::sha1_t &parentsha1)
{
// verify header length
if (be_read(&rawheader[8], 4) != V5_HEADER_SIZE)
- throw CHDERR_INVALID_FILE;
+ throw std::error_condition(error::INVALID_FILE);
// extract core info
m_logicalbytes = be_read(&rawheader[32], 8);
@@ -1908,7 +1935,7 @@ void chd_file::parse_v5_header(uint8_t *rawheader, util::sha1_t &parentsha1)
}
/**
- * @fn chd_error chd_file::compress_v5_map()
+ * @fn std::error_condition chd_file::compress_v5_map()
*
* @brief -------------------------------------------------
* compress_v5_map - compress the v5 map and write it to the end of the file
@@ -1917,10 +1944,10 @@ void chd_file::parse_v5_header(uint8_t *rawheader, util::sha1_t &parentsha1)
* @exception CHDERR_COMPRESSION_ERROR Thrown when a chderr compression error error
* condition occurs.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::compress_v5_map()
+std::error_condition chd_file::compress_v5_map()
{
try
{
@@ -2015,10 +2042,10 @@ chd_error chd_file::compress_v5_map()
bitstream_out bitbuf(&compressed[16], compressed.size() - 16);
huffman_error err = encoder.compute_tree_from_histo();
if (err != HUFFERR_NONE)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(error::COMPRESSION_ERROR);
err = encoder.export_tree_rle(bitbuf);
if (err != HUFFERR_NONE)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(error::COMPRESSION_ERROR);
// encode the data
for (uint8_t *src = &compression_rle[0]; src < dest; src++)
@@ -2113,9 +2140,9 @@ chd_error chd_file::compress_v5_map()
uint8_t rawbuf[sizeof(uint64_t)];
be_write(rawbuf, m_mapoffset, 8);
file_write(m_mapoffset_offset, rawbuf, sizeof(rawbuf));
- return CHDERR_NONE;
+ return std::error_condition();
}
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
return err;
}
@@ -2160,7 +2187,7 @@ void chd_file::decompress_v5_map()
huffman_decoder<16, 8> decoder;
huffman_error err = decoder.import_tree_rle(bitbuf);
if (err != HUFFERR_NONE)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(error::DECOMPRESSION_ERROR);
uint8_t lastcomp = 0;
int repcount = 0;
for (int hunknum = 0; hunknum < m_hunkcount; hunknum++)
@@ -2244,11 +2271,11 @@ void chd_file::decompress_v5_map()
// verify the final CRC
if (util::crc16_creator::simple(&m_rawmap[0], m_hunkcount * 12) != mapcrc)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(error::DECOMPRESSION_ERROR);
}
/**
- * @fn chd_error chd_file::create_common()
+ * @fn std::error_condition chd_file::create_common()
*
* @brief -------------------------------------------------
* create_common - command path when creating a new CHD file
@@ -2264,7 +2291,7 @@ void chd_file::decompress_v5_map()
* @return The new common.
*/
-chd_error chd_file::create_common()
+std::error_condition chd_file::create_common()
{
// wrap in try for proper error handling
try
@@ -2273,14 +2300,14 @@ chd_error chd_file::create_common()
m_metaoffset = 0;
// if we have a parent, it must be V3 or later
- if (m_parent != nullptr && m_parent->version() < 3)
- throw CHDERR_UNSUPPORTED_VERSION;
+ if (m_parent && m_parent->version() < 3)
+ throw std::error_condition(error::UNSUPPORTED_VERSION);
// must be an even number of units per hunk
if (m_hunkbytes % m_unitbytes != 0)
- throw CHDERR_INVALID_PARAMETER;
- if (m_parent != nullptr && m_unitbytes != m_parent->unit_bytes())
- throw CHDERR_INVALID_PARAMETER;
+ throw std::error_condition(std::errc::invalid_argument);
+ if (m_parent && m_unitbytes != m_parent->unit_bytes())
+ throw std::error_condition(std::errc::invalid_argument);
// verify the compression types
bool found_zero = false;
@@ -2290,9 +2317,9 @@ chd_error chd_file::create_common()
if (elem == CHD_CODEC_NONE)
found_zero = true;
else if (found_zero)
- throw CHDERR_INVALID_PARAMETER;
+ throw std::error_condition(std::errc::invalid_argument);
else if (!chd_codec_list::codec_exists(elem))
- throw CHDERR_UNKNOWN_COMPRESSION;
+ throw std::error_condition(error::UNKNOWN_COMPRESSION);
}
// create our V5 header
@@ -2342,10 +2369,9 @@ chd_error chd_file::create_common()
// finish opening the file
create_open_common();
}
-
- // handle errors by closing ourself
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
+ // handle errors by closing ourself
close();
return err;
}
@@ -2354,11 +2380,11 @@ chd_error chd_file::create_common()
close();
throw;
}
- return CHDERR_NONE;
+ return std::error_condition();
}
/**
- * @fn chd_error chd_file::open_common(bool writeable)
+ * @fn std::error_condition chd_file::open_common(bool writeable)
*
* @brief -------------------------------------------------
* open_common - common path when opening an existing CHD file for input
@@ -2377,10 +2403,10 @@ chd_error chd_file::create_common()
*
* @param writeable true if writeable.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file::open_common(bool writeable)
+std::error_condition chd_file::open_common(bool writeable)
{
// wrap in try for proper error handling
try
@@ -2394,7 +2420,7 @@ chd_error chd_file::open_common(bool writeable)
// verify the signature
if (memcmp(rawheader, "MComprHD", 8) != 0)
- throw CHDERR_INVALID_FILE;
+ throw std::error_condition(error::INVALID_FILE);
m_version = be_read(&rawheader[12], 4);
@@ -2405,7 +2431,7 @@ chd_error chd_file::open_common(bool writeable)
case 3: parse_v3_header(rawheader, parentsha1); break;
case 4: parse_v4_header(rawheader, parentsha1); break;
case 5: parse_v5_header(rawheader, parentsha1); break;
- default: throw CHDERR_UNSUPPORTED_VERSION;
+ default: throw std::error_condition(error::UNSUPPORTED_VERSION);
}
// only allow writes to the most recent version
@@ -2413,27 +2439,26 @@ chd_error chd_file::open_common(bool writeable)
m_allow_writes = false;
if (writeable && !m_allow_writes)
- throw CHDERR_FILE_NOT_WRITEABLE;
+ throw std::error_condition(error::FILE_NOT_WRITEABLE);
// make sure we have a parent if we need one (and don't if we don't)
if (parentsha1 != util::sha1_t::null)
{
- if (m_parent == nullptr)
+ if (!m_parent)
m_parent_missing = true;
else if (m_parent->sha1() != parentsha1)
- throw CHDERR_INVALID_PARENT;
+ throw std::error_condition(error::INVALID_PARENT);
}
- else if (m_parent != nullptr)
- throw CHDERR_INVALID_PARAMETER;
+ else if (m_parent)
+ throw std::error_condition(std::errc::invalid_argument);
// finish opening the file
create_open_common();
- return CHDERR_NONE;
+ return std::error_condition();
}
-
- // handle errors by closing ourself
- catch (chd_error &err)
+ catch (std::error_condition const &err)
{
+ // handle errors by closing ourself
close();
return err;
}
@@ -2457,7 +2482,7 @@ void chd_file::create_open_common()
{
m_decompressor[decompnum] = chd_codec_list::new_decompressor(m_compression[decompnum], *this);
if (m_decompressor[decompnum] == nullptr && m_compression[decompnum] != 0)
- throw CHDERR_UNKNOWN_COMPRESSION;
+ throw std::error_condition(error::UNKNOWN_COMPRESSION);
}
// read the map; v5+ compressed drives need to read and decompress their map
@@ -2494,30 +2519,30 @@ void chd_file::create_open_common()
void chd_file::verify_proper_compression_append(uint32_t hunknum)
{
// punt if no file
- if (m_file == nullptr)
- throw CHDERR_NOT_OPEN;
+ if (!m_file)
+ throw std::error_condition(error::NOT_OPEN);
// return an error if out of range
if (hunknum >= m_hunkcount)
- throw CHDERR_HUNK_OUT_OF_RANGE;
+ throw std::error_condition(error::HUNK_OUT_OF_RANGE);
// if not writeable, fail
if (!m_allow_writes)
- throw CHDERR_FILE_NOT_WRITEABLE;
+ throw std::error_condition(error::FILE_NOT_WRITEABLE);
// compressed writes only via this interface
if (!compressed())
- throw CHDERR_FILE_NOT_WRITEABLE;
+ throw std::error_condition(error::FILE_NOT_WRITEABLE);
// only permitted to write new blocks
uint8_t *rawmap = &m_rawmap[hunknum * 12];
if (rawmap[0] != 0xff)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(error::COMPRESSION_ERROR);
// if this isn't the first block, only permitted to write immediately
// after the previous one
if (hunknum != 0 && rawmap[-12] == 0xff)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(error::COMPRESSION_ERROR);
}
/**
@@ -2572,7 +2597,7 @@ void chd_file::hunk_copy_from_self(uint32_t hunknum, uint32_t otherhunk)
// only permitted to reference prior hunks
if (otherhunk >= hunknum)
- throw CHDERR_INVALID_PARAMETER;
+ throw std::error_condition(std::errc::invalid_argument);
// update the map entry
uint8_t *rawmap = &m_rawmap[hunknum * 12];
@@ -2841,7 +2866,7 @@ void chd_file_compressor::compress_begin()
}
/**
- * @fn chd_error chd_file_compressor::compress_continue(double &progress, double &ratio)
+ * @fn std::error_condition chd_file_compressor::compress_continue(double &progress, double &ratio)
*
* @brief -------------------------------------------------
* compress_continue - continue compression
@@ -2850,14 +2875,14 @@ void chd_file_compressor::compress_begin()
* @param [in,out] progress The progress.
* @param [in,out] ratio The ratio.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chd_file_compressor::compress_continue(double &progress, double &ratio)
+std::error_condition chd_file_compressor::compress_continue(double &progress, double &ratio)
{
// if we got an error, return an error
if (m_read_error)
- return CHDERR_READ_ERROR;
+ return std::errc::io_error;
// if done reading, queue some more
while (m_read_queue_offset < m_logicalbytes && osd_work_queue_items(m_read_queue) < 2)
@@ -2911,8 +2936,8 @@ chd_error chd_file_compressor::compress_continue(double &progress, double &ratio
// if we're uncompressed, use regular writes
else if (!compressed())
{
- chd_error err = write_hunk(item.m_hunknum, item.m_data);
- if (err != CHDERR_NONE)
+ std::error_condition err = write_hunk(item.m_hunknum, item.m_data);
+ if (err)
return err;
// writes of all-0 data don't actually take space, so see if we count this
@@ -2973,7 +2998,7 @@ chd_error chd_file_compressor::compress_continue(double &progress, double &ratio
{
osd_work_queue_wait(m_read_queue, 30 * osd_ticks_per_second());
if (!compressed())
- return CHDERR_NONE;
+ return std::error_condition();
set_raw_sha1(m_compsha1.finish());
return compress_v5_map();
}
@@ -2994,7 +3019,7 @@ chd_error chd_file_compressor::compress_continue(double &progress, double &ratio
m_work_item[m_write_hunk % WORK_BUFFER_HUNKS].m_osd != nullptr)
osd_work_item_wait(m_work_item[m_write_hunk % WORK_BUFFER_HUNKS].m_osd, osd_ticks_per_second());
- return m_walking_parent ? CHDERR_WALKING_PARENT : CHDERR_COMPRESSING;
+ return m_walking_parent ? error::WALKING_PARENT : error::COMPRESSING;
}
/**
@@ -3171,12 +3196,12 @@ void chd_file_compressor::async_read()
// advance the read pointer
m_read_done_offset += numbytes;
}
- catch (chd_error& err)
+ catch (std::error_condition const &err)
{
- fprintf(stderr, "CHD error occurred: %s\n", chd_file::error_string(err));
+ fprintf(stderr, "CHD error occurred: %s\n", err.message().c_str());
m_read_error = true;
}
- catch (std::exception& ex)
+ catch (std::exception const &ex)
{
fprintf(stderr, "exception occurred: %s\n", ex.what());
m_read_error = true;
diff --git a/src/lib/util/chd.h b/src/lib/util/chd.h
index 705967d3dda..8d3e639438b 100644
--- a/src/lib/util/chd.h
+++ b/src/lib/util/chd.h
@@ -7,18 +7,22 @@
MAME Compressed Hunks of Data file format
***************************************************************************/
-
-#ifndef MAME_UTIL_CHD_H
-#define MAME_UTIL_CHD_H
+#ifndef MAME_LIB_UTIL_CHD_H
+#define MAME_LIB_UTIL_CHD_H
#pragma once
-#include "osdcore.h"
-#include <string>
-#include "corefile.h"
-#include "hashing.h"
#include "chdcodec.h"
+#include "hashing.h"
+#include "ioprocs.h"
+
+#include "osdcore.h"
+
#include <atomic>
+#include <string>
+#include <string_view>
+#include <system_error>
+
/***************************************************************************
@@ -190,86 +194,49 @@
//**************************************************************************
// pseudo-codecs returned by hunk_info
-const chd_codec_type CHD_CODEC_SELF = 1; // copy of another hunk
-const chd_codec_type CHD_CODEC_PARENT = 2; // copy of a parent's hunk
-const chd_codec_type CHD_CODEC_MINI = 3; // legacy "mini" 8-byte repeat
+constexpr chd_codec_type CHD_CODEC_SELF = 1; // copy of another hunk
+constexpr chd_codec_type CHD_CODEC_PARENT = 2; // copy of a parent's hunk
+constexpr chd_codec_type CHD_CODEC_MINI = 3; // legacy "mini" 8-byte repeat
// core types
typedef uint32_t chd_metadata_tag;
// metadata parameters
-const chd_metadata_tag CHDMETATAG_WILDCARD = 0;
-const uint32_t CHDMETAINDEX_APPEND = ~0;
+constexpr chd_metadata_tag CHDMETATAG_WILDCARD = 0;
+constexpr uint32_t CHDMETAINDEX_APPEND = ~0;
// metadata flags
-const uint8_t CHD_MDFLAGS_CHECKSUM = 0x01; // indicates data is checksummed
+constexpr uint8_t CHD_MDFLAGS_CHECKSUM = 0x01; // indicates data is checksummed
// standard hard disk metadata
-const chd_metadata_tag HARD_DISK_METADATA_TAG = CHD_MAKE_TAG('G','D','D','D');
+constexpr chd_metadata_tag HARD_DISK_METADATA_TAG = CHD_MAKE_TAG('G','D','D','D');
extern const char *HARD_DISK_METADATA_FORMAT;
// hard disk identify information
-const chd_metadata_tag HARD_DISK_IDENT_METADATA_TAG = CHD_MAKE_TAG('I','D','N','T');
+constexpr chd_metadata_tag HARD_DISK_IDENT_METADATA_TAG = CHD_MAKE_TAG('I','D','N','T');
// hard disk key information
-const chd_metadata_tag HARD_DISK_KEY_METADATA_TAG = CHD_MAKE_TAG('K','E','Y',' ');
+constexpr chd_metadata_tag HARD_DISK_KEY_METADATA_TAG = CHD_MAKE_TAG('K','E','Y',' ');
// pcmcia CIS information
-const chd_metadata_tag PCMCIA_CIS_METADATA_TAG = CHD_MAKE_TAG('C','I','S',' ');
+constexpr chd_metadata_tag PCMCIA_CIS_METADATA_TAG = CHD_MAKE_TAG('C','I','S',' ');
// standard CD-ROM metadata
-const chd_metadata_tag CDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','C','D');
-const chd_metadata_tag CDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C','H','T','R');
+constexpr chd_metadata_tag CDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','C','D');
+constexpr chd_metadata_tag CDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C','H','T','R');
extern const char *CDROM_TRACK_METADATA_FORMAT;
-const chd_metadata_tag CDROM_TRACK_METADATA2_TAG = CHD_MAKE_TAG('C','H','T','2');
+constexpr chd_metadata_tag CDROM_TRACK_METADATA2_TAG = CHD_MAKE_TAG('C','H','T','2');
extern const char *CDROM_TRACK_METADATA2_FORMAT;
-const chd_metadata_tag GDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','G','T');
-const chd_metadata_tag GDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C', 'H', 'G', 'D');
+constexpr chd_metadata_tag GDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','G','T');
+constexpr chd_metadata_tag GDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C', 'H', 'G', 'D');
extern const char *GDROM_TRACK_METADATA_FORMAT;
// standard A/V metadata
-const chd_metadata_tag AV_METADATA_TAG = CHD_MAKE_TAG('A','V','A','V');
+constexpr chd_metadata_tag AV_METADATA_TAG = CHD_MAKE_TAG('A','V','A','V');
extern const char *AV_METADATA_FORMAT;
// A/V laserdisc frame metadata
-const chd_metadata_tag AV_LD_METADATA_TAG = CHD_MAKE_TAG('A','V','L','D');
-
-// error types
-enum chd_error
-{
- CHDERR_NONE,
- CHDERR_NO_INTERFACE,
- CHDERR_OUT_OF_MEMORY,
- CHDERR_NOT_OPEN,
- CHDERR_ALREADY_OPEN,
- CHDERR_INVALID_FILE,
- CHDERR_INVALID_PARAMETER,
- CHDERR_INVALID_DATA,
- CHDERR_FILE_NOT_FOUND,
- CHDERR_REQUIRES_PARENT,
- CHDERR_FILE_NOT_WRITEABLE,
- CHDERR_READ_ERROR,
- CHDERR_WRITE_ERROR,
- CHDERR_CODEC_ERROR,
- CHDERR_INVALID_PARENT,
- CHDERR_HUNK_OUT_OF_RANGE,
- CHDERR_DECOMPRESSION_ERROR,
- CHDERR_COMPRESSION_ERROR,
- CHDERR_CANT_CREATE_FILE,
- CHDERR_CANT_VERIFY,
- CHDERR_NOT_SUPPORTED,
- CHDERR_METADATA_NOT_FOUND,
- CHDERR_INVALID_METADATA_SIZE,
- CHDERR_UNSUPPORTED_VERSION,
- CHDERR_VERIFY_INCOMPLETE,
- CHDERR_INVALID_METADATA,
- CHDERR_INVALID_STATE,
- CHDERR_OPERATION_PENDING,
- CHDERR_UNSUPPORTED_FORMAT,
- CHDERR_UNKNOWN_COMPRESSION,
- CHDERR_WALKING_PARENT,
- CHDERR_COMPRESSING
-};
+constexpr chd_metadata_tag AV_LD_METADATA_TAG = CHD_MAKE_TAG('A','V','L','D');
@@ -277,9 +244,6 @@ enum chd_error
// TYPE DEFINITIONS
//**************************************************************************
-class chd_codec;
-
-
// ======================> chd_file
// core file class
@@ -289,22 +253,49 @@ class chd_file
friend class chd_verifier;
// constants
- static const uint32_t HEADER_VERSION = 5;
- static const uint32_t V3_HEADER_SIZE = 120;
- static const uint32_t V4_HEADER_SIZE = 108;
- static const uint32_t V5_HEADER_SIZE = 124;
- static const uint32_t MAX_HEADER_SIZE = V5_HEADER_SIZE;
+ static constexpr uint32_t HEADER_VERSION = 5;
+ static constexpr uint32_t V3_HEADER_SIZE = 120;
+ static constexpr uint32_t V4_HEADER_SIZE = 108;
+ static constexpr uint32_t V5_HEADER_SIZE = 124;
+ static constexpr uint32_t MAX_HEADER_SIZE = V5_HEADER_SIZE;
public:
+ // error types
+ enum class error
+ {
+ NO_INTERFACE = 1,
+ NOT_OPEN,
+ ALREADY_OPEN,
+ INVALID_FILE,
+ INVALID_DATA,
+ REQUIRES_PARENT,
+ FILE_NOT_WRITEABLE,
+ CODEC_ERROR,
+ INVALID_PARENT,
+ HUNK_OUT_OF_RANGE,
+ DECOMPRESSION_ERROR,
+ COMPRESSION_ERROR,
+ CANT_VERIFY,
+ METADATA_NOT_FOUND,
+ INVALID_METADATA_SIZE,
+ UNSUPPORTED_VERSION,
+ VERIFY_INCOMPLETE,
+ INVALID_METADATA,
+ INVALID_STATE,
+ OPERATION_PENDING,
+ UNSUPPORTED_FORMAT,
+ UNKNOWN_COMPRESSION,
+ WALKING_PARENT,
+ COMPRESSING
+ };
+
// construction/destruction
chd_file();
virtual ~chd_file();
- // operators
- operator util::core_file &() { return *m_file; }
-
// getters
- bool opened() const { return (m_file != nullptr); }
+ util::random_read &file();
+ bool opened() const { return bool(m_file); }
uint32_t version() const { return m_version; }
uint64_t logical_bytes() const { return m_logicalbytes; }
uint32_t hunk_bytes() const { return m_hunkbytes; }
@@ -317,52 +308,49 @@ public:
util::sha1_t sha1();
util::sha1_t raw_sha1();
util::sha1_t parent_sha1();
- chd_error hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes);
+ std::error_condition hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes);
// setters
void set_raw_sha1(util::sha1_t rawdata);
void set_parent_sha1(util::sha1_t parent);
// file create
- chd_error create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]);
- chd_error create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]);
- chd_error create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent);
- chd_error create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent);
+ std::error_condition create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]);
+ std::error_condition create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]);
+ std::error_condition create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent);
+ std::error_condition create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent);
// file open
- chd_error open(const char *filename, bool writeable = false, chd_file *parent = nullptr);
- chd_error open(util::core_file &file, bool writeable = false, chd_file *parent = nullptr);
+ std::error_condition open(std::string_view filename, bool writeable = false, chd_file *parent = nullptr);
+ std::error_condition open(util::random_read_write::ptr &&file, bool writeable = false, chd_file *parent = nullptr);
// file close
void close();
// read/write
- chd_error read_hunk(uint32_t hunknum, void *buffer);
- chd_error write_hunk(uint32_t hunknum, const void *buffer);
- chd_error read_units(uint64_t unitnum, void *buffer, uint32_t count = 1);
- chd_error write_units(uint64_t unitnum, const void *buffer, uint32_t count = 1);
- chd_error read_bytes(uint64_t offset, void *buffer, uint32_t bytes);
- chd_error write_bytes(uint64_t offset, const void *buffer, uint32_t bytes);
+ std::error_condition read_hunk(uint32_t hunknum, void *buffer);
+ std::error_condition write_hunk(uint32_t hunknum, const void *buffer);
+ std::error_condition read_units(uint64_t unitnum, void *buffer, uint32_t count = 1);
+ std::error_condition write_units(uint64_t unitnum, const void *buffer, uint32_t count = 1);
+ std::error_condition read_bytes(uint64_t offset, void *buffer, uint32_t bytes);
+ std::error_condition write_bytes(uint64_t offset, const void *buffer, uint32_t bytes);
// metadata management
- chd_error read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output);
- chd_error read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output);
- chd_error read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen);
- chd_error read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output, chd_metadata_tag &resulttag, uint8_t &resultflags);
- chd_error write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags = CHD_MDFLAGS_CHECKSUM);
- chd_error write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const std::string &input, uint8_t flags = CHD_MDFLAGS_CHECKSUM) { return write_metadata(metatag, metaindex, input.c_str(), input.length() + 1, flags); }
- chd_error write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const std::vector<uint8_t> &input, uint8_t flags = CHD_MDFLAGS_CHECKSUM) { return write_metadata(metatag, metaindex, &input[0], input.size(), flags); }
- chd_error delete_metadata(chd_metadata_tag metatag, uint32_t metaindex);
- chd_error clone_all_metadata(chd_file &source);
+ std::error_condition read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output);
+ std::error_condition read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output);
+ std::error_condition read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen);
+ std::error_condition read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output, chd_metadata_tag &resulttag, uint8_t &resultflags);
+ std::error_condition write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags = CHD_MDFLAGS_CHECKSUM);
+ std::error_condition write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const std::string &input, uint8_t flags = CHD_MDFLAGS_CHECKSUM) { return write_metadata(metatag, metaindex, input.c_str(), input.length() + 1, flags); }
+ std::error_condition write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const std::vector<uint8_t> &input, uint8_t flags = CHD_MDFLAGS_CHECKSUM) { return write_metadata(metatag, metaindex, &input[0], input.size(), flags); }
+ std::error_condition delete_metadata(chd_metadata_tag metatag, uint32_t metaindex);
+ std::error_condition clone_all_metadata(chd_file &source);
// hashing helper
util::sha1_t compute_overall_sha1(util::sha1_t rawsha1);
// codec interfaces
- chd_error codec_configure(chd_codec_type codec, int param, void *config);
-
- // static helpers
- static const char *error_string(chd_error err);
+ std::error_condition codec_configure(chd_codec_type codec, int param, void *config);
private:
struct metadata_entry;
@@ -383,10 +371,10 @@ private:
void parse_v3_header(uint8_t *rawheader, util::sha1_t &parentsha1);
void parse_v4_header(uint8_t *rawheader, util::sha1_t &parentsha1);
void parse_v5_header(uint8_t *rawheader, util::sha1_t &parentsha1);
- chd_error compress_v5_map();
+ std::error_condition compress_v5_map();
void decompress_v5_map();
- chd_error create_common();
- chd_error open_common(bool writeable);
+ std::error_condition create_common();
+ std::error_condition open_common(bool writeable);
void create_open_common();
void verify_proper_compression_append(uint32_t hunknum);
void hunk_write_compressed(uint32_t hunknum, int8_t compression, const uint8_t *compressed, uint32_t complength, util::crc16_t crc16);
@@ -398,42 +386,41 @@ private:
static int CLIB_DECL metadata_hash_compare(const void *elem1, const void *elem2);
// file characteristics
- util::core_file * m_file; // handle to the open core file
- bool m_owns_file; // flag indicating if this file should be closed on chd_close()
+ util::random_read_write::ptr m_file; // handle to the open core file
bool m_allow_reads; // permit reads from this CHD?
bool m_allow_writes; // permit writes to this CHD?
// core parameters from the header
- uint32_t m_version; // version of the header
- uint64_t m_logicalbytes; // logical size of the raw CHD data in bytes
- uint64_t m_mapoffset; // offset of map
- uint64_t m_metaoffset; // offset to first metadata bit
- uint32_t m_hunkbytes; // size of each raw hunk in bytes
- uint32_t m_hunkcount; // number of hunks represented
- uint32_t m_unitbytes; // size of each unit in bytes
- uint64_t m_unitcount; // number of units represented
+ uint32_t m_version; // version of the header
+ uint64_t m_logicalbytes; // logical size of the raw CHD data in bytes
+ uint64_t m_mapoffset; // offset of map
+ uint64_t m_metaoffset; // offset to first metadata bit
+ uint32_t m_hunkbytes; // size of each raw hunk in bytes
+ uint32_t m_hunkcount; // number of hunks represented
+ uint32_t m_unitbytes; // size of each unit in bytes
+ uint64_t m_unitcount; // number of units represented
chd_codec_type m_compression[4]; // array of compression types used
chd_file * m_parent; // pointer to parent file, or nullptr if none
bool m_parent_missing; // are we missing our parent?
// key offsets within the header
- uint64_t m_mapoffset_offset; // offset of map offset field
- uint64_t m_metaoffset_offset;// offset of metaoffset field
- uint64_t m_sha1_offset; // offset of SHA1 field
- uint64_t m_rawsha1_offset; // offset of raw SHA1 field
- uint64_t m_parentsha1_offset;// offset of paren SHA1 field
+ uint64_t m_mapoffset_offset; // offset of map offset field
+ uint64_t m_metaoffset_offset;// offset of metaoffset field
+ uint64_t m_sha1_offset; // offset of SHA1 field
+ uint64_t m_rawsha1_offset; // offset of raw SHA1 field
+ uint64_t m_parentsha1_offset;// offset of paren SHA1 field
// map information
- uint32_t m_mapentrybytes; // length of each entry in a map
- std::vector<uint8_t> m_rawmap; // raw map data
+ uint32_t m_mapentrybytes; // length of each entry in a map
+ std::vector<uint8_t> m_rawmap; // raw map data
// compression management
- chd_decompressor * m_decompressor[4]; // array of decompression codecs
- std::vector<uint8_t> m_compressed; // temporary buffer for compressed data
+ chd_decompressor::ptr m_decompressor[4]; // array of decompression codecs
+ std::vector<uint8_t> m_compressed; // temporary buffer for compressed data
// caching
- std::vector<uint8_t> m_cache; // single-hunk cache for partial reads/writes
- uint32_t m_cachehunk; // which hunk is in the cache?
+ std::vector<uint8_t> m_cache; // single-hunk cache for partial reads/writes
+ uint32_t m_cachehunk; // which hunk is in the cache?
};
@@ -449,7 +436,7 @@ public:
// compression management
void compress_begin();
- chd_error compress_continue(double &progress, double &ratio);
+ std::error_condition compress_continue(double &progress, double &ratio);
protected:
// required override: read more data
@@ -470,24 +457,24 @@ private:
void add(uint64_t itemnum, util::crc16_t crc16, util::sha1_t sha1);
// constants
- static const uint64_t NOT_FOUND = ~uint64_t(0);
+ static constexpr uint64_t NOT_FOUND = ~uint64_t(0);
+
private:
// internal entry
struct entry_t
{
entry_t * m_next; // next entry in list
- uint64_t m_itemnum; // item number
+ uint64_t m_itemnum; // item number
util::sha1_t m_sha1; // SHA-1 of the block
};
// block of entries
struct entry_block
{
- entry_block(entry_block *prev)
- : m_next(prev), m_nextalloc(0) { }
+ entry_block(entry_block *prev) : m_next(prev), m_nextalloc(0) { }
entry_block * m_next; // next block in list
- uint32_t m_nextalloc; // next to be allocated
+ uint32_t m_nextalloc; // next to be allocated
entry_t m_array[16384]; // array of entries
};
@@ -551,8 +538,8 @@ private:
// current compression status
bool m_walking_parent; // are we building the parent map?
- uint64_t m_total_in; // total bytes in
- uint64_t m_total_out; // total bytes out
+ uint64_t m_total_in; // total bytes in
+ uint64_t m_total_out; // total bytes out
util::sha1_creator m_compsha1; // running SHA-1 on raw data
// hash lookup maps
@@ -561,20 +548,31 @@ private:
// read I/O thread
osd_work_queue * m_read_queue; // work queue for reading
- uint64_t m_read_queue_offset;// next offset to enqueue
- uint64_t m_read_done_offset; // next offset that will complete
+ uint64_t m_read_queue_offset;// next offset to enqueue
+ uint64_t m_read_done_offset; // next offset that will complete
bool m_read_error; // error during reading?
// work item thread
- static const int WORK_BUFFER_HUNKS = 256;
+ static constexpr int WORK_BUFFER_HUNKS = 256;
osd_work_queue * m_work_queue; // queue for doing work on other threads
- std::vector<uint8_t> m_work_buffer; // buffer containing hunk data to work on
- std::vector<uint8_t> m_compressed_buffer;// buffer containing compressed data
+ std::vector<uint8_t> m_work_buffer; // buffer containing hunk data to work on
+ std::vector<uint8_t> m_compressed_buffer;// buffer containing compressed data
work_item m_work_item[WORK_BUFFER_HUNKS]; // status of each hunk
chd_compressor_group * m_codecs[WORK_MAX_THREADS]; // codecs to use
// output state
- uint32_t m_write_hunk; // next hunk to write
+ uint32_t m_write_hunk; // next hunk to write
};
-#endif // MAME_UTIL_CHD_H
+
+// error category for CHD errors
+std::error_category const &chd_category() noexcept;
+inline std::error_condition make_error_condition(chd_file::error err) noexcept { return std::error_condition(int(err), chd_category()); }
+
+namespace std {
+
+template <> struct is_error_condition_enum<chd_file::error> : public std::true_type { };
+
+} // namespace std
+
+#endif // MAME_LIB_UTIL_CHD_H
diff --git a/src/lib/util/chdcd.cpp b/src/lib/util/chdcd.cpp
index ef013b41f48..63b633536bf 100644
--- a/src/lib/util/chdcd.cpp
+++ b/src/lib/util/chdcd.cpp
@@ -7,15 +7,19 @@
***************************************************************************/
-#include <cctype>
-#include <cstdlib>
-#include <cassert>
-#include "osdcore.h"
-#include "chd.h"
#include "chdcd.h"
+
+#include "chd.h"
#include "corefile.h"
#include "corestr.h"
+#include "osdcore.h"
+
+#include <cassert>
+#include <cctype>
+#include <cerrno>
+#include <cstdlib>
+
/***************************************************************************
@@ -230,8 +234,8 @@ static uint32_t parse_wav_sample(const char *filename, uint32_t *dataoffs)
uint64_t fsize = 0;
std::uint32_t actual;
- osd_file::error filerr = osd_file::open(filename, OPEN_FLAG_READ, file, fsize);
- if (filerr != osd_file::error::NONE)
+ std::error_condition const filerr = osd_file::open(filename, OPEN_FLAG_READ, file, fsize);
+ if (filerr)
{
printf("ERROR: could not open (%s)\n", filename);
return 0;
@@ -449,7 +453,7 @@ uint64_t read_uint64(FILE *infile)
-------------------------------------------------*/
/**
- * @fn chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
+ * @fn std::error_condition chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
*
* @brief Chdcd parse nero.
*
@@ -457,26 +461,25 @@ uint64_t read_uint64(FILE *infile)
* @param [in,out] outtoc The outtoc.
* @param [in,out] outinfo The outinfo.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
+std::error_condition chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
{
- FILE *infile;
unsigned char buffer[12];
uint32_t chain_offs, chunk_size;
int done = 0;
std::string path = std::string(tocfname);
- infile = fopen(tocfname, "rb");
- path = get_file_path(path);
-
- if (infile == (FILE *)nullptr)
+ FILE *infile = fopen(tocfname, "rb");
+ if (!infile)
{
- return CHDERR_FILE_NOT_FOUND;
+ return std::error_condition(errno, std::generic_category());
}
+ path = get_file_path(path);
+
/* clear structures */
memset(&outtoc, 0, sizeof(outtoc));
outinfo.reset();
@@ -489,7 +492,7 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_
{
printf("ERROR: Not a Nero 5.5 or later image!\n");
fclose(infile);
- return CHDERR_UNSUPPORTED_VERSION;
+ return chd_file::error::UNSUPPORTED_FORMAT;
}
chain_offs = buffer[11] | (buffer[10]<<8) | (buffer[9]<<16) | (buffer[8]<<24);
@@ -498,7 +501,7 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_
{
printf("ERROR: File size is > 4GB, this version of CHDMAN cannot handle it.");
fclose(infile);
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
}
// printf("NER5 detected, chain offset: %x\n", chain_offs);
@@ -559,12 +562,12 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_
case 0x0300: // Mode 2 Form 1
printf("ERROR: Mode 2 Form 1 tracks not supported\n");
fclose(infile);
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
case 0x0500: // raw data
printf("ERROR: Raw data tracks not supported\n");
fclose(infile);
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
case 0x0600: // 2352 byte mode 2 raw
outtoc.tracks[track-1].trktype = CD_TRACK_MODE2_RAW;
@@ -579,22 +582,22 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_
case 0x0f00: // raw data with sub-channel
printf("ERROR: Raw data tracks with sub-channel not supported\n");
fclose(infile);
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
case 0x1000: // audio with sub-channel
printf("ERROR: Audio tracks with sub-channel not supported\n");
fclose(infile);
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
case 0x1100: // raw Mode 2 Form 1 with sub-channel
printf("ERROR: Raw Mode 2 Form 1 tracks with sub-channel not supported\n");
fclose(infile);
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
default:
printf("ERROR: Unknown track type %x, contact MAMEDEV!\n", mode);
fclose(infile);
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
}
outtoc.tracks[track-1].datasize = size;
@@ -627,7 +630,7 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_
fclose(infile);
- return CHDERR_NONE;
+ return std::error_condition();
}
/*-------------------------------------------------
@@ -635,7 +638,7 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_
-------------------------------------------------*/
/**
- * @fn chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
+ * @fn std::error_condition chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
*
* @brief Chdcd parse ISO.
*
@@ -643,22 +646,21 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_
* @param [in,out] outtoc The outtoc.
* @param [in,out] outinfo The outinfo.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
+std::error_condition chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
{
- FILE *infile;
std::string path = std::string(tocfname);
- infile = fopen(tocfname, "rb");
- path = get_file_path(path);
-
- if (infile == (FILE *)nullptr)
+ FILE *infile = fopen(tocfname, "rb");
+ if (!infile)
{
- return CHDERR_FILE_NOT_FOUND;
+ return std::error_condition(errno, std::generic_category());
}
+ path = get_file_path(path);
+
/* clear structures */
memset(&outtoc, 0, sizeof(outtoc));
outinfo.reset();
@@ -693,7 +695,7 @@ chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
outinfo.track[0].swap = false;
} else {
printf("ERROR: Unrecognized track type\n");
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
}
outtoc.tracks[0].subtype = CD_SUB_NONE;
@@ -709,7 +711,7 @@ chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
outtoc.tracks[0].padframes = 0;
- return CHDERR_NONE;
+ return std::error_condition();
}
/*-------------------------------------------------
@@ -717,7 +719,7 @@ chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
-------------------------------------------------*/
/**
- * @fn static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
+ * @fn static std::error_condition chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
*
* @brief Chdcd parse GDI.
*
@@ -725,24 +727,23 @@ chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
* @param [in,out] outtoc The outtoc.
* @param [in,out] outinfo The outinfo.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
+static std::error_condition chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
{
- FILE *infile;
int i, numtracks;
std::string path = std::string(tocfname);
- infile = fopen(tocfname, "rt");
- path = get_file_path(path);
-
- if (infile == (FILE *)nullptr)
+ FILE *infile = fopen(tocfname, "rt");
+ if (!infile)
{
- return CHDERR_FILE_NOT_FOUND;
+ return std::error_condition(errno, std::generic_category());
}
+ path = get_file_path(path);
+
/* clear structures */
memset(&outtoc, 0, sizeof(outtoc));
outinfo.reset();
@@ -841,7 +842,7 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
/* store the number of tracks found */
outtoc.numtrks = numtracks;
- return CHDERR_NONE;
+ return std::error_condition();
}
/*-------------------------------------------------
@@ -849,7 +850,7 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
-------------------------------------------------*/
/**
- * @fn chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
+ * @fn std::error_condition chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
*
* @brief Chdcd parse cue.
*
@@ -857,25 +858,25 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_
* @param [in,out] outtoc The outtoc.
* @param [in,out] outinfo The outinfo.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
+std::error_condition chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
{
- FILE *infile;
int i, trknum;
static char token[512];
std::string lastfname;
uint32_t wavlen, wavoffs;
std::string path = std::string(tocfname);
- infile = fopen(tocfname, "rt");
- path = get_file_path(path);
- if (infile == (FILE *)nullptr)
+ FILE *infile = fopen(tocfname, "rt");
+ if (!infile)
{
- return CHDERR_FILE_NOT_FOUND;
+ return std::error_condition(errno, std::generic_category());
}
+ path = get_file_path(path);
+
/* clear structures */
memset(&outtoc, 0, sizeof(outtoc));
outinfo.reset();
@@ -921,14 +922,14 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
{
fclose(infile);
printf("ERROR: couldn't read [%s] or not a valid .WAV\n", lastfname.c_str());
- return CHDERR_INVALID_DATA;
+ return chd_file::error::INVALID_DATA;
}
}
else
{
fclose(infile);
printf("ERROR: Unhandled track type %s\n", token);
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
}
}
else if (!strcmp(token, "TRACK"))
@@ -970,7 +971,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
{
fclose(infile);
printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token);
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
}
/* next (optional) token on the line is the subcode type */
@@ -1083,7 +1084,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
if (tlen == 0)
{
printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str());
- return CHDERR_FILE_NOT_FOUND;
+ return std::errc::no_such_file_or_directory;
}
outinfo.track[trknum].offset = outinfo.track[trknum-1].offset + outtoc.tracks[trknum-1].frames * (outtoc.tracks[trknum-1].datasize + outtoc.tracks[trknum-1].subsize);
outtoc.tracks[trknum].frames = (tlen - outinfo.track[trknum].offset) / (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
@@ -1094,7 +1095,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
if (tlen == 0)
{
printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str());
- return CHDERR_FILE_NOT_FOUND;
+ return std::errc::no_such_file_or_directory;
}
tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
outtoc.tracks[trknum].frames = tlen;
@@ -1120,7 +1121,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
if (!outtoc.tracks[trknum].frames)
{
printf("ERROR: unable to determine size of track %d, missing INDEX 01 markers?\n", trknum+1);
- return CHDERR_INVALID_DATA;
+ return chd_file::error::INVALID_DATA;
}
}
else /* data files are different */
@@ -1129,7 +1130,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
if (tlen == 0)
{
printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum].fname.c_str());
- return CHDERR_FILE_NOT_FOUND;
+ return std::errc::no_such_file_or_directory;
}
tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
outtoc.tracks[trknum].frames = tlen;
@@ -1140,7 +1141,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
//printf("trk %d: %d frames @ offset %d\n", trknum+1, outtoc.tracks[trknum].frames, outinfo.track[trknum].offset);
}
- return CHDERR_NONE;
+ return std::error_condition();
}
/*---------------------------------------------------------------------------------------
@@ -1161,18 +1162,18 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
bool chdcd_is_gdicue(const char *tocfname)
{
- FILE *infile;
bool has_rem_singledensity = false;
bool has_rem_highdensity = false;
std::string path = std::string(tocfname);
- infile = fopen(tocfname, "rt");
- path = get_file_path(path);
- if (infile == (FILE *)nullptr)
+ FILE *infile = fopen(tocfname, "rt");
+ if (!infile)
{
return false;
}
+ path = get_file_path(path);
+
while (!feof(infile))
{
fgets(linebuffer, 511, infile);
@@ -1195,7 +1196,7 @@ bool chdcd_is_gdicue(const char *tocfname)
------------------------------------------------------------------*/
/**
- * @fn chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
+ * @fn std::error_condition chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
*
* @brief Chdcd parse cue.
*
@@ -1203,7 +1204,7 @@ bool chdcd_is_gdicue(const char *tocfname)
* @param [in,out] outtoc The outtoc.
* @param [in,out] outinfo The outinfo.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*
* Dreamcast discs have two images on a single disc. The first image is SINGLE-DENSITY and the second image
* is HIGH-DENSITY. The SINGLE-DENSITY area starts 0 LBA and HIGH-DENSITY area starts 45000 LBA.
@@ -1218,9 +1219,8 @@ bool chdcd_is_gdicue(const char *tocfname)
* layout from a TOSEC .gdi.
*/
-chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
+std::error_condition chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
{
- FILE *infile;
int i, trknum;
static char token[512];
std::string lastfname;
@@ -1229,13 +1229,14 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac
enum gdi_area current_area = SINGLE_DENSITY;
enum gdi_pattern disc_pattern = TYPE_UNKNOWN;
- infile = fopen(tocfname, "rt");
- path = get_file_path(path);
- if (infile == (FILE *)nullptr)
+ FILE *infile = fopen(tocfname, "rt");
+ if (!infile)
{
- return CHDERR_FILE_NOT_FOUND;
+ return std::error_condition(errno, std::generic_category());
}
+ path = get_file_path(path);
+
/* clear structures */
memset(&outtoc, 0, sizeof(outtoc));
outinfo.reset();
@@ -1297,14 +1298,14 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac
{
fclose(infile);
printf("ERROR: couldn't read [%s] or not a valid .WAV\n", lastfname.c_str());
- return CHDERR_INVALID_DATA;
+ return chd_file::error::INVALID_DATA;
}
}
else
{
fclose(infile);
printf("ERROR: Unhandled track type %s\n", token);
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
}
}
else if (!strcmp(token, "TRACK"))
@@ -1349,7 +1350,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac
{
fclose(infile);
printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token);
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
}
/* next (optional) token on the line is the subcode type */
@@ -1462,7 +1463,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac
if (tlen == 0)
{
printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str());
- return CHDERR_FILE_NOT_FOUND;
+ return std::errc::no_such_file_or_directory;
}
outinfo.track[trknum].offset = outinfo.track[trknum-1].offset + outtoc.tracks[trknum-1].frames * (outtoc.tracks[trknum-1].datasize + outtoc.tracks[trknum-1].subsize);
outtoc.tracks[trknum].frames = (tlen - outinfo.track[trknum].offset) / (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
@@ -1473,7 +1474,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac
if (tlen == 0)
{
printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str());
- return CHDERR_FILE_NOT_FOUND;
+ return std::errc::no_such_file_or_directory;
}
tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
outtoc.tracks[trknum].frames = tlen;
@@ -1499,7 +1500,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac
if (!outtoc.tracks[trknum].frames)
{
printf("ERROR: unable to determine size of track %d, missing INDEX 01 markers?\n", trknum+1);
- return CHDERR_INVALID_DATA;
+ return chd_file::error::INVALID_DATA;
}
}
else /* data files are different */
@@ -1508,7 +1509,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac
if (tlen == 0)
{
printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum].fname.c_str());
- return CHDERR_FILE_NOT_FOUND;
+ return std::errc::no_such_file_or_directory;
}
tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
outtoc.tracks[trknum].frames = tlen;
@@ -1638,7 +1639,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac
}
#endif
- return CHDERR_NONE;
+ return std::error_condition();
}
/*-------------------------------------------------
@@ -1646,7 +1647,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac
-------------------------------------------------*/
/**
- * @fn chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
+ * @fn std::error_condition chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
*
* @brief Chdcd parse TOC.
*
@@ -1654,12 +1655,11 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac
* @param [in,out] outtoc The outtoc.
* @param [in,out] outinfo The outinfo.
*
- * @return A chd_error.
+ * @return A std::error_condition.
*/
-chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
+std::error_condition chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo)
{
- FILE *infile;
int i, trknum;
static char token[512];
char tocftemp[512];
@@ -1695,14 +1695,14 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
std::string path = std::string(tocfname);
- infile = fopen(tocfname, "rt");
- path = get_file_path(path);
-
- if (infile == (FILE *)nullptr)
+ FILE *infile = fopen(tocfname, "rt");
+ if (!infile)
{
- return CHDERR_FILE_NOT_FOUND;
+ return std::error_condition(errno, std::generic_category());
}
+ path = get_file_path(path);
+
/* clear structures */
memset(&outtoc, 0, sizeof(outtoc));
outinfo.reset();
@@ -1817,7 +1817,7 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
{
fclose(infile);
printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token);
- return CHDERR_UNSUPPORTED_FORMAT;
+ return chd_file::error::UNSUPPORTED_FORMAT;
}
/* next (optional) token on the line is the subcode type */
@@ -1844,5 +1844,5 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i
/* store the number of tracks found */
outtoc.numtrks = trknum + 1;
- return CHDERR_NONE;
+ return std::error_condition();
}
diff --git a/src/lib/util/chdcd.h b/src/lib/util/chdcd.h
index 65e4b943964..95f214e5831 100644
--- a/src/lib/util/chdcd.h
+++ b/src/lib/util/chdcd.h
@@ -5,14 +5,16 @@
CDRDAO TOC parser for CHD compression frontend
***************************************************************************/
-
-#ifndef MAME_UTIL_CHDCD_H
-#define MAME_UTIL_CHDCD_H
+#ifndef MAME_LIB_UTIL_CHDCD_H
+#define MAME_LIB_UTIL_CHDCD_H
#pragma once
#include "cdrom.h"
+#include <system_error>
+
+
struct chdcd_track_input_entry
{
chdcd_track_input_entry() { reset(); }
@@ -33,6 +35,6 @@ struct chdcd_track_input_info
};
-chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo);
+std::error_condition chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo);
-#endif // MAME_UTIL_CHDCD_H
+#endif // MAME_LIB_UTIL_CHDCD_H
diff --git a/src/lib/util/chdcodec.cpp b/src/lib/util/chdcodec.cpp
index 4f5c23b3104..eca9403b56c 100644
--- a/src/lib/util/chdcodec.cpp
+++ b/src/lib/util/chdcodec.cpp
@@ -8,24 +8,29 @@
***************************************************************************/
-#include <cassert>
+#include "chdcodec.h"
-#include "chd.h"
-#include "hashing.h"
#include "avhuff.h"
-#include "flac.h"
#include "cdrom.h"
-#include <zlib.h>
-#include "lzma/C/LzmaEnc.h"
+#include "chd.h"
+#include "flac.h"
+#include "hashing.h"
+
#include "lzma/C/LzmaDec.h"
+#include "lzma/C/LzmaEnc.h"
+
+#include <zlib.h>
+
#include <new>
+namespace {
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 };
+constexpr uint8_t f_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 };
@@ -35,7 +40,7 @@ static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff
// ======================> chd_zlib_allocator
-// allocation helper clas for zlib
+// allocation helper class for zlib
class chd_zlib_allocator
{
public:
@@ -51,7 +56,8 @@ private:
static voidpf fast_alloc(voidpf opaque, uInt items, uInt size);
static void fast_free(voidpf opaque, voidpf address);
- static const int MAX_ZLIB_ALLOCS = 64;
+ static constexpr int MAX_ZLIB_ALLOCS = 64;
+
uint32_t * m_allocptr[MAX_ZLIB_ALLOCS];
};
@@ -111,7 +117,7 @@ private:
static void *fast_alloc(void *p, size_t size);
static void fast_free(void *p, void *address);
- static const int MAX_LZMA_ALLOCS = 64;
+ static constexpr int MAX_LZMA_ALLOCS = 64;
uint32_t * m_allocptr[MAX_LZMA_ALLOCS];
};
@@ -287,7 +293,7 @@ private:
// ======================> chd_cd_compressor
-template<class _BaseCompressor, class _SubcodeCompressor>
+template<class BaseCompressor, class SubcodeCompressor>
class chd_cd_compressor : public chd_compressor
{
public:
@@ -300,7 +306,7 @@ public:
{
// make sure the CHD's hunk size is an even multiple of the frame size
if (hunkbytes % CD_FRAME_SIZE != 0)
- throw CHDERR_CODEC_ERROR;
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
}
// core functionality
@@ -323,10 +329,10 @@ public:
// clear out ECC data if we can
uint8_t *sector = &m_buffer[framenum * CD_MAX_SECTOR_DATA];
- if (memcmp(sector, s_cd_sync_header, sizeof(s_cd_sync_header)) == 0 && ecc_verify(sector))
+ if (memcmp(sector, f_cd_sync_header, sizeof(f_cd_sync_header)) == 0 && ecc_verify(sector))
{
dest[framenum / 8] |= 1 << (framenum % 8);
- memset(sector, 0, sizeof(s_cd_sync_header));
+ memset(sector, 0, sizeof(f_cd_sync_header));
ecc_clear(sector);
}
}
@@ -334,7 +340,7 @@ public:
// encode the base portion
uint32_t complen = m_base_compressor.compress(&m_buffer[0], frames * CD_MAX_SECTOR_DATA, &dest[header_bytes]);
if (complen >= srclen)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// write compressed length
dest[ecc_bytes + 0] = complen >> ((complen_bytes - 1) * 8);
@@ -348,15 +354,15 @@ public:
private:
// internal state
- _BaseCompressor m_base_compressor;
- _SubcodeCompressor m_subcode_compressor;
+ BaseCompressor m_base_compressor;
+ SubcodeCompressor m_subcode_compressor;
std::vector<uint8_t> m_buffer;
};
// ======================> chd_cd_decompressor
-template<class _BaseDecompressor, class _SubcodeDecompressor>
+template<class BaseDecompressor, class SubcodeDecompressor>
class chd_cd_decompressor : public chd_decompressor
{
public:
@@ -369,7 +375,7 @@ public:
{
// make sure the CHD's hunk size is an even multiple of the frame size
if (hunkbytes % CD_FRAME_SIZE != 0)
- throw CHDERR_CODEC_ERROR;
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
}
// core functionality
@@ -400,7 +406,7 @@ public:
uint8_t *sector = &dest[framenum * CD_FRAME_SIZE];
if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
{
- memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
+ memcpy(sector, f_cd_sync_header, sizeof(f_cd_sync_header));
ecc_generate(sector);
}
}
@@ -408,8 +414,8 @@ public:
private:
// internal state
- _BaseDecompressor m_base_decompressor;
- _SubcodeDecompressor m_subcode_decompressor;
+ BaseDecompressor m_base_decompressor;
+ SubcodeDecompressor m_subcode_decompressor;
std::vector<uint8_t> m_buffer;
};
@@ -460,25 +466,65 @@ private:
// CODEC LIST
//**************************************************************************
+// an entry in the list
+struct codec_entry
+{
+ chd_codec_type m_type;
+ bool m_lossy;
+ const char * m_name;
+ chd_compressor::ptr (*m_construct_compressor)(chd_file &, uint32_t, bool);
+ chd_decompressor::ptr (*m_construct_decompressor)(chd_file &, uint32_t, bool);
+
+ template <class CompressorClass>
+ static chd_compressor::ptr construct_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
+ {
+ return std::make_unique<CompressorClass>(chd, hunkbytes, lossy);
+ }
+
+ template <class DecompressorClass>
+ static chd_decompressor::ptr construct_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
+ {
+ return std::make_unique<DecompressorClass>(chd, hunkbytes, lossy);
+ }
+};
+
+
// static list of available known codecs
-const chd_codec_list::codec_entry chd_codec_list::s_codec_list[] =
+const codec_entry f_codec_list[] =
{
// general codecs
- { CHD_CODEC_ZLIB, false, "Deflate", &chd_codec_list::construct_compressor<chd_zlib_compressor>, &chd_codec_list::construct_decompressor<chd_zlib_decompressor> },
- { CHD_CODEC_LZMA, false, "LZMA", &chd_codec_list::construct_compressor<chd_lzma_compressor>, &chd_codec_list::construct_decompressor<chd_lzma_decompressor> },
- { CHD_CODEC_HUFFMAN, false, "Huffman", &chd_codec_list::construct_compressor<chd_huffman_compressor>, &chd_codec_list::construct_decompressor<chd_huffman_decompressor> },
- { CHD_CODEC_FLAC, false, "FLAC", &chd_codec_list::construct_compressor<chd_flac_compressor>, &chd_codec_list::construct_decompressor<chd_flac_decompressor> },
+ { CHD_CODEC_ZLIB, false, "Deflate", &codec_entry::construct_compressor<chd_zlib_compressor>, &codec_entry::construct_decompressor<chd_zlib_decompressor> },
+ { CHD_CODEC_LZMA, false, "LZMA", &codec_entry::construct_compressor<chd_lzma_compressor>, &codec_entry::construct_decompressor<chd_lzma_decompressor> },
+ { CHD_CODEC_HUFFMAN, false, "Huffman", &codec_entry::construct_compressor<chd_huffman_compressor>, &codec_entry::construct_decompressor<chd_huffman_decompressor> },
+ { CHD_CODEC_FLAC, false, "FLAC", &codec_entry::construct_compressor<chd_flac_compressor>, &codec_entry::construct_decompressor<chd_flac_decompressor> },
// general codecs with CD frontend
- { CHD_CODEC_CD_ZLIB, false, "CD Deflate", &chd_codec_list::construct_compressor<chd_cd_compressor<chd_zlib_compressor, chd_zlib_compressor> >, &chd_codec_list::construct_decompressor<chd_cd_decompressor<chd_zlib_decompressor, chd_zlib_decompressor> > },
- { CHD_CODEC_CD_LZMA, false, "CD LZMA", &chd_codec_list::construct_compressor<chd_cd_compressor<chd_lzma_compressor, chd_zlib_compressor> >, &chd_codec_list::construct_decompressor<chd_cd_decompressor<chd_lzma_decompressor, chd_zlib_decompressor> > },
- { CHD_CODEC_CD_FLAC, false, "CD FLAC", &chd_codec_list::construct_compressor<chd_cd_flac_compressor>, &chd_codec_list::construct_decompressor<chd_cd_flac_decompressor> },
+ { CHD_CODEC_CD_ZLIB, false, "CD Deflate", &codec_entry::construct_compressor<chd_cd_compressor<chd_zlib_compressor, chd_zlib_compressor> >, &codec_entry::construct_decompressor<chd_cd_decompressor<chd_zlib_decompressor, chd_zlib_decompressor> > },
+ { CHD_CODEC_CD_LZMA, false, "CD LZMA", &codec_entry::construct_compressor<chd_cd_compressor<chd_lzma_compressor, chd_zlib_compressor> >, &codec_entry::construct_decompressor<chd_cd_decompressor<chd_lzma_decompressor, chd_zlib_decompressor> > },
+ { CHD_CODEC_CD_FLAC, false, "CD FLAC", &codec_entry::construct_compressor<chd_cd_flac_compressor>, &codec_entry::construct_decompressor<chd_cd_flac_decompressor> },
// A/V codecs
- { CHD_CODEC_AVHUFF, false, "A/V Huffman", &chd_codec_list::construct_compressor<chd_avhuff_compressor>, &chd_codec_list::construct_decompressor<chd_avhuff_decompressor> },
+ { CHD_CODEC_AVHUFF, false, "A/V Huffman", &codec_entry::construct_compressor<chd_avhuff_compressor>, &codec_entry::construct_decompressor<chd_avhuff_decompressor> },
};
+//-------------------------------------------------
+// find_in_list - create a new compressor
+// instance of the given type
+//-------------------------------------------------
+
+const codec_entry *find_in_list(chd_codec_type type)
+{
+ // find in the list and construct the class
+ for (auto & elem : f_codec_list)
+ if (elem.m_type == type)
+ return &elem;
+ return nullptr;
+}
+
+} // anonymous namespace
+
+
//**************************************************************************
// CHD CODEC
@@ -512,7 +558,7 @@ chd_codec::~chd_codec()
void chd_codec::configure(int param, void *config)
{
// if not overridden, it is always a failure
- throw CHDERR_INVALID_PARAMETER;
+ throw std::error_condition(std::errc::invalid_argument);
}
@@ -556,11 +602,11 @@ chd_decompressor::chd_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy
// instance of the given type
//-------------------------------------------------
-chd_compressor *chd_codec_list::new_compressor(chd_codec_type type, chd_file &chd)
+chd_compressor::ptr chd_codec_list::new_compressor(chd_codec_type type, chd_file &chd)
{
// find in the list and construct the class
- const codec_entry *entry = find_in_list(type);
- return (entry == nullptr) ? nullptr : (*entry->m_construct_compressor)(chd, chd.hunk_bytes(), entry->m_lossy);
+ codec_entry const *const entry = find_in_list(type);
+ return entry ? (*entry->m_construct_compressor)(chd, chd.hunk_bytes(), entry->m_lossy) : nullptr;
}
@@ -569,39 +615,36 @@ chd_compressor *chd_codec_list::new_compressor(chd_codec_type type, chd_file &ch
// instance of the given type
//-------------------------------------------------
-chd_decompressor *chd_codec_list::new_decompressor(chd_codec_type type, chd_file &chd)
+chd_decompressor::ptr chd_codec_list::new_decompressor(chd_codec_type type, chd_file &chd)
{
// find in the list and construct the class
const codec_entry *entry = find_in_list(type);
- return (entry == nullptr) ? nullptr : (*entry->m_construct_decompressor)(chd, chd.hunk_bytes(), entry->m_lossy);
+ return entry ? (*entry->m_construct_decompressor)(chd, chd.hunk_bytes(), entry->m_lossy) : nullptr;
}
//-------------------------------------------------
-// codec_name - return the name of the given
-// codec
+// codec_exists - determine whether a codec type
+// corresponds to a supported codec
//-------------------------------------------------
-const char *chd_codec_list::codec_name(chd_codec_type type)
+bool chd_codec_list::codec_exists(chd_codec_type type)
{
// find in the list and construct the class
- const codec_entry *entry = find_in_list(type);
- return (entry == nullptr) ? nullptr : entry->m_name;
+ return bool(find_in_list(type));
}
//-------------------------------------------------
-// find_in_list - create a new compressor
-// instance of the given type
+// codec_name - return the name of the given
+// codec
//-------------------------------------------------
-const chd_codec_list::codec_entry *chd_codec_list::find_in_list(chd_codec_type type)
+const char *chd_codec_list::codec_name(chd_codec_type type)
{
// find in the list and construct the class
- for (auto & elem : s_codec_list)
- if (elem.m_type == type)
- return &elem;
- return nullptr;
+ const codec_entry *entry = find_in_list(type);
+ return entry ? entry->m_name : nullptr;
}
@@ -615,25 +658,24 @@ const chd_codec_list::codec_entry *chd_codec_list::find_in_list(chd_codec_type t
//-------------------------------------------------
chd_compressor_group::chd_compressor_group(chd_file &chd, uint32_t compressor_list[4])
- : m_hunkbytes(chd.hunk_bytes()),
- m_compress_test(m_hunkbytes)
+ : m_hunkbytes(chd.hunk_bytes())
+ , m_compress_test(m_hunkbytes)
#if CHDCODEC_VERIFY_COMPRESSION
- ,m_decompressed(m_hunkbytes)
+ , m_decompressed(m_hunkbytes)
#endif
{
// verify the compression types and initialize the codecs
for (int codecnum = 0; codecnum < std::size(m_compressor); codecnum++)
{
- m_compressor[codecnum] = nullptr;
if (compressor_list[codecnum] != CHD_CODEC_NONE)
{
m_compressor[codecnum] = chd_codec_list::new_compressor(compressor_list[codecnum], chd);
- if (m_compressor[codecnum] == nullptr)
- throw CHDERR_UNKNOWN_COMPRESSION;
+ if (!m_compressor[codecnum])
+ throw std::error_condition(chd_file::error::UNKNOWN_COMPRESSION);
#if CHDCODEC_VERIFY_COMPRESSION
m_decompressor[codecnum] = chd_codec_list::new_decompressor(compressor_list[codecnum], chd);
- if (m_decompressor[codecnum] == nullptr)
- throw CHDERR_UNKNOWN_COMPRESSION;
+ if (!m_decompressor[codecnum])
+ throw std::error_condition(chd_file::error::UNKNOWN_COMPRESSION);
#endif
}
}
@@ -646,9 +688,7 @@ chd_compressor_group::chd_compressor_group(chd_file &chd, uint32_t compressor_li
chd_compressor_group::~chd_compressor_group()
{
- // delete the codecs and the test buffer
- for (auto & elem : m_compressor)
- delete elem;
+ // codecs and test buffer deleted automatically
}
@@ -664,7 +704,7 @@ int8_t chd_compressor_group::find_best_compressor(const uint8_t *src, uint8_t *c
complen = m_hunkbytes;
int8_t compression = -1;
for (int codecnum = 0; codecnum < std::size(m_compressor); codecnum++)
- if (m_compressor[codecnum] != nullptr)
+ if (m_compressor[codecnum])
{
// attempt to compress, swallowing errors
try
@@ -702,7 +742,9 @@ printf(" codec%d=%d bytes \n", codecnum, compbytes);
memcpy(compressed, &m_compress_test[0], compbytes);
}
}
- catch (...) { }
+ catch (...)
+ {
+ }
}
// if the best is none, copy it over
@@ -835,7 +877,7 @@ chd_zlib_compressor::chd_zlib_compressor(chd_file &chd, uint32_t hunkbytes, bool
if (zerr == Z_MEM_ERROR)
throw std::bad_alloc();
else if (zerr != Z_OK)
- throw CHDERR_CODEC_ERROR;
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
}
@@ -864,14 +906,14 @@ uint32_t chd_zlib_compressor::compress(const uint8_t *src, uint32_t srclen, uint
m_deflater.total_out = 0;
int zerr = deflateReset(&m_deflater);
if (zerr != Z_OK)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// do it
zerr = deflate(&m_deflater, Z_FINISH);
// if we ended up with more data than we started with, return an error
if (zerr != Z_STREAM_END || m_deflater.total_out >= srclen)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// otherwise, return the length
return m_deflater.total_out;
@@ -900,7 +942,7 @@ chd_zlib_decompressor::chd_zlib_decompressor(chd_file &chd, uint32_t hunkbytes,
if (zerr == Z_MEM_ERROR)
throw std::bad_alloc();
else if (zerr != Z_OK)
- throw CHDERR_CODEC_ERROR;
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
}
@@ -930,14 +972,14 @@ void chd_zlib_decompressor::decompress(const uint8_t *src, uint32_t complen, uin
m_inflater.total_out = 0;
int zerr = inflateReset(&m_inflater);
if (zerr != Z_OK)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// do it
zerr = inflate(&m_inflater, Z_FINISH);
if (zerr != Z_STREAM_END)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
if (m_inflater.total_out != destlen)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
}
@@ -1071,20 +1113,20 @@ uint32_t chd_lzma_compressor::compress(const uint8_t *src, uint32_t srclen, uint
// allocate the encoder
CLzmaEncHandle encoder = LzmaEnc_Create(&m_allocator);
if (encoder == nullptr)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
try
{
// configure the encoder
SRes res = LzmaEnc_SetProps(encoder, &m_props);
if (res != SZ_OK)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// run it
SizeT complen = srclen;
res = LzmaEnc_MemEncode(encoder, dest, &complen, src, srclen, 0, nullptr, &m_allocator, &m_allocator);
if (res != SZ_OK)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// clean up
LzmaEnc_Destroy(encoder, &m_allocator, &m_allocator);
@@ -1140,24 +1182,24 @@ chd_lzma_decompressor::chd_lzma_decompressor(chd_file &chd, uint32_t hunkbytes,
// convert to decoder properties
CLzmaEncHandle enc = LzmaEnc_Create(&m_allocator);
if (!enc)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK)
{
LzmaEnc_Destroy(enc, &m_allocator, &m_allocator);
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
}
Byte decoder_props[LZMA_PROPS_SIZE];
SizeT props_size = sizeof(decoder_props);
if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK)
{
LzmaEnc_Destroy(enc, &m_allocator, &m_allocator);
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
}
LzmaEnc_Destroy(enc, &m_allocator, &m_allocator);
// do memory allocations
if (LzmaDec_Allocate(&m_decoder, decoder_props, LZMA_PROPS_SIZE, &m_allocator) != SZ_OK)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
}
@@ -1188,7 +1230,7 @@ void chd_lzma_decompressor::decompress(const uint8_t *src, uint32_t complen, uin
ELzmaStatus status;
SRes res = LzmaDec_DecodeToBuf(&m_decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status);
if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
}
@@ -1216,7 +1258,7 @@ uint32_t chd_huffman_compressor::compress(const uint8_t *src, uint32_t srclen, u
{
uint32_t complen;
if (m_encoder.encode(src, srclen, dest, srclen, complen) != HUFFERR_NONE)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
return complen;
}
@@ -1244,7 +1286,7 @@ chd_huffman_decompressor::chd_huffman_decompressor(chd_file &chd, uint32_t hunkb
void chd_huffman_decompressor::decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
if (m_decoder.decode(src, complen, dest, destlen) != HUFFERR_NONE)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
}
@@ -1282,19 +1324,19 @@ uint32_t chd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, uint
// reset and encode big-endian
m_encoder.reset(dest + 1, hunkbytes() - 1);
if (!m_encoder.encode_interleaved(reinterpret_cast<const int16_t *>(src), srclen / 4, !m_big_endian))
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
uint32_t complen_be = m_encoder.finish();
// reset and encode little-endian
m_encoder.reset(dest + 1, hunkbytes() - 1);
if (!m_encoder.encode_interleaved(reinterpret_cast<const int16_t *>(src), srclen / 4, m_big_endian))
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
uint32_t complen_le = m_encoder.finish();
// pick the best one and add a byte
uint32_t complen = std::min(complen_le, complen_be);
if (complen + 1 >= hunkbytes())
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// if big-endian was better, re-do it
dest[0] = 'L';
@@ -1303,7 +1345,7 @@ uint32_t chd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, uint
dest[0] = 'B';
m_encoder.reset(dest + 1, hunkbytes() - 1);
if (!m_encoder.encode_interleaved(reinterpret_cast<const int16_t *>(src), srclen / 4, !m_big_endian))
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
m_encoder.finish();
}
return complen + 1;
@@ -1358,13 +1400,13 @@ void chd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen, uin
else if (src[0] == 'B')
swap_endian = !m_big_endian;
else
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// reset and decode
if (!m_decoder.reset(44100, 2, chd_flac_compressor::blocksize(destlen), src + 1, complen - 1))
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
if (!m_decoder.decode_interleaved(reinterpret_cast<int16_t *>(dest), destlen / 4, swap_endian))
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// finish up
m_decoder.finish();
@@ -1386,7 +1428,7 @@ chd_cd_flac_compressor::chd_cd_flac_compressor(chd_file &chd, uint32_t hunkbytes
{
// make sure the CHD's hunk size is an even multiple of the frame size
if (hunkbytes % CD_FRAME_SIZE != 0)
- throw CHDERR_CODEC_ERROR;
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
// determine whether we want native or swapped samples
uint16_t native_endian = 0;
@@ -1409,7 +1451,7 @@ chd_cd_flac_compressor::chd_cd_flac_compressor(chd_file &chd, uint32_t hunkbytes
if (zerr == Z_MEM_ERROR)
throw std::bad_alloc();
else if (zerr != Z_OK)
- throw CHDERR_CODEC_ERROR;
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
}
@@ -1442,7 +1484,7 @@ uint32_t chd_cd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, u
m_encoder.reset(dest, hunkbytes());
uint8_t *buffer = &m_buffer[0];
if (!m_encoder.encode_interleaved(reinterpret_cast<int16_t *>(buffer), frames * CD_MAX_SECTOR_DATA/4, m_swap_endian))
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// finish up
uint32_t complen = m_encoder.finish();
@@ -1456,7 +1498,7 @@ uint32_t chd_cd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, u
m_deflater.total_out = 0;
int zerr = deflateReset(&m_deflater);
if (zerr != Z_OK)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
// do it
zerr = deflate(&m_deflater, Z_FINISH);
@@ -1464,7 +1506,7 @@ uint32_t chd_cd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, u
// if we ended up with more data than we started with, return an error
complen += m_deflater.total_out;
if (zerr != Z_STREAM_END || complen >= srclen)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
return complen;
}
@@ -1515,7 +1557,7 @@ chd_cd_flac_decompressor::chd_cd_flac_decompressor(chd_file &chd, uint32_t hunkb
{
// make sure the CHD's hunk size is an even multiple of the frame size
if (hunkbytes % CD_FRAME_SIZE != 0)
- throw CHDERR_CODEC_ERROR;
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
// determine whether we want native or swapped samples
uint16_t native_endian = 0;
@@ -1532,7 +1574,7 @@ chd_cd_flac_decompressor::chd_cd_flac_decompressor(chd_file &chd, uint32_t hunkb
if (zerr == Z_MEM_ERROR)
throw std::bad_alloc();
else if (zerr != Z_OK)
- throw CHDERR_CODEC_ERROR;
+ throw std::error_condition(chd_file::error::CODEC_ERROR);
}
/**
@@ -1569,10 +1611,10 @@ void chd_cd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen,
// reset and decode
uint32_t frames = destlen / CD_FRAME_SIZE;
if (!m_decoder.reset(44100, 2, chd_cd_flac_compressor::blocksize(frames * CD_MAX_SECTOR_DATA), src, complen))
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
uint8_t *buffer = &m_buffer[0];
if (!m_decoder.decode_interleaved(reinterpret_cast<int16_t *>(buffer), frames * CD_MAX_SECTOR_DATA/4, m_swap_endian))
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// inflate the subcode data
uint32_t offset = m_decoder.finish();
@@ -1584,14 +1626,14 @@ void chd_cd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen,
m_inflater.total_out = 0;
int zerr = inflateReset(&m_inflater);
if (zerr != Z_OK)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// do it
zerr = inflate(&m_inflater, Z_FINISH);
if (zerr != Z_STREAM_END)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
if (m_inflater.total_out != frames * CD_MAX_SUBCODE_DATA)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// reassemble the data
for (uint32_t framenum = 0; framenum < frames; framenum++)
@@ -1620,15 +1662,15 @@ void chd_cd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen,
*/
chd_avhuff_compressor::chd_avhuff_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
- : chd_compressor(chd, hunkbytes, lossy),
- m_postinit(false)
+ : chd_compressor(chd, hunkbytes, lossy)
+ , m_postinit(false)
{
try
{
// attempt to do a post-init now
postinit();
}
- catch (chd_error &)
+ catch (std::error_condition const &)
{
// if we're creating a new CHD, it won't work but that's ok
}
@@ -1665,14 +1707,14 @@ uint32_t chd_avhuff_compressor::compress(const uint8_t *src, uint32_t srclen, ui
int size = avhuff_encoder::raw_data_size(src);
while (size < srclen)
if (src[size++] != 0)
- throw CHDERR_INVALID_DATA;
+ throw std::error_condition(chd_file::error::INVALID_DATA);
}
// encode the audio and video
uint32_t complen;
avhuff_error averr = m_encoder.encode_data(src, dest, complen);
if (averr != AVHERR_NONE || complen > srclen)
- throw CHDERR_COMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::COMPRESSION_ERROR);
return complen;
}
@@ -1693,21 +1735,21 @@ void chd_avhuff_compressor::postinit()
{
// get the metadata
std::string metadata;
- chd_error err = chd().read_metadata(AV_METADATA_TAG, 0, metadata);
- if (err != CHDERR_NONE)
+ std::error_condition err = chd().read_metadata(AV_METADATA_TAG, 0, metadata);
+ if (err)
throw err;
// extract the info
int fps, fpsfrac, width, height, interlaced, channels, rate;
if (sscanf(metadata.c_str(), AV_METADATA_FORMAT, &fps, &fpsfrac, &width, &height, &interlaced, &channels, &rate) != 7)
- throw CHDERR_INVALID_METADATA;
+ throw std::error_condition(chd_file::error::INVALID_METADATA);
// compute the bytes per frame
uint32_t fps_times_1million = fps * 1000000 + fpsfrac;
uint32_t max_samples_per_frame = (uint64_t(rate) * 1000000 + fps_times_1million - 1) / fps_times_1million;
uint32_t bytes_per_frame = 12 + channels * max_samples_per_frame * 2 + width * height * 2;
if (bytes_per_frame > hunkbytes())
- throw CHDERR_INVALID_METADATA;
+ throw std::error_condition(chd_file::error::INVALID_METADATA);
// done with post-init
m_postinit = true;
@@ -1757,7 +1799,7 @@ void chd_avhuff_decompressor::decompress(const uint8_t *src, uint32_t complen, u
// decode the audio and video
avhuff_error averr = m_decoder.decode_data(src, complen, dest);
if (averr != AVHERR_NONE)
- throw CHDERR_DECOMPRESSION_ERROR;
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// pad short frames with 0
if (dest != nullptr)
@@ -1790,5 +1832,5 @@ void chd_avhuff_decompressor::configure(int param, void *config)
// anything else is invalid
else
- throw CHDERR_INVALID_PARAMETER;
+ throw std::error_condition(std::errc::invalid_argument);
}
diff --git a/src/lib/util/chdcodec.h b/src/lib/util/chdcodec.h
index dc9c074fd37..700ae8f8979 100644
--- a/src/lib/util/chdcodec.h
+++ b/src/lib/util/chdcodec.h
@@ -7,13 +7,15 @@
Codecs used by the CHD format
***************************************************************************/
-
-#ifndef MAME_UTIL_CHDCODEC_H
-#define MAME_UTIL_CHDCODEC_H
+#ifndef MAME_LIB_UTIL_CHDCODEC_H
+#define MAME_LIB_UTIL_CHDCODEC_H
#pragma once
+#include "utilfwd.h"
+
#include <cstdint>
+#include <memory>
#include <vector>
@@ -21,20 +23,9 @@
//**************************************************************************
-// MACROS
-//**************************************************************************
-
-#define CHD_MAKE_TAG(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
-
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// forward references
-class chd_file;
-
// base types
typedef uint32_t chd_codec_type;
@@ -63,7 +54,7 @@ public:
private:
// internal state
chd_file & m_chd;
- uint32_t m_hunkbytes;
+ uint32_t m_hunkbytes;
bool m_lossy;
};
@@ -78,6 +69,8 @@ protected:
chd_compressor(chd_file &file, uint32_t hunkbytes, bool lossy);
public:
+ using ptr = std::unique_ptr<chd_compressor>;
+
// implementation
virtual uint32_t compress(const uint8_t *src, uint32_t srclen, uint8_t *dest) = 0;
};
@@ -93,6 +86,8 @@ protected:
chd_decompressor(chd_file &file, uint32_t hunkbytes, bool lossy);
public:
+ using ptr = std::unique_ptr<chd_decompressor>;
+
// implementation
virtual void decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) = 0;
};
@@ -105,35 +100,12 @@ class chd_codec_list
{
public:
// create compressors or decompressors
- static chd_compressor *new_compressor(chd_codec_type type, chd_file &file);
- static chd_decompressor *new_decompressor(chd_codec_type type, chd_file &file);
+ static chd_compressor::ptr new_compressor(chd_codec_type type, chd_file &file);
+ static chd_decompressor::ptr new_decompressor(chd_codec_type type, chd_file &file);
// utilities
- static bool codec_exists(chd_codec_type type) { return (find_in_list(type) != nullptr); }
+ static bool codec_exists(chd_codec_type type);
static const char *codec_name(chd_codec_type type);
-
-private:
- // an entry in the list
- struct codec_entry
- {
- chd_codec_type m_type;
- bool m_lossy;
- const char * m_name;
- chd_compressor * (*m_construct_compressor)(chd_file &, uint32_t, bool);
- chd_decompressor * (*m_construct_decompressor)(chd_file &, uint32_t, bool);
- };
-
- // internal helper functions
- static const codec_entry *find_in_list(chd_codec_type type);
-
- template<class _CompressorClass>
- static chd_compressor *construct_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy) { return new _CompressorClass(chd, hunkbytes, lossy); }
-
- template<class _DecompressorClass>
- static chd_decompressor *construct_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy) { return new _DecompressorClass(chd, hunkbytes, lossy); }
-
- // the static list
- static const codec_entry s_codec_list[];
};
@@ -152,37 +124,48 @@ public:
private:
// internal state
- uint32_t m_hunkbytes; // number of bytes in a hunk
- chd_compressor * m_compressor[4]; // array of active codecs
- std::vector<uint8_t> m_compress_test; // test buffer for compression
+ uint32_t m_hunkbytes; // number of bytes in a hunk
+ chd_compressor::ptr m_compressor[4]; // array of active codecs
+ std::vector<uint8_t> m_compress_test; // test buffer for compression
#if CHDCODEC_VERIFY_COMPRESSION
- chd_decompressor * m_decompressor[4]; // array of active codecs
- std::vector<uint8_t> m_decompressed; // verification buffer
+ chd_decompressor::ptr m_decompressor[4]; // array of active codecs
+ std::vector<uint8_t> m_decompressed; // verification buffer
#endif
};
//**************************************************************************
+// MACROS
+//**************************************************************************
+
+constexpr chd_codec_type CHD_MAKE_TAG(char a, char b, char c, char d)
+{
+ return (uint32_t(uint8_t(a)) << 24) | uint32_t(uint8_t((b)) << 16) | uint32_t(uint8_t((c)) << 8) | uint32_t(uint8_t(d));
+}
+
+
+
+//**************************************************************************
// CONSTANTS
//**************************************************************************
// currently-defined codecs
-const chd_codec_type CHD_CODEC_NONE = 0;
+constexpr chd_codec_type CHD_CODEC_NONE = 0;
// general codecs
-const chd_codec_type CHD_CODEC_ZLIB = CHD_MAKE_TAG('z','l','i','b');
-const chd_codec_type CHD_CODEC_LZMA = CHD_MAKE_TAG('l','z','m','a');
-const chd_codec_type CHD_CODEC_HUFFMAN = CHD_MAKE_TAG('h','u','f','f');
-const chd_codec_type CHD_CODEC_FLAC = CHD_MAKE_TAG('f','l','a','c');
+constexpr chd_codec_type CHD_CODEC_ZLIB = CHD_MAKE_TAG('z','l','i','b');
+constexpr chd_codec_type CHD_CODEC_LZMA = CHD_MAKE_TAG('l','z','m','a');
+constexpr chd_codec_type CHD_CODEC_HUFFMAN = CHD_MAKE_TAG('h','u','f','f');
+constexpr chd_codec_type CHD_CODEC_FLAC = CHD_MAKE_TAG('f','l','a','c');
// general codecs with CD frontend
-const chd_codec_type CHD_CODEC_CD_ZLIB = CHD_MAKE_TAG('c','d','z','l');
-const chd_codec_type CHD_CODEC_CD_LZMA = CHD_MAKE_TAG('c','d','l','z');
-const chd_codec_type CHD_CODEC_CD_FLAC = CHD_MAKE_TAG('c','d','f','l');
+constexpr chd_codec_type CHD_CODEC_CD_ZLIB = CHD_MAKE_TAG('c','d','z','l');
+constexpr chd_codec_type CHD_CODEC_CD_LZMA = CHD_MAKE_TAG('c','d','l','z');
+constexpr chd_codec_type CHD_CODEC_CD_FLAC = CHD_MAKE_TAG('c','d','f','l');
// A/V codecs
-const chd_codec_type CHD_CODEC_AVHUFF = CHD_MAKE_TAG('a','v','h','u');
+constexpr chd_codec_type CHD_CODEC_AVHUFF = CHD_MAKE_TAG('a','v','h','u');
// A/V codec configuration parameters
enum
@@ -190,4 +173,4 @@ enum
AVHUFF_CODEC_DECOMPRESS_CONFIG = 1
};
-#endif // MAME_UTIL_CHDCODEC_H
+#endif // MAME_LIB_UTIL_CHDCODEC_H
diff --git a/src/lib/util/corefile.cpp b/src/lib/util/corefile.cpp
index e681c0f1fac..0c72e1337be 100644
--- a/src/lib/util/corefile.cpp
+++ b/src/lib/util/corefile.cpp
@@ -12,18 +12,16 @@
#include "coretmpl.h"
#include "osdcore.h"
+#include "path.h"
#include "unicode.h"
#include "vecstream.h"
-#include <zlib.h>
-
#include <algorithm>
#include <cassert>
+#include <cctype>
#include <cstring>
#include <iterator>
-#include <cctype>
-
namespace util {
@@ -43,110 +41,11 @@ namespace {
TYPE DEFINITIONS
***************************************************************************/
-class zlib_data
-{
-public:
- typedef std::unique_ptr<zlib_data> ptr;
-
- static int start_compression(int level, std::uint64_t offset, ptr &data)
- {
- ptr result(new zlib_data(offset));
- result->reset_output();
- auto const zerr = deflateInit(&result->m_stream, level);
- result->m_compress = (Z_OK == zerr);
- if (result->m_compress) data = std::move(result);
- return zerr;
- }
- static int start_decompression(std::uint64_t offset, ptr &data)
- {
- ptr result(new zlib_data(offset));
- auto const zerr = inflateInit(&result->m_stream);
- result->m_decompress = (Z_OK == zerr);
- if (result->m_decompress) data = std::move(result);
- return zerr;
- }
-
- ~zlib_data()
- {
- if (m_compress) deflateEnd(&m_stream);
- else if (m_decompress) inflateEnd(&m_stream);
- }
-
- std::size_t buffer_size() const { return sizeof(m_buffer); }
- void const *buffer_data() const { return m_buffer; }
- void *buffer_data() { return m_buffer; }
-
- // general-purpose output buffer manipulation
- bool output_full() const { return 0 == m_stream.avail_out; }
- std::size_t output_space() const { return m_stream.avail_out; }
- void set_output(void *data, std::uint32_t size)
- {
- m_stream.next_out = reinterpret_cast<Bytef *>(data);
- m_stream.avail_out = size;
- }
-
- // working with output to the internal buffer
- bool has_output() const { return m_stream.avail_out != sizeof(m_buffer); }
- std::size_t output_size() const { return sizeof(m_buffer) - m_stream.avail_out; }
- void reset_output()
- {
- m_stream.next_out = m_buffer;
- m_stream.avail_out = sizeof(m_buffer);
- }
-
- // general-purpose input buffer manipulation
- bool has_input() const { return 0 != m_stream.avail_in; }
- std::size_t input_size() const { return m_stream.avail_in; }
- void set_input(void const *data, std::uint32_t size)
- {
- m_stream.next_in = const_cast<Bytef *>(reinterpret_cast<Bytef const *>(data));
- m_stream.avail_in = size;
- }
-
- // working with input from the internal buffer
- void reset_input(std::uint32_t size)
- {
- m_stream.next_in = m_buffer;
- m_stream.avail_in = size;
- }
-
- int compress() { assert(m_compress); return deflate(&m_stream, Z_NO_FLUSH); }
- int finalise() { assert(m_compress); return deflate(&m_stream, Z_FINISH); }
- int decompress() { assert(m_decompress); return inflate(&m_stream, Z_SYNC_FLUSH); }
-
- std::uint64_t realoffset() const { return m_realoffset; }
- void add_realoffset(std::uint32_t increment) { m_realoffset += increment; }
-
- bool is_nextoffset(std::uint64_t value) const { return m_nextoffset == value; }
- void add_nextoffset(std::uint32_t increment) { m_nextoffset += increment; }
-
-private:
- zlib_data(std::uint64_t offset)
- : m_compress(false)
- , m_decompress(false)
- , m_realoffset(offset)
- , m_nextoffset(offset)
- {
- m_stream.zalloc = Z_NULL;
- m_stream.zfree = Z_NULL;
- m_stream.opaque = Z_NULL;
- m_stream.avail_in = m_stream.avail_out = 0;
- }
-
- bool m_compress, m_decompress;
- z_stream m_stream;
- std::uint8_t m_buffer[1024];
- std::uint64_t m_realoffset;
- std::uint64_t m_nextoffset;
-};
-
-
class core_proxy_file : public core_file
{
public:
- core_proxy_file(core_file &file) : m_file(file) { }
+ core_proxy_file(core_file &file) noexcept : m_file(file) { }
virtual ~core_proxy_file() override { }
- virtual osd_file::error compress(int level) override { return m_file.compress(level); }
virtual int seek(std::int64_t offset, int whence) override { return m_file.seek(offset, whence); }
virtual std::uint64_t tell() const override { return m_file.tell(); }
@@ -162,9 +61,9 @@ public:
virtual std::uint32_t write(const void *buffer, std::uint32_t length) override { return m_file.write(buffer, length); }
virtual int puts(std::string_view s) override { return m_file.puts(s); }
virtual int vprintf(util::format_argument_pack<std::ostream> const &args) override { return m_file.vprintf(args); }
- virtual osd_file::error truncate(std::uint64_t offset) override { return m_file.truncate(offset); }
+ virtual std::error_condition truncate(std::uint64_t offset) override { return m_file.truncate(offset); }
- virtual osd_file::error flush() override { return m_file.flush(); }
+ virtual std::error_condition flush() override { return m_file.flush(); }
private:
core_file &m_file;
@@ -230,12 +129,12 @@ public:
if (copy)
{
void *const buf = allocate();
- if (buf) std::memcpy(buf, data, length);
+ if (buf)
+ std::memcpy(buf, data, length);
}
}
~core_in_memory_file() override { purge(); }
- virtual osd_file::error compress(int level) override { return osd_file::error::INVALID_ACCESS; }
virtual int seek(std::int64_t offset, int whence) override;
virtual std::uint64_t tell() const override { return m_offset; }
@@ -246,8 +145,8 @@ public:
virtual void const *buffer() override { return m_data; }
virtual std::uint32_t write(void const *buffer, std::uint32_t length) override { return 0; }
- virtual osd_file::error truncate(std::uint64_t offset) override;
- virtual osd_file::error flush() override { clear_putback(); return osd_file::error::NONE; }
+ virtual std::error_condition truncate(std::uint64_t offset) override;
+ virtual std::error_condition flush() override { clear_putback(); return std::error_condition(); }
protected:
core_in_memory_file(std::uint32_t openflags, std::uint64_t length)
@@ -262,7 +161,8 @@ protected:
bool is_loaded() const { return nullptr != m_data; }
void *allocate()
{
- if (m_data) return nullptr;
+ if (m_data)
+ return nullptr;
void *data = malloc(m_length);
if (data)
{
@@ -273,7 +173,8 @@ protected:
}
void purge()
{
- if (m_data && m_data_allocated) free(const_cast<void *>(m_data));
+ if (m_data && m_data_allocated)
+ free(const_cast<void *>(m_data));
m_data_allocated = false;
m_data = nullptr;
}
@@ -301,23 +202,18 @@ public:
core_osd_file(std::uint32_t openmode, osd_file::ptr &&file, std::uint64_t length)
: core_in_memory_file(openmode, length)
, m_file(std::move(file))
- , m_zdata()
, m_bufferbase(0)
, m_bufferbytes(0)
{
}
~core_osd_file() override;
- virtual osd_file::error compress(int level) override;
-
- virtual int seek(std::int64_t offset, int whence) override;
-
virtual std::uint32_t read(void *buffer, std::uint32_t length) override;
virtual void const *buffer() override;
virtual std::uint32_t write(void const *buffer, std::uint32_t length) override;
- virtual osd_file::error truncate(std::uint64_t offset) override;
- virtual osd_file::error flush() override;
+ virtual std::error_condition truncate(std::uint64_t offset) override;
+ virtual std::error_condition flush() override;
protected:
@@ -326,11 +222,7 @@ protected:
private:
static constexpr std::size_t FILE_BUFFER_SIZE = 512;
- osd_file::error osd_or_zlib_read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual);
- osd_file::error osd_or_zlib_write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual);
-
osd_file::ptr m_file; // OSD file handle
- zlib_data::ptr m_zdata; // compression data
std::uint64_t m_bufferbase; // base offset of internal buffer
std::uint32_t m_bufferbytes; // bytes currently loaded into buffer
std::uint8_t m_buffer[FILE_BUFFER_SIZE]; // buffer data
@@ -673,14 +565,14 @@ std::uint32_t core_in_memory_file::read(void *buffer, std::uint32_t length)
truncate - truncate a file
-------------------------------------------------*/
-osd_file::error core_in_memory_file::truncate(std::uint64_t offset)
+std::error_condition core_in_memory_file::truncate(std::uint64_t offset)
{
if (m_length < offset)
- return osd_file::error::FAILURE;
+ return std::errc::io_error; // TODO: revisit this error code
// adjust to new length and offset
set_length(offset);
- return osd_file::error::NONE;
+ return std::error_condition();
}
@@ -719,91 +611,6 @@ std::size_t core_in_memory_file::safe_buffer_copy(
core_osd_file::~core_osd_file()
{
// close files and free memory
- if (m_zdata)
- core_osd_file::compress(FCOMPRESS_NONE);
-}
-
-
-/*-------------------------------------------------
- compress - enable/disable streaming file
- compression via zlib; level is 0 to disable
- compression, or up to 9 for max compression
--------------------------------------------------*/
-
-osd_file::error core_osd_file::compress(int level)
-{
- osd_file::error result = osd_file::error::NONE;
-
- // can only do this for read-only and write-only cases
- if (read_access() && write_access())
- return osd_file::error::INVALID_ACCESS;
-
- // if we have been compressing, flush and free the data
- if (m_zdata && (level == FCOMPRESS_NONE))
- {
- int zerr = Z_OK;
-
- // flush any remaining data if we are writing
- while (write_access() && (zerr != Z_STREAM_END))
- {
- // deflate some more
- zerr = m_zdata->finalise();
- if ((zerr != Z_STREAM_END) && (zerr != Z_OK))
- {
- result = osd_file::error::INVALID_DATA;
- break;
- }
-
- // write the data
- if (m_zdata->has_output())
- {
- std::uint32_t actualdata;
- auto const filerr = m_file->write(m_zdata->buffer_data(), m_zdata->realoffset(), m_zdata->output_size(), actualdata);
- if (filerr != osd_file::error::NONE)
- break;
- m_zdata->add_realoffset(actualdata);
- m_zdata->reset_output();
- }
- }
-
- // free memory
- m_zdata.reset();
- }
-
- // if we are just starting to compress, allocate a new buffer
- if (!m_zdata && (level > FCOMPRESS_NONE))
- {
- int zerr;
-
- // initialize the stream and compressor
- if (write_access())
- zerr = zlib_data::start_compression(level, offset(), m_zdata);
- else
- zerr = zlib_data::start_decompression(offset(), m_zdata);
-
- // on error, return an error
- if (zerr != Z_OK)
- return osd_file::error::OUT_OF_MEMORY;
-
- // flush buffers
- m_bufferbytes = 0;
- }
-
- return result;
-}
-
-
-/*-------------------------------------------------
- seek - seek within a file
--------------------------------------------------*/
-
-int core_osd_file::seek(std::int64_t offset, int whence)
-{
- // error if compressing
- if (m_zdata)
- return 1;
- else
- return core_in_memory_file::seek(offset, whence);
}
@@ -833,7 +640,7 @@ std::uint32_t core_osd_file::read(void *buffer, std::uint32_t length)
// read as much as makes sense into the buffer
m_bufferbase = offset() + bytes_read;
m_bufferbytes = 0;
- osd_or_zlib_read(m_buffer, m_bufferbase, sizeof(m_buffer), m_bufferbytes);
+ m_file->read(m_buffer, m_bufferbase, sizeof(m_buffer), m_bufferbytes);
// do a bounded copy from the buffer to the destination
bytes_read += safe_buffer_copy(m_buffer, 0, m_bufferbytes, buffer, bytes_read, length);
@@ -842,7 +649,7 @@ std::uint32_t core_osd_file::read(void *buffer, std::uint32_t length)
{
// read the remainder directly from the file
std::uint32_t new_bytes_read = 0;
- osd_or_zlib_read(reinterpret_cast<std::uint8_t *>(buffer) + bytes_read, offset() + bytes_read, length - bytes_read, new_bytes_read);
+ m_file->read(reinterpret_cast<std::uint8_t *>(buffer) + bytes_read, offset() + bytes_read, length - bytes_read, new_bytes_read);
bytes_read += new_bytes_read;
}
}
@@ -866,18 +673,16 @@ void const *core_osd_file::buffer()
{
// allocate some memory
void *buf = allocate();
- if (!buf) return nullptr;
+ if (!buf)
+ return nullptr;
// read the file
std::uint32_t read_length = 0;
- auto const filerr = osd_or_zlib_read(buf, 0, length(), read_length);
- if ((filerr != osd_file::error::NONE) || (read_length != length()))
+ auto const filerr = m_file->read(buf, 0, length(), read_length);
+ if (filerr || (read_length != length()))
purge();
else
- {
- // close the file because we don't need it anymore
- m_file.reset();
- }
+ m_file.reset(); // close the file because we don't need it anymore
}
return core_in_memory_file::buffer();
}
@@ -901,7 +706,7 @@ std::uint32_t core_osd_file::write(void const *buffer, std::uint32_t length)
// do the write
std::uint32_t bytes_written = 0;
- osd_or_zlib_write(buffer, offset(), length, bytes_written);
+ m_file->write(buffer, offset(), length, bytes_written);
// return the number of bytes written
add_offset(bytes_written);
@@ -913,19 +718,19 @@ std::uint32_t core_osd_file::write(void const *buffer, std::uint32_t length)
truncate - truncate a file
-------------------------------------------------*/
-osd_file::error core_osd_file::truncate(std::uint64_t offset)
+std::error_condition core_osd_file::truncate(std::uint64_t offset)
{
if (is_loaded())
return core_in_memory_file::truncate(offset);
// truncate file
auto const err = m_file->truncate(offset);
- if (err != osd_file::error::NONE)
+ if (err)
return err;
// and adjust to new length and offset
set_length(offset);
- return osd_file::error::NONE;
+ return std::error_condition();
}
@@ -933,7 +738,7 @@ osd_file::error core_osd_file::truncate(std::uint64_t offset)
flush - flush file buffers
-------------------------------------------------*/
-osd_file::error core_osd_file::flush()
+std::error_condition core_osd_file::flush()
{
if (is_loaded())
return core_in_memory_file::flush();
@@ -947,116 +752,6 @@ osd_file::error core_osd_file::flush()
return m_file->flush();
}
-
-/*-------------------------------------------------
- osd_or_zlib_read - wrapper for osd_read that
- handles zlib-compressed data
--------------------------------------------------*/
-
-osd_file::error core_osd_file::osd_or_zlib_read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual)
-{
- // if no compression, just pass through
- if (!m_zdata)
- return m_file->read(buffer, offset, length, actual);
-
- // if the offset doesn't match the next offset, fail
- if (!m_zdata->is_nextoffset(offset))
- return osd_file::error::INVALID_ACCESS;
-
- // set up the destination
- osd_file::error filerr = osd_file::error::NONE;
- m_zdata->set_output(buffer, length);
- while (!m_zdata->output_full())
- {
- // if we didn't make progress, report an error or the end
- if (m_zdata->has_input())
- {
- auto const zerr = m_zdata->decompress();
- if (Z_OK != zerr)
- {
- if (Z_STREAM_END != zerr) filerr = osd_file::error::INVALID_DATA;
- break;
- }
- }
-
- // fetch more data if needed
- if (!m_zdata->has_input())
- {
- std::uint32_t actualdata = 0;
- filerr = m_file->read(m_zdata->buffer_data(), m_zdata->realoffset(), m_zdata->buffer_size(), actualdata);
- if (filerr != osd_file::error::NONE) break;
- m_zdata->add_realoffset(actualdata);
- m_zdata->reset_input(actualdata);
- if (!m_zdata->has_input()) break;
- }
- }
-
- // adjust everything
- actual = length - m_zdata->output_space();
- m_zdata->add_nextoffset(actual);
- return filerr;
-}
-
-
-/*-------------------------------------------------
- osd_or_zlib_write - wrapper for osd_write that
- handles zlib-compressed data
--------------------------------------------------*/
-
-/**
- * @fn osd_file::error osd_or_zlib_write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t actual)
- *
- * @brief OSD or zlib write.
- *
- * @param buffer The buffer.
- * @param offset The offset.
- * @param length The length.
- * @param [in,out] actual The actual.
- *
- * @return A osd_file::error.
- */
-
-osd_file::error core_osd_file::osd_or_zlib_write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual)
-{
- // if no compression, just pass through
- if (!m_zdata)
- return m_file->write(buffer, offset, length, actual);
-
- // if the offset doesn't match the next offset, fail
- if (!m_zdata->is_nextoffset(offset))
- return osd_file::error::INVALID_ACCESS;
-
- // set up the source
- m_zdata->set_input(buffer, length);
- while (m_zdata->has_input())
- {
- // if we didn't make progress, report an error or the end
- auto const zerr = m_zdata->compress();
- if (zerr != Z_OK)
- {
- actual = length - m_zdata->input_size();
- m_zdata->add_nextoffset(actual);
- return osd_file::error::INVALID_DATA;
- }
-
- // write more data if we are full up
- if (m_zdata->output_full())
- {
- std::uint32_t actualdata = 0;
- auto const filerr = m_file->write(m_zdata->buffer_data(), m_zdata->realoffset(), m_zdata->output_size(), actualdata);
- if (filerr != osd_file::error::NONE)
- return filerr;
- m_zdata->add_realoffset(actualdata);
- m_zdata->reset_output();
- }
- }
-
- // we wrote everything
- actual = length;
- m_zdata->add_nextoffset(actual);
- return osd_file::error::NONE;
-}
-
} // anonymous namespace
@@ -1070,23 +765,23 @@ osd_file::error core_osd_file::osd_or_zlib_write(void const *buffer, std::uint64
return an error code
-------------------------------------------------*/
-osd_file::error core_file::open(std::string const &filename, std::uint32_t openflags, ptr &file)
+std::error_condition core_file::open(std::string_view filename, std::uint32_t openflags, ptr &file)
{
try
{
// attempt to open the file
osd_file::ptr f;
std::uint64_t length = 0;
- auto const filerr = osd_file::open(filename, openflags, f, length);
- if (filerr != osd_file::error::NONE)
+ auto const filerr = osd_file::open(std::string(filename), openflags, f, length); // FIXME: allow osd_file to accept std::string_view
+ if (filerr)
return filerr;
file = std::make_unique<core_osd_file>(openflags, std::move(f), length);
- return osd_file::error::NONE;
+ return std::error_condition();
}
catch (...)
{
- return osd_file::error::OUT_OF_MEMORY;
+ return std::errc::not_enough_memory;
}
}
@@ -1096,20 +791,20 @@ osd_file::error core_file::open(std::string const &filename, std::uint32_t openf
like access and return an error code
-------------------------------------------------*/
-osd_file::error core_file::open_ram(void const *data, std::size_t length, std::uint32_t openflags, ptr &file)
+std::error_condition core_file::open_ram(void const *data, std::size_t length, std::uint32_t openflags, ptr &file)
{
// can only do this for read access
if ((openflags & OPEN_FLAG_WRITE) || (openflags & OPEN_FLAG_CREATE))
- return osd_file::error::INVALID_ACCESS;
+ return std::errc::invalid_argument;
try
{
file.reset(new core_in_memory_file(openflags, data, length, false));
- return osd_file::error::NONE;
+ return std::error_condition();
}
catch (...)
{
- return osd_file::error::OUT_OF_MEMORY;
+ return std::errc::not_enough_memory;
}
}
@@ -1120,24 +815,24 @@ osd_file::error core_file::open_ram(void const *data, std::size_t length, std::u
error code
-------------------------------------------------*/
-osd_file::error core_file::open_ram_copy(void const *data, std::size_t length, std::uint32_t openflags, ptr &file)
+std::error_condition core_file::open_ram_copy(void const *data, std::size_t length, std::uint32_t openflags, ptr &file)
{
// can only do this for read access
if ((openflags & OPEN_FLAG_WRITE) || (openflags & OPEN_FLAG_CREATE))
- return osd_file::error::INVALID_ACCESS;
+ return std::errc::invalid_argument;
try
{
ptr result(new core_in_memory_file(openflags, data, length, true));
if (!result->buffer())
- return osd_file::error::OUT_OF_MEMORY;
+ return std::errc::not_enough_memory;
file = std::move(result);
- return osd_file::error::NONE;
+ return std::error_condition();
}
catch (...)
{
- return osd_file::error::OUT_OF_MEMORY;
+ return std::errc::not_enough_memory;
}
}
@@ -1147,17 +842,14 @@ osd_file::error core_file::open_ram_copy(void const *data, std::size_t length, s
object and return an error code
-------------------------------------------------*/
-osd_file::error core_file::open_proxy(core_file &file, ptr &proxy)
+std::error_condition core_file::open_proxy(core_file &file, ptr &proxy)
{
- try
- {
- proxy = std::make_unique<core_proxy_file>(file);
- return osd_file::error::NONE;
- }
- catch (...)
- {
- return osd_file::error::OUT_OF_MEMORY;
- }
+ ptr result(new (std::nothrow) core_proxy_file(file));
+ if (!result)
+ return std::errc::not_enough_memory;
+
+ proxy = std::move(result);
+ return std::error_condition();
}
@@ -1176,61 +868,64 @@ core_file::~core_file()
pointer
-------------------------------------------------*/
-osd_file::error core_file::load(std::string const &filename, void **data, std::uint32_t &length)
+std::error_condition core_file::load(std::string_view filename, void **data, std::uint32_t &length)
{
ptr file;
// attempt to open the file
auto const err = open(filename, OPEN_FLAG_READ, file);
- if (err != osd_file::error::NONE)
+ if (err)
return err;
// get the size
auto const size = file->size();
if (std::uint32_t(size) != size)
- return osd_file::error::OUT_OF_MEMORY;
+ return std::errc::file_too_large;
// allocate memory
*data = malloc(size);
+ if (!*data)
+ return std::errc::not_enough_memory;
length = std::uint32_t(size);
// read the data
if (file->read(*data, size) != size)
{
free(*data);
- return osd_file::error::FAILURE;
+ return std::errc::io_error; // TODO: revisit this error code
}
// close the file and return data
- return osd_file::error::NONE;
+ return std::error_condition();
}
-osd_file::error core_file::load(std::string const &filename, std::vector<uint8_t> &data)
+std::error_condition core_file::load(std::string_view filename, std::vector<uint8_t> &data)
{
ptr file;
// attempt to open the file
auto const err = open(filename, OPEN_FLAG_READ, file);
- if (err != osd_file::error::NONE)
+ if (err)
return err;
// get the size
auto const size = file->size();
if (std::uint32_t(size) != size)
- return osd_file::error::OUT_OF_MEMORY;
+ return std::errc::file_too_large;
// allocate memory
- data.resize(size);
+ try { data.resize(size); }
+ catch (...) { return std::errc::not_enough_memory; }
// read the data
if (file->read(&data[0], size) != size)
{
data.clear();
- return osd_file::error::FAILURE;
+ return std::errc::io_error; // TODO: revisit this error code
}
// close the file and return data
- return osd_file::error::NONE;
+ return std::error_condition();
}
@@ -1256,7 +951,7 @@ core_file::core_file()
// assumptions about path separators
// -------------------------------------------------
-std::string_view core_filename_extract_base(std::string_view name, bool strip_extension)
+std::string_view core_filename_extract_base(std::string_view name, bool strip_extension) noexcept
{
// find the start of the basename
auto const start = std::find_if(name.rbegin(), name.rend(), &util::is_directory_separator);
@@ -1279,7 +974,7 @@ std::string_view core_filename_extract_base(std::string_view name, bool strip_ex
// core_filename_extract_extension
// -------------------------------------------------
-std::string_view core_filename_extract_extension(std::string_view filename, bool strip_period)
+std::string_view core_filename_extract_extension(std::string_view filename, bool strip_period) noexcept
{
auto loc = filename.find_last_of('.');
if (loc != std::string_view::npos)
@@ -1294,7 +989,7 @@ std::string_view core_filename_extract_extension(std::string_view filename, bool
// filename end with the specified extension?
// -------------------------------------------------
-bool core_filename_ends_with(std::string_view filename, std::string_view extension)
+bool core_filename_ends_with(std::string_view filename, std::string_view extension) noexcept
{
auto namelen = filename.length();
auto extlen = extension.length();
diff --git a/src/lib/util/corefile.h b/src/lib/util/corefile.h
index 6aaa8f609e1..19febbb46f1 100644
--- a/src/lib/util/corefile.h
+++ b/src/lib/util/corefile.h
@@ -12,14 +12,13 @@
#pragma once
-
#include "osdfile.h"
#include "strformat.h"
#include <cstdint>
#include <memory>
-#include <string>
#include <string_view>
+#include <system_error>
namespace util {
@@ -30,11 +29,6 @@ namespace util {
#define OPEN_FLAG_NO_BOM 0x0100 /* don't output BOM */
-#define FCOMPRESS_NONE 0 /* no compression */
-#define FCOMPRESS_MIN 1 /* minimal compression */
-#define FCOMPRESS_MEDIUM 6 /* standard compression */
-#define FCOMPRESS_MAX 9 /* maximum compression */
-
/***************************************************************************
TYPE DEFINITIONS
@@ -49,23 +43,20 @@ public:
// ----- file open/close -----
// open a file with the specified filename
- static osd_file::error open(std::string const &filename, std::uint32_t openflags, ptr &file);
+ static std::error_condition open(std::string_view filename, std::uint32_t openflags, ptr &file);
// open a RAM-based "file" using the given data and length (read-only)
- static osd_file::error open_ram(const void *data, std::size_t length, std::uint32_t openflags, ptr &file);
+ static std::error_condition open_ram(const void *data, std::size_t length, std::uint32_t openflags, ptr &file);
// open a RAM-based "file" using the given data and length (read-only), copying the data
- static osd_file::error open_ram_copy(const void *data, std::size_t length, std::uint32_t openflags, ptr &file);
+ static std::error_condition open_ram_copy(const void *data, std::size_t length, std::uint32_t openflags, ptr &file);
// open a proxy "file" that forwards requests to another file object
- static osd_file::error open_proxy(core_file &file, ptr &proxy);
+ static std::error_condition open_proxy(core_file &file, ptr &proxy);
// close an open file
virtual ~core_file();
- // enable/disable streaming file compression via zlib; level is 0 to disable compression, or up to 9 for max compression
- virtual osd_file::error compress(int level) = 0;
-
// ----- file positioning -----
@@ -101,8 +92,8 @@ public:
virtual const void *buffer() = 0;
// open a file with the specified filename, read it into memory, and return a pointer
- static osd_file::error load(std::string const &filename, void **data, std::uint32_t &length);
- static osd_file::error load(std::string const &filename, std::vector<uint8_t> &data);
+ static std::error_condition load(std::string_view filename, void **data, std::uint32_t &length);
+ static std::error_condition load(std::string_view filename, std::vector<uint8_t> &data);
// ----- file write -----
@@ -121,32 +112,16 @@ public:
}
// file truncation
- virtual osd_file::error truncate(std::uint64_t offset) = 0;
+ virtual std::error_condition truncate(std::uint64_t offset) = 0;
// flush file buffers
- virtual osd_file::error flush() = 0;
+ virtual std::error_condition flush() = 0;
protected:
core_file();
};
-
-/***************************************************************************
- INLINE FUNCTIONS
-***************************************************************************/
-
-// is a given character a directory separator?
-
-constexpr bool is_directory_separator(char c)
-{
-#if defined(WIN32)
- return ('\\' == c) || ('/' == c) || (':' == c);
-#else
- return '/' == c;
-#endif
-}
-
} // namespace util
@@ -157,13 +132,13 @@ constexpr bool is_directory_separator(char c)
/* ----- filename utilities ----- */
// extract the base part of a filename (remove extensions and paths)
-std::string_view core_filename_extract_base(std::string_view name, bool strip_extension = false);
+std::string_view core_filename_extract_base(std::string_view name, bool strip_extension = false) noexcept;
// extracts the file extension from a filename
-std::string_view core_filename_extract_extension(std::string_view filename, bool strip_period = false);
+std::string_view core_filename_extract_extension(std::string_view filename, bool strip_period = false) noexcept;
// true if the given filename ends with a particular extension
-bool core_filename_ends_with(std::string_view filename, std::string_view extension);
+bool core_filename_ends_with(std::string_view filename, std::string_view extension) noexcept;
#endif // MAME_LIB_UTIL_COREFILE_H
diff --git a/src/lib/util/harddisk.cpp b/src/lib/util/harddisk.cpp
index e91759c44f2..2e8d14f9a8a 100644
--- a/src/lib/util/harddisk.cpp
+++ b/src/lib/util/harddisk.cpp
@@ -8,11 +8,13 @@
***************************************************************************/
-#include <cassert>
#include "harddisk.h"
-#include "osdcore.h"
+
+#include "corefile.h"
+
#include <cstdlib>
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
@@ -40,7 +42,7 @@ hard_disk_file *hard_disk_open(chd_file *chd)
int cylinders, heads, sectors, sectorbytes;
hard_disk_file *file;
std::string metadata;
- chd_error err;
+ std::error_condition err;
/* punt if no CHD */
if (chd == nullptr)
@@ -48,7 +50,7 @@ hard_disk_file *hard_disk_open(chd_file *chd)
/* read the hard disk metadata */
err = chd->read_metadata(HARD_DISK_METADATA_TAG, 0, metadata);
- if (err != CHDERR_NONE)
+ if (err)
return nullptr;
/* parse the metadata */
@@ -177,8 +179,8 @@ uint32_t hard_disk_read(hard_disk_file *file, uint32_t lbasector, void *buffer)
{
if (file->chd)
{
- chd_error err = file->chd->read_units(lbasector, buffer);
- return (err == CHDERR_NONE);
+ std::error_condition err = file->chd->read_units(lbasector, buffer);
+ return !err;
}
else
{
@@ -211,8 +213,8 @@ uint32_t hard_disk_write(hard_disk_file *file, uint32_t lbasector, const void *b
{
if (file->chd)
{
- chd_error err = file->chd->write_units(lbasector, buffer);
- return (err == CHDERR_NONE);
+ std::error_condition err = file->chd->write_units(lbasector, buffer);
+ return !err;
}
else
{
diff --git a/src/lib/util/harddisk.h b/src/lib/util/harddisk.h
index 2a4b727e7e7..e6fae165f19 100644
--- a/src/lib/util/harddisk.h
+++ b/src/lib/util/harddisk.h
@@ -8,13 +8,15 @@
***************************************************************************/
-#ifndef MAME_UTIL_HARDDISK_H
-#define MAME_UTIL_HARDDISK_H
+#ifndef MAME_LIB_UTIL_HARDDISK_H
+#define MAME_LIB_UTIL_HARDDISK_H
#pragma once
-#include "osdcore.h"
#include "chd.h"
+#include "utilfwd.h"
+
+#include "osdcore.h"
/***************************************************************************
@@ -49,4 +51,4 @@ hard_disk_info *hard_disk_get_info(hard_disk_file *file);
uint32_t hard_disk_read(hard_disk_file *file, uint32_t lbasector, void *buffer);
uint32_t hard_disk_write(hard_disk_file *file, uint32_t lbasector, const void *buffer);
-#endif // MAME_UTIL_HARDDISK_H
+#endif // MAME_LIB_UTIL_HARDDISK_H
diff --git a/src/lib/util/ioprocs.cpp b/src/lib/util/ioprocs.cpp
new file mode 100644
index 00000000000..1f52a3daf97
--- /dev/null
+++ b/src/lib/util/ioprocs.cpp
@@ -0,0 +1,1248 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ ioprocs.h
+
+ I/O interfaces
+
+***************************************************************************/
+
+#include "ioprocs.h"
+
+#include "corefile.h"
+#include "ioprocsfill.h"
+
+#include "osdfile.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cerrno>
+#include <cstring>
+#include <iterator>
+#include <limits>
+#include <type_traits>
+
+
+namespace util {
+
+namespace {
+
+// helper for holding a block of memory and deallocating it (or not) as necessary
+
+template <typename T, bool Owned>
+class ram_adapter_base : public virtual random_access
+{
+public:
+ virtual ~ram_adapter_base()
+ {
+ if constexpr (Owned)
+ std::free(m_data);
+ }
+
+ virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override
+ {
+ switch (whence)
+ {
+ case SEEK_SET:
+ if (0 > offset)
+ return std::errc::invalid_argument;
+ m_pointer = std::uint64_t(offset);
+ return std::error_condition();
+
+ case SEEK_CUR:
+ if (0 > offset)
+ {
+ if (std::uint64_t(-offset) > m_pointer)
+ return std::errc::invalid_argument;
+ }
+ else if ((std::numeric_limits<std::uint64_t>::max() - offset) < m_pointer)
+ {
+ return std::errc::invalid_argument;
+ }
+ m_pointer += offset;
+ return std::error_condition();
+
+ case SEEK_END:
+ if (0 > offset)
+ {
+ if (std::uint64_t(-offset) > m_size)
+ return std::errc::invalid_argument;
+ }
+ else if ((std::numeric_limits<std::uint64_t>::max() - offset) < m_size)
+ {
+ return std::errc::invalid_argument;
+ }
+ m_pointer = std::uint64_t(m_size) + offset;
+ return std::error_condition();
+
+ default:
+ return std::errc::invalid_argument;
+ }
+ }
+
+ virtual std::error_condition tell(std::uint64_t &result) noexcept override
+ {
+ result = m_pointer;
+ return std::error_condition();
+ }
+
+ virtual std::error_condition length(std::uint64_t &result) noexcept override
+ {
+ if (std::numeric_limits<uint64_t>::max() < m_size)
+ return std::errc::file_too_large;
+
+ result = m_size;
+ return std::error_condition();
+ }
+
+protected:
+ template <typename U>
+ ram_adapter_base(U *data, std::size_t size) noexcept : m_data(reinterpret_cast<T>(data)), m_size(size)
+ {
+ static_assert(sizeof(*m_data) == 1U, "Element type must be byte-sized");
+ assert(m_data || !m_size);
+ }
+
+ T m_data;
+ std::uint64_t m_pointer = 0U;
+ std::size_t m_size;
+};
+
+
+// RAM read implementation
+
+template <typename T, bool Owned>
+class ram_read_adapter : public ram_adapter_base<T, Owned>, public virtual random_read
+{
+public:
+ template <typename U>
+ ram_read_adapter(U *data, std::size_t size) noexcept : ram_adapter_base<T, Owned>(data, size)
+ {
+ }
+
+ virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ do_read(this->m_pointer, buffer, length, actual);
+ this->m_pointer += actual;
+ return std::error_condition();
+ }
+
+ virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ do_read(offset, buffer, length, actual);
+ return std::error_condition();
+ }
+
+private:
+ void do_read(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) const noexcept
+ {
+ if ((offset < this->m_size) && length)
+ {
+ actual = std::min(std::size_t(this->m_size - offset), length);
+ if constexpr (Owned)
+ std::memcpy(buffer, this->m_data + offset, actual);
+ else
+ std::memmove(buffer, this->m_data + offset, actual);
+ }
+ else
+ {
+ actual = 0U;
+ }
+ }
+};
+
+
+// helper for holding a stdio FILE and closing it (or not) as necessary
+
+class stdio_adapter_base : public virtual random_access
+{
+public:
+ virtual ~stdio_adapter_base()
+ {
+ if (m_close)
+ std::fclose(m_file);
+ }
+
+ virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override
+ {
+ if ((std::numeric_limits<long>::max() < offset) || (std::numeric_limits<long>::min() > offset))
+ return std::errc::invalid_argument;
+ else if (!std::fseek(m_file, long(offset), whence))
+ return std::error_condition();
+ else
+ return std::error_condition(errno, std::generic_category());
+ }
+
+ virtual std::error_condition tell(std::uint64_t &result) noexcept override
+ {
+ long const pos = std::ftell(m_file);
+ if (0 > pos)
+ return std::error_condition(errno, std::generic_category());
+ result = static_cast<unsigned long>(pos);
+ return std::error_condition();
+ }
+
+ virtual std::error_condition length(std::uint64_t &result) noexcept override
+ {
+ std::fpos_t oldpos;
+ if (std::fgetpos(m_file, &oldpos))
+ return std::error_condition(errno, std::generic_category());
+
+ long endpos = -1;
+ if (!std::fseek(m_file, 0, SEEK_END))
+ {
+ m_dangling_read = m_dangling_write = false;
+ endpos = std::ftell(m_file);
+ }
+ std::error_condition err;
+ if (0 > endpos)
+ err.assign(errno, std::generic_category());
+ else if (std::numeric_limits<std::uint64_t>::max() < static_cast<unsigned long>(endpos))
+ err = std::errc::file_too_large;
+ else
+ result = static_cast<unsigned long>(endpos);
+
+ if (!std::fsetpos(m_file, &oldpos))
+ m_dangling_read = m_dangling_write = false;
+ else if (!err)
+ err.assign(errno, std::generic_category());
+
+ return err;
+ }
+
+protected:
+ stdio_adapter_base(FILE *file, bool close) noexcept : m_file(file), m_close(close)
+ {
+ assert(m_file);
+ }
+
+ FILE *file() noexcept
+ {
+ return m_file;
+ }
+
+private:
+ FILE *const m_file;
+ bool const m_close;
+
+protected:
+ bool m_dangling_read = true, m_dangling_write = true;
+};
+
+
+// stdio read implementation
+
+class stdio_read_adapter : public stdio_adapter_base, public virtual random_read
+{
+public:
+ stdio_read_adapter(FILE *file, bool close) noexcept : stdio_adapter_base(file, close)
+ {
+ }
+
+ virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ if (m_dangling_write)
+ {
+ if (std::fflush(file()))
+ {
+ std::clearerr(file());
+ actual = 0U;
+ return std::error_condition(errno, std::generic_category());
+ }
+ m_dangling_write = false;
+ }
+
+ actual = std::fread(buffer, sizeof(std::uint8_t), length, file());
+ m_dangling_read = true;
+ if (length != actual)
+ {
+ if (std::ferror(file()))
+ {
+ std::clearerr(file());
+ return std::error_condition(errno, std::generic_category());
+ }
+ else if (std::feof(file()))
+ {
+ m_dangling_read = false;
+ }
+ }
+
+ return std::error_condition();
+ }
+
+ virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ actual = 0U;
+
+ if (static_cast<unsigned long>(std::numeric_limits<long>::max()) < offset)
+ return std::errc::invalid_argument;
+
+ std::fpos_t oldpos;
+ if (std::fgetpos(file(), &oldpos))
+ return std::error_condition(errno, std::generic_category());
+
+ std::error_condition err;
+ if (std::fseek(file(), long(static_cast<unsigned long>(offset)), SEEK_SET))
+ {
+ err.assign(errno, std::generic_category());
+ }
+ else
+ {
+ m_dangling_write = false;
+ actual = std::fread(buffer, sizeof(std::uint8_t), length, file());
+ m_dangling_read = true;
+ if (length != actual)
+ {
+ if (std::ferror(file()))
+ {
+ err.assign(errno, std::generic_category());
+ std::clearerr(file());
+ }
+ else if (std::feof(file()))
+ {
+ m_dangling_read = false;
+ }
+ }
+ }
+
+ if (!std::fsetpos(file(), &oldpos))
+ m_dangling_read = m_dangling_write = false;
+ else if (!err)
+ err.assign(errno, std::generic_category());
+
+ return err;
+ }
+};
+
+
+// stdio read/write implementation
+
+class stdio_read_write_adapter : public stdio_read_adapter, public random_read_write
+{
+public:
+ using stdio_read_adapter::stdio_read_adapter;
+
+ virtual std::error_condition finalize() noexcept override
+ {
+ return std::error_condition();
+ }
+
+ virtual std::error_condition flush() noexcept override
+ {
+ if (std::fflush(file()))
+ {
+ std::clearerr(file());
+ return std::error_condition(errno, std::generic_category());
+ }
+ m_dangling_write = false;
+ return std::error_condition();
+ }
+
+ virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ if (m_dangling_read)
+ {
+ if (std::fseek(file(), 0, SEEK_CUR))
+ {
+ actual = 0U;
+ return std::error_condition(errno, std::generic_category());
+ }
+ m_dangling_read = false;
+ }
+
+ actual = std::fwrite(buffer, sizeof(std::uint8_t), length, file());
+ m_dangling_write = true;
+ if (length != actual)
+ {
+ std::clearerr(file());
+ return std::error_condition(errno, std::generic_category());
+ }
+
+ return std::error_condition();
+ }
+
+ virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ actual = 0U;
+
+ if (static_cast<unsigned long>(std::numeric_limits<long>::max()) < offset)
+ return std::errc::invalid_argument;
+
+ std::fpos_t oldpos;
+ if (std::fgetpos(file(), &oldpos))
+ return std::error_condition(errno, std::generic_category());
+
+ std::error_condition err;
+ if (std::fseek(file(), long(static_cast<unsigned long>(offset)), SEEK_SET))
+ {
+ err.assign(errno, std::generic_category());
+ }
+ else
+ {
+ m_dangling_read = false;
+ actual = std::fwrite(buffer, sizeof(std::uint8_t), length, file());
+ m_dangling_write = true;
+ if (length != actual)
+ {
+ err.assign(errno, std::generic_category());
+ std::clearerr(file());
+ }
+ }
+
+ if (!std::fsetpos(file(), &oldpos))
+ m_dangling_read = m_dangling_write = false;
+ else if (!err)
+ err.assign(errno, std::generic_category());
+
+ return err;
+ }
+};
+
+
+// stdio helper that fills space when writing past the end-of-file
+
+class stdio_read_write_filler : public random_read_fill_wrapper<stdio_read_write_adapter>
+{
+public:
+ stdio_read_write_filler(FILE *file, bool close, std::uint8_t fill) noexcept : random_read_fill_wrapper<stdio_read_write_adapter>(file, close)
+ {
+ set_filler(fill);
+ }
+
+ virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ actual = 0U;
+
+ long const offset = std::ftell(file());
+ if (0 > offset)
+ return std::error_condition(errno, std::generic_category());
+
+ if (std::fseek(file(), 0, SEEK_END))
+ {
+ std::error_condition err(errno, std::generic_category());
+ if (!std::fseek(file(), offset, SEEK_SET))
+ m_dangling_read = m_dangling_write = false;
+ return err;
+ }
+ m_dangling_read = m_dangling_write = false;
+ long endpos = std::ftell(file());
+ if (0 > endpos)
+ {
+ std::error_condition err(errno, std::generic_category());
+ std::fseek(file(), offset, SEEK_SET);
+ return err;
+ }
+
+ if (offset > endpos)
+ {
+ std::uint8_t block[1024];
+ std::fill_n(
+ block,
+ std::min<std::common_type_t<std::size_t, std::uint64_t, long> >(std::size(block), offset - endpos),
+ get_filler());
+ do
+ {
+ std::size_t const chunk = std::min<std::common_type_t<std::size_t, std::uint64_t, long> >(std::size(block), offset - endpos);
+ std::size_t const filled = std::fwrite(block, sizeof(block[0]), chunk, file());
+ endpos += filled;
+ m_dangling_write = true;
+ if (chunk != filled)
+ {
+ std::error_condition err(errno, std::generic_category());
+ std::clearerr(file());
+ if (!std::fseek(file(), offset, SEEK_SET))
+ m_dangling_write = false;
+ return err;
+ }
+ }
+ while (static_cast<unsigned long>(endpos) < offset);
+ }
+ else if ((offset < endpos) && std::fseek(file(), offset, SEEK_SET))
+ {
+ return std::error_condition(errno, std::generic_category());
+ }
+
+ actual = std::fwrite(buffer, sizeof(std::uint8_t), length, file());
+ m_dangling_write = true;
+ if (length != actual)
+ {
+ std::clearerr(file());
+ return std::error_condition(errno, std::generic_category());
+ }
+
+ return std::error_condition();
+ }
+
+ virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ actual = 0U;
+
+ if (static_cast<unsigned long>(std::numeric_limits<long>::max()) < offset)
+ return std::errc::invalid_argument;
+
+ std::fpos_t oldpos;
+ if (std::fgetpos(file(), &oldpos))
+ return std::error_condition(errno, std::generic_category());
+
+ std::error_condition err;
+ if (std::fseek(file(), 0, SEEK_END))
+ {
+ err.assign(errno, std::generic_category());
+ }
+ else
+ {
+ m_dangling_read = m_dangling_write = false;
+ long endpos = std::ftell(file());
+ if (0 > endpos)
+ {
+ err.assign(errno, std::generic_category());
+ }
+ else if (static_cast<unsigned long>(endpos) > offset)
+ {
+ if (std::fseek(file(), long(static_cast<unsigned long>(offset)), SEEK_SET))
+ err.assign(errno, std::generic_category());
+ }
+ else if (static_cast<unsigned long>(endpos) < offset)
+ {
+ std::uint8_t block[1024];
+ std::fill_n(
+ block,
+ std::min<std::common_type_t<std::size_t, std::uint64_t, long> >(std::size(block), offset - endpos),
+ get_filler());
+ do
+ {
+ std::size_t const chunk = std::min<std::common_type_t<std::size_t, std::uint64_t, long> >(std::size(block), offset - endpos);
+ std::size_t const filled = std::fwrite(block, sizeof(block[0]), chunk, file());
+ endpos += filled;
+ m_dangling_write = true;
+ if (chunk != filled)
+ {
+ err.assign(errno, std::generic_category());
+ std::clearerr(file());
+ }
+ }
+ while (!err && (static_cast<unsigned long>(endpos) < offset));
+ }
+ }
+
+ if (!err)
+ {
+ actual = std::fwrite(buffer, sizeof(std::uint8_t), length, file());
+ m_dangling_write = true;
+ if (length != actual)
+ {
+ err.assign(errno, std::generic_category());
+ std::clearerr(file());
+ }
+ }
+
+ if (!std::fsetpos(file(), &oldpos))
+ m_dangling_read = m_dangling_write = false;
+ else if (!err)
+ err.assign(errno, std::generic_category());
+
+ return err;
+ }
+};
+
+
+// helper class for holding an osd_file and closing it (or not) as necessary
+
+class osd_file_adapter_base : public virtual random_access
+{
+public:
+ virtual ~osd_file_adapter_base()
+ {
+ if (m_close)
+ delete m_file;
+ }
+
+ virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override
+ {
+ switch (whence)
+ {
+ case SEEK_SET:
+ if (0 > offset)
+ return std::errc::invalid_argument;
+ m_pointer = std::uint64_t(offset);
+ return std::error_condition();
+
+ case SEEK_CUR:
+ if (0 > offset)
+ {
+ if (std::uint64_t(-offset) > m_pointer)
+ return std::errc::invalid_argument;
+ }
+ else if ((std::numeric_limits<std::uint64_t>::max() - offset) < m_pointer)
+ {
+ return std::errc::invalid_argument;
+ }
+ m_pointer += offset;
+ return std::error_condition();
+
+ // TODO: add SEEK_END when osd_file can support it - should it return a different error?
+ default:
+ return std::errc::invalid_argument;
+ }
+ }
+
+ virtual std::error_condition tell(std::uint64_t &result) noexcept override
+ {
+ result = m_pointer;
+ return std::error_condition();
+ }
+
+ virtual std::error_condition length(std::uint64_t &result) noexcept override
+ {
+ // not supported by osd_file
+ return std::errc::not_supported; // TODO: revisit this error code
+ }
+
+protected:
+ osd_file_adapter_base(osd_file::ptr &&file) noexcept : m_file(file.release()), m_close(true)
+ {
+ assert(m_file);
+ }
+
+ osd_file_adapter_base(osd_file &file) noexcept : m_file(&file), m_close(false)
+ {
+ }
+
+ osd_file &file() noexcept
+ {
+ return *m_file;
+ }
+
+ std::uint64_t m_pointer = 0U;
+
+private:
+ osd_file *const m_file;
+ bool const m_close;
+};
+
+
+// osd_file read implementation
+
+class osd_file_read_adapter : public osd_file_adapter_base, public virtual random_read
+{
+public:
+ osd_file_read_adapter(osd_file::ptr &&file) noexcept : osd_file_adapter_base(std::move(file))
+ {
+ }
+
+ osd_file_read_adapter(osd_file &file) noexcept : osd_file_adapter_base(file)
+ {
+ }
+
+ virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ // TODO: should the client have to deal with reading less than expected even if EOF isn't hit?
+ if (std::numeric_limits<std::uint32_t>::max() < length)
+ {
+ actual = 0U;
+ return std::errc::invalid_argument;
+ }
+
+ // actual length not valid on error
+ std::uint32_t count;
+ std::error_condition err = file().read(buffer, m_pointer, std::uint32_t(length), count);
+ if (!err)
+ {
+ m_pointer += count;
+ actual = std::size_t(count);
+ }
+ else
+ {
+ actual = 0U;
+ }
+ return err;
+ }
+
+ virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ // TODO: should the client have to deal with reading less than expected even if EOF isn't hit?
+ if (std::numeric_limits<std::uint32_t>::max() < length)
+ {
+ actual = 0U;
+ return std::errc::invalid_argument;
+ }
+
+ // actual length not valid on error
+ std::uint32_t count;
+ std::error_condition err = file().read(buffer, offset, std::uint32_t(length), count);
+ if (!err)
+ actual = std::size_t(count);
+ else
+ actual = 0U;
+ return err;
+ }
+};
+
+
+// osd_file read/write implementation
+
+class osd_file_read_write_adapter : public osd_file_read_adapter, public random_read_write
+{
+public:
+ using osd_file_read_adapter::osd_file_read_adapter;
+
+ virtual std::error_condition finalize() noexcept override
+ {
+ return std::error_condition();
+ }
+
+ virtual std::error_condition flush() noexcept override
+ {
+ return file().flush();
+ }
+
+ virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ actual = 0U;
+ while (length)
+ {
+ // actual length not valid on error
+ std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
+ std::uint32_t written;
+ std::error_condition err = file().write(buffer, m_pointer, chunk, written);
+ if (err)
+ return err;
+ m_pointer += written;
+ buffer = reinterpret_cast<std::uint8_t const *>(buffer) + written;
+ length -= written;
+ actual += written;
+ }
+ return std::error_condition();
+ }
+
+ virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ actual = 0U;
+ while (length)
+ {
+ // actual length not valid on error
+ std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
+ std::uint32_t written;
+ std::error_condition err = file().write(buffer, offset, chunk, written);
+ if (err)
+ return err;
+ offset += written;
+ buffer = reinterpret_cast<std::uint8_t const *>(buffer) + written;
+ length -= written;
+ actual += written;
+ }
+ return std::error_condition();
+ }
+};
+
+
+// helper class for holding a core_file and closing it (or not) as necessary
+
+class core_file_adapter_base : public virtual random_access
+{
+public:
+ virtual ~core_file_adapter_base()
+ {
+ if (m_close)
+ delete m_file;
+ }
+
+ virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override
+ {
+ if (!m_file->seek(offset, whence))
+ return std::error_condition();
+ else
+ return std::errc::invalid_argument; // TODO: better error reporting for core_file
+ }
+
+ virtual std::error_condition tell(std::uint64_t &result) noexcept override
+ {
+ // no error reporting
+ result = m_file->tell();
+ return std::error_condition();
+ }
+
+ virtual std::error_condition length(std::uint64_t &result) noexcept override
+ {
+ // no error reporting
+ result = m_file->size();
+ return std::error_condition();
+ }
+
+protected:
+ core_file_adapter_base(core_file::ptr &&file) noexcept : m_file(file.release()), m_close(true)
+ {
+ assert(m_file);
+ }
+
+ core_file_adapter_base(core_file &file) noexcept : m_file(&file), m_close(false)
+ {
+ }
+
+ core_file &file() noexcept
+ {
+ return *m_file;
+ }
+
+private:
+ core_file *const m_file;
+ bool const m_close;
+};
+
+
+// core_file read implementation
+
+class core_file_read_adapter : public core_file_adapter_base, public virtual random_read
+{
+public:
+ core_file_read_adapter(core_file::ptr &&file) noexcept : core_file_adapter_base(std::move(file))
+ {
+ }
+
+ core_file_read_adapter(core_file &file) noexcept : core_file_adapter_base(file)
+ {
+ }
+
+ virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ // TODO: should the client have to deal with reading less than expected even if EOF isn't hit?
+ if (std::numeric_limits<std::uint32_t>::max() < length)
+ {
+ actual = 0U;
+ return std::errc::invalid_argument;
+ }
+
+ // no way to distinguish between EOF and error
+ actual = file().read(buffer, std::uint32_t(length));
+ return std::error_condition();
+ }
+
+ virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ actual = 0U;
+
+ // TODO: should the client have to deal with reading less than expected even if EOF isn't hit?
+ if (std::numeric_limits<std::uint32_t>::max() < length)
+ return std::errc::invalid_argument;
+
+ // no error reporting for tell
+ std::uint64_t const oldpos = file().tell();
+ if (file().seek(offset, SEEK_SET))
+ {
+ file().seek(oldpos, SEEK_SET);
+ return std::errc::invalid_argument; // TODO: better error reporting for core_file
+ }
+
+ // no way to distinguish between EOF and error
+ actual = file().read(buffer, std::uint32_t(length));
+
+ if (!file().seek(oldpos, SEEK_SET))
+ return std::error_condition();
+ else
+ return std::errc::invalid_argument; // TODO: better error reporting for core_file
+ }
+};
+
+
+// core_file read/write implementation
+
+class core_file_read_write_adapter : public core_file_read_adapter, public random_read_write
+{
+public:
+ using core_file_read_adapter::core_file_read_adapter;
+
+ virtual std::error_condition finalize() noexcept override
+ {
+ return std::error_condition();
+ }
+
+ virtual std::error_condition flush() noexcept override
+ {
+ return file().flush();
+ }
+
+ virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ actual = 0U;
+ while (length)
+ {
+ std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
+ std::uint32_t const written = file().write(buffer, chunk);
+ actual += written;
+ if (written < chunk)
+ return std::errc::io_error; // TODO: better error reporting for core_file
+ buffer = reinterpret_cast<std::uint8_t const *>(buffer) + written;
+ length -= written;
+ }
+ return std::error_condition();
+ }
+
+ virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ actual = 0U;
+
+ // no error reporting for tell
+ std::uint64_t const oldpos = file().tell();
+ if (file().seek(offset, SEEK_SET))
+ {
+ file().seek(oldpos, SEEK_SET);
+ return std::errc::invalid_argument; // TODO: better error reporting for core_file
+ }
+
+ std::error_condition err;
+ while (!err && length)
+ {
+ std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
+ std::uint32_t const written = file().write(buffer, chunk);
+ actual += written;
+ if (written < chunk)
+ {
+ err = std::errc::io_error; // TODO: better error reporting for core_file
+ }
+ else
+ {
+ buffer = reinterpret_cast<std::uint8_t const *>(buffer) + written;
+ length -= written;
+ }
+ }
+
+ if (!file().seek(oldpos, SEEK_SET) || err)
+ return err;
+ else
+ return std::errc::invalid_argument; // TODO: better error reporting for core_file
+ }
+};
+
+
+// core_file helper that fills space when writing past the end-of-file
+
+class core_file_read_write_filler : public random_read_fill_wrapper<core_file_read_write_adapter>
+{
+public:
+ core_file_read_write_filler(core_file::ptr &&file, std::uint8_t fill) noexcept : random_read_fill_wrapper<core_file_read_write_adapter>(std::move(file))
+ {
+ set_filler(fill);
+ }
+
+ core_file_read_write_filler(core_file &file, std::uint8_t fill) noexcept : random_read_fill_wrapper<core_file_read_write_adapter>(file)
+ {
+ set_filler(fill);
+ }
+
+ virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ // no error reporting for tell or size
+ std::uint64_t const offset = file().tell();
+ std::uint64_t endpos = file().size();
+ if (endpos < offset)
+ {
+ if (file().seek(endpos, SEEK_SET))
+ {
+ file().seek(offset, SEEK_SET);
+ actual = 0U;
+ return std::errc::invalid_argument; // TODO: better error reporting for core_file
+ }
+ std::uint8_t block[1024];
+ std::fill_n(
+ block,
+ std::min<std::common_type_t<std::size_t, std::uint64_t> >(std::size(block), offset - endpos),
+ get_filler());
+ do
+ {
+ std::uint32_t const chunk = std::min<std::common_type_t<std::size_t, std::uint64_t> >(sizeof(block), offset - endpos);
+ std::uint32_t const filled = file().write(block, chunk);
+ endpos += filled;
+ if (chunk != filled)
+ {
+ file().seek(offset, SEEK_SET);
+ actual = 0U;
+ return std::errc::io_error; // TODO: better error reporting for core_file
+ }
+ }
+ while (endpos < offset);
+ }
+
+ return core_file_read_write_adapter::write(buffer, length, actual);
+ }
+
+ virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ actual = 0U;
+
+ // no error reporting for tell
+ std::uint64_t const oldpos = file().tell();
+ if (file().seek(0, SEEK_END))
+ {
+ file().seek(oldpos, SEEK_SET);
+ return std::errc::invalid_argument; // TODO: better error reporting for core_file
+ }
+ std::uint64_t endpos = file().tell();
+
+ std::error_condition err;
+ if (endpos > offset)
+ {
+ if (file().seek(offset, SEEK_SET))
+ err = std::errc::invalid_argument; // TODO: better error reporting for core_file
+ }
+ else if (endpos < offset)
+ {
+ std::uint8_t block[1024];
+ std::fill_n(
+ block,
+ std::min<std::common_type_t<std::size_t, std::uint64_t> >(std::size(block), offset - endpos),
+ get_filler());
+ do
+ {
+ std::uint32_t const chunk = std::min<std::common_type_t<std::size_t, std::uint64_t> >(sizeof(block), offset - endpos);
+ std::uint32_t const filled = file().write(block, chunk);
+ endpos += filled;
+ if (chunk != filled)
+ err = std::errc::io_error; // TODO: better error reporting for core_file
+ }
+ while (!err && (endpos < offset));
+ }
+
+ while (!err && length)
+ {
+ std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
+ std::uint32_t const written = file().write(buffer, chunk);
+ actual += written;
+ if (written < chunk)
+ {
+ err = std::errc::io_error; // TODO: better error reporting for core_file
+ }
+ else
+ {
+ buffer = reinterpret_cast<std::uint8_t const *>(buffer) + written;
+ length -= written;
+ }
+ }
+
+ if (!file().seek(oldpos, SEEK_SET) || err)
+ return err;
+ else
+ return std::errc::invalid_argument; // TODO: better error reporting for core_file
+ }
+};
+
+} // anonymous namespace
+
+
+// creating RAM read adapters
+
+random_read::ptr ram_read(void const *data, std::size_t size) noexcept
+{
+ random_read::ptr result;
+ if (data || !size)
+ result.reset(new (std::nothrow) ram_read_adapter<std::uint8_t const *const, false>(data, size));
+ return result;
+}
+
+random_read::ptr ram_read(void const *data, std::size_t size, std::uint8_t filler) noexcept
+{
+ std::unique_ptr<random_read_fill_wrapper<ram_read_adapter<std::uint8_t const *const, false> > > result;
+ if (data || !size)
+ result.reset(new (std::nothrow) decltype(result)::element_type(data, size));
+ if (result)
+ result->set_filler(filler);
+ return result;
+}
+
+random_read::ptr ram_read_copy(void const *data, std::size_t size) noexcept
+{
+ random_read::ptr result;
+ void *const copy = size ? std::malloc(size) : nullptr;
+ if (copy)
+ std::memcpy(copy, data, size);
+ if (copy || !size)
+ result.reset(new (std::nothrow) ram_read_adapter<std::uint8_t *const, true>(copy, size));
+ if (!result)
+ std::free(copy);
+ return result;
+}
+
+random_read::ptr ram_read_copy(void const *data, std::size_t size, std::uint8_t filler) noexcept
+{
+ std::unique_ptr<random_read_fill_wrapper<ram_read_adapter<std::uint8_t *const, true> > > result;
+ void *const copy = size ? std::malloc(size) : nullptr;
+ if (copy)
+ std::memcpy(copy, data, size);
+ if (copy || !size)
+ result.reset(new (std::nothrow) decltype(result)::element_type(copy, size));
+ if (!result)
+ std::free(copy);
+ return result;
+}
+
+
+// creating stdio read adapters
+
+random_read::ptr stdio_read(FILE *file) noexcept
+{
+ random_read::ptr result;
+ if (file)
+ result.reset(new (std::nothrow) stdio_read_adapter(file, true));
+ return result;
+}
+
+random_read::ptr stdio_read(FILE *file, std::uint8_t filler) noexcept
+{
+ std::unique_ptr<random_read_fill_wrapper<stdio_read_adapter> > result;
+ if (file)
+ result.reset(new (std::nothrow) decltype(result)::element_type(file, true));
+ if (result)
+ result->set_filler(filler);
+ return result;
+}
+
+random_read::ptr stdio_read_noclose(FILE *file) noexcept
+{
+ random_read::ptr result;
+ if (file)
+ result.reset(new (std::nothrow) stdio_read_adapter(file, false));
+ return result;
+}
+
+random_read::ptr stdio_read_noclose(FILE *file, std::uint8_t filler) noexcept
+{
+ std::unique_ptr<random_read_fill_wrapper<stdio_read_adapter> > result;
+ if (file)
+ result.reset(new (std::nothrow) decltype(result)::element_type(file, false));
+ if (result)
+ result->set_filler(filler);
+ return result;
+}
+
+
+// creating stdio read/write adapters
+
+random_read_write::ptr stdio_read_write(FILE *file) noexcept
+{
+ random_read_write::ptr result;
+ if (file)
+ result.reset(new (std::nothrow) stdio_read_write_adapter(file, true));
+ return result;
+}
+
+random_read_write::ptr stdio_read_write(FILE *file, std::uint8_t filler) noexcept
+{
+ random_read_write::ptr result;
+ if (file)
+ result.reset(new (std::nothrow) stdio_read_write_filler(file, true, filler));
+ return result;
+}
+
+random_read_write::ptr stdio_read_write_noclose(FILE *file) noexcept
+{
+ random_read_write::ptr result;
+ if (file)
+ result.reset(new (std::nothrow) stdio_read_write_adapter(file, false));
+ return result;
+}
+
+random_read_write::ptr stdio_read_write_noclose(FILE *file, std::uint8_t filler) noexcept
+{
+ random_read_write::ptr result;
+ if (file)
+ result.reset(new (std::nothrow) stdio_read_write_filler(file, false, filler));
+ return result;
+}
+
+
+// creating osd_file read adapters
+
+random_read::ptr osd_file_read(osd_file::ptr &&file) noexcept
+{
+ random_read::ptr result;
+ if (file)
+ result.reset(new (std::nothrow) osd_file_read_adapter(std::move(file)));
+ return result;
+}
+
+random_read::ptr osd_file_read(osd_file &file) noexcept
+{
+ return random_read::ptr(new (std::nothrow) osd_file_read_adapter(file));
+}
+
+
+// creating osd_file read/write adapters
+
+random_read_write::ptr osd_file_read_write(osd_file::ptr &&file) noexcept
+{
+ random_read_write::ptr result;
+ if (file)
+ result.reset(new (std::nothrow) osd_file_read_write_adapter(std::move(file)));
+ return result;
+}
+
+random_read_write::ptr osd_file_read_write(osd_file &file) noexcept
+{
+ return random_read_write::ptr(new (std::nothrow) osd_file_read_write_adapter(file));
+}
+
+
+// creating core_file read adapters
+
+random_read::ptr core_file_read(core_file::ptr &&file) noexcept
+{
+ random_read::ptr result;
+ if (file)
+ result.reset(new (std::nothrow) core_file_read_adapter(std::move(file)));
+ return result;
+}
+
+random_read::ptr core_file_read(core_file::ptr &&file, std::uint8_t filler) noexcept
+{
+ std::unique_ptr<random_read_fill_wrapper<core_file_read_adapter> > result;
+ if (file)
+ result.reset(new (std::nothrow) decltype(result)::element_type(std::move(file)));
+ if (result)
+ result->set_filler(filler);
+ return result;
+}
+
+random_read::ptr core_file_read(core_file &file) noexcept
+{
+ return random_read::ptr(new (std::nothrow) core_file_read_adapter(file));
+}
+
+random_read::ptr core_file_read(core_file &file, std::uint8_t filler) noexcept
+{
+ std::unique_ptr<random_read_fill_wrapper<core_file_read_adapter> > result;
+ result.reset(new (std::nothrow) decltype(result)::element_type(file));
+ if (result)
+ result->set_filler(filler);
+ return result;
+}
+
+
+// creating core_file read/write adapters
+
+random_read_write::ptr core_file_read_write(core_file::ptr &&file) noexcept
+{
+ random_read_write::ptr result;
+ if (file)
+ result.reset(new (std::nothrow) core_file_read_write_adapter(std::move(file)));
+ return result;
+}
+
+random_read_write::ptr core_file_read_write(core_file::ptr &&file, std::uint8_t filler) noexcept
+{
+ random_read_write::ptr result;
+ if (file)
+ result.reset(new (std::nothrow) core_file_read_write_filler(std::move(file), filler));
+ return result;
+}
+
+random_read_write::ptr core_file_read_write(core_file &file) noexcept
+{
+ return random_read_write::ptr(new (std::nothrow) core_file_read_write_adapter(file));
+}
+
+random_read_write::ptr core_file_read_write(core_file &file, std::uint8_t filler) noexcept
+{
+ return random_read_write::ptr(new (std::nothrow) core_file_read_write_filler(file, filler));
+}
+
+} // namespace util
diff --git a/src/lib/util/ioprocs.h b/src/lib/util/ioprocs.h
new file mode 100644
index 00000000000..78c06e71318
--- /dev/null
+++ b/src/lib/util/ioprocs.h
@@ -0,0 +1,130 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ ioprocs.h
+
+ I/O interfaces
+
+***************************************************************************/
+#ifndef MAME_LIB_UTIL_IOPROCS_H
+#define MAME_LIB_UTIL_IOPROCS_H
+
+#pragma once
+
+#include "utilfwd.h"
+
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <memory>
+#include <system_error>
+
+
+// FIXME: make a proper place for OSD forward declarations
+class osd_file;
+
+
+namespace util {
+
+class read_stream
+{
+public:
+ using ptr = std::unique_ptr<read_stream>;
+
+ virtual ~read_stream() = default;
+
+ virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
+};
+
+
+class write_stream
+{
+public:
+ using ptr = std::unique_ptr<write_stream>;
+
+ virtual ~write_stream() = default;
+
+ virtual std::error_condition finalize() noexcept = 0;
+ virtual std::error_condition flush() noexcept = 0;
+ virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
+};
+
+
+class read_write_stream : public virtual read_stream, public virtual write_stream
+{
+public:
+ using ptr = std::unique_ptr<read_write_stream>;
+};
+
+
+class random_access
+{
+public:
+ virtual ~random_access() = default;
+
+ virtual std::error_condition seek(std::int64_t offset, int whence) noexcept = 0;
+ virtual std::error_condition tell(std::uint64_t &result) noexcept = 0;
+ virtual std::error_condition length(std::uint64_t &result) noexcept = 0;
+};
+
+
+class random_read : public virtual read_stream, public virtual random_access
+{
+public:
+ using ptr = std::unique_ptr<random_read>;
+
+ virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
+};
+
+
+class random_write : public virtual write_stream, public virtual random_access
+{
+public:
+ using ptr = std::unique_ptr<random_write>;
+
+ virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
+};
+
+
+class random_read_write : public read_write_stream, public virtual random_read, public virtual random_write
+{
+public:
+ using ptr = std::unique_ptr<random_read_write>;
+};
+
+
+random_read::ptr ram_read(void const *data, std::size_t size) noexcept;
+random_read::ptr ram_read(void const *data, std::size_t size, std::uint8_t filler) noexcept;
+random_read::ptr ram_read_copy(void const *data, std::size_t size) noexcept;
+random_read::ptr ram_read_copy(void const *data, std::size_t size, std::uint8_t filler) noexcept;
+
+random_read::ptr stdio_read(FILE *file) noexcept;
+random_read::ptr stdio_read(FILE *file, std::uint8_t filler) noexcept;
+random_read::ptr stdio_read_noclose(FILE *file) noexcept;
+random_read::ptr stdio_read_noclose(FILE *file, std::uint8_t filler) noexcept;
+
+random_read_write::ptr stdio_read_write(FILE *file) noexcept;
+random_read_write::ptr stdio_read_write(FILE *file, std::uint8_t filler) noexcept;
+random_read_write::ptr stdio_read_write_noclose(FILE *file) noexcept;
+random_read_write::ptr stdio_read_write_noclose(FILE *file, std::uint8_t filler) noexcept;
+
+random_read::ptr osd_file_read(std::unique_ptr<osd_file> &&file) noexcept;
+random_read::ptr osd_file_read(osd_file &file) noexcept;
+
+random_read_write::ptr osd_file_read_write(std::unique_ptr<osd_file> &&file) noexcept;
+random_read_write::ptr osd_file_read_write(osd_file &file) noexcept;
+
+random_read::ptr core_file_read(std::unique_ptr<core_file> &&file) noexcept;
+random_read::ptr core_file_read(std::unique_ptr<core_file> &&file, std::uint8_t filler) noexcept;
+random_read::ptr core_file_read(core_file &file) noexcept;
+random_read::ptr core_file_read(core_file &file, std::uint8_t filler) noexcept;
+
+random_read_write::ptr core_file_read_write(std::unique_ptr<core_file> &&file) noexcept;
+random_read_write::ptr core_file_read_write(std::unique_ptr<core_file> &&file, std::uint8_t filler) noexcept;
+random_read_write::ptr core_file_read_write(core_file &file) noexcept;
+random_read_write::ptr core_file_read_write(core_file &file, std::uint8_t filler) noexcept;
+
+} // namespace util
+
+#endif // MAME_LIB_UTIL_IOPROCS_H
diff --git a/src/lib/util/ioprocsfill.h b/src/lib/util/ioprocsfill.h
new file mode 100644
index 00000000000..e49b10687f0
--- /dev/null
+++ b/src/lib/util/ioprocsfill.h
@@ -0,0 +1,163 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ ioprocsfill.h
+
+ Wrappers that automatically fill extra space
+
+***************************************************************************/
+#ifndef MAME_LIB_UTIL_IOPROCSFILL_H
+#define MAME_LIB_UTIL_IOPROCSFILL_H
+
+#pragma once
+
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <system_error>
+
+
+namespace util {
+
+template <std::uint8_t DefaultFiller>
+class fill_wrapper_base
+{
+public:
+ std::uint8_t get_filler() const noexcept
+ {
+ return m_filler;
+ }
+
+ void set_filler(std::uint8_t filler) noexcept
+ {
+ m_filler = filler;
+ }
+
+private:
+ std::uint8_t m_filler = DefaultFiller;
+};
+
+
+template <typename Base, std::uint8_t DefaultFiller = 0U>
+class read_stream_fill_wrapper : public Base, public virtual fill_wrapper_base<DefaultFiller>
+{
+public:
+ using Base::Base;
+
+ virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ std::error_condition err = Base::read(buffer, length, actual);
+ assert(length >= actual);
+ std::fill(
+ reinterpret_cast<std::uint8_t *>(buffer) + actual,
+ reinterpret_cast<std::uint8_t *>(buffer) + length,
+ fill_wrapper_base<DefaultFiller>::get_filler());
+ return err;
+ }
+};
+
+
+template <typename Base, std::uint8_t DefaultFiller = 0U>
+class random_read_fill_wrapper : public read_stream_fill_wrapper<Base, DefaultFiller>
+{
+public:
+ using read_stream_fill_wrapper<Base, DefaultFiller>::read_stream_fill_wrapper;
+
+ virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ std::error_condition err = Base::read_at(offset, buffer, length, actual);
+ assert(length >= actual);
+ std::fill(
+ reinterpret_cast<std::uint8_t *>(buffer) + actual,
+ reinterpret_cast<std::uint8_t *>(buffer) + length,
+ fill_wrapper_base<DefaultFiller>::get_filler());
+ return err;
+ }
+};
+
+
+template <typename Base, std::uint8_t DefaultFiller = 0U, std::size_t FillBlock = 1024U>
+class random_write_fill_wrapper : public Base, public virtual fill_wrapper_base<DefaultFiller>
+{
+public:
+ using Base::Base;
+
+ virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ std::error_condition err;
+ actual = 0U;
+
+ std::uint64_t offset;
+ std::uint64_t current;
+ err = Base::tell(offset);
+ if (err)
+ return err;
+ err = Base::length(current);
+ if (err)
+ return err;
+
+ if (current < offset)
+ {
+ std::uint64_t unfilled = offset - current;
+ std::uint8_t fill_buffer[FillBlock];
+ std::fill(
+ fill_buffer,
+ fill_buffer + std::min<std::common_type_t<std::size_t, std::uint64_t> >(FillBlock, unfilled),
+ fill_wrapper_base<DefaultFiller>::get_filler());
+ do
+ {
+ std::size_t const chunk = std::min<std::common_type_t<std::size_t, std::uint64_t> >(FillBlock, unfilled);
+ err = Base::write_at(current, fill_buffer, chunk, actual);
+ if (err)
+ {
+ actual = 0U;
+ return err;
+ }
+ current += chunk;
+ unfilled -= chunk;
+ }
+ while (unfilled);
+ }
+
+ return Base::write(buffer, length, actual);
+ }
+
+ virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ std::error_condition err;
+ std::uint64_t current;
+ err = Base::length(current);
+ if (!err && (current < offset))
+ {
+ std::uint64_t unfilled = offset - current;
+ std::uint8_t fill_buffer[FillBlock];
+ std::fill(
+ fill_buffer,
+ fill_buffer + std::min<std::common_type_t<std::size_t, std::uint64_t> >(FillBlock, unfilled),
+ fill_wrapper_base<DefaultFiller>::get_filler());
+ do
+ {
+ std::size_t const chunk = std::min<std::common_type_t<std::size_t, std::uint64_t> >(FillBlock, unfilled);
+ err = Base::write_at(current, fill_buffer, chunk, actual);
+ current += chunk;
+ unfilled -= chunk;
+ }
+ while (unfilled && !err);
+ }
+ if (err)
+ {
+ actual = 0U;
+ return err;
+ }
+ return Base::write_at(offset, buffer, length, actual);
+ }
+};
+
+
+template <typename Base, std::uint8_t DefaultFiller = 0U, std::size_t FillBlock = 1024U>
+using random_read_write_fill_wrapper = random_write_fill_wrapper<random_read_fill_wrapper<Base, DefaultFiller>, DefaultFiller, FillBlock>;
+
+} // namespace util
+
+#endif // MAME_LIB_UTIL_IOPROCSFILL_H
diff --git a/src/lib/util/ioprocsfilter.cpp b/src/lib/util/ioprocsfilter.cpp
new file mode 100644
index 00000000000..da67b8c41f2
--- /dev/null
+++ b/src/lib/util/ioprocsfilter.cpp
@@ -0,0 +1,598 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ ioprocs.h
+
+ I/O filters
+
+***************************************************************************/
+
+#include "ioprocsfilter.h"
+
+#include "ioprocs.h"
+
+#include <zlib.h>
+
+#include <algorithm>
+#include <cassert>
+#include <cerrno>
+#include <cstdint>
+#include <limits>
+#include <system_error>
+#include <type_traits>
+#include <utility>
+
+
+namespace util {
+
+namespace {
+
+// helper class for holding zlib data
+
+class zlib_data
+{
+protected:
+ zlib_data(std::size_t buffer_size) noexcept :
+ m_buffer_size(std::min<std::common_type_t<uInt, std::size_t> >(std::numeric_limits<uInt>::max(), buffer_size))
+ {
+ assert(buffer_size);
+ }
+
+ z_stream &get_z_stream() noexcept { return m_z_stream; }
+ z_stream const &get_z_stream() const noexcept { return m_z_stream; }
+ Bytef *get_buffer() noexcept { return m_buffer.get(); }
+ Bytef const *get_buffer() const noexcept { return m_buffer.get(); }
+ std::size_t get_buffer_size() const noexcept { return m_buffer_size; }
+
+ bool input_empty() const noexcept { return !m_z_stream.avail_in; }
+ bool output_available() const noexcept { return bool(m_z_stream.avail_out); }
+
+ void initialize_z_stream() noexcept
+ {
+ m_z_stream.zalloc = Z_NULL;
+ m_z_stream.zfree = Z_NULL;
+ m_z_stream.opaque = Z_NULL;
+ }
+
+ std::error_condition allocate_buffer() noexcept
+ {
+ if (!m_buffer)
+ m_buffer.reset(new (std::nothrow) Bytef [m_buffer_size]);
+ return m_buffer ? std::error_condition() : std::errc::not_enough_memory;
+ }
+
+ void release_buffer() noexcept
+ {
+ m_buffer.reset();
+ }
+
+ static std::error_condition convert_z_error(int err) noexcept
+ {
+ switch (err)
+ {
+ case Z_OK:
+ case Z_STREAM_END:
+ return std::error_condition();
+ case Z_NEED_DICT:
+ return std::errc::invalid_argument;
+ case Z_ERRNO:
+ return std::error_condition(errno, std::generic_category());
+ case Z_STREAM_ERROR:
+ return std::errc::invalid_argument;
+ case Z_DATA_ERROR:
+ return std::errc::invalid_argument; // TODO: revisit this error code
+ case Z_MEM_ERROR:
+ return std::errc::not_enough_memory;
+ case Z_BUF_ERROR:
+ return std::errc::operation_would_block; // TODO: revisit this error code (should be handled internally)
+ case Z_VERSION_ERROR:
+ return std::errc::invalid_argument; // TODO: revisit this error code (library ABI mismatch)
+ default:
+ return std::errc::io_error; // TODO: better default error code
+ }
+ }
+
+private:
+ z_stream m_z_stream;
+ std::unique_ptr<Bytef []> m_buffer;
+ std::size_t const m_buffer_size;
+};
+
+
+// helper class for decompressing deflated data
+
+class inflate_data : private zlib_data
+{
+protected:
+ using zlib_data::zlib_data;
+
+ ~inflate_data()
+ {
+ if (m_inflate_initialized)
+ inflateEnd(&get_z_stream());
+ }
+
+ using zlib_data::input_empty;
+
+ bool stream_initialized() const noexcept
+ {
+ return m_inflate_initialized;
+ }
+
+ std::error_condition initialize_z_stream() noexcept
+ {
+ if (m_inflate_initialized)
+ return std::errc::invalid_argument;
+ std::error_condition err = allocate_buffer();
+ if (err)
+ return err;
+ zlib_data::initialize_z_stream();
+ int const zerr = inflateInit(&get_z_stream());
+ if (Z_OK == zerr)
+ m_inflate_initialized = true;
+ return convert_z_error(zerr);
+ }
+
+ std::error_condition close_z_stream() noexcept
+ {
+ if (!m_inflate_initialized)
+ return std::errc::invalid_argument;
+ int const zerr = inflateEnd(&get_z_stream());
+ m_inflate_initialized = false;
+ return convert_z_error(zerr);
+ }
+
+ std::error_condition decompress_some(bool &stream_end) noexcept
+ {
+ assert(m_inflate_initialized);
+ int const zerr = inflate(&get_z_stream(), Z_SYNC_FLUSH);
+ if (!get_z_stream().avail_in)
+ reset_input();
+ stream_end = Z_STREAM_END == zerr;
+ return convert_z_error(zerr);
+ }
+
+ std::size_t input_available() const noexcept
+ {
+ return std::size_t(get_z_stream().avail_in);
+ }
+
+ void reset_input() noexcept
+ {
+ get_z_stream().next_in = get_buffer();
+ get_z_stream().avail_in = 0U;
+ }
+
+ std::pair<void *, std::size_t> get_unfilled_input() noexcept
+ {
+ assert(get_buffer());
+ Bytef *const base = get_z_stream().next_in + get_z_stream().avail_in;
+ return std::make_pair(base, get_buffer() + get_buffer_size() - base);
+ }
+
+ void add_input(std::size_t length) noexcept
+ {
+ assert(get_buffer());
+ get_z_stream().avail_in += length;
+ assert((get_buffer() + get_buffer_size()) >= (get_z_stream().next_in + get_z_stream().avail_in));
+ }
+
+ std::size_t output_produced() const noexcept
+ {
+ return m_output_max - get_z_stream().avail_out;
+ }
+
+ void set_output(void *buffer, std::size_t length) noexcept
+ {
+ m_output_max = std::min<std::common_type_t<uInt, std::size_t> >(std::numeric_limits<uInt>::max(), length);
+ get_z_stream().next_out = reinterpret_cast<Bytef *>(buffer);
+ get_z_stream().avail_out = uInt(m_output_max);
+ }
+
+private:
+ std::error_condition allocate_buffer() noexcept
+ {
+ std::error_condition err;
+ if (!get_buffer())
+ {
+ err = zlib_data::allocate_buffer();
+ reset_input();
+ }
+ return err;
+ }
+
+ bool m_inflate_initialized = false;
+ std::size_t m_output_max = 0U;
+};
+
+
+// helper class for deflating data
+
+class deflate_data : private zlib_data
+{
+protected:
+ deflate_data(int level, std::size_t buffer_size) noexcept : zlib_data(buffer_size), m_level(level)
+ {
+ }
+
+ ~deflate_data()
+ {
+ if (m_deflate_initialized)
+ deflateEnd(&get_z_stream());
+ }
+
+ using zlib_data::input_empty;
+ using zlib_data::output_available;
+
+ bool stream_initialized() const noexcept
+ {
+ return m_deflate_initialized;
+ }
+
+ bool compression_finished() const noexcept
+ {
+ return m_compression_finished;
+ }
+
+ std::error_condition initialize_z_stream() noexcept
+ {
+ if (m_deflate_initialized)
+ return std::errc::invalid_argument;
+ std::error_condition err = allocate_buffer();
+ if (err)
+ return err;
+ zlib_data::initialize_z_stream();
+ int const zerr = deflateInit(&get_z_stream(), m_level);
+ reset_output();
+ if (Z_OK == zerr)
+ m_deflate_initialized = true;
+ return convert_z_error(zerr);
+ }
+
+ std::error_condition close_z_stream() noexcept
+ {
+ if (!m_deflate_initialized)
+ return std::errc::invalid_argument;
+ m_deflate_initialized = m_compression_finished = false;
+ return convert_z_error(deflateEnd(&get_z_stream()));
+ }
+
+ std::error_condition reset_z_stream() noexcept
+ {
+ if (!m_deflate_initialized)
+ return std::errc::invalid_argument;
+ assert(get_buffer());
+ reset_output();
+ m_compression_finished = false;
+ return convert_z_error(deflateReset(&get_z_stream()));
+ }
+
+ std::error_condition compress_some() noexcept
+ {
+ assert(m_deflate_initialized);
+ return convert_z_error(deflate(&get_z_stream(), Z_NO_FLUSH));
+ }
+
+ std::error_condition finish_compression() noexcept
+ {
+ assert(m_deflate_initialized);
+ int const zerr = deflate(&get_z_stream(), Z_FINISH);
+ if (Z_STREAM_END == zerr)
+ m_compression_finished = true;
+ return convert_z_error(zerr);
+ }
+
+ std::size_t input_used() const noexcept
+ {
+ return m_input_max - get_z_stream().avail_in;
+ }
+
+ void set_input(void const *data, std::size_t length) noexcept
+ {
+ m_input_max = std::min<std::common_type_t<uInt, std::size_t> >(std::numeric_limits<uInt>::max(), length);
+ get_z_stream().next_in = const_cast<Bytef z_const *>(reinterpret_cast<Bytef const *>(data));
+ get_z_stream().avail_in = uInt(m_input_max);
+ }
+
+ std::pair<void const *, std::size_t> get_output() const noexcept
+ {
+ assert(get_buffer());
+ return std::make_pair(
+ &get_buffer()[m_output_used],
+ get_buffer_size() - get_z_stream().avail_out - m_output_used);
+ }
+
+ void consume_output(std::size_t length) noexcept
+ {
+ m_output_used += length;
+ assert(m_output_used <= (get_buffer_size() - get_z_stream().avail_out));
+ if (m_output_used == (get_buffer_size() - get_z_stream().avail_out))
+ reset_output();
+ }
+
+private:
+ void reset_output() noexcept
+ {
+ assert(get_buffer());
+ m_output_used = 0U;
+ get_z_stream().next_out = get_buffer();
+ get_z_stream().avail_out = uInt(get_buffer_size());
+ }
+
+ int const m_level;
+ bool m_deflate_initialized = false;
+ bool m_compression_finished = false;
+ std::size_t m_output_used = 0U;
+ std::size_t m_input_max = 0U;
+};
+
+
+// helper for holding an object and deleting it (or not) as necessary
+
+template <typename T>
+class filter_base
+{
+protected:
+ filter_base(std::unique_ptr<T> &&object) noexcept : m_object(object.release()), m_owned(true)
+ {
+ assert(m_object);
+ }
+
+ filter_base(T &object) noexcept : m_object(&object), m_owned(false)
+ {
+ }
+
+ ~filter_base()
+ {
+ if (m_owned)
+ delete m_object;
+ }
+
+ T &object() noexcept
+ {
+ return *m_object;
+ }
+
+private:
+ T *const m_object;
+ bool const m_owned;
+};
+
+
+// filter for decompressing deflated data
+
+template <typename Stream>
+class zlib_read_filter : public read_stream, protected filter_base<Stream>, protected inflate_data
+{
+public:
+ zlib_read_filter(std::unique_ptr<Stream> &&stream, std::size_t read_chunk) noexcept :
+ filter_base<Stream>(std::move(stream)),
+ inflate_data(read_chunk)
+ {
+ }
+
+ zlib_read_filter(Stream &stream, std::size_t read_chunk) noexcept :
+ filter_base<Stream>(stream),
+ inflate_data(read_chunk)
+ {
+ }
+
+ virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ std::error_condition err;
+ actual = 0U;
+
+ if (!stream_initialized())
+ err = initialize_z_stream();
+
+ if (!err && (length > actual))
+ {
+ bool short_input = false;
+ do
+ {
+ if (input_empty())
+ {
+ auto const space = get_unfilled_input();
+ std::size_t filled;
+ err = this->object().read(space.first, space.second, filled);
+ add_input(filled);
+ short_input = space.second > filled;
+ }
+
+ if (!err && !input_empty())
+ {
+ set_output(reinterpret_cast<std::uint8_t *>(buffer) + actual, length - actual);
+ bool stream_end;
+ err = decompress_some(stream_end);
+ actual += output_produced();
+
+ if (stream_end)
+ {
+ assert(!err);
+ if constexpr (std::is_base_of_v<random_read, Stream>)
+ {
+ if (!input_empty())
+ {
+ std::int64_t const overshoot = std::uint64_t(input_available());
+ reset_input();
+ return this->object().seek(-overshoot, SEEK_CUR);
+ }
+ }
+ else
+ {
+ return std::error_condition();
+ }
+ }
+ }
+ }
+ while (!err && (length > actual) && !short_input);
+ }
+
+ return err;
+ }
+};
+
+
+// filter for deflating data
+
+class zlib_write_filter : public write_stream, protected filter_base<write_stream>, protected deflate_data
+{
+public:
+ zlib_write_filter(write_stream::ptr &&stream, int level, std::size_t buffer_size) noexcept :
+ filter_base<write_stream>(std::move(stream)),
+ deflate_data(level, buffer_size)
+ {
+ }
+
+ zlib_write_filter(write_stream &stream, int level, std::size_t buffer_size) noexcept :
+ filter_base<write_stream>(stream),
+ deflate_data(level, buffer_size)
+ {
+ }
+
+ ~zlib_write_filter()
+ {
+ finalize();
+ }
+
+ virtual std::error_condition finalize() noexcept override
+ {
+ if (!stream_initialized())
+ return std::error_condition();
+
+ do
+ {
+ if (!compression_finished() && output_available())
+ {
+ std::error_condition err = finish_compression();
+ if (err)
+ return err;
+ }
+
+ while ((compression_finished() && get_output().second) || !output_available())
+ {
+ std::error_condition err = write_some();
+ if (err)
+ return err;
+ }
+ }
+ while (!compression_finished());
+
+ return close_z_stream();
+ }
+
+ virtual std::error_condition flush() noexcept override
+ {
+ if (stream_initialized())
+ {
+ auto const output = get_output();
+ if (output.second)
+ {
+ std::size_t written;
+ std::error_condition err = object().write(output.first, output.second, written);
+ consume_output(written);
+ if (err)
+ {
+ object().flush();
+ return err;
+ }
+ }
+ }
+ return object().flush();
+ }
+
+ virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ std::error_condition err;
+ actual = 0U;
+
+ if (!stream_initialized())
+ {
+ err = initialize_z_stream();
+ }
+ else if (compression_finished())
+ {
+ while (!err && get_output().second)
+ err = write_some();
+ if (!err)
+ err = reset_z_stream();
+ }
+
+ while (!err && (length > actual))
+ {
+ set_input(reinterpret_cast<std::uint8_t const *>(buffer) + actual, length - actual);
+ do
+ {
+ if (output_available())
+ err = compress_some();
+
+ while (!err && !output_available())
+ err = write_some();
+ }
+ while (!err && !input_empty());
+ actual += input_used();
+ }
+
+ return err;
+ }
+
+private:
+ std::error_condition write_some() noexcept
+ {
+ auto const output = get_output();
+ std::size_t written;
+ std::error_condition err = object().write(output.first, output.second, written);
+ consume_output(written);
+ return err;
+ }
+};
+
+} // anonymous namespace
+
+
+// creating decompressing filters
+
+read_stream::ptr zlib_read(read_stream::ptr &&stream, std::size_t read_chunk) noexcept
+{
+ read_stream::ptr result;
+ if (stream)
+ result.reset(new (std::nothrow) zlib_read_filter<read_stream>(std::move(stream), read_chunk));
+ return result;
+}
+
+read_stream::ptr zlib_read(random_read::ptr &&stream, std::size_t read_chunk) noexcept
+{
+ read_stream::ptr result;
+ if (stream)
+ result.reset(new (std::nothrow) zlib_read_filter<random_read>(std::move(stream), read_chunk));
+ return result;
+}
+
+read_stream::ptr zlib_read(read_stream &stream, std::size_t read_chunk) noexcept
+{
+ return read_stream::ptr(new (std::nothrow) zlib_read_filter<read_stream>(stream, read_chunk));
+}
+
+read_stream::ptr zlib_read(random_read &stream, std::size_t read_chunk) noexcept
+{
+ return read_stream::ptr(new (std::nothrow) zlib_read_filter<random_read>(stream, read_chunk));
+}
+
+
+// creating compressing filters
+
+write_stream::ptr zlib_write(write_stream::ptr &&stream, int level, std::size_t buffer_size) noexcept
+{
+ write_stream::ptr result;
+ if (stream)
+ result.reset(new (std::nothrow) zlib_write_filter(std::move(stream), level, buffer_size));
+ return result;
+}
+
+write_stream::ptr zlib_write(write_stream &stream, int level, std::size_t buffer_size) noexcept
+{
+ return write_stream::ptr(new (std::nothrow) zlib_write_filter(stream, level, buffer_size));
+}
+
+} // namespace util
diff --git a/src/lib/util/ioprocsfilter.h b/src/lib/util/ioprocsfilter.h
new file mode 100644
index 00000000000..a146dd737ce
--- /dev/null
+++ b/src/lib/util/ioprocsfilter.h
@@ -0,0 +1,31 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ ioprocs.h
+
+ I/O filters
+
+***************************************************************************/
+#ifndef MAME_LIB_UTIL_IOPROCSFILTER_H
+#define MAME_LIB_UTIL_IOPROCSFILTER_H
+
+#include "utilfwd.h"
+
+#include <cstdlib>
+#include <memory>
+
+
+namespace util {
+
+std::unique_ptr<read_stream> zlib_read(std::unique_ptr<read_stream> &&stream, std::size_t read_chunk) noexcept;
+std::unique_ptr<read_stream> zlib_read(std::unique_ptr<random_read> &&stream, std::size_t read_chunk) noexcept;
+std::unique_ptr<read_stream> zlib_read(read_stream &stream, std::size_t read_chunk) noexcept;
+std::unique_ptr<read_stream> zlib_read(random_read &stream, std::size_t read_chunk) noexcept;
+
+std::unique_ptr<write_stream> zlib_write(std::unique_ptr<write_stream> &&stream, int level, std::size_t buffer_size) noexcept;
+std::unique_ptr<write_stream> zlib_write(write_stream &stream, int level, std::size_t buffer_size) noexcept;
+
+} // namespace util
+
+#endif // MAME_LIB_UTIL_IOPROCSFILTER_H
diff --git a/src/lib/util/ioprocsvec.h b/src/lib/util/ioprocsvec.h
new file mode 100644
index 00000000000..27dda095ad3
--- /dev/null
+++ b/src/lib/util/ioprocsvec.h
@@ -0,0 +1,211 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ ioprocsvec.h
+
+ Helper for using a vector as an in-memory file
+
+***************************************************************************/
+#ifndef MAME_LIB_UTIL_IOPROCSVEC_H
+#define MAME_LIB_UTIL_IOPROCSVEC_H
+
+#include "ioprocs.h"
+
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <limits>
+#include <system_error>
+#include <type_traits>
+#include <vector>
+
+
+namespace util {
+
+template <typename T = std::uint8_t>
+class vector_read_write_adapter : public random_read_write
+{
+public:
+ vector_read_write_adapter(std::vector<T> &storage) noexcept : m_storage(storage)
+ {
+ check_resized();
+ }
+
+ virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override
+ {
+ switch (whence)
+ {
+ case SEEK_SET:
+ if (0 > offset)
+ return std::errc::invalid_argument;
+ m_pointer = std::uint64_t(offset);
+ return std::error_condition();
+
+ case SEEK_CUR:
+ if (0 > offset)
+ {
+ if (std::uint64_t(-offset) > m_pointer)
+ return std::errc::invalid_argument;
+ }
+ else if ((std::numeric_limits<std::uint64_t>::max() - offset) < m_pointer)
+ {
+ return std::errc::invalid_argument;
+ }
+ m_pointer += offset;
+ return std::error_condition();
+
+ case SEEK_END:
+ check_resized();
+ if (0 > offset)
+ {
+ if (std::uint64_t(-offset) > m_size)
+ return std::errc::invalid_argument;
+ }
+ else if ((std::numeric_limits<std::uint64_t>::max() - offset) < m_size)
+ {
+ return std::errc::invalid_argument;
+ }
+ m_pointer = std::uint64_t(m_size) + offset;
+ return std::error_condition();
+
+ default:
+ return std::errc::invalid_argument;
+ }
+ }
+
+ virtual std::error_condition tell(std::uint64_t &result) noexcept override
+ {
+ result = m_pointer;
+ return std::error_condition();
+ }
+
+ virtual std::error_condition length(std::uint64_t &result) noexcept override
+ {
+ check_resized();
+ if (std::numeric_limits<uint64_t>::max() < m_size)
+ return std::errc::file_too_large;
+
+ result = m_size;
+ return std::error_condition();
+ }
+
+ virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ do_read(m_pointer, buffer, length, actual);
+ m_pointer += actual;
+ return std::error_condition();
+ }
+
+ virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ do_read(offset, buffer, length, actual);
+ return std::error_condition();
+ }
+
+ virtual std::error_condition finalize() noexcept override
+ {
+ return std::error_condition();
+ }
+
+ virtual std::error_condition flush() noexcept override
+ {
+ return std::error_condition();
+ }
+
+ virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ std::error_condition result = do_write(m_pointer, buffer, length, actual);
+ m_pointer += actual;
+ return result;
+ }
+
+ virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ {
+ return do_write(offset, buffer, length, actual);
+ }
+
+private:
+ using elements_type = typename std::vector<T>::size_type;
+ using common_size_type = std::common_type_t<std::uint64_t, std::size_t>;
+
+ void check_resized() noexcept
+ {
+ if (m_storage.size() != m_elements)
+ {
+ m_elements = m_storage.size();
+ m_size = m_elements * sizeof(T);
+ }
+ }
+
+ void do_read(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept
+ {
+ check_resized();
+ if ((offset < m_size) && length)
+ {
+ actual = std::min(std::size_t(m_size - offset), length);
+ std::memmove(buffer, reinterpret_cast<std::uint8_t *>(m_storage.data()) + offset, actual);
+ }
+ else
+ {
+ actual = 0U;
+ }
+ }
+
+ std::error_condition do_write(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept
+ {
+ check_resized();
+ std::size_t allocated = m_elements * sizeof(T);
+ std::uint64_t const target = ((std::numeric_limits<std::uint64_t>::max() - offset) >= length)
+ ? (offset + length)
+ : std::numeric_limits<std::uint64_t>::max();
+
+ std::error_condition result;
+ if (target > allocated)
+ {
+ elements_type const required = std::min<std::common_type_t<elements_type, std::uint64_t> >(
+ std::numeric_limits<elements_type>::max(),
+ (target + sizeof(T) - 1) / sizeof(T)); // technically can overflow but unlikely
+ try { m_storage.resize(required); } // unpredictable if constructing/assigning T can throw
+ catch (...) { result = std::errc::not_enough_memory; }
+ m_elements = m_storage.size();
+ allocated = m_elements * sizeof(T);
+ assert(allocated >= m_size);
+
+ if (offset > m_size)
+ {
+ std::size_t const new_size = std::size_t(std::min<common_size_type>(allocated, offset));
+ std::memset(
+ reinterpret_cast<std::uint8_t *>(m_storage.data()) + m_size,
+ 0x00, // POSIX says unwritten areas of files should read as zero
+ new_size - m_size);
+ m_size = new_size;
+ }
+ }
+
+ std::size_t const limit = std::min<common_size_type>(target, allocated);
+ if (limit > offset)
+ {
+ actual = std::size_t(limit - offset);
+ std::memmove(reinterpret_cast<std::uint8_t *>(m_storage.data()) + offset, buffer, actual);
+ m_size = limit;
+ }
+ else
+ {
+ actual = 0U;
+ }
+ if (!result && (actual < length))
+ result = std::errc::no_space_on_device;
+
+ return result;
+ }
+
+ std::vector<T> &m_storage;
+ std::uint64_t m_pointer = 0U;
+ elements_type m_elements = 0U;
+ std::size_t m_size = 0U;
+};
+
+} // namespace util
+
+#endif // MAME_LIB_UTIL_IOPROCSVEC_H
diff --git a/src/lib/util/path.cpp b/src/lib/util/path.cpp
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/lib/util/path.cpp
diff --git a/src/lib/util/path.h b/src/lib/util/path.h
new file mode 100644
index 00000000000..1291d7b17d3
--- /dev/null
+++ b/src/lib/util/path.h
@@ -0,0 +1,65 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ path.h
+
+ Filesystem path utilties
+
+***************************************************************************/
+#ifndef MAME_LIB_UTIL_PATH_H
+#define MAME_LIB_UTIL_PATH_H
+
+#include "osdfile.h" // for PATH_SEPARATOR
+
+#include <string>
+#include <utility>
+
+
+namespace util {
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+// is a given character a directory separator?
+
+constexpr bool is_directory_separator(char c)
+{
+#if defined(WIN32)
+ return ('\\' == c) || ('/' == c) || (':' == c);
+#else
+ return '/' == c;
+#endif
+}
+
+
+// append to a path
+
+template <typename T, typename... U>
+inline std::string &path_append(std::string &path, T &&next, U &&... more)
+{
+ if (!path.empty() && !is_directory_separator(path.back()))
+ path.append(PATH_SEPARATOR);
+ path.append(std::forward<T>(next));
+ if constexpr (sizeof...(U))
+ return path_append(std::forward<U>(more)...);
+ else
+ return path;
+}
+
+
+// concatenate paths
+
+template <typename T, typename... U>
+inline std::string path_concat(T &&first, U &&... more)
+{
+ std::string result(std::forward<T>(first));
+ if constexpr (sizeof...(U))
+ path_append(result, std::forward<U>(more)...);
+ return result;
+}
+
+} // namespace util
+
+#endif // MAME_LIB_UTIL_PATH_H
diff --git a/src/lib/util/strformat.h b/src/lib/util/strformat.h
index b8c9b4f1a99..a3ba1d11261 100644
--- a/src/lib/util/strformat.h
+++ b/src/lib/util/strformat.h
@@ -578,16 +578,16 @@ template <typename Stream, typename T>
class format_output
{
private:
- template <typename U> struct string_semantics
- { static constexpr bool value = false; };
- template <typename CharT, typename Traits, typename Allocator> struct string_semantics<std::basic_string<CharT, Traits, Allocator> >
- { static constexpr bool value = true; };
- template <typename CharT, typename Traits> struct string_semantics<std::basic_string_view<CharT, Traits> >
- { static constexpr bool value = true; };
- template <typename U> struct signed_integer_semantics
- { static constexpr bool value = std::is_integral_v<U>&& std::is_signed_v<U>; };
- template <typename U> struct unsigned_integer_semantics
- { static constexpr bool value = std::is_integral_v<U>&& !std::is_signed_v<U>; };
+ template <typename U>
+ struct string_semantics : public std::false_type { };
+ template <typename CharT, typename Traits, typename Allocator>
+ struct string_semantics<std::basic_string<CharT, Traits, Allocator> > : public std::true_type { };
+ template <typename CharT, typename Traits>
+ struct string_semantics<std::basic_string_view<CharT, Traits> > : public std::true_type { };
+ template <typename U>
+ using signed_integer_semantics = std::bool_constant<std::is_integral_v<U> && std::is_signed_v<U> >;
+ template <typename U>
+ using unsigned_integer_semantics = std::bool_constant<std::is_integral_v<U> && !std::is_signed_v<U> >;
static void apply_signed(Stream &str, char16_t const &value)
{
@@ -865,8 +865,8 @@ template <typename Stream, typename T>
class format_output<Stream, T *>
{
protected:
- template <typename U> struct string_semantics
- { static constexpr bool value = std::is_same<std::remove_const_t<U>, typename Stream::char_type>::value; };
+ template <typename U>
+ using string_semantics = std::bool_constant<std::is_same_v<std::remove_const_t<U>, typename Stream::char_type> >;
public:
template <typename U>
@@ -940,10 +940,10 @@ template <typename T>
class format_make_integer
{
private:
- template <typename U> struct use_unsigned_cast
- { static constexpr bool value = std::is_convertible<U const, unsigned>::value && std::is_unsigned<U>::value; };
- template <typename U> struct use_signed_cast
- { static constexpr bool value = !use_unsigned_cast<U>::value && std::is_convertible<U const, int>::value; };
+ template <typename U>
+ using use_unsigned_cast = std::bool_constant<std::is_convertible_v<U const, unsigned> && std::is_unsigned_v<U> >;
+ template <typename U>
+ using use_signed_cast = std::bool_constant<!use_unsigned_cast<U>::value && std::is_convertible_v<U const, int> >;
public:
template <typename U> static bool apply(U const &value, int &result)
@@ -974,14 +974,14 @@ template <typename T>
class format_store_integer
{
private:
- template <typename U> struct is_non_const_ptr
- { static constexpr bool value = std::is_pointer<U>::value && !std::is_const<std::remove_pointer_t<U> >::value; };
- template <typename U> struct is_unsigned_ptr
- { static constexpr bool value = std::is_pointer<U>::value && std::is_unsigned<std::remove_pointer_t<U> >::value; };
- template <typename U> struct use_unsigned_cast
- { static constexpr bool value = is_non_const_ptr<U>::value && is_unsigned_ptr<U>::value && std::is_convertible<std::make_unsigned_t<std::streamoff>, std::remove_pointer_t<U> >::value; };
- template <typename U> struct use_signed_cast
- { static constexpr bool value = is_non_const_ptr<U>::value && !use_unsigned_cast<U>::value && std::is_convertible<std::streamoff, std::remove_pointer_t<U> >::value; };
+ template <typename U>
+ using is_non_const_ptr = std::bool_constant<std::is_pointer_v<U> && !std::is_const_v<std::remove_pointer_t<U> > >;
+ template <typename U>
+ using is_unsigned_ptr = std::bool_constant<std::is_pointer_v<U> && std::is_unsigned_v<std::remove_pointer_t<U> > >;
+ template <typename U>
+ using use_unsigned_cast = std::bool_constant<is_non_const_ptr<U>::value && is_unsigned_ptr<U>::value && std::is_convertible_v<std::make_unsigned_t<std::streamoff>, std::remove_pointer_t<U> > >;
+ template <typename U>
+ using use_signed_cast = std::bool_constant<is_non_const_ptr<U>::value && !use_unsigned_cast<U>::value && std::is_convertible_v<std::streamoff, std::remove_pointer_t<U> > >;
public:
template <typename U> static bool apply(U const &value, std::streamoff data)
@@ -1091,11 +1091,11 @@ public:
protected:
template <typename T>
- struct handle_char_ptr { static constexpr bool value = std::is_pointer<T>::value && std::is_same<std::remove_cv_t<std::remove_pointer_t<T> >, char_type>::value; };
+ using handle_char_ptr = std::bool_constant<std::is_pointer_v<T> && std::is_same_v<std::remove_cv_t<std::remove_pointer_t<T> >, char_type> >;
template <typename T>
- struct handle_char_array { static constexpr bool value = std::is_array<T>::value && std::is_same<std::remove_cv_t<std::remove_extent_t<T> >, char_type>::value; };
+ using handle_char_array = std::bool_constant<std::is_array_v<T> && std::is_same_v<std::remove_cv_t<std::remove_extent_t<T> >, char_type> >;
template <typename T>
- struct handle_container { static constexpr bool value = !handle_char_ptr<T>::value && !handle_char_array<T>::value; };
+ using handle_container = std::bool_constant<!handle_char_ptr<T>::value && !handle_char_array<T>::value>;
template <typename Format>
format_argument_pack(
diff --git a/src/lib/util/timeconv.cpp b/src/lib/util/timeconv.cpp
index 99953712003..469b6b592a2 100644
--- a/src/lib/util/timeconv.cpp
+++ b/src/lib/util/timeconv.cpp
@@ -14,42 +14,10 @@
namespace util {
-/***************************************************************************
- PROTOTYPES
-***************************************************************************/
-
-static std::chrono::system_clock::duration calculate_system_clock_adjustment();
-
-
-/***************************************************************************
- GLOBAL VARIABLES
-***************************************************************************/
-
-std::chrono::system_clock::duration system_clock_adjustment(calculate_system_clock_adjustment());
-
-
-/***************************************************************************
- IMPLEMENTATION
-***************************************************************************/
-
-arbitrary_datetime arbitrary_datetime::now()
-{
- time_t sec;
- time(&sec);
- auto t = *localtime(&sec);
-
- arbitrary_datetime dt;
- dt.year = t.tm_year + 1900;
- dt.month = t.tm_mon + 1;
- dt.day_of_month = t.tm_mday;
- dt.hour = t.tm_hour;
- dt.minute = t.tm_min;
- dt.second = t.tm_sec;
- return dt;
-}
+namespace {
-static std::chrono::system_clock::duration calculate_system_clock_adjustment()
+std::chrono::system_clock::duration calculate_system_clock_adjustment()
{
constexpr auto days_in_year(365);
constexpr auto days_in_four_years((days_in_year * 4) + 1);
@@ -84,6 +52,39 @@ static std::chrono::system_clock::duration calculate_system_clock_adjustment()
return result - std::chrono::system_clock::from_time_t(0).time_since_epoch();
}
+} // anonymous namespace
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+std::chrono::system_clock::duration system_clock_adjustment(calculate_system_clock_adjustment());
+
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+arbitrary_datetime arbitrary_datetime::now()
+{
+ time_t sec;
+ time(&sec);
+ auto t = *localtime(&sec);
+
+ arbitrary_datetime dt;
+ dt.year = t.tm_year + 1900;
+ dt.month = t.tm_mon + 1;
+ dt.day_of_month = t.tm_mday;
+ dt.hour = t.tm_hour;
+ dt.minute = t.tm_min;
+ dt.second = t.tm_sec;
+
+ return dt;
+}
+
// -------------------------------------------------
diff --git a/src/lib/util/timeconv.h b/src/lib/util/timeconv.h
index f9d1b070012..91327dbac16 100644
--- a/src/lib/util/timeconv.h
+++ b/src/lib/util/timeconv.h
@@ -22,6 +22,7 @@
namespace util {
+
/***************************************************************************
GLOBAL VARIABLES
***************************************************************************/
@@ -58,7 +59,7 @@ struct arbitrary_datetime
// date of the epoch's begining
//---------------------------------------------------------
-template<typename Rep, int Y, int M, int D, int H, int N, int S, typename Ratio>
+template <typename Rep, int Y, int M, int D, int H, int N, int S, typename Ratio>
class arbitrary_clock
{
public:
@@ -89,7 +90,7 @@ public:
// with a different scale to this arbitrary_clock's scale
//---------------------------------------------------------
- template<typename Rep2, int YY, int MM, int DD, int HH, int NN, int SS, typename Ratio2>
+ template <typename Rep2, int YY, int MM, int DD, int HH, int NN, int SS, typename Ratio2>
static time_point from_arbitrary_time_point(const std::chrono::time_point<arbitrary_clock<Rep2, YY, MM, DD, HH, NN, SS, Ratio2> > &tp)
{
arbitrary_datetime dt;
@@ -111,7 +112,7 @@ public:
// of this scale to one of different scale
//---------------------------------------------------------
- template<typename Rep2, int YY, int MM, int DD, int HH, int NN, int SS, typename Ratio2>
+ template <typename Rep2, int YY, int MM, int DD, int HH, int NN, int SS, typename Ratio2>
static std::chrono::time_point<arbitrary_clock<Rep2, YY, MM, DD, HH, NN, SS, Ratio2> > to_arbitrary_time_point(const time_point &tp)
{
return arbitrary_clock<Rep2, YY, MM, DD, HH, NN, SS, Ratio2>::from_arbitrary_time_point(tp);
@@ -125,14 +126,14 @@ public:
static struct tm to_tm(const time_point &tp)
{
std::chrono::time_point<tm_conversion_clock> normalized_tp = to_arbitrary_time_point<
- std::int64_t,
- tm_conversion_clock::base_year,
- tm_conversion_clock::base_month,
- tm_conversion_clock::base_day,
- tm_conversion_clock::base_hour,
- tm_conversion_clock::base_minute,
- tm_conversion_clock::base_second,
- tm_conversion_clock::period>(tp);
+ std::int64_t,
+ tm_conversion_clock::base_year,
+ tm_conversion_clock::base_month,
+ tm_conversion_clock::base_day,
+ tm_conversion_clock::base_hour,
+ tm_conversion_clock::base_minute,
+ tm_conversion_clock::base_second,
+ tm_conversion_clock::period>(tp);
return internal_to_tm(normalized_tp.time_since_epoch());
}
@@ -144,14 +145,14 @@ public:
static std::chrono::time_point<std::chrono::system_clock> to_system_clock(const time_point &tp)
{
auto normalized_tp = to_arbitrary_time_point<
- std::int64_t,
- system_conversion_clock::base_year,
- system_conversion_clock::base_month,
- system_conversion_clock::base_day,
- system_conversion_clock::base_hour,
- system_conversion_clock::base_minute,
- system_conversion_clock::base_second,
- system_conversion_clock::period>(tp);
+ std::int64_t,
+ system_conversion_clock::base_year,
+ system_conversion_clock::base_month,
+ system_conversion_clock::base_day,
+ system_conversion_clock::base_hour,
+ system_conversion_clock::base_minute,
+ system_conversion_clock::base_second,
+ system_conversion_clock::period>(tp);
return std::chrono::time_point<std::chrono::system_clock>(normalized_tp.time_since_epoch() + system_clock_adjustment);
}
diff --git a/src/lib/util/un7z.cpp b/src/lib/util/un7z.cpp
index 879da294c69..b35af479d5d 100644
--- a/src/lib/util/un7z.cpp
+++ b/src/lib/util/un7z.cpp
@@ -13,11 +13,13 @@
#include "unzip.h"
#include "corestr.h"
-#include "osdcore.h"
-#include "osdfile.h"
+#include "ioprocs.h"
#include "unicode.h"
#include "timeconv.h"
+#include "osdcore.h"
+#include "osdfile.h"
+
#include "lzma/C/7z.h"
#include "lzma/C/7zAlloc.h"
#include "lzma/C/7zCrc.h"
@@ -38,47 +40,71 @@
namespace util {
+
namespace {
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
-struct CSzFile
+struct CFileInStream : public ISeekInStream
{
- CSzFile() : currfpos(0), length(0), osdfile() {}
+ CFileInStream() noexcept
+ {
+ Read = [] (void *pp, void *buf, size_t *size) { return reinterpret_cast<CFileInStream *>(pp)->read(buf, *size); };
+ Seek = [] (void *pp, Int64 *pos, ESzSeek origin) { return reinterpret_cast<CFileInStream *>(pp)->seek(*pos, origin); };
+ }
- std::uint64_t currfpos;
- std::uint64_t length;
- osd_file::ptr osdfile;
+ random_read::ptr file;
+ std::uint64_t currfpos = 0;
+ std::uint64_t length = 0;
- SRes read(void *data, std::size_t &size)
+private:
+ SRes read(void *data, std::size_t &size) noexcept
{
- if (!osdfile)
+ if (!file)
{
- osd_printf_error("un7z: called CSzFile::read without file\n");
+ osd_printf_error("un7z: called CFileInStream::read without file\n");
return SZ_ERROR_READ;
}
if (!size)
return SZ_OK;
- // TODO: this casts a size_t to a uint32_t, so it will fail if >=4GB is requested at once (need a loop)
- std::uint32_t read_length(0);
- auto const err = osdfile->read(data, currfpos, size, read_length);
+ std::size_t read_length(0);
+ std::error_condition const err = file->read_at(currfpos, data, size, read_length);
size = read_length;
currfpos += read_length;
- return (osd_file::error::NONE == err) ? SZ_OK : SZ_ERROR_READ;
+ return !err ? SZ_OK : SZ_ERROR_READ;
}
- SRes seek(Int64 &pos, ESzSeek origin)
+ SRes seek(Int64 &pos, ESzSeek origin) noexcept
{
+ // need to synthesise this because the OSD file wrapper doesn't implement SEEK_END
switch (origin)
{
- case SZ_SEEK_CUR: currfpos += pos; break;
- case SZ_SEEK_SET: currfpos = pos; break;
- case SZ_SEEK_END: currfpos = length + pos; break;
- default: return SZ_ERROR_READ;
+ case SZ_SEEK_CUR:
+ if ((0 > pos) && (-pos > currfpos))
+ {
+ osd_printf_error("un7z: attemped to seek back %d bytes when current offset is %u\n", -pos, currfpos);
+ return SZ_ERROR_READ;
+ }
+ currfpos += pos;
+ break;
+ case SZ_SEEK_SET:
+ currfpos = pos;
+ break;
+ case SZ_SEEK_END:
+ if ((0 > pos) && (-pos > length))
+ {
+ osd_printf_error("un7z: attemped to seek %d bytes before end of file %u\n", -pos, currfpos);
+ return SZ_ERROR_READ;
+ }
+ currfpos = length + pos;
+ break;
+ default:
+ return SZ_ERROR_READ;
}
pos = currfpos;
return SZ_OK;
@@ -86,18 +112,18 @@ struct CSzFile
};
-struct CFileInStream : public ISeekInStream, public CSzFile
-{
- CFileInStream();
-};
-
-
-class m7z_file_impl
+class m7z_file_impl
{
public:
typedef std::unique_ptr<m7z_file_impl> ptr;
- m7z_file_impl(const std::string &filename);
+ m7z_file_impl(std::string &&filename) noexcept;
+
+ m7z_file_impl(random_read::ptr &&file) noexcept
+ : m7z_file_impl(std::string())
+ {
+ m_archive_stream.file = std::move(file);
+ }
virtual ~m7z_file_impl()
{
@@ -107,7 +133,7 @@ public:
SzArEx_Free(&m_db, &m_alloc_imp);
}
- static ptr find_cached(const std::string &filename)
+ static ptr find_cached(std::string_view filename) noexcept
{
std::lock_guard<std::mutex> guard(s_cache_mutex);
for (std::size_t cachenum = 0; cachenum < s_cache.size(); cachenum++)
@@ -115,47 +141,60 @@ public:
// if we have a valid entry and it matches our filename, use it and remove from the cache
if (s_cache[cachenum] && (filename == s_cache[cachenum]->m_filename))
{
+ using std::swap;
ptr result;
- std::swap(s_cache[cachenum], result);
+ swap(s_cache[cachenum], result);
osd_printf_verbose("un7z: found %s in cache\n", filename);
return result;
}
}
return ptr();
}
- static void close(ptr &&archive);
- static void cache_clear()
+
+ static void close(ptr &&archive) noexcept;
+
+ static void cache_clear() noexcept
{
// clear call cache entries
std::lock_guard<std::mutex> guard(s_cache_mutex);
- for (std::size_t cachenum = 0; cachenum < s_cache.size(); s_cache[cachenum++].reset()) { }
+ for (auto &cached : s_cache)
+ cached.reset();
}
- archive_file::error initialize();
+ std::error_condition initialize() noexcept;
- int first_file() { return search(0, 0, std::string(), false, false, false); }
- int next_file() { return (m_curr_file_idx < 0) ? -1 : search(m_curr_file_idx + 1, 0, std::string(), false, false, false); }
+ int first_file() noexcept
+ {
+ return search(0, 0, std::string_view(), false, false, false);
+ }
- int search(std::uint32_t crc)
+ int next_file() noexcept
{
- return search(0, crc, std::string(), true, false, false);
+ return (m_curr_file_idx < 0) ? -1 : search(m_curr_file_idx + 1, 0, std::string_view(), false, false, false);
}
- int search(const std::string &filename, bool partialpath)
+
+ int search(std::uint32_t crc) noexcept
+ {
+ return search(0, crc, std::string_view(), true, false, false);
+ }
+
+ int search(std::string_view filename, bool partialpath) noexcept
{
return search(0, 0, filename, false, true, partialpath);
}
- int search(std::uint32_t crc, const std::string &filename, bool partialpath)
+
+ int search(std::uint32_t crc, std::string_view filename, bool partialpath) noexcept
{
return search(0, crc, filename, true, true, partialpath);
}
- bool current_is_directory() const { return m_curr_is_dir; }
- const std::string &current_name() const { return m_curr_name; }
- std::uint64_t current_uncompressed_length() const { return m_curr_length; }
- virtual std::chrono::system_clock::time_point current_last_modified() const { return m_curr_modified; }
- std::uint32_t current_crc() const { return m_curr_crc; }
+ bool current_is_directory() const noexcept { return m_curr_is_dir; }
+ const std::string &current_name() const noexcept { return m_curr_name; }
+ std::uint64_t current_uncompressed_length() const noexcept { return m_curr_length; }
+ virtual std::chrono::system_clock::time_point current_last_modified() const noexcept { return m_curr_modified; }
+ std::uint32_t current_crc() const noexcept { return m_curr_crc; }
- archive_file::error decompress(void *buffer, std::uint32_t length);
+ std::error_condition decompress(void *buffer, std::size_t length) noexcept;
private:
m7z_file_impl(const m7z_file_impl &) = delete;
@@ -166,12 +205,12 @@ private:
int search(
int i,
std::uint32_t search_crc,
- const std::string &search_filename,
+ std::string_view search_filename,
bool matchcrc,
bool matchname,
- bool partialpath);
+ bool partialpath) noexcept;
void make_utf8_name(int index);
- void set_curr_modified();
+ void set_curr_modified() noexcept;
static constexpr std::size_t CACHE_SIZE = 8;
static std::array<ptr, CACHE_SIZE> s_cache;
@@ -187,7 +226,7 @@ private:
std::uint32_t m_curr_crc; // current file crc
std::vector<UInt16> m_utf16_buf;
- std::vector<char32_t> m_uchar_buf;
+ std::vector<char32_t> m_uchar_buf;
std::vector<char> m_utf8_buf;
CFileInStream m_archive_stream;
@@ -201,39 +240,38 @@ private:
UInt32 m_block_index;
Byte * m_out_buffer;
std::size_t m_out_buffer_size;
-
};
class m7z_file_wrapper : public archive_file
{
public:
- m7z_file_wrapper(m7z_file_impl::ptr &&impl) : m_impl(std::move(impl)) { assert(m_impl); }
+ m7z_file_wrapper(m7z_file_impl::ptr &&impl) noexcept : m_impl(std::move(impl)) { assert(m_impl); }
virtual ~m7z_file_wrapper() override { m7z_file_impl::close(std::move(m_impl)); }
- virtual int first_file() override { return m_impl->first_file(); }
- virtual int next_file() override { return m_impl->next_file(); }
+ virtual int first_file() noexcept override { return m_impl->first_file(); }
+ virtual int next_file() noexcept override { return m_impl->next_file(); }
- virtual int search(std::uint32_t crc) override
+ virtual int search(std::uint32_t crc) noexcept override
{
return m_impl->search(crc);
}
- virtual int search(const std::string &filename, bool partialpath) override
+ virtual int search(std::string_view filename, bool partialpath) noexcept override
{
return m_impl->search(filename, partialpath);
}
- virtual int search(std::uint32_t crc, const std::string &filename, bool partialpath) override
+ virtual int search(std::uint32_t crc, std::string_view filename, bool partialpath) noexcept override
{
return m_impl->search(crc, filename, partialpath);
}
- virtual bool current_is_directory() const override { return m_impl->current_is_directory(); }
- virtual const std::string &current_name() const override { return m_impl->current_name(); }
- virtual std::uint64_t current_uncompressed_length() const override { return m_impl->current_uncompressed_length(); }
- virtual std::chrono::system_clock::time_point current_last_modified() const override { return m_impl->current_last_modified(); }
- virtual std::uint32_t current_crc() const override { return m_impl->current_crc(); }
+ virtual bool current_is_directory() const noexcept override { return m_impl->current_is_directory(); }
+ virtual const std::string &current_name() const noexcept override { return m_impl->current_name(); }
+ virtual std::uint64_t current_uncompressed_length() const noexcept override { return m_impl->current_uncompressed_length(); }
+ virtual std::chrono::system_clock::time_point current_last_modified() const noexcept override { return m_impl->current_last_modified(); }
+ virtual std::uint32_t current_crc() const noexcept override { return m_impl->current_crc(); }
- virtual error decompress(void *buffer, std::uint32_t length) override { return m_impl->decompress(buffer, length); }
+ virtual std::error_condition decompress(void *buffer, std::size_t length) noexcept override { return m_impl->decompress(buffer, length); }
private:
m7z_file_impl::ptr m_impl;
@@ -251,48 +289,20 @@ std::mutex m7z_file_impl::s_cache_mutex;
/***************************************************************************
- 7Zip Memory / File handling (adapted from 7zfile.c/.h and 7zalloc.c/.h)
-***************************************************************************/
-
-/* ---------- FileInStream ---------- */
-
-extern "C" {
-static SRes FileInStream_Read(void *pp, void *buf, size_t *size)
-{
- return (reinterpret_cast<CFileInStream *>(pp)->read(buf, *size) == 0) ? SZ_OK : SZ_ERROR_READ;
-}
-
-static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)
-{
- return reinterpret_cast<CFileInStream *>(pp)->seek(*pos, origin);
-}
-
-} // extern "C"
-
-
-CFileInStream::CFileInStream()
-{
- Read = &FileInStream_Read;
- Seek = &FileInStream_Seek;
-}
-
-
-
-/***************************************************************************
CACHE MANAGEMENT
***************************************************************************/
-m7z_file_impl::m7z_file_impl(const std::string &filename)
- : m_filename(filename)
+m7z_file_impl::m7z_file_impl(std::string &&filename) noexcept
+ : m_filename(std::move(filename))
, m_curr_file_idx(-1)
, m_curr_is_dir(false)
, m_curr_name()
, m_curr_length(0)
, m_curr_modified()
, m_curr_crc(0)
- , m_utf16_buf(128)
- , m_uchar_buf(128)
- , m_utf8_buf(512)
+ , m_utf16_buf()
+ , m_uchar_buf()
+ , m_utf8_buf()
, m_inited(false)
, m_block_index(0)
, m_out_buffer(nullptr)
@@ -310,15 +320,45 @@ m7z_file_impl::m7z_file_impl(const std::string &filename)
}
-archive_file::error m7z_file_impl::initialize()
+std::error_condition m7z_file_impl::initialize() noexcept
{
- osd_file::error const err = osd_file::open(m_filename, OPEN_FLAG_READ, m_archive_stream.osdfile, m_archive_stream.length);
- if (err != osd_file::error::NONE)
- return archive_file::error::FILE_ERROR;
+ try
+ {
+ if (m_utf16_buf.size() < 128)
+ m_utf16_buf.resize(128);
+ if (m_uchar_buf.size() < 128)
+ m_uchar_buf.resize(128);
+ m_utf8_buf.reserve(512);
+ }
+ catch (...)
+ {
+ return std::errc::not_enough_memory;
+ }
- osd_printf_verbose("un7z: opened archive file %s\n", m_filename);
+ if (!m_archive_stream.file)
+ {
+ osd_file::ptr file;
+ std::error_condition const err = osd_file::open(m_filename, OPEN_FLAG_READ, file, m_archive_stream.length);
+ if (err)
+ return err;
+ m_archive_stream.file = osd_file_read(std::move(file));
+ osd_printf_verbose("un7z: opened archive file %s\n", m_filename);
+ }
+ else if (!m_archive_stream.length)
+ {
+ std::error_condition const err = m_archive_stream.file->length(m_archive_stream.length);
+ if (err)
+ {
+ osd_printf_verbose(
+ "un7z: error getting length of archive file %s (%s:%d %s)\n",
+ m_filename, err.category().name(), err.value(), err.message());
+ return err;
+ }
+ }
- CrcGenerateTable(); // FIXME: doesn't belong here - it should be called once statically
+ // TODO: coordinate this with other LZMA users in the codebase?
+ struct crc_table_generator { crc_table_generator() { CrcGenerateTable(); } };
+ static crc_table_generator crc_table;
SzArEx_Init(&m_db);
m_inited = true;
@@ -329,13 +369,13 @@ archive_file::error m7z_file_impl::initialize()
switch (res)
{
case SZ_ERROR_UNSUPPORTED: return archive_file::error::UNSUPPORTED;
- case SZ_ERROR_MEM: return archive_file::error::OUT_OF_MEMORY;
+ case SZ_ERROR_MEM: return std::errc::not_enough_memory;
case SZ_ERROR_INPUT_EOF: return archive_file::error::FILE_TRUNCATED;
- default: return archive_file::error::FILE_ERROR;
+ default: return std::errc::io_error; // TODO: better default error?
}
}
- return archive_file::error::NONE;
+ return std::error_condition();
}
@@ -344,33 +384,38 @@ archive_file::error m7z_file_impl::initialize()
to the cache
-------------------------------------------------*/
-void m7z_file_impl::close(ptr &&archive)
+void m7z_file_impl::close(ptr &&archive) noexcept
{
- if (!archive) return;
+ // if the filename isn't empty, the implementation can be cached
+ if (archive && !archive->m_filename.empty())
+ {
+ // close the open files
+ osd_printf_verbose("un7z: closing archive file %s and sending to cache\n", archive->m_filename);
+ archive->m_archive_stream.file.reset();
- // close the open files
- osd_printf_verbose("un7z: closing archive file %s and sending to cache\n", archive->m_filename);
- archive->m_archive_stream.osdfile.reset();
+ // find the first nullptr entry in the cache
+ std::lock_guard<std::mutex> guard(s_cache_mutex);
+ std::size_t cachenum;
+ for (cachenum = 0; cachenum < s_cache.size(); cachenum++)
+ if (!s_cache[cachenum])
+ break;
- // find the first nullptr entry in the cache
- std::lock_guard<std::mutex> guard(s_cache_mutex);
- std::size_t cachenum;
- for (cachenum = 0; cachenum < s_cache.size(); cachenum++)
- if (!s_cache[cachenum])
- break;
+ // if no room left in the cache, free the bottommost entry
+ if (cachenum == s_cache.size())
+ {
+ cachenum--;
+ osd_printf_verbose("un7z: removing %s from cache to make space\n", s_cache[cachenum]->m_filename);
+ s_cache[cachenum].reset();
+ }
- // if no room left in the cache, free the bottommost entry
- if (cachenum == s_cache.size())
- {
- cachenum--;
- osd_printf_verbose("un7z: removing %s from cache to make space\n", s_cache[cachenum]->m_filename);
- s_cache[cachenum].reset();
+ // move everyone else down and place us at the top
+ for ( ; cachenum > 0; cachenum--)
+ s_cache[cachenum] = std::move(s_cache[cachenum - 1]);
+ s_cache[0] = std::move(archive);
}
- // move everyone else down and place us at the top
- for ( ; cachenum > 0; cachenum--)
- s_cache[cachenum] = std::move(s_cache[cachenum - 1]);
- s_cache[0] = std::move(archive);
+ // make sure it's cleaned up
+ archive.reset();
}
@@ -384,7 +429,7 @@ void m7z_file_impl::close(ptr &&archive)
from a _7Z into the target buffer
-------------------------------------------------*/
-archive_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length)
+std::error_condition m7z_file_impl::decompress(void *buffer, std::size_t length) noexcept
{
// if we don't have enough buffer, error
if (length < m_curr_length)
@@ -394,15 +439,19 @@ archive_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length
}
// make sure the file is open..
- if (!m_archive_stream.osdfile)
+ if (!m_archive_stream.file)
{
- m_archive_stream.currfpos = 0;
- osd_file::error const err = osd_file::open(m_filename, OPEN_FLAG_READ, m_archive_stream.osdfile, m_archive_stream.length);
- if (err != osd_file::error::NONE)
+ m_archive_stream.currfpos = 0; // FIXME: should it really be changing the file pointer out from under LZMA?
+ osd_file::ptr file;
+ std::error_condition const err = osd_file::open(m_filename, OPEN_FLAG_READ, file, m_archive_stream.length);
+ if (err)
{
- osd_printf_error("un7z: error reopening archive file %s (%d)\n", m_filename, int(err));
- return archive_file::error::FILE_ERROR;
+ osd_printf_error(
+ "un7z: error reopening archive file %s (%s:%d %s)\n",
+ m_filename, err.category().name(), err.value(), err.message());
+ return err;
}
+ m_archive_stream.file = osd_file_read(std::move(file));
osd_printf_verbose("un7z: reopened archive file %s\n", m_filename);
}
@@ -419,7 +468,7 @@ archive_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length
switch (res)
{
case SZ_ERROR_UNSUPPORTED: return archive_file::error::UNSUPPORTED;
- case SZ_ERROR_MEM: return archive_file::error::OUT_OF_MEMORY;
+ case SZ_ERROR_MEM: return std::errc::not_enough_memory;
case SZ_ERROR_INPUT_EOF: return archive_file::error::FILE_TRUNCATED;
default: return archive_file::error::DECOMPRESS_ERROR;
}
@@ -427,45 +476,64 @@ archive_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length
// copy to destination buffer
std::memcpy(buffer, m_out_buffer + offset, (std::min<std::size_t>)(length, out_size_processed));
- return archive_file::error::NONE;
+ return std::error_condition();
}
int m7z_file_impl::search(
int i,
std::uint32_t search_crc,
- const std::string &search_filename,
+ std::string_view search_filename,
bool matchcrc,
bool matchname,
- bool partialpath)
+ bool partialpath) noexcept
{
- for ( ; i < m_db.NumFiles; i++)
- {
- make_utf8_name(i);
- bool const is_dir(SzArEx_IsDir(&m_db, i));
- const std::uint64_t size(SzArEx_GetFileSize(&m_db, i));
- const std::uint32_t crc(m_db.CRCs.Vals[i]);
- const bool crcmatch(SzBitArray_Check(m_db.CRCs.Defs, i) && (crc == search_crc));
- auto const partialoffset(m_utf8_buf.size() - 1 - search_filename.length());
- bool const partialpossible((m_utf8_buf.size() > (search_filename.length() + 1)) && (m_utf8_buf[partialoffset - 1] == '/'));
- const bool namematch(
- !core_stricmp(search_filename.c_str(), &m_utf8_buf[0]) ||
- (partialpath && partialpossible && !core_stricmp(search_filename.c_str(), &m_utf8_buf[partialoffset])));
-
- const bool found = ((!matchcrc && !matchname) || !is_dir) && (!matchcrc || crcmatch) && (!matchname || namematch);
- if (found)
+ try
+ {
+ for ( ; i < m_db.NumFiles; i++)
{
- m_curr_file_idx = i;
- m_curr_is_dir = is_dir;
- m_curr_name = &m_utf8_buf[0];
- m_curr_length = size;
- set_curr_modified();
- m_curr_crc = crc;
-
- return i;
+ make_utf8_name(i);
+ bool const is_dir(SzArEx_IsDir(&m_db, i));
+ const std::uint64_t size(SzArEx_GetFileSize(&m_db, i));
+ const std::uint32_t crc(m_db.CRCs.Vals[i]);
+
+ const bool crcmatch(SzBitArray_Check(m_db.CRCs.Defs, i) && (crc == search_crc));
+ bool found;
+ if (!matchname)
+ {
+ found = !matchcrc || (crcmatch && !is_dir);
+ }
+ else
+ {
+ auto const partialoffset = m_utf8_buf.size() - search_filename.length();
+ const bool namematch =
+ (search_filename.length() == m_utf8_buf.size()) &&
+ (search_filename.empty() || !core_strnicmp(&search_filename[0], &m_utf8_buf[0], search_filename.length()));
+ bool const partialmatch =
+ partialpath &&
+ ((m_utf8_buf.size() > search_filename.length()) && (m_utf8_buf[partialoffset - 1] == '/')) &&
+ (search_filename.empty() || !core_strnicmp(&search_filename[0], &m_utf8_buf[partialoffset], search_filename.length()));
+ found = (!matchcrc || crcmatch) && (namematch || partialmatch);
+ }
+
+ if (found)
+ {
+ // set the name first - resizing it can throw an exception, and we want the state to be consistent
+ m_curr_name.assign(m_utf8_buf.begin(), m_utf8_buf.end());
+ m_curr_file_idx = i;
+ m_curr_is_dir = is_dir;
+ m_curr_length = size;
+ set_curr_modified();
+ m_curr_crc = crc;
+
+ return i;
+ }
}
}
-
+ catch (...)
+ {
+ // allocation error handling name
+ }
return -1;
}
@@ -475,14 +543,14 @@ void m7z_file_impl::make_utf8_name(int index)
std::size_t len, out_pos;
len = SzArEx_GetFileNameUtf16(&m_db, index, nullptr);
- m_utf16_buf.resize((std::max<std::size_t>)(m_utf16_buf.size(), len));
+ m_utf16_buf.resize(std::max<std::size_t>(m_utf16_buf.size(), len));
SzArEx_GetFileNameUtf16(&m_db, index, &m_utf16_buf[0]);
- m_uchar_buf.resize((std::max<std::size_t>)(m_uchar_buf.size(), len));
+ m_uchar_buf.resize(std::max<std::size_t>(m_uchar_buf.size(), len));
out_pos = 0;
for (std::size_t in_pos = 0; in_pos < (len - 1); )
{
- const int used = uchar_from_utf16(&m_uchar_buf[out_pos], (char16_t *)&m_utf16_buf[in_pos], len - in_pos);
+ const int used = uchar_from_utf16(&m_uchar_buf[out_pos], reinterpret_cast<char16_t const *>(&m_utf16_buf[in_pos]), len - in_pos);
if (used < 0)
{
in_pos++;
@@ -497,7 +565,7 @@ void m7z_file_impl::make_utf8_name(int index)
}
len = out_pos;
- m_utf8_buf.resize((std::max<std::size_t>)(m_utf8_buf.size(), 4 * len + 1));
+ m_utf8_buf.resize((std::max<std::size_t>)(m_utf8_buf.size(), 4 * len));
out_pos = 0;
for (std::size_t in_pos = 0; in_pos < len; in_pos++)
{
@@ -508,30 +576,35 @@ void m7z_file_impl::make_utf8_name(int index)
out_pos += produced;
assert(out_pos < m_utf8_buf.size());
}
- m_utf8_buf[out_pos++] = '\0';
m_utf8_buf.resize(out_pos);
}
-void m7z_file_impl::set_curr_modified()
+void m7z_file_impl::set_curr_modified() noexcept
{
if (SzBitWithVals_Check(&m_db.MTime, m_curr_file_idx))
{
CNtfsFileTime const &file_time(m_db.MTime.Vals[m_curr_file_idx]);
- auto ticks = ntfs_duration_from_filetime(file_time.High, file_time.Low);
- m_curr_modified = system_clock_time_point_from_ntfs_duration(ticks);
- }
- else
- {
- // FIXME: what do we do about a lack of time?
+ try
+ {
+ auto ticks = ntfs_duration_from_filetime(file_time.High, file_time.Low);
+ m_curr_modified = system_clock_time_point_from_ntfs_duration(ticks);
+ return;
+ }
+ catch (...)
+ {
+ }
}
+
+ // no modification time available, or out-of-range exception
+ m_curr_modified = std::chrono::system_clock::from_time_t(std::time_t(0));
}
} // anonymous namespace
-archive_file::error archive_file::open_7z(const std::string &filename, ptr &result)
+std::error_condition archive_file::open_7z(std::string_view filename, ptr &result) noexcept
{
// ensure we start with a nullptr result
result.reset();
@@ -542,21 +615,49 @@ archive_file::error archive_file::open_7z(const std::string &filename, ptr &resu
if (!newimpl)
{
// allocate memory for the 7z file structure
- try { newimpl = std::make_unique<m7z_file_impl>(filename); }
- catch (...) { return error::OUT_OF_MEMORY; }
- error const err = newimpl->initialize();
- if (err != error::NONE) return err;
+ try { newimpl = std::make_unique<m7z_file_impl>(std::string(filename)); }
+ catch (...) { return std::errc::not_enough_memory; }
+ auto const err = newimpl->initialize();
+ if (err)
+ return err;
}
- try
+ // allocate the archive API wrapper
+ result.reset(new (std::nothrow) m7z_file_wrapper(std::move(newimpl)));
+ if (result)
{
- result = std::make_unique<m7z_file_wrapper>(std::move(newimpl));
- return error::NONE;
+ return std::error_condition();
}
- catch (...)
+ else
+ {
+ m7z_file_impl::close(std::move(newimpl));
+ return std::errc::not_enough_memory;
+ }
+}
+
+std::error_condition archive_file::open_7z(random_read::ptr &&file, ptr &result) noexcept
+{
+ // ensure we start with a nullptr result
+ result.reset();
+
+ // allocate memory for the zip_file structure
+ m7z_file_impl::ptr newimpl(new (std::nothrow) m7z_file_impl(std::move(file)));
+ if (!newimpl)
+ return std::errc::not_enough_memory;
+ auto const err = newimpl->initialize();
+ if (err)
+ return err;
+
+ // allocate the archive API wrapper
+ result.reset(new (std::nothrow) m7z_file_wrapper(std::move(newimpl)));
+ if (result)
+ {
+ return std::error_condition();
+ }
+ else
{
m7z_file_impl::close(std::move(newimpl));
- return error::OUT_OF_MEMORY;
+ return std::errc::not_enough_memory;
}
}
@@ -566,7 +667,7 @@ archive_file::error archive_file::open_7z(const std::string &filename, ptr &resu
cache and free all memory
-------------------------------------------------*/
-void m7z_file_cache_clear()
+void m7z_file_cache_clear() noexcept
{
// This is a trampoline called from unzip.cpp to avoid the need to have the zip and 7zip code in one file
m7z_file_impl::cache_clear();
diff --git a/src/lib/util/unzip.cpp b/src/lib/util/unzip.cpp
index a275cc7df06..d7df8fa5ce9 100644
--- a/src/lib/util/unzip.cpp
+++ b/src/lib/util/unzip.cpp
@@ -12,9 +12,11 @@
#include "corestr.h"
#include "hashing.h"
+#include "ioprocs.h"
+#include "timeconv.h"
+
#include "osdcore.h"
#include "osdfile.h"
-#include "timeconv.h"
#include "lzma/C/LzmaDec.h"
@@ -23,6 +25,7 @@
#include <algorithm>
#include <array>
#include <cassert>
+#include <cerrno>
#include <chrono>
#include <cstring>
#include <cstdlib>
@@ -34,31 +37,55 @@
namespace util {
+
namespace {
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
+class archive_category_impl : public std::error_category
+{
+public:
+ virtual char const *name() const noexcept override { return "archive"; }
+
+ virtual std::string message(int condition) const override
+ {
+ using namespace std::literals;
+ static std::string_view const s_messages[] = {
+ "No error"sv,
+ "Bad archive signature"sv,
+ "Decompression error"sv,
+ "Archive file truncated"sv,
+ "Archive file corrupt"sv,
+ "Archive file uses unsupported features"sv,
+ "Buffer too small for data"sv };
+ if ((0 <= condition) && (std::size(s_messages) > condition))
+ return std::string(s_messages[condition]);
+ else
+ return "Unknown error"s;
+ }
+};
+
+
class zip_file_impl
{
public:
- typedef std::unique_ptr<zip_file_impl> ptr;
-
- zip_file_impl(const std::string &filename)
- : m_filename(filename)
- , m_file()
- , m_length(0)
- , m_ecd()
- , m_cd()
- , m_cd_pos(0)
- , m_header()
- , m_curr_is_dir(false)
- , m_buffer()
+ using ptr = std::unique_ptr<zip_file_impl>;
+
+ zip_file_impl(std::string &&filename) noexcept
+ : m_filename(std::move(filename))
{
std::fill(m_buffer.begin(), m_buffer.end(), 0);
}
- static ptr find_cached(const std::string &filename)
+ zip_file_impl(random_read::ptr &&file) noexcept
+ : zip_file_impl(std::string())
+ {
+ m_file = std::move(file);
+ }
+
+ static ptr find_cached(std::string_view filename) noexcept
{
std::lock_guard<std::mutex> guard(s_cache_mutex);
for (std::size_t cachenum = 0; cachenum < s_cache.size(); cachenum++)
@@ -66,27 +93,31 @@ public:
// if we have a valid entry and it matches our filename, use it and remove from the cache
if (s_cache[cachenum] && (filename == s_cache[cachenum]->m_filename))
{
+ using std::swap;
ptr result;
- std::swap(s_cache[cachenum], result);
+ swap(s_cache[cachenum], result);
osd_printf_verbose("unzip: found %s in cache\n", filename);
return result;
}
}
return ptr();
}
- static void close(ptr &&zip);
- static void cache_clear()
+
+ static void close(ptr &&zip) noexcept;
+
+ static void cache_clear() noexcept
{
// clear call cache entries
std::lock_guard<std::mutex> guard(s_cache_mutex);
- for (std::size_t cachenum = 0; cachenum < s_cache.size(); s_cache[cachenum++].reset()) { }
+ for (auto &cached : s_cache)
+ cached.reset();
}
- archive_file::error initialize()
+ std::error_condition initialize() noexcept
{
// read ecd data
auto const ziperr = read_ecd();
- if (ziperr != archive_file::error::NONE)
+ if (ziperr)
return ziperr;
// verify that we can work with this zipfile (no disk spanning allowed)
@@ -111,7 +142,7 @@ public:
catch (...)
{
osd_printf_error("unzip: %s failed to allocate memory for central directory\n", m_filename);
- return archive_file::error::OUT_OF_MEMORY;
+ return std::errc::not_enough_memory;
}
// read the central directory
@@ -119,13 +150,15 @@ public:
std::size_t cd_offs(0);
while (cd_remaining)
{
- std::uint32_t const chunk(std::uint32_t((std::min<std::uint64_t>)(std::numeric_limits<std::uint32_t>::max(), cd_remaining)));
- std::uint32_t read_length(0);
- auto const filerr = m_file->read(&m_cd[cd_offs], m_ecd.cd_start_disk_offset + cd_offs, chunk, read_length);
- if (filerr != osd_file::error::NONE)
+ std::size_t const chunk(std::size_t(std::min<std::uint64_t>(std::numeric_limits<std::size_t>::max(), cd_remaining)));
+ std::size_t read_length(0);
+ std::error_condition const filerr = m_file->read_at(m_ecd.cd_start_disk_offset + cd_offs, &m_cd[cd_offs], chunk, read_length);
+ if (filerr)
{
- osd_printf_error("unzip: %s error reading central directory (%d)\n", m_filename, int(filerr));
- return archive_file::error::FILE_ERROR;
+ osd_printf_error(
+ "unzip: %s error reading central directory (%s:%d %s)\n",
+ m_filename, filerr.category().name(), filerr.value(), filerr.message());
+ return filerr;
}
if (!read_length)
{
@@ -137,39 +170,45 @@ public:
}
osd_printf_verbose("unzip: read %s central directory\n", m_filename);
- return archive_file::error::NONE;
+ return std::error_condition();
}
- int first_file()
+ int first_file() noexcept
{
m_cd_pos = 0;
- return search(0, std::string(), false, false, false);
+ return search(0, std::string_view(), false, false, false);
}
- int next_file()
+
+ int next_file() noexcept
{
- return search(0, std::string(), false, false, false);
+ return search(0, std::string_view(), false, false, false);
}
- int search(std::uint32_t crc)
+ int search(std::uint32_t crc) noexcept
{
m_cd_pos = 0;
- return search(crc, std::string(), true, false, false);
+ return search(crc, std::string_view(), true, false, false);
}
- int search(const std::string &filename, bool partialpath)
+
+ int search(std::string_view filename, bool partialpath) noexcept
{
m_cd_pos = 0;
return search(0, filename, false, true, partialpath);
}
- int search(std::uint32_t crc, const std::string &filename, bool partialpath)
+
+ int search(std::uint32_t crc, std::string_view filename, bool partialpath) noexcept
{
m_cd_pos = 0;
return search(crc, filename, true, true, partialpath);
}
- bool current_is_directory() const { return m_curr_is_dir; }
- const std::string &current_name() const { return m_header.file_name; }
- std::uint64_t current_uncompressed_length() const { return m_header.uncompressed_length; }
- std::chrono::system_clock::time_point current_last_modified() const
+ bool current_is_directory() const noexcept { return m_curr_is_dir; }
+
+ const std::string &current_name() const noexcept { return m_header.file_name; }
+
+ std::uint64_t current_uncompressed_length() const noexcept { return m_header.uncompressed_length; }
+
+ std::chrono::system_clock::time_point current_last_modified() const noexcept
{
if (!m_header.modified_cached)
{
@@ -178,9 +217,10 @@ public:
}
return m_header.modified;
}
- std::uint32_t current_crc() const { return m_header.crc; }
- archive_file::error decompress(void *buffer, std::uint32_t length);
+ std::uint32_t current_crc() const noexcept { return m_header.crc; }
+
+ std::error_condition decompress(void *buffer, std::size_t length) noexcept;
private:
zip_file_impl(const zip_file_impl &) = delete;
@@ -188,28 +228,43 @@ private:
zip_file_impl &operator=(const zip_file_impl &) = delete;
zip_file_impl &operator=(zip_file_impl &&) = delete;
- int search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname, bool partialpath);
+ int search(std::uint32_t search_crc, std::string_view search_filename, bool matchcrc, bool matchname, bool partialpath) noexcept;
- archive_file::error reopen()
+ std::error_condition reopen() noexcept
{
if (!m_file)
{
- auto const filerr = osd_file::open(m_filename, OPEN_FLAG_READ, m_file, m_length);
- if (filerr != osd_file::error::NONE)
+ osd_file::ptr file;
+ auto const filerr = osd_file::open(m_filename, OPEN_FLAG_READ, file, m_length);
+ if (filerr)
{
// this would spam every time it looks for a non-existent archive, which is a lot
- //osd_printf_error("unzip: error reopening archive file %s (%d)\n", m_filename, int(filerr));
- return archive_file::error::FILE_ERROR;
+ //osd_printf_error("unzip: error reopening archive file %s (%s:%d %s)\n", m_filename, filerr.category().name(), filerr.value(), filerr.message());
+ return filerr;
}
- else
+ m_file = osd_file_read(std::move(file));
+ if (!m_file)
{
- osd_printf_verbose("unzip: opened archive file %s\n", m_filename);
+ osd_printf_error("unzip: not enough memory to open archive file %s\n", m_filename);
+ return std::errc::not_enough_memory;
}
+ osd_printf_verbose("unzip: opened archive file %s\n", m_filename);
}
- return archive_file::error::NONE;
+ else if (!m_length)
+ {
+ auto const filerr = m_file->length(m_length);
+ if (filerr)
+ {
+ osd_printf_verbose(
+ "unzip: error getting length of archive file %s (%s:%d %s)\n",
+ m_filename, filerr.category().name(), filerr.value(), filerr.message());
+ return filerr;
+ }
+ }
+ return std::error_condition();
}
- static std::chrono::system_clock::time_point decode_dos_time(std::uint16_t date, std::uint16_t time)
+ static std::chrono::system_clock::time_point decode_dos_time(std::uint16_t date, std::uint16_t time) noexcept
{
// FIXME: work out why this doesn't always work
// negative tm_isdst should automatically determine whether DST is in effect for the date,
@@ -228,16 +283,22 @@ private:
}
// ZIP file parsing
- archive_file::error read_ecd();
- archive_file::error get_compressed_data_offset(std::uint64_t &offset);
+ std::error_condition read_ecd() noexcept;
+ std::error_condition get_compressed_data_offset(std::uint64_t &offset) noexcept;
// decompression interfaces
- archive_file::error decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length);
- archive_file::error decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length);
- archive_file::error decompress_data_type_14(std::uint64_t offset, void *buffer, std::uint32_t length);
+ std::error_condition decompress_data_type_0(std::uint64_t offset, void *buffer, std::size_t length) noexcept;
+ std::error_condition decompress_data_type_8(std::uint64_t offset, void *buffer, std::size_t length) noexcept;
+ std::error_condition decompress_data_type_14(std::uint64_t offset, void *buffer, std::size_t length) noexcept;
struct file_header
{
+ file_header() noexcept { }
+ file_header(file_header const &) = default;
+ file_header(file_header &&) noexcept = default;
+ file_header &operator=(file_header const &) = default;
+ file_header &operator=(file_header &&) noexcept = default;
+
std::uint16_t version_created; // version made by
std::uint16_t version_needed; // version needed to extract
std::uint16_t bit_flag; // general purpose bit flag
@@ -271,15 +332,15 @@ private:
static std::mutex s_cache_mutex;
const std::string m_filename; // copy of ZIP filename (for caching)
- osd_file::ptr m_file; // OSD file handle
- std::uint64_t m_length; // length of zip file
+ random_read::ptr m_file; // file handle
+ std::uint64_t m_length = 0; // length of zip file
ecd m_ecd; // end of central directory
std::vector<std::uint8_t> m_cd; // central directory raw data
- std::uint32_t m_cd_pos; // position in central directory
+ std::uint32_t m_cd_pos = 0; // position in central directory
file_header m_header; // current file header
- bool m_curr_is_dir; // current file is directory
+ bool m_curr_is_dir = false; // current file is directory
std::array<std::uint8_t, DECOMPRESS_BUFSIZE> m_buffer; // buffer for decompression
};
@@ -288,32 +349,32 @@ private:
class zip_file_wrapper : public archive_file
{
public:
- zip_file_wrapper(zip_file_impl::ptr &&impl) : m_impl(std::move(impl)) { assert(m_impl); }
+ zip_file_wrapper(zip_file_impl::ptr &&impl) noexcept : m_impl(std::move(impl)) { assert(m_impl); }
virtual ~zip_file_wrapper() { zip_file_impl::close(std::move(m_impl)); }
- virtual int first_file() override { return m_impl->first_file(); }
- virtual int next_file() override { return m_impl->next_file(); }
+ virtual int first_file() noexcept override { return m_impl->first_file(); }
+ virtual int next_file() noexcept override { return m_impl->next_file(); }
- virtual int search(std::uint32_t crc) override
+ virtual int search(std::uint32_t crc) noexcept override
{
return m_impl->search(crc);
}
- virtual int search(const std::string &filename, bool partialpath) override
+ virtual int search(std::string_view filename, bool partialpath) noexcept override
{
return m_impl->search(filename, partialpath);
}
- virtual int search(std::uint32_t crc, const std::string &filename, bool partialpath) override
+ virtual int search(std::uint32_t crc, std::string_view filename, bool partialpath) noexcept override
{
return m_impl->search(crc, filename, partialpath);
}
- virtual bool current_is_directory() const override { return m_impl->current_is_directory(); }
- virtual const std::string &current_name() const override { return m_impl->current_name(); }
- virtual std::uint64_t current_uncompressed_length() const override { return m_impl->current_uncompressed_length(); }
- virtual std::chrono::system_clock::time_point current_last_modified() const override { return m_impl->current_last_modified(); }
- virtual std::uint32_t current_crc() const override { return m_impl->current_crc(); }
+ virtual bool current_is_directory() const noexcept override { return m_impl->current_is_directory(); }
+ virtual const std::string &current_name() const noexcept override { return m_impl->current_name(); }
+ virtual std::uint64_t current_uncompressed_length() const noexcept override { return m_impl->current_uncompressed_length(); }
+ virtual std::chrono::system_clock::time_point current_last_modified() const noexcept override { return m_impl->current_last_modified(); }
+ virtual std::uint32_t current_crc() const noexcept override { return m_impl->current_crc(); }
- virtual error decompress(void *buffer, std::uint32_t length) override { return m_impl->decompress(buffer, length); }
+ virtual std::error_condition decompress(void *buffer, std::size_t length) noexcept override { return m_impl->decompress(buffer, length); }
private:
zip_file_impl::ptr m_impl;
@@ -323,19 +384,19 @@ private:
class reader_base
{
protected:
- reader_base(void const *buf) : m_buffer(reinterpret_cast<std::uint8_t const *>(buf)) { }
+ reader_base(void const *buf) noexcept : m_buffer(reinterpret_cast<std::uint8_t const *>(buf)) { }
- std::uint8_t read_byte(std::size_t offs) const
+ std::uint8_t read_byte(std::size_t offs) const noexcept
{
return m_buffer[offs];
}
- std::uint16_t read_word(std::size_t offs) const
+ std::uint16_t read_word(std::size_t offs) const noexcept
{
return
(std::uint16_t(m_buffer[offs + 1]) << 8) |
(std::uint16_t(m_buffer[offs + 0]) << 0);
}
- std::uint32_t read_dword(std::size_t offs) const
+ std::uint32_t read_dword(std::size_t offs) const noexcept
{
return
(std::uint32_t(m_buffer[offs + 3]) << 24) |
@@ -343,7 +404,7 @@ protected:
(std::uint32_t(m_buffer[offs + 1]) << 8) |
(std::uint32_t(m_buffer[offs + 0]) << 0);
}
- std::uint64_t read_qword(std::size_t offs) const
+ std::uint64_t read_qword(std::size_t offs) const noexcept
{
return
(std::uint64_t(m_buffer[offs + 7]) << 56) |
@@ -371,17 +432,17 @@ protected:
class extra_field_reader : private reader_base
{
public:
- extra_field_reader(void const *buf, std::size_t len) : reader_base(buf), m_length(len) { }
+ extra_field_reader(void const *buf, std::size_t len) noexcept : reader_base(buf), m_length(len) { }
- std::uint16_t header_id() const { return read_word(0x00); }
- std::uint16_t data_size() const { return read_word(0x02); }
- void const * data() const { return m_buffer + 0x04; }
- extra_field_reader next() const { return extra_field_reader(m_buffer + total_length(), m_length - total_length()); }
+ std::uint16_t header_id() const noexcept { return read_word(0x00); }
+ std::uint16_t data_size() const noexcept { return read_word(0x02); }
+ void const * data() const noexcept { return m_buffer + 0x04; }
+ extra_field_reader next() const noexcept { return extra_field_reader(m_buffer + total_length(), m_length - total_length()); }
- bool length_sufficient() const { return (m_length >= minimum_length()) && (m_length >= total_length()); }
+ bool length_sufficient() const noexcept { return (m_length >= minimum_length()) && (m_length >= total_length()); }
- std::size_t total_length() const { return minimum_length() + data_size(); }
- static std::size_t minimum_length() { return 0x04; }
+ std::size_t total_length() const noexcept { return minimum_length() + data_size(); }
+ static constexpr std::size_t minimum_length() { return 0x04; }
private:
std::size_t m_length;
@@ -391,131 +452,131 @@ private:
class local_file_header_reader : private reader_base
{
public:
- local_file_header_reader(void const *buf) : reader_base(buf) { }
-
- std::uint32_t signature() const { return read_dword(0x00); }
- std::uint8_t version_needed() const { return m_buffer[0x04]; }
- std::uint8_t os_needed() const { return m_buffer[0x05]; }
- std::uint16_t general_flag() const { return read_word(0x06); }
- std::uint16_t compression_method() const { return read_word(0x08); }
- std::uint16_t modified_time() const { return read_word(0x0a); }
- std::uint16_t modified_date() const { return read_word(0x0c); }
- std::uint32_t crc32() const { return read_dword(0x0e); }
- std::uint32_t compressed_size() const { return read_dword(0x12); }
- std::uint32_t uncompressed_size() const { return read_dword(0x16); }
- std::uint16_t file_name_length() const { return read_word(0x1a); }
- std::uint16_t extra_field_length() const { return read_word(0x1c); }
+ local_file_header_reader(void const *buf) noexcept : reader_base(buf) { }
+
+ std::uint32_t signature() const noexcept { return read_dword(0x00); }
+ std::uint8_t version_needed() const noexcept { return m_buffer[0x04]; }
+ std::uint8_t os_needed() const noexcept { return m_buffer[0x05]; }
+ std::uint16_t general_flag() const noexcept { return read_word(0x06); }
+ std::uint16_t compression_method() const noexcept { return read_word(0x08); }
+ std::uint16_t modified_time() const noexcept { return read_word(0x0a); }
+ std::uint16_t modified_date() const noexcept { return read_word(0x0c); }
+ std::uint32_t crc32() const noexcept { return read_dword(0x0e); }
+ std::uint32_t compressed_size() const noexcept { return read_dword(0x12); }
+ std::uint32_t uncompressed_size() const noexcept { return read_dword(0x16); }
+ std::uint16_t file_name_length() const noexcept { return read_word(0x1a); }
+ std::uint16_t extra_field_length() const noexcept { return read_word(0x1c); }
std::string file_name() const { return read_string(0x1e, file_name_length()); }
void file_name(std::string &result) const { read_string(result, 0x1e, file_name_length()); }
- extra_field_reader extra_field() const { return extra_field_reader(m_buffer + 0x1e + file_name_length(), extra_field_length()); }
+ extra_field_reader extra_field() const noexcept { return extra_field_reader(m_buffer + 0x1e + file_name_length(), extra_field_length()); }
- bool signature_correct() const { return signature() == 0x04034b50; }
+ bool signature_correct() const noexcept { return signature() == 0x04034b50; }
- std::size_t total_length() const { return minimum_length() + file_name_length() + extra_field_length(); }
- static std::size_t minimum_length() { return 0x1e; }
+ std::size_t total_length() const noexcept { return minimum_length() + file_name_length() + extra_field_length(); }
+ static constexpr std::size_t minimum_length() { return 0x1e; }
};
class central_dir_entry_reader : private reader_base
{
public:
- central_dir_entry_reader(void const *buf) : reader_base(buf) { }
-
- std::uint32_t signature() const { return read_dword(0x00); }
- std::uint8_t version_created() const { return m_buffer[0x04]; }
- std::uint8_t os_created() const { return m_buffer[0x05]; }
- std::uint8_t version_needed() const { return m_buffer[0x06]; }
- std::uint8_t os_needed() const { return m_buffer[0x07]; }
- std::uint16_t general_flag() const { return read_word(0x08); }
- std::uint16_t compression_method() const { return read_word(0x0a); }
- std::uint16_t modified_time() const { return read_word(0x0c); }
- std::uint16_t modified_date() const { return read_word(0x0e); }
- std::uint32_t crc32() const { return read_dword(0x10); }
- std::uint32_t compressed_size() const { return read_dword(0x14); }
- std::uint32_t uncompressed_size() const { return read_dword(0x18); }
- std::uint16_t file_name_length() const { return read_word(0x1c); }
- std::uint16_t extra_field_length() const { return read_word(0x1e); }
- std::uint16_t file_comment_length() const { return read_word(0x20); }
- std::uint16_t start_disk() const { return read_word(0x22); }
- std::uint16_t int_file_attr() const { return read_word(0x24); }
- std::uint32_t ext_file_attr() const { return read_dword(0x26); }
- std::uint32_t header_offset() const { return read_dword(0x2a); }
+ central_dir_entry_reader(void const *buf) noexcept : reader_base(buf) { }
+
+ std::uint32_t signature() const noexcept { return read_dword(0x00); }
+ std::uint8_t version_created() const noexcept { return m_buffer[0x04]; }
+ std::uint8_t os_created() const noexcept { return m_buffer[0x05]; }
+ std::uint8_t version_needed() const noexcept { return m_buffer[0x06]; }
+ std::uint8_t os_needed() const noexcept { return m_buffer[0x07]; }
+ std::uint16_t general_flag() const noexcept { return read_word(0x08); }
+ std::uint16_t compression_method() const noexcept { return read_word(0x0a); }
+ std::uint16_t modified_time() const noexcept { return read_word(0x0c); }
+ std::uint16_t modified_date() const noexcept { return read_word(0x0e); }
+ std::uint32_t crc32() const noexcept { return read_dword(0x10); }
+ std::uint32_t compressed_size() const noexcept { return read_dword(0x14); }
+ std::uint32_t uncompressed_size() const noexcept { return read_dword(0x18); }
+ std::uint16_t file_name_length() const noexcept { return read_word(0x1c); }
+ std::uint16_t extra_field_length() const noexcept { return read_word(0x1e); }
+ std::uint16_t file_comment_length() const noexcept { return read_word(0x20); }
+ std::uint16_t start_disk() const noexcept { return read_word(0x22); }
+ std::uint16_t int_file_attr() const noexcept { return read_word(0x24); }
+ std::uint32_t ext_file_attr() const noexcept { return read_dword(0x26); }
+ std::uint32_t header_offset() const noexcept { return read_dword(0x2a); }
std::string file_name() const { return read_string(0x2e, file_name_length()); }
void file_name(std::string &result) const { read_string(result, 0x2e, file_name_length()); }
- extra_field_reader extra_field() const { return extra_field_reader(m_buffer + 0x2e + file_name_length(), extra_field_length()); }
+ extra_field_reader extra_field() const noexcept { return extra_field_reader(m_buffer + 0x2e + file_name_length(), extra_field_length()); }
std::string file_comment() const { return read_string(0x2e + file_name_length() + extra_field_length(), file_comment_length()); }
void file_comment(std::string &result) const { read_string(result, 0x2e + file_name_length() + extra_field_length(), file_comment_length()); }
- bool signature_correct() const { return signature() == 0x02014b50; }
+ bool signature_correct() const noexcept { return signature() == 0x02014b50; }
- std::size_t total_length() const { return minimum_length() + file_name_length() + extra_field_length() + file_comment_length(); }
- static std::size_t minimum_length() { return 0x2e; }
+ std::size_t total_length() const noexcept { return minimum_length() + file_name_length() + extra_field_length() + file_comment_length(); }
+ static constexpr std::size_t minimum_length() { return 0x2e; }
};
class ecd64_reader : private reader_base
{
public:
- ecd64_reader(void const *buf) : reader_base(buf) { }
-
- std::uint32_t signature() const { return read_dword(0x00); }
- std::uint64_t ecd64_size() const { return read_qword(0x04); }
- std::uint8_t version_created() const { return m_buffer[0x0c]; }
- std::uint8_t os_created() const { return m_buffer[0x0d]; }
- std::uint8_t version_needed() const { return m_buffer[0x0e]; }
- std::uint8_t os_needed() const { return m_buffer[0x0f]; }
- std::uint32_t this_disk_no() const { return read_dword(0x10); }
- std::uint32_t dir_start_disk() const { return read_dword(0x14); }
- std::uint64_t dir_disk_entries() const { return read_qword(0x18); }
- std::uint64_t dir_total_entries() const { return read_qword(0x20); }
- std::uint64_t dir_size() const { return read_qword(0x28); }
- std::uint64_t dir_offset() const { return read_qword(0x30); }
- void const * extensible_data() const { return m_buffer + 0x38; }
-
- bool signature_correct() const { return signature() == 0x06064b50; }
-
- std::size_t total_length() const { return 0x0c + ecd64_size(); }
- static std::size_t minimum_length() { return 0x38; }
+ ecd64_reader(void const *buf) noexcept : reader_base(buf) { }
+
+ std::uint32_t signature() const noexcept { return read_dword(0x00); }
+ std::uint64_t ecd64_size() const noexcept { return read_qword(0x04); }
+ std::uint8_t version_created() const noexcept { return m_buffer[0x0c]; }
+ std::uint8_t os_created() const noexcept { return m_buffer[0x0d]; }
+ std::uint8_t version_needed() const noexcept { return m_buffer[0x0e]; }
+ std::uint8_t os_needed() const noexcept { return m_buffer[0x0f]; }
+ std::uint32_t this_disk_no() const noexcept { return read_dword(0x10); }
+ std::uint32_t dir_start_disk() const noexcept { return read_dword(0x14); }
+ std::uint64_t dir_disk_entries() const noexcept { return read_qword(0x18); }
+ std::uint64_t dir_total_entries() const noexcept { return read_qword(0x20); }
+ std::uint64_t dir_size() const noexcept { return read_qword(0x28); }
+ std::uint64_t dir_offset() const noexcept { return read_qword(0x30); }
+ void const * extensible_data() const noexcept { return m_buffer + 0x38; }
+
+ bool signature_correct() const noexcept { return signature() == 0x06064b50; }
+
+ std::size_t total_length() const noexcept { return 0x0c + ecd64_size(); }
+ static constexpr std::size_t minimum_length() { return 0x38; }
};
class ecd64_locator_reader : private reader_base
{
public:
- ecd64_locator_reader(void const *buf) : reader_base(buf) { }
+ ecd64_locator_reader(void const *buf) noexcept : reader_base(buf) { }
- std::uint32_t signature() const { return read_dword(0x00); }
- std::uint32_t ecd64_disk() const { return read_dword(0x04); }
- std::uint64_t ecd64_offset() const { return read_qword(0x08); }
- std::uint32_t total_disks() const { return read_dword(0x10); }
+ std::uint32_t signature() const noexcept { return read_dword(0x00); }
+ std::uint32_t ecd64_disk() const noexcept { return read_dword(0x04); }
+ std::uint64_t ecd64_offset() const noexcept { return read_qword(0x08); }
+ std::uint32_t total_disks() const noexcept { return read_dword(0x10); }
- bool signature_correct() const { return signature() == 0x07064b50; }
+ bool signature_correct() const noexcept { return signature() == 0x07064b50; }
- std::size_t total_length() const { return minimum_length(); }
- static std::size_t minimum_length() { return 0x14; }
+ std::size_t total_length() const noexcept { return minimum_length(); }
+ static constexpr std::size_t minimum_length() { return 0x14; }
};
class ecd_reader : private reader_base
{
public:
- ecd_reader(void const *buf) : reader_base(buf) { }
-
- std::uint32_t signature() const { return read_dword(0x00); }
- std::uint16_t this_disk_no() const { return read_word(0x04); }
- std::uint16_t dir_start_disk() const { return read_word(0x06); }
- std::uint16_t dir_disk_entries() const { return read_word(0x08); }
- std::uint16_t dir_total_entries() const { return read_word(0x0a); }
- std::uint32_t dir_size() const { return read_dword(0x0c); }
- std::uint32_t dir_offset() const { return read_dword(0x10); }
- std::uint16_t comment_length() const { return read_word(0x14); }
+ ecd_reader(void const *buf) noexcept : reader_base(buf) { }
+
+ std::uint32_t signature() const noexcept { return read_dword(0x00); }
+ std::uint16_t this_disk_no() const noexcept { return read_word(0x04); }
+ std::uint16_t dir_start_disk() const noexcept { return read_word(0x06); }
+ std::uint16_t dir_disk_entries() const noexcept { return read_word(0x08); }
+ std::uint16_t dir_total_entries() const noexcept { return read_word(0x0a); }
+ std::uint32_t dir_size() const noexcept { return read_dword(0x0c); }
+ std::uint32_t dir_offset() const noexcept { return read_dword(0x10); }
+ std::uint16_t comment_length() const noexcept { return read_word(0x14); }
std::string comment() const { return read_string(0x16, comment_length()); }
void comment(std::string &result) const { read_string(result, 0x16, comment_length()); }
- bool signature_correct() const { return signature() == 0x06054b50; }
+ bool signature_correct() const noexcept { return signature() == 0x06054b50; }
- std::size_t total_length() const { return minimum_length() + comment_length(); }
- static std::size_t minimum_length() { return 0x16; }
+ std::size_t total_length() const noexcept { return minimum_length() + comment_length(); }
+ static constexpr std::size_t minimum_length() { return 0x16; }
};
@@ -525,7 +586,7 @@ public:
template <typename T>
zip64_ext_info_reader(
T const &header,
- extra_field_reader const &field)
+ extra_field_reader const &field) noexcept
: reader_base(field.data())
, m_uncompressed_size(header.uncompressed_size())
, m_compressed_size(header.compressed_size())
@@ -538,13 +599,13 @@ public:
{
}
- std::uint64_t uncompressed_size() const { return ~m_uncompressed_size ? m_uncompressed_size : read_qword(0x00); }
- std::uint64_t compressed_size() const { return ~m_compressed_size ? m_compressed_size : read_qword(m_offs_compressed_size); }
- std::uint64_t header_offset() const { return ~m_header_offset ? m_header_offset : read_qword(m_offs_header_offset); }
- std::uint32_t start_disk() const { return ~m_start_disk ? m_start_disk : read_dword(m_offs_start_disk); }
+ std::uint64_t uncompressed_size() const noexcept { return ~m_uncompressed_size ? m_uncompressed_size : read_qword(0x00); }
+ std::uint64_t compressed_size() const noexcept { return ~m_compressed_size ? m_compressed_size : read_qword(m_offs_compressed_size); }
+ std::uint64_t header_offset() const noexcept { return ~m_header_offset ? m_header_offset : read_qword(m_offs_header_offset); }
+ std::uint32_t start_disk() const noexcept { return ~m_start_disk ? m_start_disk : read_dword(m_offs_start_disk); }
- std::size_t total_length() const { return minimum_length() + m_offs_end; }
- static std::size_t minimum_length() { return 0x00; }
+ std::size_t total_length() const noexcept { return minimum_length() + m_offs_end; }
+ static constexpr std::size_t minimum_length() { return 0x00; }
private:
std::uint32_t m_uncompressed_size;
@@ -562,15 +623,15 @@ private:
class utf8_path_reader : private reader_base
{
public:
- utf8_path_reader(extra_field_reader const &field) : reader_base(field.data()), m_length(field.data_size()) { }
+ utf8_path_reader(extra_field_reader const &field) noexcept : reader_base(field.data()), m_length(field.data_size()) { }
- std::uint8_t version() const { return m_buffer[0]; }
- std::uint32_t name_crc32() const { return read_dword(0x01); }
+ std::uint8_t version() const noexcept { return m_buffer[0]; }
+ std::uint32_t name_crc32() const noexcept { return read_dword(0x01); }
std::string unicode_name() const { return read_string(0x05, m_length - 0x05); }
void unicode_name(std::string &result) const { return read_string(result, 0x05, m_length - 0x05); }
- std::size_t total_length() const { return m_length; }
- static std::size_t minimum_length() { return 0x05; }
+ std::size_t total_length() const noexcept { return m_length; }
+ static constexpr std::size_t minimum_length() { return 0x05; }
private:
std::size_t m_length;
@@ -580,17 +641,17 @@ private:
class ntfs_tag_reader : private reader_base
{
public:
- ntfs_tag_reader(void const *buf, std::size_t len) : reader_base(buf), m_length(len) { }
+ ntfs_tag_reader(void const *buf, std::size_t len) noexcept : reader_base(buf), m_length(len) { }
- std::uint16_t tag() const { return read_word(0x00); }
- std::uint16_t size() const { return read_word(0x02); }
- void const * data() const { return m_buffer + 0x04; }
- ntfs_tag_reader next() const { return ntfs_tag_reader(m_buffer + total_length(), m_length - total_length()); }
+ std::uint16_t tag() const noexcept { return read_word(0x00); }
+ std::uint16_t size() const noexcept { return read_word(0x02); }
+ void const * data() const noexcept { return m_buffer + 0x04; }
+ ntfs_tag_reader next() const noexcept { return ntfs_tag_reader(m_buffer + total_length(), m_length - total_length()); }
- bool length_sufficient() const { return (m_length >= minimum_length()) && (m_length >= total_length()); }
+ bool length_sufficient() const noexcept { return (m_length >= minimum_length()) && (m_length >= total_length()); }
- std::size_t total_length() const { return minimum_length() + size(); }
- static std::size_t minimum_length() { return 0x04; }
+ std::size_t total_length() const noexcept { return minimum_length() + size(); }
+ static constexpr std::size_t minimum_length() { return 0x04; }
private:
std::size_t m_length;
@@ -600,13 +661,13 @@ private:
class ntfs_reader : private reader_base
{
public:
- ntfs_reader(extra_field_reader const &field) : reader_base(field.data()), m_length(field.data_size()) { }
+ ntfs_reader(extra_field_reader const &field) noexcept : reader_base(field.data()), m_length(field.data_size()) { }
- std::uint32_t reserved() const { return read_dword(0x00); }
- ntfs_tag_reader tag1() const { return ntfs_tag_reader(m_buffer + 0x04, m_length - 4); }
+ std::uint32_t reserved() const noexcept { return read_dword(0x00); }
+ ntfs_tag_reader tag1() const noexcept { return ntfs_tag_reader(m_buffer + 0x04, m_length - 4); }
- std::size_t total_length() const { return m_length; }
- static std::size_t minimum_length() { return 0x08; }
+ std::size_t total_length() const noexcept { return m_length; }
+ static constexpr std::size_t minimum_length() { return 0x08; }
private:
std::size_t m_length;
@@ -616,14 +677,14 @@ private:
class ntfs_times_reader : private reader_base
{
public:
- ntfs_times_reader(ntfs_tag_reader const &tag) : reader_base(tag.data()) { }
+ ntfs_times_reader(ntfs_tag_reader const &tag) noexcept : reader_base(tag.data()) { }
- std::uint64_t mtime() const { return read_qword(0x00); }
- std::uint64_t atime() const { return read_qword(0x08); }
- std::uint64_t ctime() const { return read_qword(0x10); }
+ std::uint64_t mtime() const noexcept { return read_qword(0x00); }
+ std::uint64_t atime() const noexcept { return read_qword(0x08); }
+ std::uint64_t ctime() const noexcept { return read_qword(0x10); }
- std::size_t total_length() const { return minimum_length(); }
- static std::size_t minimum_length() { return 0x18; }
+ std::size_t total_length() const noexcept { return minimum_length(); }
+ static constexpr std::size_t minimum_length() { return 0x18; }
};
@@ -632,16 +693,16 @@ class general_flag_reader
public:
general_flag_reader(std::uint16_t val) : m_value(val) { }
- bool encrypted() const { return bool(m_value & 0x0001); }
- bool implode_8k_dict() const { return bool(m_value & 0x0002); }
- bool implode_3_trees() const { return bool(m_value & 0x0004); }
- unsigned deflate_option() const { return unsigned((m_value >> 1) & 0x0003); }
- bool lzma_eos_mark() const { return bool(m_value & 0x0002); }
- bool use_descriptor() const { return bool(m_value & 0x0008); }
- bool patch_data() const { return bool(m_value & 0x0020); }
- bool strong_encryption() const { return bool(m_value & 0x0040); }
- bool utf8_encoding() const { return bool(m_value & 0x0800); }
- bool directory_encryption() const { return bool(m_value & 0x2000); }
+ bool encrypted() const noexcept { return bool(m_value & 0x0001); }
+ bool implode_8k_dict() const noexcept { return bool(m_value & 0x0002); }
+ bool implode_3_trees() const noexcept { return bool(m_value & 0x0004); }
+ unsigned deflate_option() const noexcept { return unsigned((m_value >> 1) & 0x0003); }
+ bool lzma_eos_mark() const noexcept { return bool(m_value & 0x0002); }
+ bool use_descriptor() const noexcept { return bool(m_value & 0x0008); }
+ bool patch_data() const noexcept { return bool(m_value & 0x0020); }
+ bool strong_encryption() const noexcept { return bool(m_value & 0x0040); }
+ bool utf8_encoding() const noexcept { return bool(m_value & 0x0800); }
+ bool directory_encryption() const noexcept { return bool(m_value & 0x2000); }
private:
std::uint16_t m_value;
@@ -653,6 +714,8 @@ private:
GLOBAL VARIABLES
***************************************************************************/
+archive_category_impl const f_archive_category_instance;
+
std::array<zip_file_impl::ptr, zip_file_impl::CACHE_SIZE> zip_file_impl::s_cache;
std::mutex zip_file_impl::s_cache_mutex;
@@ -663,33 +726,38 @@ std::mutex zip_file_impl::s_cache_mutex;
to the cache
-------------------------------------------------*/
-void zip_file_impl::close(ptr &&zip)
+void zip_file_impl::close(ptr &&zip) noexcept
{
- if (!zip) return;
+ // if the filename isn't empty, the cached directory can be reused
+ if (zip && !zip->m_filename.empty())
+ {
+ // close the open files
+ osd_printf_verbose("unzip: closing archive file %s and sending to cache\n", zip->m_filename);
+ zip->m_file.reset();
- // close the open files
- osd_printf_verbose("unzip: closing archive file %s and sending to cache\n", zip->m_filename);
- zip->m_file.reset();
+ // find the first nullptr entry in the cache
+ std::lock_guard<std::mutex> guard(s_cache_mutex);
+ std::size_t cachenum;
+ for (cachenum = 0; cachenum < s_cache.size(); cachenum++)
+ if (!s_cache[cachenum])
+ break;
- // find the first nullptr entry in the cache
- std::lock_guard<std::mutex> guard(s_cache_mutex);
- std::size_t cachenum;
- for (cachenum = 0; cachenum < s_cache.size(); cachenum++)
- if (!s_cache[cachenum])
- break;
+ // if no room left in the cache, free the bottommost entry
+ if (cachenum == s_cache.size())
+ {
+ cachenum--;
+ osd_printf_verbose("unzip: removing %s from cache to make space\n", s_cache[cachenum]->m_filename);
+ s_cache[cachenum].reset();
+ }
- // if no room left in the cache, free the bottommost entry
- if (cachenum == s_cache.size())
- {
- cachenum--;
- osd_printf_verbose("unzip: removing %s from cache to make space\n", s_cache[cachenum]->m_filename);
- s_cache[cachenum].reset();
+ // move everyone else down and place us at the top
+ for ( ; cachenum > 0; cachenum--)
+ s_cache[cachenum] = std::move(s_cache[cachenum - 1]);
+ s_cache[0] = std::move(zip);
}
- // move everyone else down and place us at the top
- for ( ; cachenum > 0; cachenum--)
- s_cache[cachenum] = std::move(s_cache[cachenum - 1]);
- s_cache[0] = std::move(zip);
+ // make sure it's cleaned up
+ zip.reset();
}
@@ -702,7 +770,7 @@ void zip_file_impl::close(ptr &&zip)
entry in the ZIP
-------------------------------------------------*/
-int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname, bool partialpath)
+int zip_file_impl::search(std::uint32_t search_crc, std::string_view search_filename, bool matchcrc, bool matchname, bool partialpath) noexcept
{
// if we're at or past the end, we're done
while ((m_cd_pos + central_dir_entry_reader::minimum_length()) <= m_ecd.cd_size)
@@ -712,98 +780,123 @@ int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_fi
if (!reader.signature_correct() || ((m_cd_pos + reader.total_length()) > m_ecd.cd_size))
break;
- // extract file header info
- m_header.version_created = reader.version_created();
- m_header.version_needed = reader.version_needed();
- m_header.bit_flag = reader.general_flag();
- m_header.compression = reader.compression_method();
- m_header.crc = reader.crc32();
- m_header.compressed_length = reader.compressed_size();
- m_header.uncompressed_length = reader.uncompressed_size();
- m_header.start_disk_number = reader.start_disk();
- m_header.local_header_offset = reader.header_offset();
-
- // don't immediately decode DOS timestamp - it's expensive
- m_header.modified_date = reader.modified_date();
- m_header.modified_time = reader.modified_time();
- m_header.modified_cached = false;
-
- // advance the position
- m_cd_pos += reader.total_length();
-
- // copy the filename
- bool is_utf8(general_flag_reader(m_header.bit_flag).utf8_encoding());
- reader.file_name(m_header.file_name);
-
- // walk the extra data
- for (auto extra = reader.extra_field(); extra.length_sufficient(); extra = extra.next())
+ // setting std::string can raise allocation exceptions
+ try
{
- // look for ZIP64 extended info
- if ((extra.header_id() == 0x0001) && (extra.data_size() >= zip64_ext_info_reader::minimum_length()))
+ // extract file header info
+ file_header header;
+ header.version_created = reader.version_created();
+ header.version_needed = reader.version_needed();
+ header.bit_flag = reader.general_flag();
+ header.compression = reader.compression_method();
+ header.crc = reader.crc32();
+ header.compressed_length = reader.compressed_size();
+ header.uncompressed_length = reader.uncompressed_size();
+ header.start_disk_number = reader.start_disk();
+ header.local_header_offset = reader.header_offset();
+
+ // don't immediately decode DOS timestamp - it's expensive
+ header.modified_date = reader.modified_date();
+ header.modified_time = reader.modified_time();
+ header.modified_cached = false;
+
+ // copy the filename
+ bool is_utf8(general_flag_reader(header.bit_flag).utf8_encoding());
+ reader.file_name(header.file_name);
+
+ // walk the extra data
+ for (auto extra = reader.extra_field(); extra.length_sufficient(); extra = extra.next())
{
- zip64_ext_info_reader const ext64(reader, extra);
- if (extra.data_size() >= ext64.total_length())
+ // look for ZIP64 extended info
+ if ((extra.header_id() == 0x0001) && (extra.data_size() >= zip64_ext_info_reader::minimum_length()))
{
- m_header.compressed_length = ext64.compressed_size();
- m_header.uncompressed_length = ext64.uncompressed_size();
- m_header.start_disk_number = ext64.start_disk();
- m_header.local_header_offset = ext64.header_offset();
+ zip64_ext_info_reader const ext64(reader, extra);
+ if (extra.data_size() >= ext64.total_length())
+ {
+ header.compressed_length = ext64.compressed_size();
+ header.uncompressed_length = ext64.uncompressed_size();
+ header.start_disk_number = ext64.start_disk();
+ header.local_header_offset = ext64.header_offset();
+ }
}
- }
- // look for Info-ZIP UTF-8 path
- if (!is_utf8 && (extra.header_id() == 0x7075) && (extra.data_size() >= utf8_path_reader::minimum_length()))
- {
- utf8_path_reader const utf8path(extra);
- if (utf8path.version() == 1)
+ // look for Info-ZIP UTF-8 path
+ if (!is_utf8 && (extra.header_id() == 0x7075) && (extra.data_size() >= utf8_path_reader::minimum_length()))
{
- auto const addr(m_header.file_name.empty() ? nullptr : &m_header.file_name[0]);
- auto const length(m_header.file_name.empty() ? 0 : m_header.file_name.length() * sizeof(m_header.file_name[0]));
- auto const crc(crc32_creator::simple(addr, length));
- if (utf8path.name_crc32() == crc.m_raw)
+ utf8_path_reader const utf8path(extra);
+ if (utf8path.version() == 1)
{
- utf8path.unicode_name(m_header.file_name);
- is_utf8 = true;
+ auto const addr(header.file_name.empty() ? nullptr : &header.file_name[0]);
+ auto const length(header.file_name.empty() ? 0 : header.file_name.length() * sizeof(header.file_name[0]));
+ auto const crc(crc32_creator::simple(addr, length));
+ if (utf8path.name_crc32() == crc.m_raw)
+ {
+ utf8path.unicode_name(header.file_name);
+ is_utf8 = true;
+ }
}
}
- }
- // look for NTFS extra field
- if ((extra.header_id() == 0x000a) && (extra.data_size() >= ntfs_reader::minimum_length()))
- {
- ntfs_reader const ntfs(extra);
- for (auto tag = ntfs.tag1(); tag.length_sufficient(); tag = tag.next())
+ // look for NTFS extra field
+ if ((extra.header_id() == 0x000a) && (extra.data_size() >= ntfs_reader::minimum_length()))
{
- if ((tag.tag() == 0x0001) && (tag.size() >= ntfs_times_reader::minimum_length()))
+ ntfs_reader const ntfs(extra);
+ for (auto tag = ntfs.tag1(); tag.length_sufficient(); tag = tag.next())
{
- ntfs_times_reader const times(tag);
- ntfs_duration const ticks(times.mtime());
- m_header.modified = system_clock_time_point_from_ntfs_duration(ticks);
- m_header.modified_cached = true;
+ if ((tag.tag() == 0x0001) && (tag.size() >= ntfs_times_reader::minimum_length()))
+ {
+ ntfs_times_reader const times(tag);
+ ntfs_duration const ticks(times.mtime());
+ try
+ {
+ header.modified = system_clock_time_point_from_ntfs_duration(ticks);
+ header.modified_cached = true;
+ }
+ catch (...)
+ {
+ // out-of-range exception - let it fall back to DOS-style timestamp
+ }
+ }
}
}
}
- }
- // FIXME: if (!is_utf8) convert filename to UTF8 (assume CP437 or something)
+ // FIXME: if (!is_utf8) convert filename to UTF8 (assume CP437 or something)
- // chop off trailing slash for directory entries
- bool const is_dir(!m_header.file_name.empty() && (m_header.file_name.back() == '/'));
- if (is_dir) m_header.file_name.resize(m_header.file_name.length() - 1);
+ // chop off trailing slash for directory entries
+ bool const is_dir(!header.file_name.empty() && (header.file_name.back() == '/'));
+ if (is_dir)
+ header.file_name.resize(header.file_name.length() - 1);
- // check to see if it matches query
- bool const crcmatch(search_crc == m_header.crc);
- auto const partialoffset(m_header.file_name.length() - search_filename.length());
- bool const partialpossible((m_header.file_name.length() > search_filename.length()) && (m_header.file_name[partialoffset - 1] == '/'));
- const bool namematch(
- !core_stricmp(search_filename.c_str(), m_header.file_name.c_str()) ||
- (partialpath && partialpossible && !core_stricmp(search_filename.c_str(), m_header.file_name.c_str() + partialoffset)));
+ // advance the position
+ m_header = std::move(header);
+ m_curr_is_dir = is_dir;
+ m_cd_pos += reader.total_length();
+ }
+ catch (...)
+ {
+ break;
+ }
- bool const found = ((!matchcrc && !matchname) || !is_dir) && (!matchcrc || crcmatch) && (!matchname || namematch);
- if (found)
+ // quick return if not required to match on name
+ if (!matchname)
{
- m_curr_is_dir = is_dir;
- return 0;
+ if (!matchcrc || ((search_crc == m_header.crc) && !m_curr_is_dir))
+ return 0;
+ }
+ else if (!m_curr_is_dir)
+ {
+ // check to see if it matches query
+ auto const partialoffset = m_header.file_name.length() - search_filename.length();
+ const bool namematch =
+ (search_filename.length() == m_header.file_name.length()) &&
+ (search_filename.empty() || !core_strnicmp(&search_filename[0], &m_header.file_name[0], search_filename.length()));
+ bool const partialmatch =
+ partialpath &&
+ ((m_header.file_name.length() > search_filename.length()) && (m_header.file_name[partialoffset - 1] == '/')) &&
+ (search_filename.empty() || !core_strnicmp(&search_filename[0], &m_header.file_name[partialoffset], search_filename.length()));
+ if ((!matchcrc || (search_crc == m_header.crc)) && (namematch || partialmatch))
+ return 0;
}
}
return -1;
@@ -815,11 +908,8 @@ int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_fi
from a ZIP into the target buffer
-------------------------------------------------*/
-archive_file::error zip_file_impl::decompress(void *buffer, std::uint32_t length)
+std::error_condition zip_file_impl::decompress(void *buffer, std::size_t length) noexcept
{
- archive_file::error ziperr;
- std::uint64_t offset;
-
// if we don't have enough buffer, error
if (length < m_header.uncompressed_length)
{
@@ -835,33 +925,29 @@ archive_file::error zip_file_impl::decompress(void *buffer, std::uint32_t length
}
// get the compressed data offset
- ziperr = get_compressed_data_offset(offset);
- if (ziperr != archive_file::error::NONE)
+ std::uint64_t offset;
+ auto const ziperr = get_compressed_data_offset(offset);
+ if (ziperr)
return ziperr;
// handle compression types
switch (m_header.compression)
{
case 0:
- ziperr = decompress_data_type_0(offset, buffer, length);
- break;
+ return decompress_data_type_0(offset, buffer, length);
case 8:
- ziperr = decompress_data_type_8(offset, buffer, length);
- break;
+ return decompress_data_type_8(offset, buffer, length);
case 14:
- ziperr = decompress_data_type_14(offset, buffer, length);
- break;
+ return decompress_data_type_14(offset, buffer, length);
default:
osd_printf_error(
"unzip: %s in %s uses unsupported compression method %u\n",
- m_header.file_name.c_str(), m_filename.c_str(), m_header.compression);
- ziperr = archive_file::error::UNSUPPORTED;
- break;
+ m_header.file_name, m_filename, m_header.compression);
+ return archive_file::error::UNSUPPORTED;
}
- return ziperr;
}
@@ -874,16 +960,16 @@ archive_file::error zip_file_impl::decompress(void *buffer, std::uint32_t length
read_ecd - read the ECD data
-------------------------------------------------*/
-archive_file::error zip_file_impl::read_ecd()
+std::error_condition zip_file_impl::read_ecd() noexcept
{
// make sure the file handle is open
auto const ziperr = reopen();
- if (ziperr != archive_file::error::NONE)
+ if (ziperr)
return ziperr;
// we may need multiple tries
- osd_file::error error;
- std::uint32_t read_length;
+ std::error_condition filerr;
+ std::size_t read_length;
std::uint32_t buflen = 1024;
while (buflen < 65536)
{
@@ -893,19 +979,26 @@ archive_file::error zip_file_impl::read_ecd()
// allocate buffer
std::unique_ptr<std::uint8_t []> buffer;
- try { buffer.reset(new std::uint8_t[buflen + 1]); }
- catch (...)
+ buffer.reset(new (std::nothrow) std::uint8_t[buflen + 1]);
+ if (!buffer)
{
osd_printf_error("unzip: %s failed to allocate memory for ECD search\n", m_filename);
- return archive_file::error::OUT_OF_MEMORY;
+ return std::errc::not_enough_memory;
}
// read in one buffers' worth of data
- error = m_file->read(&buffer[0], m_length - buflen, buflen, read_length);
- if ((error != osd_file::error::NONE) || (read_length != buflen))
+ filerr = m_file->read_at(m_length - buflen, &buffer[0], buflen, read_length);
+ if (filerr)
+ {
+ osd_printf_error(
+ "unzip: error reading %s to search for ECD (%s:%d %s)\n",
+ m_filename, filerr.category().name(), filerr.value(), filerr.message());
+ return filerr;
+ }
+ if (read_length != buflen)
{
- osd_printf_error("unzip: %s error reading file to search for ECD (%d)\n", m_filename, int(error));
- return archive_file::error::FILE_ERROR;
+ osd_printf_error("unzip: unexpectedly reached end-of-file while reading %s to search for ECD\n", m_filename);
+ return archive_file::error::FILE_TRUNCATED;
}
// find the ECD signature
@@ -935,19 +1028,26 @@ archive_file::error zip_file_impl::read_ecd()
if ((m_length - buflen + offset) < ecd64_locator_reader::minimum_length())
{
osd_printf_verbose("unzip: %s too small to contain ZIP64 ECD locator\n", m_filename);
- return archive_file::error::NONE;
+ return std::error_condition();
}
// try to read the ZIP64 ECD locator
- error = m_file->read(
- &buffer[0],
+ filerr = m_file->read_at(
m_length - buflen + offset - ecd64_locator_reader::minimum_length(),
+ &buffer[0],
ecd64_locator_reader::minimum_length(),
read_length);
- if ((error != osd_file::error::NONE) || (read_length != ecd64_locator_reader::minimum_length()))
+ if (filerr)
+ {
+ osd_printf_error(
+ "unzip: error reading %s to search for ZIP64 ECD locator (%s:%d %s)\n",
+ m_filename, filerr.category().name(), filerr.value(), filerr.message());
+ return filerr;
+ }
+ if (read_length != ecd64_locator_reader::minimum_length())
{
- osd_printf_error("unzip: error reading %s to search for ZIP64 ECD locator (%d)\n", m_filename, int(error));
- return archive_file::error::FILE_ERROR;
+ osd_printf_error("unzip: unexpectedly reached end-of-file while reading %s to search for ZIP64 ECD locator\n", m_filename);
+ return archive_file::error::FILE_TRUNCATED;
}
// if the signature isn't correct, it's not a ZIP64 archive
@@ -955,7 +1055,7 @@ archive_file::error zip_file_impl::read_ecd()
if (!ecd64_loc_rd.signature_correct())
{
osd_printf_verbose("unzip: %s has no ZIP64 ECD locator\n", m_filename);
- return archive_file::error::NONE;
+ return std::error_condition();
}
// check that the ZIP64 ECD is in this segment (assuming this segment is the last segment)
@@ -966,11 +1066,13 @@ archive_file::error zip_file_impl::read_ecd()
}
// try to read the ZIP64 ECD
- error = m_file->read(&buffer[0], ecd64_loc_rd.ecd64_offset(), ecd64_reader::minimum_length(), read_length);
- if (error != osd_file::error::NONE)
+ filerr = m_file->read_at(ecd64_loc_rd.ecd64_offset(), &buffer[0], ecd64_reader::minimum_length(), read_length);
+ if (filerr)
{
- osd_printf_error("unzip: error reading %s ZIP64 ECD (%d)\n", m_filename, int(error));
- return archive_file::error::FILE_ERROR;
+ osd_printf_error(
+ "unzip: error reading %s ZIP64 ECD (%s:%d %s)\n",
+ m_filename, filerr.category().name(), filerr.value(), filerr.message());
+ return filerr;
}
if (read_length != ecd64_reader::minimum_length())
{
@@ -983,8 +1085,8 @@ archive_file::error zip_file_impl::read_ecd()
if (!ecd64_rd.signature_correct())
{
osd_printf_error(
- "unzip: %s ZIP64 ECD has incorrect signature 0x%08lx\n",
- m_filename.c_str(), long(ecd64_rd.signature()));
+ "unzip: %s ZIP64 ECD has incorrect signature 0x%08x\n",
+ m_filename, ecd64_rd.signature());
return archive_file::error::BAD_SIGNATURE;
}
if (ecd64_rd.total_length() < ecd64_reader::minimum_length())
@@ -996,7 +1098,7 @@ archive_file::error zip_file_impl::read_ecd()
{
osd_printf_error(
"unzip: %s ZIP64 ECD requires unsupported version %u.%u\n",
- m_filename.c_str(), unsigned(ecd64_rd.version_needed() / 10), unsigned(ecd64_rd.version_needed() % 10));
+ m_filename, ecd64_rd.version_needed() / 10, ecd64_rd.version_needed() % 10);
return archive_file::error::UNSUPPORTED;
}
osd_printf_verbose("unzip: found %s ZIP64 ECD\n", m_filename);
@@ -1009,7 +1111,7 @@ archive_file::error zip_file_impl::read_ecd()
m_ecd.cd_size = ecd64_rd.dir_size();
m_ecd.cd_start_disk_offset = ecd64_rd.dir_offset();
- return archive_file::error::NONE;
+ return std::error_condition();
}
// didn't find it; free this buffer and expand our search
@@ -1024,7 +1126,7 @@ archive_file::error zip_file_impl::read_ecd()
}
}
osd_printf_error("unzip: %s couldn't find ECD in last 64KiB\n", m_filename);
- return archive_file::error::OUT_OF_MEMORY;
+ return archive_file::error::UNSUPPORTED; // TODO: revisit this error code
}
@@ -1033,7 +1135,7 @@ archive_file::error zip_file_impl::read_ecd()
offset of the compressed data
-------------------------------------------------*/
-archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &offset)
+std::error_condition zip_file_impl::get_compressed_data_offset(std::uint64_t &offset) noexcept
{
// don't support a number of features
general_flag_reader const flags(m_header.bit_flag);
@@ -1046,7 +1148,7 @@ archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &off
{
osd_printf_error(
"unzip: %s in %s requires unsupported version %u.%u\n",
- m_header.file_name.c_str(), m_filename.c_str(), unsigned(m_header.version_needed / 10), unsigned(m_header.version_needed % 10));
+ m_header.file_name, m_filename, m_header.version_needed / 10, m_header.version_needed % 10);
return archive_file::error::UNSUPPORTED;
}
if (flags.encrypted() || flags.strong_encryption())
@@ -1062,24 +1164,24 @@ archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &off
// make sure the file handle is open
auto const ziperr = reopen();
- if (ziperr != archive_file::error::NONE)
+ if (ziperr)
return ziperr;
// now go read the fixed-sized part of the local file header
- std::uint32_t read_length;
- auto const error = m_file->read(&m_buffer[0], m_header.local_header_offset, local_file_header_reader::minimum_length(), read_length);
- if (error != osd_file::error::NONE)
+ std::size_t read_length;
+ std::error_condition const filerr = m_file->read_at(m_header.local_header_offset, &m_buffer[0], local_file_header_reader::minimum_length(), read_length);
+ if (filerr)
{
osd_printf_error(
- "unzip: error reading local file header for %s in %s (%d)\n",
- m_header.file_name.c_str(), m_filename.c_str(), int(error));
- return archive_file::error::FILE_ERROR;
+ "unzip: error reading local file header for %s in %s (%s:%d %s)\n",
+ m_header.file_name, m_filename, filerr.category().name(), filerr.value(), filerr.message());
+ return filerr;
}
if (read_length != local_file_header_reader::minimum_length())
{
osd_printf_error(
"unzip: unexpectedly reached end-of-file while reading local file header for %s in %s\n",
- m_header.file_name.c_str(), m_filename.c_str());
+ m_header.file_name, m_filename);
return archive_file::error::FILE_TRUNCATED;
}
@@ -1088,13 +1190,13 @@ archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &off
if (!reader.signature_correct())
{
osd_printf_error(
- "unzip: local file header for %s in %s has incorrect signature %04lx\n",
- m_header.file_name.c_str(), m_filename.c_str(), long(reader.signature()));
+ "unzip: local file header for %s in %s has incorrect signature %04x\n",
+ m_header.file_name, m_filename, reader.signature());
return archive_file::error::BAD_SIGNATURE;
}
offset = m_header.local_header_offset + reader.total_length();
- return archive_file::error::NONE;
+ return std::error_condition();
}
@@ -1108,24 +1210,28 @@ archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &off
type 0 data (which is uncompressed)
-------------------------------------------------*/
-archive_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length)
+std::error_condition zip_file_impl::decompress_data_type_0(std::uint64_t offset, void *buffer, std::size_t length) noexcept
{
// the data is uncompressed; just read it
- std::uint32_t read_length(0);
- auto const filerr = m_file->read(buffer, offset, m_header.compressed_length, read_length);
- if (filerr != osd_file::error::NONE)
+ std::size_t read_length(0);
+ std::error_condition const filerr = m_file->read_at(offset, buffer, m_header.compressed_length, read_length);
+ if (filerr)
{
- osd_printf_error("unzip: error reading %s from %s (%d)\n", m_header.file_name, m_filename, int(filerr));
- return archive_file::error::FILE_ERROR;
+ osd_printf_error(
+ "unzip: error reading %s from %s (%s:%d %s)\n",
+ m_header.file_name, m_filename, filerr.category().name(), filerr.value(), filerr.message());
+ return filerr;
}
else if (read_length != m_header.compressed_length)
{
- osd_printf_error("unzip: unexpectedly reached end-of-file while reading %s from %s\n", m_header.file_name, m_filename);
+ osd_printf_error(
+ "unzip: unexpectedly reached end-of-file while reading %s from %s\n",
+ m_header.file_name, m_filename);
return archive_file::error::FILE_TRUNCATED;
}
else
{
- return archive_file::error::NONE;
+ return std::error_condition();
}
}
@@ -1135,8 +1241,23 @@ archive_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset,
type 8 data (which is deflated)
-------------------------------------------------*/
-archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length)
+std::error_condition zip_file_impl::decompress_data_type_8(std::uint64_t offset, void *buffer, std::size_t length) noexcept
{
+ auto const convert_zerr =
+ [] (int e) -> std::error_condition
+ {
+ switch (e)
+ {
+ case Z_OK:
+ return std::error_condition();
+ case Z_ERRNO:
+ return std::error_condition(errno, std::generic_category());
+ case Z_MEM_ERROR:
+ return std::errc::not_enough_memory;
+ default:
+ return archive_file::error::DECOMPRESS_ERROR;
+ }
+ };
std::uint64_t input_remaining = m_header.compressed_length;
int zerr;
@@ -1153,38 +1274,39 @@ archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset,
zerr = inflateInit2(&stream, -MAX_WBITS);
if (zerr != Z_OK)
{
+ auto result = convert_zerr(zerr);
osd_printf_error(
"unzip: error allocating zlib stream to inflate %s from %s (%d)\n",
- m_header.file_name.c_str(), m_filename.c_str(), zerr);
- return archive_file::error::DECOMPRESS_ERROR;
+ m_header.file_name, m_filename, zerr);
+ return result;
}
// loop until we're done
while (true)
{
// read in the next chunk of data
- std::uint32_t read_length(0);
- auto const filerr = m_file->read(
- &m_buffer[0],
+ std::size_t read_length(0);
+ auto const filerr = m_file->read_at(
offset,
- std::uint32_t((std::min<std::uint64_t>)(input_remaining, m_buffer.size())),
+ &m_buffer[0],
+ std::size_t((std::min<std::uint64_t>)(input_remaining, m_buffer.size())),
read_length);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
osd_printf_error(
- "unzip: error reading compressed data for %s in %s (%d)\n",
- m_header.file_name.c_str(), m_filename.c_str(), int(filerr));
+ "unzip: error reading compressed data for %s in %s (%s:%d %s)\n",
+ m_header.file_name, m_filename, filerr.category().name(), filerr.value(), filerr.message());
inflateEnd(&stream);
- return archive_file::error::FILE_ERROR;
+ return filerr;
}
offset += read_length;
// if we read nothing, but still have data left, the file is truncated
- if ((read_length == 0) && (input_remaining > 0))
+ if (!read_length && input_remaining)
{
osd_printf_error(
"unzip: unexpectedly reached end-of-file while reading compressed data for %s in %s\n",
- m_header.file_name.c_str(), m_filename.c_str());
+ m_header.file_name, m_filename);
inflateEnd(&stream);
return archive_file::error::FILE_TRUNCATED;
}
@@ -1206,9 +1328,12 @@ archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset,
}
else if (zerr != Z_OK)
{
- osd_printf_error("unzip: error inflating %s from %s (%d)\n", m_header.file_name, m_filename, zerr);
+ auto result = convert_zerr(zerr);
+ osd_printf_error(
+ "unzip: error inflating %s from %s (%d)\n",
+ m_header.file_name, m_filename, zerr);
inflateEnd(&stream);
- return archive_file::error::DECOMPRESS_ERROR;
+ return result;
}
}
@@ -1216,20 +1341,23 @@ archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset,
zerr = inflateEnd(&stream);
if (zerr != Z_OK)
{
- osd_printf_error("unzip: error finishing inflation of %s from %s (%d)\n", m_header.file_name, m_filename, zerr);
- return archive_file::error::DECOMPRESS_ERROR;
+ auto result = convert_zerr(zerr);
+ osd_printf_error(
+ "unzip: error finishing inflation of %s from %s (%d)\n",
+ m_header.file_name, m_filename, zerr);
+ return result;
}
// if anything looks funny, report an error
- if ((stream.avail_out > 0) || (input_remaining > 0))
+ if (stream.avail_out || input_remaining)
{
osd_printf_error(
"unzip: inflation of %s from %s doesn't appear to have completed correctly\n",
- m_header.file_name.c_str(), m_filename.c_str());
+ m_header.file_name, m_filename);
return archive_file::error::DECOMPRESS_ERROR;
}
- return archive_file::error::NONE;
+ return std::error_condition();
}
@@ -1238,7 +1366,7 @@ archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset,
type 14 data (LZMA)
-------------------------------------------------*/
-archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, void *buffer, std::uint32_t length)
+std::error_condition zip_file_impl::decompress_data_type_14(std::uint64_t offset, void *buffer, std::size_t length) noexcept
{
// two-byte version
// two-byte properties size (little-endian)
@@ -1253,15 +1381,15 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset,
SizeT output_remaining(length);
std::uint64_t input_remaining(m_header.compressed_length);
- std::uint32_t read_length;
- osd_file::error filerr;
+ std::size_t read_length;
+ std::error_condition filerr;
SRes lzerr;
ELzmaStatus lzstatus(LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK);
// reset the stream
ISzAlloc alloc_imp;
- alloc_imp.Alloc = [](void *p, std::size_t size) -> void * { return (size == 0) ? nullptr : std::malloc(size); };
- alloc_imp.Free = [](void *p, void *address) -> void { std::free(address); };
+ alloc_imp.Alloc = [] (void *p, std::size_t size) -> void * { return size ? std::malloc(size) : nullptr; };
+ alloc_imp.Free = [] (void *p, void *address) -> void { std::free(address); };
CLzmaDec stream;
LzmaDec_Construct(&stream);
@@ -1270,16 +1398,16 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset,
{
osd_printf_error(
"unzip:compressed data for %s in %s is too small to hold LZMA properties header\n",
- m_header.file_name.c_str(), m_filename.c_str());
+ m_header.file_name, m_filename);
return archive_file::error::DECOMPRESS_ERROR;
}
- filerr = m_file->read(&m_buffer[0], offset, 4, read_length);
- if (filerr != osd_file::error::NONE)
+ filerr = m_file->read_at(offset, &m_buffer[0], 4, read_length);
+ if (filerr)
{
osd_printf_error(
- "unzip: error reading LZMA properties header for %s in %s (%d)\n",
- m_header.file_name.c_str(), m_filename.c_str(), int(filerr));
- return archive_file::error::FILE_ERROR;
+ "unzip: error reading LZMA properties header for %s in %s (%s:%d %s)\n",
+ m_header.file_name, m_filename, filerr.category().name(), filerr.value(), filerr.message());
+ return filerr;
}
offset += read_length;
input_remaining -= read_length;
@@ -1287,7 +1415,7 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset,
{
osd_printf_error(
"unzip: unexpectedly reached end-of-file while reading LZMA properties header for %s in %s\n",
- m_header.file_name.c_str(), m_filename.c_str());
+ m_header.file_name, m_filename);
return archive_file::error::FILE_TRUNCATED;
}
std::uint16_t const props_size((std::uint16_t(m_buffer[3]) << 8) | std::uint16_t(m_buffer[2]));
@@ -1295,23 +1423,23 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset,
{
osd_printf_error(
"unzip: %s in %s has excessively large LZMA properties\n",
- m_header.file_name.c_str(), m_filename.c_str());
+ m_header.file_name, m_filename);
return archive_file::error::UNSUPPORTED;
}
else if (props_size > input_remaining)
{
osd_printf_error(
"unzip:compressed data for %s in %s is too small to hold LZMA properties\n",
- m_header.file_name.c_str(), m_filename.c_str());
+ m_header.file_name, m_filename);
return archive_file::error::DECOMPRESS_ERROR;
}
- filerr = m_file->read(&m_buffer[0], offset, props_size, read_length);
- if (filerr != osd_file::error::NONE)
+ filerr = m_file->read_at(offset, &m_buffer[0], props_size, read_length);
+ if (filerr)
{
osd_printf_error(
- "unzip: error reading LZMA properties for %s in %s (%d)\n",
- m_header.file_name.c_str(), m_filename.c_str(), int(filerr));
- return archive_file::error::FILE_ERROR;
+ "unzip: error reading LZMA properties for %s in %s (%s:%d %s)\n",
+ m_header.file_name, m_filename, filerr.category().name(), filerr.value(), filerr.message());
+ return filerr;
}
offset += read_length;
input_remaining -= read_length;
@@ -1319,7 +1447,7 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset,
{
osd_printf_error(
"unzip: unexpectedly reached end-of-file while reading LZMA properties for %s in %s\n",
- m_header.file_name.c_str(), m_filename.c_str());
+ m_header.file_name, m_filename);
return archive_file::error::FILE_TRUNCATED;
}
@@ -1329,14 +1457,21 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset,
{
osd_printf_error(
"unzip: memory error allocating LZMA decoder to decompress %s from %s\n",
- m_header.file_name.c_str(), m_filename.c_str());
- return archive_file::error::OUT_OF_MEMORY;
+ m_header.file_name, m_filename);
+ return std::errc::not_enough_memory;
+ }
+ else if (SZ_ERROR_UNSUPPORTED)
+ {
+ osd_printf_error(
+ "unzip: LZMA decoder does not support properties for %s in %s\n",
+ m_header.file_name, m_filename);
+ return archive_file::error::UNSUPPORTED;
}
else if (SZ_OK != lzerr)
{
osd_printf_error(
"unzip: error allocating LZMA decoder to decompress %s from %s (%d)\n",
- m_header.file_name.c_str(), m_filename.c_str(), int(lzerr));
+ m_header.file_name, m_filename, int(lzerr));
return archive_file::error::DECOMPRESS_ERROR;
}
LzmaDec_Init(&stream);
@@ -1345,28 +1480,28 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset,
while (0 < input_remaining)
{
// read in the next chunk of data
- filerr = m_file->read(
- &m_buffer[0],
+ filerr = m_file->read_at(
offset,
- std::uint32_t((std::min<std::uint64_t>)(input_remaining, m_buffer.size())),
+ &m_buffer[0],
+ std::size_t((std::min<std::uint64_t>)(input_remaining, m_buffer.size())),
read_length);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
{
osd_printf_error(
- "unzip: error reading compressed data for %s in %s (%d)\n",
- m_header.file_name.c_str(), m_filename.c_str(), int(filerr));
+ "unzip: error reading compressed data for %s in %s (%s)\n",
+ m_header.file_name, m_filename);
LzmaDec_Free(&stream, &alloc_imp);
- return archive_file::error::FILE_ERROR;
+ return filerr;
}
offset += read_length;
input_remaining -= read_length;
// if we read nothing, but still have data left, the file is truncated
- if ((0 == read_length) && (0 < input_remaining))
+ if (!read_length && input_remaining)
{
osd_printf_error(
"unzip: unexpectedly reached end-of-file while reading compressed data for %s in %s\n",
- m_header.file_name.c_str(), m_filename.c_str());
+ m_header.file_name, m_filename);
LzmaDec_Free(&stream, &alloc_imp);
return archive_file::error::FILE_TRUNCATED;
}
@@ -1381,7 +1516,7 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset,
&output_remaining,
reinterpret_cast<Byte const *>(&m_buffer[0]),
&len,
- ((0 == input_remaining) && eos_mark) ? LZMA_FINISH_END : LZMA_FINISH_ANY,
+ (!input_remaining && eos_mark) ? LZMA_FINISH_END : LZMA_FINISH_ANY,
&lzstatus);
if (SZ_OK != lzerr)
{
@@ -1397,25 +1532,25 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset,
// if anything looks funny, report an error
if (LZMA_STATUS_FINISHED_WITH_MARK == lzstatus)
{
- return archive_file::error::NONE;
+ return std::error_condition();
}
else if (eos_mark)
{
osd_printf_error(
"unzip: LZMA end mark not found for %s in %s (%d)\n",
- m_header.file_name.c_str(), m_filename.c_str(), int(lzstatus));
+ m_header.file_name, m_filename, int(lzstatus));
return archive_file::error::DECOMPRESS_ERROR;
}
else if (LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK != lzstatus)
{
osd_printf_error(
"unzip: LZMA decompression of %s from %s doesn't appear to have completed correctly (%d)\n",
- m_header.file_name.c_str(), m_filename.c_str(), int(lzstatus));
+ m_header.file_name, m_filename, int(lzstatus));
return archive_file::error::DECOMPRESS_ERROR;
}
else
{
- return archive_file::error::NONE;
+ return std::error_condition();
}
}
@@ -1427,7 +1562,7 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset,
un7z.cpp TRAMPOLINES
***************************************************************************/
-void m7z_file_cache_clear();
+void m7z_file_cache_clear() noexcept;
@@ -1439,7 +1574,7 @@ void m7z_file_cache_clear();
zip_file_open - opens a ZIP file for reading
-------------------------------------------------*/
-archive_file::error archive_file::open_zip(const std::string &filename, ptr &result)
+std::error_condition archive_file::open_zip(std::string_view filename, ptr &result) noexcept
{
// ensure we start with a nullptr result
result.reset();
@@ -1450,21 +1585,49 @@ archive_file::error archive_file::open_zip(const std::string &filename, ptr &res
if (!newimpl)
{
// allocate memory for the zip_file structure
- try { newimpl = std::make_unique<zip_file_impl>(filename); }
- catch (...) { return error::OUT_OF_MEMORY; }
- auto const ziperr = newimpl->initialize();
- if (ziperr != error::NONE) return ziperr;
+ try { newimpl = std::make_unique<zip_file_impl>(std::string(filename)); }
+ catch (...) { return std::errc::not_enough_memory; }
+ auto const err = newimpl->initialize();
+ if (err)
+ return err;
+ }
+
+ // allocate the archive API wrapper
+ result.reset(new (std::nothrow) zip_file_wrapper(std::move(newimpl)));
+ if (result)
+ {
+ return std::error_condition();
+ }
+ else
+ {
+ zip_file_impl::close(std::move(newimpl));
+ return std::errc::not_enough_memory;
}
+}
- try
+std::error_condition archive_file::open_zip(random_read::ptr &&file, ptr &result) noexcept
+{
+ // ensure we start with a nullptr result
+ result.reset();
+
+ // allocate memory for the zip_file structure
+ zip_file_impl::ptr newimpl(new (std::nothrow) zip_file_impl(std::move(file)));
+ if (!newimpl)
+ return std::errc::not_enough_memory;
+ auto const err = newimpl->initialize();
+ if (err)
+ return err;
+
+ // allocate the archive API wrapper
+ result.reset(new (std::nothrow) zip_file_wrapper(std::move(newimpl)));
+ if (result)
{
- result = std::make_unique<zip_file_wrapper>(std::move(newimpl));
- return error::NONE;
+ return std::error_condition();
}
- catch (...)
+ else
{
zip_file_impl::close(std::move(newimpl));
- return error::OUT_OF_MEMORY;
+ return std::errc::not_enough_memory;
}
}
@@ -1474,7 +1637,7 @@ archive_file::error archive_file::open_zip(const std::string &filename, ptr &res
cache and free all memory
-------------------------------------------------*/
-void archive_file::cache_clear()
+void archive_file::cache_clear() noexcept
{
zip_file_impl::cache_clear();
m7z_file_cache_clear();
@@ -1485,4 +1648,15 @@ archive_file::~archive_file()
{
}
+
+/*-------------------------------------------------
+ archive_category - gets the archive error
+ category instance
+-------------------------------------------------*/
+
+std::error_category const &archive_category() noexcept
+{
+ return f_archive_category_instance;
+}
+
} // namespace util
diff --git a/src/lib/util/unzip.h b/src/lib/util/unzip.h
index b1ddb7a27d1..2108eadee28 100644
--- a/src/lib/util/unzip.h
+++ b/src/lib/util/unzip.h
@@ -7,19 +7,24 @@
archive file management.
***************************************************************************/
+#ifndef MAME_LIB_UTIL_UNZIP_H
+#define MAME_LIB_UTIL_UNZIP_H
#pragma once
-#ifndef MAME_LIB_UTIL_UNZIP_H
-#define MAME_LIB_UTIL_UNZIP_H
+#include "utilfwd.h"
#include <chrono>
#include <cstdint>
#include <memory>
#include <string>
+#include <string_view>
+#include <system_error>
+#include <type_traits>
namespace util {
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
@@ -30,12 +35,9 @@ class archive_file
public:
// Error types
- enum class error
+ enum class error : int
{
- NONE = 0,
- OUT_OF_MEMORY,
- FILE_ERROR,
- BAD_SIGNATURE,
+ BAD_SIGNATURE = 1,
DECOMPRESS_ERROR,
FILE_TRUNCATED,
FILE_CORRUPT,
@@ -49,40 +51,54 @@ public:
/* ----- archive file access ----- */
// open a ZIP file and parse its central directory
- static error open_zip(const std::string &filename, ptr &zip);
+ static std::error_condition open_zip(std::string_view filename, ptr &result) noexcept;
+ static std::error_condition open_zip(std::unique_ptr<random_read> &&file, ptr &result) noexcept;
// open a 7Z file and parse its central directory
- static error open_7z(const std::string &filename, ptr &result);
+ static std::error_condition open_7z(std::string_view filename, ptr &result) noexcept;
+ static std::error_condition open_7z(std::unique_ptr<random_read> &&file, ptr &result) noexcept;
// close an archive file (may actually be left open due to caching)
virtual ~archive_file();
// clear out all open files from the cache
- static void cache_clear();
+ static void cache_clear() noexcept;
/* ----- contained file access ----- */
// iterating over files - returns negative on reaching end
- virtual int first_file() = 0;
- virtual int next_file() = 0;
+ virtual int first_file() noexcept = 0;
+ virtual int next_file() noexcept = 0;
// find a file index by crc, filename or both - returns non-negative on match
- virtual int search(std::uint32_t crc) = 0;
- virtual int search(const std::string &filename, bool partialpath) = 0;
- virtual int search(std::uint32_t crc, const std::string &filename, bool partialpath) = 0;
+ virtual int search(std::uint32_t crc) noexcept = 0;
+ virtual int search(std::string_view filename, bool partialpath) noexcept = 0;
+ virtual int search(std::uint32_t crc, std::string_view filename, bool partialpath) noexcept = 0;
// information on most recently found file
- virtual bool current_is_directory() const = 0;
- virtual const std::string &current_name() const = 0;
- virtual std::uint64_t current_uncompressed_length() const = 0;
- virtual std::chrono::system_clock::time_point current_last_modified() const = 0;
- virtual std::uint32_t current_crc() const = 0;
+ virtual bool current_is_directory() const noexcept = 0;
+ virtual const std::string &current_name() const noexcept = 0;
+ virtual std::uint64_t current_uncompressed_length() const noexcept = 0;
+ virtual std::chrono::system_clock::time_point current_last_modified() const noexcept = 0;
+ virtual std::uint32_t current_crc() const noexcept = 0;
// decompress the most recently found file in the ZIP
- virtual error decompress(void *buffer, std::uint32_t length) = 0;
+ virtual std::error_condition decompress(void *buffer, std::size_t length) noexcept = 0;
};
+
+// error category for archive errors
+std::error_category const &archive_category() noexcept;
+inline std::error_condition make_error_condition(archive_file::error err) noexcept { return std::error_condition(int(err), archive_category()); }
+
} // namespace util
+
+namespace std {
+
+template <> struct is_error_condition_enum<util::archive_file::error> : public std::true_type { };
+
+} // namespace std
+
#endif // MAME_LIB_UTIL_UNZIP_H
diff --git a/src/lib/util/utilfwd.h b/src/lib/util/utilfwd.h
new file mode 100644
index 00000000000..fefe0631c68
--- /dev/null
+++ b/src/lib/util/utilfwd.h
@@ -0,0 +1,45 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ utilfwd.h
+
+ Forward declarations of types
+
+**********************************************************************/
+#ifndef MAME_LIB_UTIL_UTILFWD_H
+#define MAME_LIB_UTIL_UTILFWD_H
+
+// chd.h
+class chd_file;
+
+
+namespace util {
+
+// corefile.h
+class core_file;
+
+// ioprocs.h
+class read_stream;
+class write_stream;
+class read_write_stream;
+class random_access;
+class random_read;
+class random_write;
+class random_read_write;
+
+// unzip.h
+class archive_file;
+
+} // namespace util
+
+
+namespace util::xml {
+
+// xmlfile.h
+class data_node;
+class file;
+
+} // namespace util::xml
+
+#endif // MAME_LIB_UTIL_UTILFWD_H
diff --git a/src/lib/util/zippath.cpp b/src/lib/util/zippath.cpp
index 023484010b8..f317319c8c3 100644
--- a/src/lib/util/zippath.cpp
+++ b/src/lib/util/zippath.cpp
@@ -9,13 +9,13 @@
***************************************************************************/
#include "zippath.h"
-#include "unzip.h"
-#include "corestr.h"
-#include <cstdlib>
+#include "corestr.h"
+#include "unzip.h"
#include <cassert>
#include <cctype>
+#include <cstdlib>
#include <forward_list>
#include <new>
@@ -192,7 +192,7 @@ int zippath_find_sub_path(archive_file &zipfile, std::string_view subpath, osd::
// true path and ZIP entry components
// -------------------------------------------------
-osd_file::error zippath_resolve(std::string_view path, osd::directory::entry::entry_type &entry_type, archive_file::ptr &zipfile, std::string &newpath)
+std::error_condition zippath_resolve(std::string_view path, osd::directory::entry::entry_type &entry_type, archive_file::ptr &zipfile, std::string &newpath)
{
newpath.clear();
@@ -238,13 +238,13 @@ osd_file::error zippath_resolve(std::string_view path, osd::directory::entry::en
if (current_entry_type == osd::directory::entry::entry_type::NONE)
{
entry_type = osd::directory::entry::entry_type::NONE;
- return osd_file::error::NOT_FOUND;
+ return std::errc::no_such_file_or_directory;
}
// is this file a ZIP file?
if ((current_entry_type == osd::directory::entry::entry_type::FILE) &&
- ((is_zip_file(apath_trimmed) && (archive_file::open_zip(apath_trimmed, zipfile) == archive_file::error::NONE)) ||
- (is_7z_file(apath_trimmed) && (archive_file::open_7z(apath_trimmed, zipfile) == archive_file::error::NONE))))
+ ((is_zip_file(apath_trimmed) && !archive_file::open_zip(apath_trimmed, zipfile)) ||
+ (is_7z_file(apath_trimmed) && !archive_file::open_7z(apath_trimmed, zipfile))))
{
auto i = path.length() - apath.length();
while ((i > 0) && is_zip_path_separator(path[apath.length() + i - 1]))
@@ -254,53 +254,20 @@ osd_file::error zippath_resolve(std::string_view path, osd::directory::entry::en
// this was a true ZIP path - attempt to identify the type of path
zippath_find_sub_path(*zipfile, newpath, current_entry_type);
if (current_entry_type == osd::directory::entry::entry_type::NONE)
- return osd_file::error::NOT_FOUND;
+ return std::errc::no_such_file_or_directory;
}
else
{
// this was a normal path
if (went_up)
- return osd_file::error::NOT_FOUND;
+ return std::errc::no_such_file_or_directory;
newpath = path;
}
// success!
entry_type = current_entry_type;
- return osd_file::error::NONE;
-}
-
-
-// -------------------------------------------------
-// file_error_from_zip_error - translates a
-// osd_file::error to a zip_error
-// -------------------------------------------------
-
-osd_file::error file_error_from_zip_error(archive_file::error ziperr)
-{
- osd_file::error filerr;
- switch(ziperr)
- {
- case archive_file::error::NONE:
- filerr = osd_file::error::NONE;
- break;
- case archive_file::error::OUT_OF_MEMORY:
- filerr = osd_file::error::OUT_OF_MEMORY;
- break;
- case archive_file::error::BAD_SIGNATURE:
- case archive_file::error::DECOMPRESS_ERROR:
- case archive_file::error::FILE_TRUNCATED:
- case archive_file::error::FILE_CORRUPT:
- case archive_file::error::UNSUPPORTED:
- case archive_file::error::FILE_ERROR:
- filerr = osd_file::error::INVALID_DATA;
- break;
- case archive_file::error::BUFFER_TOO_SMALL:
- default:
- filerr = osd_file::error::FAILURE;
- break;
- }
- return filerr;
+ return std::error_condition();
}
@@ -309,27 +276,24 @@ osd_file::error file_error_from_zip_error(archive_file::error ziperr)
// from a zip file entry
// -------------------------------------------------
-osd_file::error create_core_file_from_zip(archive_file &zip, util::core_file::ptr &file)
+std::error_condition create_core_file_from_zip(archive_file &zip, util::core_file::ptr &file)
{
- osd_file::error filerr;
- archive_file::error ziperr;
+ // TODO: would be more efficient if we could open a memory-based core_file with uninitialised contents and decompress into it
+ std::error_condition filerr;
void *ptr = malloc(zip.current_uncompressed_length());
if (!ptr)
{
- filerr = osd_file::error::OUT_OF_MEMORY;
+ filerr = std::errc::not_enough_memory;
goto done;
}
- ziperr = zip.decompress(ptr, zip.current_uncompressed_length());
- if (ziperr != archive_file::error::NONE)
- {
- filerr = file_error_from_zip_error(ziperr);
+ filerr = zip.decompress(ptr, zip.current_uncompressed_length());
+ if (filerr)
goto done;
- }
filerr = util::core_file::open_ram_copy(ptr, zip.current_uncompressed_length(), OPEN_FLAG_READ, file);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
goto done;
done:
@@ -545,7 +509,7 @@ private:
// zippath_directory::open - opens a directory
// -------------------------------------------------
-osd_file::error zippath_directory::open(std::string_view path, ptr &directory)
+std::error_condition zippath_directory::open(std::string_view path, ptr &directory)
{
try
{
@@ -553,34 +517,34 @@ osd_file::error zippath_directory::open(std::string_view path, ptr &directory)
osd::directory::entry::entry_type entry_type;
archive_file::ptr zipfile;
std::string zipprefix;
- osd_file::error const err = zippath_resolve(path, entry_type, zipfile, zipprefix);
- if (osd_file::error::NONE != err)
+ std::error_condition const err = zippath_resolve(path, entry_type, zipfile, zipprefix);
+ if (err)
return err;
// we have to be a directory
if (osd::directory::entry::entry_type::DIR != entry_type)
- return osd_file::error::NOT_FOUND;
+ return std::errc::not_a_directory;
// was the result a ZIP?
if (zipfile)
{
directory = std::make_unique<archive_directory_impl>(std::move(zipfile), std::move(zipprefix));
- return osd_file::error::NONE;
+ return std::error_condition();
}
else
{
// a conventional directory
std::unique_ptr<filesystem_directory_impl> result(new filesystem_directory_impl(path));
if (!*result)
- return osd_file::error::FAILURE;
+ return std::errc::io_error; // TODO: any way to give a better error here?
directory = std::move(result);
- return osd_file::error::NONE;
+ return std::error_condition();
}
}
catch (std::bad_alloc const &)
{
- return osd_file::error::OUT_OF_MEMORY;
+ return std::errc::not_enough_memory;
}
}
@@ -681,7 +645,7 @@ std::string zippath_combine(const std::string &path1, const std::string &path2)
// -------------------------------------------------
/**
- * @fn osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, util::core_file::ptr &file, std::string &revised_path)
+ * @fn std::error_condition zippath_fopen(std::string_view filename, uint32_t openflags, util::core_file::ptr &file, std::string &revised_path)
*
* @brief Zippath fopen.
*
@@ -693,38 +657,35 @@ std::string zippath_combine(const std::string &path1, const std::string &path2)
* @return A osd_file::error.
*/
-osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, util::core_file::ptr &file, std::string &revised_path)
+std::error_condition zippath_fopen(std::string_view filename, uint32_t openflags, util::core_file::ptr &file, std::string &revised_path)
{
- osd_file::error filerr = osd_file::error::NOT_FOUND;
- archive_file::error ziperr;
+ std::error_condition filerr = std::errc::no_such_file_or_directory;
archive_file::ptr zip;
- int header;
- osd::directory::entry::entry_type entry_type;
- int len;
- /* first, set up the two types of paths */
+ // first, set up the two types of paths
std::string mainpath(filename);
std::string subpath;
file = nullptr;
- /* loop through */
- while((file == nullptr) && (mainpath.length() > 0)
- && ((openflags == OPEN_FLAG_READ) || subpath.empty()))
+ // loop through
+ while (!file && !mainpath.empty() && ((openflags == OPEN_FLAG_READ) || subpath.empty()))
{
- /* is the mainpath a ZIP path? */
+ // is the mainpath a ZIP path?
if (is_zip_file(mainpath) || is_7z_file(mainpath))
{
- /* this file might be a zip file - lets take a look */
- ziperr = is_zip_file(mainpath) ? archive_file::open_zip(mainpath, zip) : archive_file::open_7z(mainpath, zip);
- if (ziperr == archive_file::error::NONE)
+ // this file might be a zip file - lets take a look
+ std::error_condition const ziperr = is_zip_file(mainpath) ? archive_file::open_zip(mainpath, zip) : archive_file::open_7z(mainpath, zip);
+ if (!ziperr)
{
- /* it is a zip file - error if we're not opening for reading */
+ // it is a zip file - error if we're not opening for reading
if (openflags != OPEN_FLAG_READ)
{
- filerr = osd_file::error::ACCESS_DENIED;
+ filerr = std::errc::permission_denied;
goto done;
}
+ osd::directory::entry::entry_type entry_type;
+ int header;
if (!subpath.empty())
header = zippath_find_sub_path(*zip, subpath, entry_type);
else
@@ -732,20 +693,20 @@ osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, uti
if (header < 0)
{
- filerr = osd_file::error::NOT_FOUND;
+ filerr = std::errc::no_such_file_or_directory;
goto done;
}
- /* attempt to read the file */
+ // attempt to read the file
filerr = create_core_file_from_zip(*zip, file);
- if (filerr != osd_file::error::NONE)
+ if (filerr)
goto done;
- /* update subpath, if appropriate */
+ // update subpath, if appropriate
if (subpath.empty())
subpath.assign(zip->current_name());
- /* we're done */
+ // we're done
goto done;
}
}
@@ -753,15 +714,15 @@ osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, uti
if (subpath.empty())
filerr = util::core_file::open(std::string(filename), openflags, file);
else
- filerr = osd_file::error::NOT_FOUND;
+ filerr = std::errc::no_such_file_or_directory;
- /* if we errored, then go up a directory */
- if (filerr != osd_file::error::NONE)
+ // if we errored, then go up a directory
+ if (filerr)
{
- /* go up a directory */
+ // go up a directory
auto temp = zippath_parent(mainpath);
- /* append to the sub path */
+ // append to the sub path
if (!subpath.empty())
{
std::string temp2;
@@ -774,8 +735,8 @@ osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, uti
mainpath = mainpath.substr(temp.length());
subpath.assign(mainpath);
}
- /* get the new main path, truncating path separators */
- len = temp.length();
+ // get the new main path, truncating path separators
+ auto len = temp.length();
while (len > 0 && is_zip_file_separator(temp[len - 1]))
len--;
temp = temp.substr(0, len);
@@ -784,14 +745,14 @@ osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, uti
}
done:
- /* store the revised path */
+ // store the revised path
revised_path.clear();
- if (filerr == osd_file::error::NONE)
+ if (!filerr)
{
- /* canonicalize mainpath */
+ // canonicalize mainpath
std::string alloc_fullpath;
filerr = osd_get_full_path(alloc_fullpath, mainpath);
- if (filerr == osd_file::error::NONE)
+ if (!filerr)
{
revised_path = alloc_fullpath;
if (!subpath.empty())
diff --git a/src/lib/util/zippath.h b/src/lib/util/zippath.h
index 1eb92aa1c1d..955c75cfc8f 100644
--- a/src/lib/util/zippath.h
+++ b/src/lib/util/zippath.h
@@ -18,6 +18,7 @@
#include <string>
#include <string_view>
+#include <system_error>
namespace util {
@@ -32,7 +33,7 @@ public:
typedef std::unique_ptr<zippath_directory> ptr;
// opens a directory
- static osd_file::error open(std::string_view path, ptr &directory);
+ static std::error_condition open(std::string_view path, ptr &directory);
// closes a directory
virtual ~zippath_directory();
@@ -63,7 +64,7 @@ std::string zippath_combine(const std::string &path1, const std::string &path2);
// ----- file operations -----
// opens a zip path file
-osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, util::core_file::ptr &file, std::string &revised_path);
+std::error_condition zippath_fopen(std::string_view filename, uint32_t openflags, util::core_file::ptr &file, std::string &revised_path);
} // namespace util