Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <type_traits>
- #include <cstdint>
- template< typename C >
- bool
- is_valid(C const & c)
- {
- return (!(c < '0') && !('9' < c));
- }
- using u8 = unsigned char;
- using BCD = u8 [10];
- inline
- void
- convert(BCD const & bcd, std::int16_t & attrib)
- {
- asm("fbld %1\n" "fistps %0" : "=m"(attrib) : "m"(bcd) : "memory");
- }
- inline
- void
- convert(BCD const & bcd, std::int32_t & attrib)
- {
- asm("fbld %1\n" "fistpl %0" : "=m"(attrib) : "m"(bcd) : "memory");
- }
- inline
- void
- convert(BCD const & bcd, std::int64_t & attrib)
- {
- asm("fbld %1\n" "fistpq %0" : "=m"(attrib) : "m"(bcd) : "memory");
- }
- template< typename F >
- std::enable_if_t< (std::is_floating_point< F >{}) >
- convert(BCD const & bcd, F & attrib)
- {
- asm("fbld %1\n" : "=t"(attrib) : "m"(bcd) : "memory");
- }
- template< typename iterator, typename T >
- void
- extract_int(iterator & beg, iterator const & end, T const & attrib) = delete;
- template< typename iterator, typename T >
- bool
- extract_int(iterator & beg, iterator const & end, T & attrib)
- {
- if (beg == end) {
- return false;
- }
- BCD bcd;
- auto sbeg = beg;
- auto & sign = *sbeg;
- if (sign == '-') {
- bcd[9] = u8(0x80);
- ++sbeg;
- } else {
- bcd[9] = u8(0x00);
- if (sign == '+') {
- ++sbeg;
- }
- }
- auto length = 0;
- auto it = sbeg;
- while ((it != end) && is_valid(*it)) {
- ++length;
- ++it;
- }
- if (length == 0) {
- return false;
- }
- if (18 < length) {
- return false;
- }
- --length;
- beg = sbeg;
- char i = 17;
- while (length < i) {
- --i;
- if (length == i) {
- bcd[i / 2] = u8(*beg - '0');
- ++beg;
- --i;
- break;
- } else {
- bcd[i / 2] = u8(0x00);
- --i;
- }
- }
- ++i;
- do {
- i -= 2;
- auto & ch = bcd[i / 2];
- ch = u8((*beg - '0') << 4);
- ++beg;
- ch |= u8(*beg - '0');
- ++beg;
- } while (0 < i);
- convert(bcd, attrib);
- return true;
- }
- #include <iomanip>
- #include <iostream>
- #include <cstdlib>
- #ifdef NDEBUG
- #undef NDEBUG
- #endif
- #include <cassert>
- template< typename T = long double >
- bool
- print(std::string const & s)
- {
- auto beg = std::cbegin(s);
- T val{};
- if (extract_int(beg, std::cend(s), val)) {
- std::cout << std::fixed << std::setprecision(0) << val << std::endl;
- return true;
- }
- std::cout << "can't convert" << std::endl;
- return false;
- }
- template< typename T = long double >
- void
- check()
- {
- std::cout << __PRETTY_FUNCTION__ << std::endl;
- assert(print< T >("+135792468135792468"));
- assert(print< T >( "123456789123456789"));
- assert(print< T >("-987654321987654321"));
- assert(print< T >( "1"));
- assert(print< T >("-1"));
- assert(print< T >("+1"));
- assert(print< T >( "0"));
- assert(print< T >("-0"));
- assert(print< T >("+0"));
- assert(!print< T >("+1357924681357924680")); // 19 digits
- assert(!print< T >( "1234567891234567890")); // 19 digits
- assert(!print< T >("-9876543219876543210")); // 19 digits
- assert(!print< T >(""));
- assert(!print< T >("+"));
- assert(!print< T >("-"));
- assert(!print< T >( "A"));
- assert(!print< T >("+A"));
- assert(!print< T >("-A"));
- std::cout << std::endl;
- }
- int
- main()
- {
- // full-scale precision
- check< long double >();
- check< std::int64_t >();
- // partial precision
- check< float >();
- check< double >();
- check< std::int16_t >();
- check< std::int32_t >();
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment