-
Notifications
You must be signed in to change notification settings - Fork 278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improvements in the Error class #2141
Conversation
WOW. I'll look at this tomorrow. Thanks. |
Codecov Report
@@ Coverage Diff @@
## main #2141 +/- ##
==========================================
- Coverage 63.32% 63.31% -0.01%
==========================================
Files 97 97
Lines 19137 19152 +15
Branches 9717 9724 +7
==========================================
+ Hits 12118 12127 +9
- Misses 4751 4762 +11
+ Partials 2268 2263 -5
Continue to review full report at Codecov.
|
Seems fine to me. |
A several comments about this.
I don't know what problem is being solved here. I've never noticed anything strange about the error handling on 0.27-maintenance. I'm not saying that it's right, nor that I understand it! I'm asking "What's your problem, buddy?". Is it possible to open an issue about error reporting with a solid case where it's causing trouble? If that can be done, does it also apply to 0.27-maintenance?
I think you should wrap the strings with the N_() macro.
When you have a message like "My age is " + toString(71) + " you know", it would be better expressed as Internal::stringFormat(N_("My age is %d you know"),71). I think Microsoft have an API that supports formatting directives such as %1. So you could say N_("In the USA my birthday is written %2/%1/%3",18,1,1951)". Don't spend time figuring that out if we don't need it! |
Hi @clanmills, The purpose (1) was to solve the warnings you detected on #2116. But not only that issue, Dan and me had this task in our minds for years because there were many issues opened around that templated class over the last years: #1449, #947, #893, #648, #644, etc. Clearly somebody was not right there. The aim is to keep the functionality as similar as possible to what we had before but simplifying the code. The C++ templating features were wrongly abused around the Error class. Regarding the localisation stuff (2), where did I miss the usage of the macro N_()? I tried to keep all the strings in Finally, regarding (3), I think this would be a task to be addressed in a separated PR. In C++20 we could use the new formatting library which does what you said in a standard way. Something to keep in mind for the future 😸 |
@piponazo Thanks for the background information, Luis. I remember the discussion that you and Dan had about the templates. @D4N and you understood that and I didn't! Come back @D4N, we miss you. It's great that you've solved #2116. Sadly, I don't think we can back-port your PR to 0.27-maintenance because it will damage the library API. TBH, I hope we're at the end of 0.27-maintenance. Perhaps a final v0.27.6 about June 2022. I hope to see a plan for 'main' to be released in 2022. C'mon @alexvanderberkel. How about a team meeting? I don't think we should touch (3) - the %1 %2 formatting stuff. Great to hear that new formatting technology is in the C++20 pipeline. Using stringFormat() would be useful in samples/write-test.cpp However, that's in sample code and not localised and stringFormat()_ is internal. So, maybe nothing to be done. After lunch, I'll go over your PR to see if there are any // *****************************************************************************
void testCase(const std::string& file1,
const std::string& file2,
const std::string& thumb,
const std::string& key,
const std::string& value)
{
ExifKey ek(key);
...
if (pos == ed1.end()) {
throw Error(kerErrorMessage, "Metadatum with key = " + ek.key() + " not found");
}
...
} |
@piponazo Can you remove the mention of error-test from README-SAMPLES.md, please. I've looked at your patch and found the "+" in samples/write-test.cpp 581 rmills@rmillsm1:~/gnu/github/exiv2/mainErrorType $ curl -L https://github.com/Exiv2/exiv2/pull/2141.patch | grep '+' | grep -v ^+ | grep -v ^@ | grep -v '^ samples' | grep -v '^ src' | grep 'Metadatum with key'
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 138 100 138 0 0 368 0 --:--:-- --:--:-- --:--:-- 372
100 371k 0 371k 0 0 385k 0 --:--:-- --:--:-- --:--:-- 1828k
- throw Error(kerErrorMessage, "Metadatum with key = " + ek.key() + " not found");
582 rmills@rmillsm1:~/gnu/github/exiv2/mainErrorType $ And looking for the "throws", we find lots that you have fixed!
I have found 143 "raw/untranslated" strings in the patch. Some such as "Photoshop" don't need attention, some are correct "w+b" and "TIFF" and some are from sample code. I don't think it's worth spending more time on this. These localisation issues have been in the code forever and nobody has complained. throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Key not found");
throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Downcast failed");
if (pos == exifData.end()) throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Key not found");
throw Exiv2::Error(Exiv2::ErrorCode::kerTiffDirectoryTooLarge, "Server", serverCode);
throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Unable to init libcurl.");
throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Timeout Environmental Variable must be a positive integer.");
throw Exiv2::Error(Exiv2::ErrorCode::kerTiffDirectoryTooLarge, "Server", returnCode);
throw Error(Exiv2::ErrorCode::kerFileOpenFailed, f1, "w+b", strError());
throw Error(Exiv2::ErrorCode::kerFileOpenFailed, "iotest.txt", "w+b", strError());
throw Error(Exiv2::ErrorCode::kerFileOpenFailed, f2, "w+b", strError());
throw Error(ErrorCode::kerErrorMessage, "Iptc dataset already exists and is not repeatable");
throw Error(ErrorCode::kerErrorMessage, "Iptc dataset already exists and is not repeatable");
throw Error(ErrorCode::kerFileOpenFailed, path, "rb", strError());
if (pos == exifReadData.end()) throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Exif.Image.Make not found");
if (pos == exifReadData.end()) throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Exif.Image.DateTime not found");
if (pos == exifReadData.end()) throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Exif.Canon.OwnerName not found");
if (pos == exifReadData.end()) throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Exif.CanonCs.LensType not found");
throw Exiv2::Error(Exiv2::ErrorCode::kerGeneralError, "ARG1", "ARG2", "ARG3");
throw Error(ErrorCode::kerErrorMessage, "Metadatum with key = " + ek.key() + " not found");
throw Exiv2::Error(Exiv2::ErrorCode::kerFileOpenFailed, filename, "wb", Exiv2::strError());
throw Exiv2::Error(Exiv2::ErrorCode::kerCallFailed, filename, Exiv2::strError(), "FileIo::write");
if (pos == xmpData.end()) throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Key not found");
throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Failed to serialize XMP data");
throw Error(ErrorCode::kerCallFailed, path(), strError(), "munmap");
throw Error(ErrorCode::kerCallFailed, path(), strError(), "mmap");
throw Error(ErrorCode::kerCallFailed, path(), "MSG1", "_get_osfhandle");
throw Error(ErrorCode::kerCallFailed, path(), "MSG2", "DuplicateHandle");
throw Error(ErrorCode::kerCallFailed, path(), "MSG3", "CreateFileMapping");
throw Error(ErrorCode::kerCallFailed, path(), "MSG4", "CreateFileMapping");
throw Error(ErrorCode::kerCallFailed, path(), strError(), "FileIo::read");
throw Error(ErrorCode::kerCallFailed, path(), strError(), "FileIo::mmap");
throw Error(ErrorCode::kerFileOpenFailed, path(), "a+b", strError());
throw Error(ErrorCode::kerCallFailed, pf, strError(), "fs::remove");
throw Error(ErrorCode::kerCallFailed, pf, strError(), "fs::remove");
throw Error(ErrorCode::kerFileOpenFailed, path(), "w+b", strError());
throw Error(ErrorCode::kerErrorMessage, "No base64 data");
throw Error(ErrorCode::kerErrorMessage, "Unable to decode base 64.");
throw Error(ErrorCode::kerErrorMessage, "No base64 data");
throw Error(ErrorCode::kerErrorMessage, "Unable to decode base 64.");
throw Error(ErrorCode::kerErrorMessage, "Data By Range is empty. Please check the permission.");
throw Error(ErrorCode::kerErrorMessage, "the file length is 0");
throw Error(ErrorCode::kerErrorMessage, "Unable to allocate data");
throw Error(ErrorCode::kerErrorMessage, "unable to open src when transferring");
throw Error(ErrorCode::kerFileOpenFailed, "http",Exiv2::Internal::stringFormat("%d",serverCode), hostInfo_.Path);
throw Error(ErrorCode::kerFileOpenFailed, "http",Exiv2::Internal::stringFormat("%d",serverCode), hostInfo_.Path);
throw Error(ErrorCode::kerErrorMessage, "Please set the path of the server script to handle http post data to EXIV2_HTTP_POST environmental variable.");
throw Error(ErrorCode::kerFileOpenFailed, "http",Exiv2::Internal::stringFormat("%d",serverCode), hostInfo_.Path);
throw Error(ErrorCode::kerErrorMessage, "Unable to init libcurl.");
throw Error(ErrorCode::kerErrorMessage, "Timeout Environmental Variable must be a positive integer.");
throw Error(ErrorCode::kerFileOpenFailed, "http",Exiv2::Internal::stringFormat("%d",serverCode),path_);
throw Error(ErrorCode::kerFileOpenFailed, "http", Exiv2::Internal::stringFormat("%d", serverCode), path_);
throw Error(ErrorCode::kerErrorMessage, "Please set the path of the server script to handle http post data to EXIV2_HTTP_POST environmental variable.");
throw Error(ErrorCode::kerFileOpenFailed, "http", Exiv2::Internal::stringFormat("%d", serverCode), path_);
throw Error(ErrorCode::kerErrorMessage, "doesnt support write for this protocol.");
throw Error(ErrorCode::kerErrorMessage, "doesnt support write for this protocol.");
throw Error(ErrorCode::kerFileOpenFailed, path, "rb", strError());
throw Error(ErrorCode::kerCallFailed, path, strError(), "::stat");
throw Error(ErrorCode::kerCallFailed, path, strError(), "FileIo::read");
throw Error(ErrorCode::kerFileOpenFailed, path, "wb", strError());
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "BMFF"));
throw Error(ErrorCode::kerNotAnImage, "BMFF");
throw Exiv2::Error(Exiv2::ErrorCode::kerErrorMessage, "Failed to serialize XMP data");
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "BMFF"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Exif metadata", "BMP"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "IPTC metadata", "BMP"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "BMP"));
throw Error(ErrorCode::kerNotAnImage, "BMP");
throw(Error(ErrorCode::kerWritingImageFormatUnsupported, "BMP"));
throw Error(ErrorCode::kerErrorMessage, std::string("Lens regex didn't match for: ") + std::string(lens.label_));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "CR2"));
throw Error(ErrorCode::kerNotAnImage, "CR2");
throw(Error(ErrorCode::kerInvalidSettingForImage, "IPTC metadata", "CRW"));
throw Error(ErrorCode::kerFunctionNotSupported, "CiffEntry::add");
throw Error(ErrorCode::kerNotAnImage, "EPS");
throw Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "EPS");
throw(Error(ErrorCode::kerInvalidSettingForImage, "Exif metadata", "GIF"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "IPTC metadata", "GIF"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "GIF"));
throw Error(ErrorCode::kerNotAnImage, "GIF");
throw(Error(ErrorCode::kerWritingImageFormatUnsupported, "GIF"));
throw Error(ErrorCode::kerFileOpenFailed, path, "w+b", strError());
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "JP2"));
throw Error(ErrorCode::kerNotAnImage, "JPEG-2000");
throw Error(ErrorCode::kerTooLargeJpegSegment, "Exif");
throw Error(ErrorCode::kerTooLargeJpegSegment, "XMP");
throw Error(ErrorCode::kerTooLargeJpegSegment, "IccProfile");
throw Error(ErrorCode::kerTooLargeJpegSegment, "JPEG comment");
throw(Error(ErrorCode::kerInvalidSettingForImage, "Exif metadata", "MRW"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "IPTC metadata", "MRW"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "MRW"));
throw Error(ErrorCode::kerNotAnImage, "MRW");
throw(Error(ErrorCode::kerWritingImageFormatUnsupported, "MRW"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "ORF"));
throw Error(ErrorCode::kerNotAnImage, "ORF");
throw Error(ErrorCode::kerNotAnImage, "PGF");
throw Error(ErrorCode::kerNotAnImage, "PNG");
throw Error(ErrorCode::kerNotAnImage, "PNG");
throw Error(ErrorCode::kerErrorMessage, "Invalid native preview filter: " + nativePreview_.filter_);
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "Photoshop"));
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop"); // bad resource type
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw Error(ErrorCode::kerNotAnImage, "Photoshop");
throw(Error(ErrorCode::kerInvalidSettingForImage, "Exif metadata", "RAF"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "IPTC metadata", "RAF"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "RAF"));
throw Error(ErrorCode::kerNotAnImage, "RAF");
throw Error(ErrorCode::kerNotAnImage, "RAF");
throw(Error(ErrorCode::kerWritingImageFormatUnsupported, "RAF"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Exif metadata", "RW2"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "IPTC metadata", "RW2"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "RW2"));
throw Error(ErrorCode::kerNotAnImage, "RW2");
throw(Error(ErrorCode::kerWritingImageFormatUnsupported, "RW2"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Exif metadata", "TGA"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "IPTC metadata", "TGA"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "TGA"));
throw Error(ErrorCode::kerNotAnImage, "TGA");
throw(Error(ErrorCode::kerWritingImageFormatUnsupported, "TGA"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "TIFF"));
throw Error(ErrorCode::kerNotAnImage, "TIFF");
throw Error(ErrorCode::kerNotAnImage, "TIFF");
// throw(Error(ErrorCode::kerInvalidSettingForImage, "IPTC metadata", "WebP"));
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "WebP"));
throw Error(ErrorCode::kerNotAnImage, "WEBP");
throw Error(ErrorCode::kerXMPToolkitError, "Could not create expat parser");
throw Error(ErrorCode::kerXMPToolkitError, "Buffer length is greater than INT_MAX");
throw Error(ErrorCode::kerFunctionNotSupported, "Xmpdatum::copy");
throw(Error(ErrorCode::kerInvalidSettingForImage, "Image comment", "XMP"));
throw Error(ErrorCode::kerNotAnImage, "XMP"); |
Done! :) |
+ clang-format in Error files + Remove AnyError
This PR is resuming the work that @D4N started few years ago in #685. By including these changes we should be able to fix the issues reported in #2116 (@clanmills I would appreciate if you could give it a try).