1 /* 2 * Created by Phil Nash on 1/2/2013. 3 * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. 4 * 5 * Distributed under the Boost Software License, Version 1.0. (See accompanying 6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 */ 8 9 #include "catch_message.h" 10 #include "catch_interfaces_capture.h" 11 #include "catch_uncaught_exceptions.h" 12 13 #include <cassert> 14 #include <stack> 15 16 namespace Catch { 17 MessageInfo(StringRef const & _macroName,SourceLineInfo const & _lineInfo,ResultWas::OfType _type)18 MessageInfo::MessageInfo( StringRef const& _macroName, 19 SourceLineInfo const& _lineInfo, 20 ResultWas::OfType _type ) 21 : macroName( _macroName ), 22 lineInfo( _lineInfo ), 23 type( _type ), 24 sequence( ++globalCount ) 25 {} 26 operator ==(MessageInfo const & other) const27 bool MessageInfo::operator==( MessageInfo const& other ) const { 28 return sequence == other.sequence; 29 } 30 operator <(MessageInfo const & other) const31 bool MessageInfo::operator<( MessageInfo const& other ) const { 32 return sequence < other.sequence; 33 } 34 35 // This may need protecting if threading support is added 36 unsigned int MessageInfo::globalCount = 0; 37 38 39 //////////////////////////////////////////////////////////////////////////// 40 MessageBuilder(StringRef const & macroName,SourceLineInfo const & lineInfo,ResultWas::OfType type)41 Catch::MessageBuilder::MessageBuilder( StringRef const& macroName, 42 SourceLineInfo const& lineInfo, 43 ResultWas::OfType type ) 44 :m_info(macroName, lineInfo, type) {} 45 46 //////////////////////////////////////////////////////////////////////////// 47 48 ScopedMessage(MessageBuilder const & builder)49 ScopedMessage::ScopedMessage( MessageBuilder const& builder ) 50 : m_info( builder.m_info ), m_moved() 51 { 52 m_info.message = builder.m_stream.str(); 53 getResultCapture().pushScopedMessage( m_info ); 54 } 55 ScopedMessage(ScopedMessage && old)56 ScopedMessage::ScopedMessage( ScopedMessage&& old ) 57 : m_info( old.m_info ), m_moved() 58 { 59 old.m_moved = true; 60 } 61 ~ScopedMessage()62 ScopedMessage::~ScopedMessage() { 63 if ( !uncaught_exceptions() && !m_moved ){ 64 getResultCapture().popScopedMessage(m_info); 65 } 66 } 67 68 Capturer(StringRef macroName,SourceLineInfo const & lineInfo,ResultWas::OfType resultType,StringRef names)69 Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) { 70 auto trimmed = [&] (size_t start, size_t end) { 71 while (names[start] == ',' || isspace(names[start])) { 72 ++start; 73 } 74 while (names[end] == ',' || isspace(names[end])) { 75 --end; 76 } 77 return names.substr(start, end - start + 1); 78 }; 79 80 size_t start = 0; 81 std::stack<char> openings; 82 for (size_t pos = 0; pos < names.size(); ++pos) { 83 char c = names[pos]; 84 switch (c) { 85 case '[': 86 case '{': 87 case '(': 88 // It is basically impossible to disambiguate between 89 // comparison and start of template args in this context 90 // case '<': 91 openings.push(c); 92 break; 93 case ']': 94 case '}': 95 case ')': 96 // case '>': 97 openings.pop(); 98 break; 99 case ',': 100 if (start != pos && openings.size() == 0) { 101 m_messages.emplace_back(macroName, lineInfo, resultType); 102 m_messages.back().message = trimmed(start, pos); 103 m_messages.back().message += " := "; 104 start = pos; 105 } 106 } 107 } 108 assert(openings.size() == 0 && "Mismatched openings"); 109 m_messages.emplace_back(macroName, lineInfo, resultType); 110 m_messages.back().message = trimmed(start, names.size() - 1); 111 m_messages.back().message += " := "; 112 } ~Capturer()113 Capturer::~Capturer() { 114 if ( !uncaught_exceptions() ){ 115 assert( m_captured == m_messages.size() ); 116 for( size_t i = 0; i < m_captured; ++i ) 117 m_resultCapture.popScopedMessage( m_messages[i] ); 118 } 119 } 120 captureValue(size_t index,std::string const & value)121 void Capturer::captureValue( size_t index, std::string const& value ) { 122 assert( index < m_messages.size() ); 123 m_messages[index].message += value; 124 m_resultCapture.pushScopedMessage( m_messages[index] ); 125 m_captured++; 126 } 127 128 } // end namespace Catch 129