mozilla/rust — pull request #4656 by Kimundi (2013-01-28 16:14:49+00:00)
Title: Replaced the numeric string conversion functions, and made the api for them consistent

Right now, the string conversion functions for floats and integers are inconsistent with each other and the rest of the library, eg integers had `str(n)` for converting to base 10 and `to_str(n, radix)` for converting to a special base, while float had `to_str(n, digits)` which emitted a number in base 10 with up to `digits` trailing fractional digits etc. Additionally, float.rs had it's own conversion functions that parsed/emitted a `~str`, uint-template.rs had an own implementation that used an stack allocated `[u8]`, int-template simply delegated to the uint function, and f32 and f64 had no functions at all, instead relying on the user casting to/from float. This is my attempt at untangling this:

- Moved all numeric modules in core into a sub folder. This has nothing to do with the code itself, but made working with the files a lot easier. (feel free to revert this)
- (Central change) Added generic `to_str_bytes()` and `from_str_bytes()` functions to num.rs, along with some enums.
- Both are highly configurable and should be able to parse/emit all integer types, floating point types, and anything else that implements the necessary traits, as well as reject them if they're invalid.
- `from_str_bytes` takes a `&[u8]` and `to_str_bytes` returns a `~[u8]`
- `from_str()` and `to_str()` wrappers are provided to make working with `&str` and `~str` easier.
- For example, with this you could parse a positive-only base7 fractional number with binary exponent, and then emit it as a hexadecimal number with explicit positive sign and exactly 3 fractional digits.
- For them to work, also added a few generic math functions and a Round trait + implementations, and new functions to char.rs.
- Converted all numeric string conversion functions to use an unified naming convention and to wrap the new generic functions:
- `to_str()` just takes the number itself, and returns an as-exact-as-possible base 10 representation
- `from_str()` just takes a string, and returns Some(n) if it parses as a number in base 10, accepting also valid variations like an decimal exponent on floating point values, inf, Nan, or an explicit leading '+'.
- `to_str_radix()` emits the number in a given base as exact as possible
- `from_str_radix()` parses as a number in a given base but doesn't accept any special formats that could conflict (for example `"inf"`).
- Additionally, for floating point types the following functions are defined:
- `to_str_digits()` returns a string with up to n fractional digits
- `to_str_exact()` returns an string with exactly n fractional digits
- `to_str_hex()` returns an hexadecimal floating point representation
- `from_str_hex()` accepts an hexadecimal floating point representation with an optional binary exponent
- All types also now implement the existing ToStr, FromStr traits at type-site, as well as the new ToStrRadix and FromStrRadix traits
- They generally map to the stand-alone functions, but the ToStr implementation for floating point numbers only emits maximum 8 digits (using to_str_digits()) to make it more useful.

For backward compatibility, int-template.rs and uint-template.rs still have definitions for `str()` and some of the old functions for the local implementations that all now direct to the new generic ones. These should probably get thrown out in the long term, especially since half the other definitions changed anyway.

Also, all places changed by the floating point conversion should probably checked on whether they should uses limited digits, or the maximum calculable digits, especially the part of repr.rs that I had to change looks strange.

Additionally, while debugging I noticed that when librustc gets compiled somewhere `to_str()` gets called on an int or uint that gets counted up the powers of twos until it overflows (at least on 32bit), not sure if thats intentional. The behavior of the old functions in such a case was just to overflow silently and emit an wrong string, so...

As far as I know, `make check` passes completely, but after the rebase the test suite errors on `test private::at_exit::test_at_exit ... ` with

coretest.stage2-i686-unknown-linux-gnu: /home/marvin/dev/rust/fork/rust/src/rt/rust_kernel.cpp:426: void rust_kernel::register_exit_function(spawn_fn, fn_env_pair*): Assertion `runner == at_exit_runner && "there can be only one at_exit_runner"' failed.

and doesn't complete because of that, so I can't be totally sure.

This should close the Issues #2608, #2649 (those functions no longer exits), #4126, #1784, #4314 and #4288.

I haven't looked at bigints yet, so I don't know if it would be useful there.

Lastly, as the new string conversion functions grew over time till they worked in all corner cases, performance might be considerably worse compared to the original versions, but I'm not sure if that's even a problem or how to tell.