Giter Site home page Giter Site logo

Comments (2)

jamboree avatar jamboree commented on September 27, 2024

Bustache wasn't designed to be a lint, so I didn't consider rich error info. Probably the best we can do is to add a format_error::position() which returns the offset from the source, and let the users compute col/row and format the error msg themselves. I think the non-human-readable parts can be removed from format_error::what() (I probably mimics the MSVC STL style).

from bustache.

mbeutel avatar mbeutel commented on September 27, 2024

The pull request implements format_error::position() as you proposed.

Just in case anyone else needs this, I now use the following wrappers to augment formatting errors with line/column info by nesting exceptions:

// bustache-format.hpp

#ifndef INCLUDED_BUSTACHE_FORMAT_HPP_
#define INCLUDED_BUSTACHE_FORMAT_HPP_


#include <cstddef>   // for size_t, ptrdiff_t
#include <utility>   // for forward<>()
#include <stdexcept> // for runtime_error

#include <bustache/format.hpp>


enum class FormatTemplateType
{
    string,
    multilineString
};


class BustacheFormatError : public std::runtime_error
{
private:
    bustache::format_error error_;
    std::ptrdiff_t line_;
    std::ptrdiff_t column_;

public:
    BustacheFormatError(const bustache::format_error& _error);
    BustacheFormatError(const bustache::format_error& _error, std::ptrdiff_t _line, std::ptrdiff_t _column);

    std::ptrdiff_t line(void) const noexcept { return line_; }
    std::ptrdiff_t column(void) const noexcept { return column_; }
};


namespace detail
{


[[noreturn]] void throwBustacheFormatErrorWithPosition(FormatTemplateType templateType, const char* data, const bustache::format_error& error);


} // namespace detail


inline bustache::format bustacheFormat(const char* first, const char* last, FormatTemplateType templateType)
{
    try
    {
        return bustache::format(first, last);
    }
    catch (const bustache::format_error& error)
    {
        detail::throwBustacheFormatErrorWithPosition(templateType, first, error);
    }
}
template <typename SourceT>
    bustache::format bustacheFormat(SourceT&& source, FormatTemplateType templateType)
{
    try
    {
        return bustache::format(std::forward<SourceT>(source));
    }
    catch (const bustache::format_error& error)
    {
        detail::throwBustacheFormatErrorWithPosition(templateType, source.data(), error);
    }
}
template <std::size_t N>
    bustache::format bustacheFormat(const char (&source)[N], FormatTemplateType templateType)
{
    try
    {
        return bustache::format(source);
    }
    catch (const bustache::format_error& error)
    {
        detail::throwBustacheFormatErrorWithPosition(templateType, source, error);
    }
}


#endif // INCLUDED_BUSTACHE_FORMAT_HPP_
// bustache-format.cpp

#include <string>
#include <sstream>
#include <utility>   // for pair<>
#include <exception> // for throw_with_nested()

#include "bustache-format.hpp"


static std::string makePositionMessage(std::ptrdiff_t line, std::ptrdiff_t column)
{
        // We use 1-based indices in human-readable error messages.
    std::ostringstream sstr;
    if (line >= 0 && column >= 0)
        sstr << "in line " << (line + 1) << ", column " << (column + 1) << ":";
    else if (column >= 0)
        sstr << "at position " << (column + 1) << ":";
    else
        sstr << "at unknown position:";
    return sstr.str();
}


BustacheFormatError::BustacheFormatError(const bustache::format_error& _error)
    : std::runtime_error(makePositionMessage(-1, _error.position())), error_(_error), line_(-1), column_(_error.position())
{
}

BustacheFormatError::BustacheFormatError(const bustache::format_error& _error, std::ptrdiff_t _line, std::ptrdiff_t _column)
    : std::runtime_error(makePositionMessage(_line, _column)), error_(_error), line_(_line), column_(_column)
{
}


namespace detail
{


template <typename I, typename D>
    static std::pair<D, D> determineLineAndColumn(I data, D position)
{
    if (position < 0)
        return std::make_pair(-1, -1);

    D line = 0;
    I i0 = data;
    for (I i = data, e = data + position; i < e; ++i)
    {
        if (*i == '\n')
        {
            ++line;
            i0 = i + 1;
        }
    }
    D column = (data + position) - i0;
    return std::make_pair(line, column);
}


void throwBustacheFormatErrorWithPosition(FormatTemplateType templateType, const char* data, const bustache::format_error& error)
{
    if (error.position() < 0)
        throw;

    switch (templateType)
    {
    case FormatTemplateType::string:
        std::throw_with_nested(BustacheFormatError(error));
    case FormatTemplateType::multilineString:
        {
            auto [line, column] = determineLineAndColumn(data, error.position());
            std::throw_with_nested(BustacheFormatError(error, line, column));
        }
    }
    std::terminate();
}


} // namespace detail

from bustache.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.