• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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