Skip to content

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

Conversation

hannes-steffenhagen-diffblue
Copy link
Contributor

@hannes-steffenhagen-diffblue hannes-steffenhagen-diffblue commented Feb 14, 2019

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).

  • Each commit message has a non-empty body, explaining why the change was made.
  • Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • White-space or formatting changes outside the feature-related changed lines are in commits of their own.

Copy link
Contributor

@xbauch xbauch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

Copy link
Collaborator

@tautschnig tautschnig left a 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 \
Copy link
Collaborator

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.

Copy link
Contributor

@allredj allredj left a 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)
Copy link
Contributor

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.

Copy link
Contributor Author

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

}
else
{
throw std::out_of_range{"conversion out of range"};
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

}
auto const ul_value = std::stoul(str, nullptr, base);
auto const u_value = narrow_cast<unsigned>(ul_value);
if(u_value == ul_value)
Copy link
Contributor

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> ?

Copy link
Contributor Author

@hannes-steffenhagen-diffblue hannes-steffenhagen-diffblue Feb 15, 2019

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

Copy link
Contributor

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.

Copy link
Contributor

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).

@hannes-steffenhagen-diffblue
Copy link
Contributor Author

@romainbrenguier @tautschnig

There is now a template string2optional which can be used to convert to any of the standard integer types as long as they're smaller than (unsigned) long long. The indentation in the unit Makefile has been fixed. The safe_* functions now defer back to the optional versions, the unsafe versions use the strto* family directly now.

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.

Copy link
Contributor

@NlightNFotis NlightNFotis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid. Thanks.

@tautschnig
Copy link
Collaborator

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.

Yes, it would be very nice to get rid of all the unsafe_* ones, but that's presumably a lot more work. For now, at least it's easy to git grep for them...

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).
Copy link
Contributor

@allredj allredj left a 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

@hannes-steffenhagen-diffblue hannes-steffenhagen-diffblue merged commit a62b5da into diffblue:develop Feb 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants