예제 #1
0
void limitation_error::throw_(const char* file, std::size_t line, std::string const& descr)
{
    boost::throw_exception(boost::enable_error_info(limitation_error(descr))
        << boost::throw_file(file)
        << boost::throw_line(line)
    );
}
예제 #2
0
BOOST_LOG_API format_description< CharT > parse_format(const CharT* begin, const CharT* end)
{
    typedef CharT char_type;
    typedef format_description< char_type > description;
    typedef typename encoding< char_type >::type traits;

    const char_type* original_begin = begin;
    description descr;
    unsigned int literal_start_pos = 0;

    while (begin != end)
    {
        const char_type* p = std::find(begin, end, static_cast< char_type >('%'));
        descr.literal_chars.append(begin, p);

        if ((end - p) >= 2)
        {
            // Check for a percent placeholder
            char_type c = p[1];
            if (c == static_cast< char_type >('%'))
            {
                descr.literal_chars.push_back(static_cast< char_type >('%'));
                begin = p + 2;
                continue;
            }

            // From here on, no more literals are possible. Append the literal element.
            {
                const unsigned int literal_chars_size = static_cast< unsigned int >(descr.literal_chars.size());
                if (literal_start_pos < literal_chars_size)
                {
                    descr.format_elements.push_back(format_element::literal(literal_start_pos, literal_chars_size - literal_start_pos));
                    literal_start_pos = literal_chars_size;
                }
            }

            // Check if this is a positional argument
            if (traits::isdigit(c))
            {
                if (c != static_cast< char_type >('0'))
                {
                    // Positional argument in the form "%N%"
                    unsigned int n = 0;
                    const char_type* pp = p + 1;
                    qi::parse(pp, end, qi::uint_, n);
                    if (n == 0 || pp == end || *pp != static_cast< char_type >('%'))
                    {
                        boost::throw_exception(boost::enable_error_info(parse_error("Invalid positional format placeholder")) << boost::throw_file(__FILE__) << boost::throw_line(__LINE__)
                            << boost::log::position_info(static_cast< unsigned int >(p - original_begin))
                        );
                    }

                    // Safety check against ridiculously large argument numbers which would lead to excessive memory consumption.
                    // This could be useful if the format string is gathered from an external source (e.g. a config file).
                    if (n > 1000)
                    {
                        boost::throw_exception(boost::enable_error_info(limitation_error("Positional format placeholder too big")) << boost::throw_file(__FILE__) << boost::throw_line(__LINE__)
                            << boost::log::position_info(static_cast< unsigned int >(p - original_begin))
                        );
                    }

                    // We count positional arguments from 0, not from 1 as in format strings
                    descr.format_elements.push_back(format_element::positional_argument(n - 1));
                    begin = pp + 1; // skip the closing '%'

                    continue;
                }
                else
                {
                    // This must be the filler character, not supported yet
                }
            }

            // This must be something else, not supported yet
            boost::throw_exception(boost::enable_error_info(parse_error("Unsupported format placeholder")) << boost::throw_file(__FILE__) << boost::throw_line(__LINE__)
                << boost::log::position_info(static_cast< unsigned int >(p - original_begin))
            );
        }
        else
        {
            if (p != end)
                descr.literal_chars.push_back(static_cast< char_type >('%')); // a single '%' character at the end of the string
            begin = end;
        }
    }

    const unsigned int literal_chars_size = static_cast< unsigned int >(descr.literal_chars.size());
    if (literal_start_pos < literal_chars_size)
        descr.format_elements.push_back(format_element::literal(literal_start_pos, literal_chars_size - literal_start_pos));

    return boost::move(descr);
}