-
Notifications
You must be signed in to change notification settings - Fork 273
Add string2optional conversion functions #4192
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
Add string2optional conversion functions #4192
Conversation
ff21b7d
to
a7c0f48
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, but could we also replace the existing str2number
code by the new implementation to avoid duplication? str2number
would then possibly assert when getting nullopt
.
unit/Makefile
Outdated
@@ -70,6 +70,7 @@ SRC += analyses/ai/ai.cpp \ | |||
util/small_map.cpp \ | |||
util/small_shared_two_way_ptr.cpp \ | |||
util/std_expr.cpp \ | |||
util/string2int.cpp \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indents here look pretty weird (likely tab/space mix) - both the newly added line as well as the one above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: a7c0f48).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/100997735
} | ||
} | ||
|
||
optionalt<int> string2optional_int(const std::string &str, int base) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be templates, as is done for numeric_cast
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll write one
src/util/string2int.cpp
Outdated
} | ||
else | ||
{ | ||
throw std::out_of_range{"conversion out of range"}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why throw and then wrap the function in a try catch to return an optional? Return an optional directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because sto*
type functions throw on failure. The function that's passed into wrap
is basically just sto
, but I need to do some additional checks on the string before passing it to stol
as well as checking the conversion result and it makes sense to just use the same interface for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer wrapping just the std::stoul in that case. The string in the exception here is never used and so is just a comment. That's misleading because we would expect it to be useful somewhere.
src/util/string2int.cpp
Outdated
} | ||
auto const ul_value = std::stoul(str, nullptr, base); | ||
auto const u_value = narrow_cast<unsigned>(ul_value); | ||
if(u_value == ul_value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not pretty. What's the difference with just returning the result of numeric_cast<unsigned>
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EDIT my previous comment was based on a misreading of your comment, I'll double check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I thought we had implemented a numeric_cast from integral type to integral type but apparently it's just from mp_integer (or exprt) to integral type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally, it would be nice to extend numeric_cast and use it here, but it doesn't need to be in this PR.
You could write if(ul_value <= std::numeric_limits<T>::max() && ul_value >= std::numeric_limits<T>::min())
before doing the conversion (I don't know if that's much better).
There is now a template It's a bit concerning that we even need the unsafe versions, there are several tests that are failing if we don't leave the conversions unchecked. |
a7c0f48
to
d594ab3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solid. Thanks.
Yes, it would be very nice to get rid of all the |
These are intended as helpers for when you want to convert a string to and integer, but don't want to assert the result (e.g. when dealing with user input there's usually something better you can do than outright crashing if the conversion fails), but also don't want to deal with exceptions (which involve more code to write and read and it's easy to handle the wrong set of exceptions, whether it is too many or too few).
d594ab3
to
e9ccc27
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: e9ccc27).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/101085557
These are intended as helpers for when you want to convert a string to
and integer, but don't want to assert the result (e.g. when dealing with
user input there's usually something better you can do than outright
crashing if the conversion fails), but also don't want to deal with
exceptions (which involve more code to write and read and it's easy to
handle the wrong set of exceptions, whether it is too many or too few).