1. C++ / Говнокод #26908

    +1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    void Argument::parseAsInt()
    {
        auto res = std::from_chars(data.data(), data.data() + data.size(), dataInt);
        if (res.ec == std::errc()) {
            setTypeFlag(ArgType::Int);
        }
    }
    
    void Argument::parseAsFloat()
    {
        // Rww: gcc still does not support float from_chars(), lol
        const char *begin = data.data();
        const char *end = begin + data.size();
        char *endPtr = nullptr;
    
        dataFloat = std::strtof(begin, &endPtr);
        if (endPtr == end || dataFloat != 0.0f) {
            setTypeFlag(ArgType::Float);
        } else {
            for (const char *it = endPtr; it < end; it++) {
                if (!std::isspace(*it)) {
                    return;
                }
            }
            setTypeFlag(ArgType::Float);
        }
    }

    Говнокодил тут недавно, долго думал, что считать числом (пет, ТЗ нет). В конце-концов решил считать всё, что можно распарсить.

    Запостил: gost, 02 Сентября 2020

    Комментарии (14) RSS

    • > // Rww: gcc still does not support float from_chars(), lol
      Такова участь крестобляди.
      Ответить
    • > setTypeFlag
      - а что это за функция? Дока не гуглится по ней
      Ответить
      • Эм, ну просто метод этого класса?
        Ответить
        • А, тупо задаёт тип прочитанного значения?

          А то я подумал, что это какая-то стандартная крестометушня, чтобы подсказывать компилятору, с каким типом мы щас будем работать или в этом духе
          Ответить
        • Подтверждаю. «Argument» — это самописный класс от парсера команд, а в этих методах определяется тип аргумента.
          Ответить
    • > gcc still does not support

      Вот интересно на самом деле, в чем сложность реализации этих функций. Чел из майкрософта пишет, что он на основе готового strtod месяц (!) пилил реализацию для их либы.

      Понятно, что парсинг флоата это нетривиальная задача. Но она ведь уже давным-давно решена в сишке. И наборы тестов там уже есть.
      Ответить
      • Хуй пойми. Для плавающих питухов в «MSVCRT» есть три перегрузки:
        inline from_chars_result from_chars(const char* const _First, const char* const _Last, float& _Value,
            const chars_format _Fmt = chars_format::general) noexcept /* strengthened */ {
            return _Floating_from_chars(_First, _Last, _Value, _Fmt);
        }
        inline from_chars_result from_chars(const char* const _First, const char* const _Last, double& _Value,
            const chars_format _Fmt = chars_format::general) noexcept /* strengthened */ {
            return _Floating_from_chars(_First, _Last, _Value, _Fmt);
        }
        inline from_chars_result from_chars(const char* const _First, const char* const _Last, long double& _Value,
            const chars_format _Fmt = chars_format::general) noexcept /* strengthened */ {
            double _Dbl; // intentionally default-init
            const from_chars_result _Result = _Floating_from_chars(_First, _Last, _Dbl, _Fmt);
        
            if (_Result.ec == errc{}) {
                _Value = _Dbl;
            }
        
            return _Result;
        }
        Ответить
        • И сама реализация:
          template <class _Floating>
          _NODISCARD from_chars_result _Floating_from_chars(
              const char* const _First, const char* const _Last, _Floating& _Value, const chars_format _Fmt) noexcept {
              _Adl_verify_range(_First, _Last);
          
              _STL_ASSERT(_Fmt == chars_format::general || _Fmt == chars_format::scientific || _Fmt == chars_format::fixed
                              || _Fmt == chars_format::hex,
                  "invalid format in from_chars()");
          
              bool _Minus_sign = false;
          
              const char* _Next = _First;
          
              if (_Next == _Last) {
                  return {_First, errc::invalid_argument};
              }
          
              if (*_Next == '-') {
                  _Minus_sign = true;
                  ++_Next;
          
                  if (_Next == _Last) {
                      return {_First, errc::invalid_argument};
                  }
              }
          // продолжение следует
          Ответить
          • // Distinguish ordinary numbers versus inf/nan with a single test.
                // ordinary numbers start with ['.'] ['0', '9'] ['A', 'F'] ['a', 'f']
                // inf/nan start with ['I'] ['N'] ['i'] ['n']
                // All other starting characters are invalid.
                // Setting the 0x20 bit folds these ranges in a useful manner.
                // ordinary (and some invalid) starting characters are folded to ['.'] ['0', '9'] ['a', 'f']
                // inf/nan starting characters are folded to ['i'] ['n']
                // These are ordered: ['.'] ['0', '9'] ['a', 'f'] < ['i'] ['n']
                // Note that invalid starting characters end up on both sides of this test.
                const unsigned char _Folded_start = static_cast<unsigned char>(static_cast<unsigned char>(*_Next) | 0x20);
            
                if (_Folded_start <= 'f') { // possibly an ordinary number
                    return _Ordinary_floating_from_chars(_First, _Last, _Value, _Fmt, _Minus_sign, _Next);
                } else if (_Folded_start == 'i') { // possibly inf
                    return _Infinity_from_chars(_First, _Last, _Value, _Minus_sign, _Next);
                } else if (_Folded_start == 'n') { // possibly nan
                    return _Nan_from_chars(_First, _Last, _Value, _Minus_sign, _Next);
                } else { // definitely invalid
                    return {_First, errc::invalid_argument};
                }
            }
            Ответить
            • А, тьфу, там дальше дохуя кода. Вот, короче: https://pastebin.com/fbS0YvKK. Они там очень хардкорно парсят.
              Ответить
        • Ну я почитал в мейл листе гцц - они пишут, что реализация должна порвать принтфы и стртоды в клочья. Иначе нету смысла её пилить и можно просто сишную позвать.
          Ответить
          • То есть конечная цель — слить лалок в хламину?
            Ответить
            • Ага. Но сишники ведь потом обратно это портанут. Языки то одинаковые почти, по крайней мере в битоёбстве.
              Ответить

    Добавить комментарий