catch_message.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. #include "catch_message.h"
  9. #include "catch_interfaces_capture.h"
  10. #include "catch_uncaught_exceptions.h"
  11. #include "catch_enforce.h"
  12. #include <cassert>
  13. #include <stack>
  14. namespace Catch {
  15. MessageInfo::MessageInfo( StringRef const& _macroName,
  16. SourceLineInfo const& _lineInfo,
  17. ResultWas::OfType _type )
  18. : macroName( _macroName ),
  19. lineInfo( _lineInfo ),
  20. type( _type ),
  21. sequence( ++globalCount )
  22. {}
  23. bool MessageInfo::operator==( MessageInfo const& other ) const {
  24. return sequence == other.sequence;
  25. }
  26. bool MessageInfo::operator<( MessageInfo const& other ) const {
  27. return sequence < other.sequence;
  28. }
  29. // This may need protecting if threading support is added
  30. unsigned int MessageInfo::globalCount = 0;
  31. ////////////////////////////////////////////////////////////////////////////
  32. Catch::MessageBuilder::MessageBuilder( StringRef const& macroName,
  33. SourceLineInfo const& lineInfo,
  34. ResultWas::OfType type )
  35. :m_info(macroName, lineInfo, type) {}
  36. ////////////////////////////////////////////////////////////////////////////
  37. ScopedMessage::ScopedMessage( MessageBuilder const& builder )
  38. : m_info( builder.m_info ), m_moved()
  39. {
  40. m_info.message = builder.m_stream.str();
  41. getResultCapture().pushScopedMessage( m_info );
  42. }
  43. ScopedMessage::ScopedMessage( ScopedMessage&& old )
  44. : m_info( old.m_info ), m_moved()
  45. {
  46. old.m_moved = true;
  47. }
  48. ScopedMessage::~ScopedMessage() {
  49. if ( !uncaught_exceptions() && !m_moved ){
  50. getResultCapture().popScopedMessage(m_info);
  51. }
  52. }
  53. Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {
  54. auto trimmed = [&] (size_t start, size_t end) {
  55. while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {
  56. ++start;
  57. }
  58. while (names[end] == ',' || isspace(static_cast<unsigned char>(names[end]))) {
  59. --end;
  60. }
  61. return names.substr(start, end - start + 1);
  62. };
  63. auto skipq = [&] (size_t start, char quote) {
  64. for (auto i = start + 1; i < names.size() ; ++i) {
  65. if (names[i] == quote)
  66. return i;
  67. if (names[i] == '\\')
  68. ++i;
  69. }
  70. CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote");
  71. };
  72. size_t start = 0;
  73. std::stack<char> openings;
  74. for (size_t pos = 0; pos < names.size(); ++pos) {
  75. char c = names[pos];
  76. switch (c) {
  77. case '[':
  78. case '{':
  79. case '(':
  80. // It is basically impossible to disambiguate between
  81. // comparison and start of template args in this context
  82. // case '<':
  83. openings.push(c);
  84. break;
  85. case ']':
  86. case '}':
  87. case ')':
  88. // case '>':
  89. openings.pop();
  90. break;
  91. case '"':
  92. case '\'':
  93. pos = skipq(pos, c);
  94. break;
  95. case ',':
  96. if (start != pos && openings.empty()) {
  97. m_messages.emplace_back(macroName, lineInfo, resultType);
  98. m_messages.back().message = static_cast<std::string>(trimmed(start, pos));
  99. m_messages.back().message += " := ";
  100. start = pos;
  101. }
  102. }
  103. }
  104. assert(openings.empty() && "Mismatched openings");
  105. m_messages.emplace_back(macroName, lineInfo, resultType);
  106. m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));
  107. m_messages.back().message += " := ";
  108. }
  109. Capturer::~Capturer() {
  110. if ( !uncaught_exceptions() ){
  111. assert( m_captured == m_messages.size() );
  112. for( size_t i = 0; i < m_captured; ++i )
  113. m_resultCapture.popScopedMessage( m_messages[i] );
  114. }
  115. }
  116. void Capturer::captureValue( size_t index, std::string const& value ) {
  117. assert( index < m_messages.size() );
  118. m_messages[index].message += value;
  119. m_resultCapture.pushScopedMessage( m_messages[index] );
  120. m_captured++;
  121. }
  122. } // end namespace Catch