Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions src/trx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -849,12 +849,17 @@ std::string get_base(const std::string &delimiter, const std::string &str) {
}

std::string get_ext(const std::string &str) {
// Extract the extension from the final path component only. Scanning the
// whole path for '.' mistakes a dot in a parent directory (e.g. a
// version-numbered build path like ".../foo-5.4/out") for the extension.
const std::size_t sep = str.find_last_of("/\\");
const std::string name = (sep == std::string::npos) ? str : str.substr(sep + 1);

std::string ext;
constexpr char kDelimiter = '.';

const std::size_t pos = str.rfind(kDelimiter);
if (pos != std::string::npos && pos + 1 < str.length()) {
ext = str.substr(pos + 1);
const std::size_t pos = name.rfind(kDelimiter);
if (pos != std::string::npos && pos + 1 < name.length()) {
ext = name.substr(pos + 1);
}
return ext;
}
Expand Down
18 changes: 18 additions & 0 deletions tests/test_trx_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,3 +839,21 @@ TEST(TrxFileIo, export_dpv_to_tsf_errors) {
trx::TrxFile<float> empty;
EXPECT_THROW(empty.export_dpv_to_tsf("signal", output_path.string(), "1"), trx::TrxFormatError);
}

// get_ext must read the extension from the final path component only. A '.' in
// a parent directory (e.g. a version-numbered build path like ".../foo-5.4/")
// must not be treated as the extension. Regression for "Unsupported extension".
TEST(TrxFileIo, get_ext_uses_final_path_component) {
// Dotted parent directory, file has no extension -> empty (the bug case).
EXPECT_EQ(trx::get_ext("/a/build-5.4/out/trx_test"), "");
EXPECT_EQ(trx::get_ext("/a/build-5.4/out/trx_test.trx"), "trx");
// No path separator: whole string is the name.
EXPECT_EQ(trx::get_ext("out.trx"), "trx");
EXPECT_EQ(trx::get_ext("trx_test"), "");
// dtype-style array filenames (name.dims.dtype) resolve to the dtype, even
// under a dotted parent directory.
EXPECT_EQ(trx::get_ext("/a/shard.1/positions.3.float32"), "float32");
EXPECT_EQ(trx::get_ext("offsets.uint64"), "uint64");
// Trailing dot -> empty.
EXPECT_EQ(trx::get_ext("/a/b.c/name."), "");
}