| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 | /* *  Created by Phil Nash on 1/2/2013. *  Copyright 2013 Two Blue Cubes Ltd. All rights reserved. * *  Distributed under the Boost Software License, Version 1.0. (See accompanying *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */#include "catch_message.h"#include "catch_interfaces_capture.h"#include "catch_uncaught_exceptions.h"#include "catch_enforce.h"#include <cassert>#include <stack>namespace Catch {    MessageInfo::MessageInfo(   StringRef const& _macroName,                                SourceLineInfo const& _lineInfo,                                ResultWas::OfType _type )    :   macroName( _macroName ),        lineInfo( _lineInfo ),        type( _type ),        sequence( ++globalCount )    {}    bool MessageInfo::operator==( MessageInfo const& other ) const {        return sequence == other.sequence;    }    bool MessageInfo::operator<( MessageInfo const& other ) const {        return sequence < other.sequence;    }    // This may need protecting if threading support is added    unsigned int MessageInfo::globalCount = 0;    ////////////////////////////////////////////////////////////////////////////    Catch::MessageBuilder::MessageBuilder( StringRef const& macroName,                                           SourceLineInfo const& lineInfo,                                           ResultWas::OfType type )        :m_info(macroName, lineInfo, type) {}    ////////////////////////////////////////////////////////////////////////////    ScopedMessage::ScopedMessage( MessageBuilder const& builder )    : m_info( builder.m_info ), m_moved()    {        m_info.message = builder.m_stream.str();        getResultCapture().pushScopedMessage( m_info );    }    ScopedMessage::ScopedMessage( ScopedMessage&& old )    : m_info( old.m_info ), m_moved()    {        old.m_moved = true;    }    ScopedMessage::~ScopedMessage() {        if ( !uncaught_exceptions() && !m_moved ){            getResultCapture().popScopedMessage(m_info);        }    }    Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {        auto trimmed = [&] (size_t start, size_t end) {            while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {                ++start;            }            while (names[end] == ',' || isspace(static_cast<unsigned char>(names[end]))) {                --end;            }            return names.substr(start, end - start + 1);        };        auto skipq = [&] (size_t start, char quote) {            for (auto i = start + 1; i < names.size() ; ++i) {                if (names[i] == quote)                    return i;                if (names[i] == '\\')                    ++i;            }            CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote");        };        size_t start = 0;        std::stack<char> openings;        for (size_t pos = 0; pos < names.size(); ++pos) {            char c = names[pos];            switch (c) {            case '[':            case '{':            case '(':            // It is basically impossible to disambiguate between            // comparison and start of template args in this context//            case '<':                openings.push(c);                break;            case ']':            case '}':            case ')'://           case '>':                openings.pop();                break;            case '"':            case '\'':                pos = skipq(pos, c);                break;            case ',':                if (start != pos && openings.empty()) {                    m_messages.emplace_back(macroName, lineInfo, resultType);                    m_messages.back().message = static_cast<std::string>(trimmed(start, pos));                    m_messages.back().message += " := ";                    start = pos;                }            }        }        assert(openings.empty() && "Mismatched openings");        m_messages.emplace_back(macroName, lineInfo, resultType);        m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));        m_messages.back().message += " := ";    }    Capturer::~Capturer() {        if ( !uncaught_exceptions() ){            assert( m_captured == m_messages.size() );            for( size_t i = 0; i < m_captured; ++i  )                m_resultCapture.popScopedMessage( m_messages[i] );        }    }    void Capturer::captureValue( size_t index, std::string const& value ) {        assert( index < m_messages.size() );        m_messages[index].message += value;        m_resultCapture.pushScopedMessage( m_messages[index] );        m_captured++;    }} // end namespace Catch
 |