Информация об изменениях

Сообщение Re[4]: класс Config от 26.01.2019 20:11

Изменено 26.01.2019 21:06 Marty

Re[4]: класс Config
Здравствуйте, kov_serg, Вы писали:

_>Здравствуйте, vadfromnu, Вы писали:


V>>В функции прикопан баг, который когда-нибудь бахнет.(Я подрывался) strtol выставит errno при ошибке, но не сбросит его при успехе. Если errno уже выставлен кем-то ранее, то вместо 0 будет возвращаться defval.


_>Действительно https://github.com/gcc-mirror/gcc/blob/master/libiberty/strtol.c

_>Тогда так:

Сорян, что не по теме, но это выглядит, как говнокод. Строчки экономишь?
Re[4]: класс Config
Здравствуйте, kov_serg, Вы писали:

_>Здравствуйте, vadfromnu, Вы писали:


V>>В функции прикопан баг, который когда-нибудь бахнет.(Я подрывался) strtol выставит errno при ошибке, но не сбросит его при успехе. Если errno уже выставлен кем-то ранее, то вместо 0 будет возвращаться defval.


_>Действительно https://github.com/gcc-mirror/gcc/blob/master/libiberty/strtol.c

_>Тогда так:

Сорян, что не по теме, но это выглядит, как говнокод. Строчки экономишь?


ЗЫ Моя версия, не факт, что рабочая — просто по-человечески переписал даденое. Да, в три раза длиннее получилось, если считать по строчкам
  Скрытый текст
#include <stdlib.h>

struct int_parsing_traits
{
    // Методы не упаковываем в одну строчку (хотя они очень просятся) чтобы можно было
    // остановится в отладчике и посмотреть одновременно на входной параметр, и на условие

    bool is_space(char c) const
    {
        return c>0 && c<=32;
    }

    bool is_digit(char c) const
    {
        return c>='0' && c<='9';
    }

    bool is_sign(char c) const
    {
        return c=='-' || c=='+';
    }

    bool is_negate_sign(char c) const
    {
        return c=='-';
    }

    int to_digit(char c) const
    {
        return (c>='0' && c<='9') ? c-'0' : -1;
    }

    // Решили, что системой счисления управляет ParsingTraits
    unsigned get_base() const
    {
        return 10;
    }

}; // struct int_parsing_traits



template<typename ParsingTraits>
inline
int getint( const char *p, int defval = 0, const ParsingTraits &parsingTraits = int_parsing_traits() )
{
    // skip leading whitespaces
    while( *p && parsingTraits.is_space(*p) )
        p++;

    // check for leading sign
    if (!parsingTraits.is_sign(*p))
        return defval;

    bool neg = false;

    // is negative number?
    if (parsingTraits.is_negate_sign(*p))
        neg = true;

    unsigned resultAbs = 0;

    while(*p && parsingTraits.is_digit(*p))
    {
        int digit = parsingTraits.to_digit();

        // Тут можно вставить проверку на систему счисления,
        // а можно положится, что ParsingTraits сама знает, что делает
        if (digit<0)
            break;

        // А тут мы уже точно решили, что ParsingTraits знает систему счисления
        unsigned newRes = resultAbs * parsingTraits.get_base() + (unsigned)digit;

        if (newRes<resultAbs)
            return defval; // переполнились

        resultAbs = newRes;

        p++;
    }

    // Пробегаем по оставшейся строке, надеясь, что она состоит из пробелов
    while(*p && parsingTraits.is_space(*p))
        ++p; 

    if ( *p && !parsingTraits.is_space(*p) )
        return defval; // стопанули на чём-то, не похожем на цифру или пробел

    int result = (int)resultAbs;

    if (neg)
        result = -result;

    if (unsigned(result)!=resultAbs)
        return defval; // переполнение при смене знака

    return result;
}