Let format autodetection fail as an answer, not as an exception

MarCCD::CanRead and SMV::CanRead read the first plausible file of a
directory outside their own try, and the CLI made all three CanRead
calls outside the try that reports a bad input. "rugnux <dir>" whose
alphabetically-first plausible file is unreadable therefore terminated
with no message. CanRead now answers false for anything it cannot read,
and the CLI asks the question where it can report the answer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013nW6FNRP1bBJJ8pfHiByAT
This commit is contained in:
leonarski_fandClaude Opus 5 committed 2026-09-20 19:00:58 +02:00
1 parent 5c6dedea71
commit 404b233aa8
3 files changed
+25 -11

No files matched your search

+9 -4
View File
@@ -251,13 +251,18 @@ std::vector<std::string> CollectSweep(const std::string &path) {
return out;
}
// Asked of every input before anything is read, including inputs that are not marCCD at all, so it
// answers a question and never fails: a file it cannot open or make sense of is simply not one of
// ours. The directory arm has to be inside the try as much as the single-file one - it opens the
// first plausible file in the folder, which can be unreadable, and the throw came out of a call site
// that does not catch it, ending the run with no message at all.
bool CanRead(const std::string &path) {
std::error_code ec;
if (std::filesystem::is_directory(path, ec))
return !CollectSweep(path).empty();
if (!PlausibleExtension(std::filesystem::path(path)))
return false;
try {
if (std::filesystem::is_directory(path, ec))
return !CollectSweep(path).empty();
if (!PlausibleExtension(std::filesystem::path(path)))
return false;
return !InstrumentHeader(path).empty();
} catch (const JFJochException &) {
return false;
+9 -4
View File
@@ -222,13 +222,18 @@ std::vector<std::string> CollectSweep(const std::string &path) {
return out;
}
// Asked of every input before anything is read, including inputs that are not SMV at all, so it
// answers a question and never fails: a file it cannot open or make sense of is simply not one of
// ours. The directory arm has to be inside the try as much as the single-file one - it opens the
// first plausible file in the folder, which can be unreadable, and the throw came out of a call site
// that does not catch it, ending the run with no message at all.
bool CanRead(const std::string &path) {
std::error_code ec;
if (std::filesystem::is_directory(path, ec))
return !CollectSweep(path).empty();
if (!PlausibleExtension(std::filesystem::path(path)))
return false;
try {
if (std::filesystem::is_directory(path, ec))
return !CollectSweep(path).empty();
if (!PlausibleExtension(std::filesystem::path(path)))
return false;
const auto kv = HeaderBlock(path);
return kv.has_value() && kv->count("SIZE1") && kv->count("SIZE2");
} catch (const JFJochException &) {
+7 -3
View File
@@ -1420,10 +1420,14 @@ static int RunRugnux(int argc, char **argv) {
JFJochMarCCDReader marccd_reader;
JFJochSMVReader smv_reader;
JFJochReader *reader_ptr = nullptr;
const bool input_is_cbf = JFJochCBFReader::CanRead(input_file);
const bool input_is_marccd = !input_is_cbf && JFJochMarCCDReader::CanRead(input_file);
const bool input_is_smv = !input_is_cbf && !input_is_marccd && JFJochSMVReader::CanRead(input_file);
// Which format this is. Asked INSIDE the try: these open and read the file - a directory whose
// first plausible member cannot be read throws here - and an input the program cannot read has to
// come out as the message below, not as an unhandled exception with nothing printed at all.
bool input_is_cbf = false, input_is_marccd = false, input_is_smv = false;
try {
input_is_cbf = JFJochCBFReader::CanRead(input_file);
input_is_marccd = !input_is_cbf && JFJochMarCCDReader::CanRead(input_file);
input_is_smv = !input_is_cbf && !input_is_marccd && JFJochSMVReader::CanRead(input_file);
if (input_is_cbf) {
cbf_reader.ReadFiles(input_file);
reader_ptr = &cbf_reader;