mirror of
https://github.com/opencv/opencv.git
synced 2026-09-19 15:23:23 -05:00
core: safe handling of compressed file level extension (.gz[0-9])
- Replace unsafe pointer arithmetic and direct buffer modification with std::string methods. - Update documentation to clarify that the last digit is used as compression level and truncated from the actual filename. - Add test cases for .gz and .gz0-9
This commit is contained in:
@@ -306,8 +306,12 @@ public:
|
|||||||
before opening the file.
|
before opening the file.
|
||||||
@param filename Name of the file to open or the text string to read the data from.
|
@param filename Name of the file to open or the text string to read the data from.
|
||||||
Extension of the file (.xml, .yml/.yaml or .json) determines its format (XML, YAML or JSON
|
Extension of the file (.xml, .yml/.yaml or .json) determines its format (XML, YAML or JSON
|
||||||
respectively). Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz. If both
|
respectively). Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz.
|
||||||
FileStorage::WRITE and FileStorage::MEMORY flags are specified, source is used just to specify
|
You can also specify a compression level from 0 to 9 by appending it to the extension
|
||||||
|
(e.g. ".gz0" for no compression, ".gz9" for high compression).
|
||||||
|
The last digit will be truncated internally to write/read.
|
||||||
|
(e.g. If "a.xml.gz9" is specified, "a.xml.gz" is used for the actual file name.)
|
||||||
|
If both FileStorage::WRITE and FileStorage::MEMORY flags are specified, source is used just to specify
|
||||||
the output file format (e.g. mydata.xml, .yml etc.). A file name can also contain parameters.
|
the output file format (e.g. mydata.xml, .yml etc.). A file name can also contain parameters.
|
||||||
You can use this format, "*?base64" (e.g. "file.json?base64" (case sensitive)), as an alternative to
|
You can use this format, "*?base64" (e.g. "file.json?base64" (case sensitive)), as an alternative to
|
||||||
FileStorage::BASE64 flag.
|
FileStorage::BASE64 flag.
|
||||||
|
|||||||
@@ -544,18 +544,30 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
|
|||||||
flags = _flags;
|
flags = _flags;
|
||||||
|
|
||||||
if (!mem_mode) {
|
if (!mem_mode) {
|
||||||
char *dot_pos = strrchr((char *) filename.c_str(), '.');
|
size_t dot_idx = filename.find_last_of('.');
|
||||||
char compression = '\0';
|
char compression = '\0';
|
||||||
|
|
||||||
if (dot_pos && dot_pos[1] == 'g' && dot_pos[2] == 'z' &&
|
if (dot_idx != std::string::npos)
|
||||||
(dot_pos[3] == '\0' || (cv_isdigit(dot_pos[3]) && dot_pos[4] == '\0'))) {
|
{
|
||||||
if (append) {
|
std::string ext = filename.substr(dot_idx);
|
||||||
CV_Error(cv::Error::StsNotImplemented, "Appending data to compressed file is not implemented");
|
|
||||||
|
// Instead of `ext.starts_with(".gz")
|
||||||
|
if (ext.size() >= 3 && (ext[1] == 'g') && (ext[2] == 'z') )
|
||||||
|
{
|
||||||
|
if (ext.size() == 3)
|
||||||
|
{
|
||||||
|
// ".gz"
|
||||||
|
isGZ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(ext.size() == 4 && cv_isdigit(ext[3]))
|
||||||
|
{
|
||||||
|
// ".gz[0-9]"
|
||||||
|
isGZ = true;
|
||||||
|
compression = ext[3];
|
||||||
|
filename.pop_back(); // Replace `gz[0-9]' to 'gz'.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
isGZ = true;
|
|
||||||
compression = dot_pos[3];
|
|
||||||
if (compression)
|
|
||||||
dot_pos[3] = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isGZ) {
|
if (!isGZ) {
|
||||||
@@ -567,6 +579,9 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#if USE_ZLIB
|
#if USE_ZLIB
|
||||||
|
if (append) {
|
||||||
|
CV_Error(cv::Error::StsNotImplemented, "Appending data to compressed file is not implemented");
|
||||||
|
}
|
||||||
char mode[] = {write_mode ? 'w' : 'r', 'b', compression ? compression : '3', '\0'};
|
char mode[] = {write_mode ? 'w' : 'r', 'b', compression ? compression : '3', '\0'};
|
||||||
gzfile = gzopen(filename.c_str(), mode);
|
gzfile = gzopen(filename.c_str(), mode);
|
||||||
if (!gzfile)
|
if (!gzfile)
|
||||||
|
|||||||
@@ -2108,9 +2108,19 @@ T fsWriteRead(const T& expectedValue, const char* ext)
|
|||||||
fs_w.release();
|
fs_w.release();
|
||||||
|
|
||||||
FileStorage fs_r(fname, FileStorage::READ);
|
FileStorage fs_r(fname, FileStorage::READ);
|
||||||
|
|
||||||
T value;
|
T value;
|
||||||
fs_r["value"] >> value;
|
fs_r["value"] >> value;
|
||||||
|
fs_r.release();
|
||||||
|
|
||||||
|
// If ext is `.gz[0-9]`, fname on storage will end with `.gz`.
|
||||||
|
// FileStorage::Impl::open() truncates the last digit internally.
|
||||||
|
if (isdigit(fname.back()))
|
||||||
|
{
|
||||||
|
fname.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(fname.c_str());
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2143,7 +2153,7 @@ TEST_P(FileStorage_exact_type, long_int)
|
|||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(Core_InputOutput,
|
INSTANTIATE_TEST_CASE_P(Core_InputOutput,
|
||||||
FileStorage_exact_type, Values(".yml", ".xml", ".json")
|
FileStorage_exact_type, Values(".yml", ".xml", ".json", ".xml.gz", ".xml.gz0", ".xml.gz9")
|
||||||
);
|
);
|
||||||
|
|
||||||
}} // namespace
|
}} // namespace
|
||||||
|
|||||||
Reference in New Issue
Block a user