• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

antonvw / wex / 20415036585

21 Dec 2025 07:58PM UTC coverage: 64.382% (+0.02%) from 64.359%
20415036585

push

github

antonvw
prototype is OK

18633 of 31707 branches covered (58.77%)

Branch coverage included in aggregate %.

14798 of 20219 relevant lines covered (73.19%)

1510.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.5
/src/factory/unified-diff-parser.cpp
1
////////////////////////////////////////////////////////////////////////////////
2
// Name:      unified-diff-parser.cpp
3
// Purpose:   Implementation of unified_diff_parser
4
//            https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html
5
// Author:    Anton van Wezenbeek
6
// Copyright: (c) 2025 Anton van Wezenbeek
7
////////////////////////////////////////////////////////////////////////////////
8

9
#include <boost/parser/parser.hpp>
10
#include <wex/core/log.h>
11
#include <wex/factory/unified-diff.h>
12

13
#include "unified-diff-parser.h"
14

15
namespace bp = boost::parser;
16

17
wex::factory::unified_diff_parser::unified_diff_parser(unified_diff* diff)
3✔
18
  : m_diff(diff)
3✔
19
{
20
  m_diff->m_diffs = 0;
3✔
21
  m_diff->m_type  = unified_diff::diff_t::UNKNOWN;
3✔
22
}
3✔
23

24
bool wex::factory::unified_diff_parser::parse()
3✔
25
{
26
  auto const action_diff = [this](const auto& ctx)
1✔
27
  {
28
    const auto tpl    = _attr(ctx);
1✔
29
    m_diff->m_path[0] = wex::path(std::get<0>(tpl));
1✔
30
    m_diff->m_path[1] = wex::path(std::get<1>(tpl));
1✔
31

32
    log::debug("unified_diff_parser") << "action_diff" << m_diff->m_path[0];
1✔
33

34
    for (const auto& hunk : std::get<2>(tpl))
2✔
35
    {
36
      int index = 0;
1✔
37

38
      for (const auto& number : std::get<0>(hunk))
3✔
39
      {
40
        if (const auto* val = std::get_if<std::tuple<int, int>>(&number); val)
2✔
41
        {
42
          m_diff->m_range[index]     = std::get<0>(*val);
1✔
43
          m_diff->m_range[index + 1] = std::get<1>(*val);
1✔
44
        }
45
        else
46
        {
47
          m_diff->m_range[index]     = std::get<int>(number);
1✔
48
          m_diff->m_range[index + 1] = 1;
1✔
49
        }
50

51
        index += 2;
2✔
52
      }
53

54
      for (const auto& file : std::get<1>(hunk))
3✔
55
      {
56
        switch (file[0])
2!
57
        {
58
          case '+':
1✔
59
            m_diff->m_text[0].push_back(file.substr(1));
1✔
60
            break;
1✔
61
          case '-':
×
62
            m_diff->m_text[1].push_back(file.substr(1));
×
63
            break;
×
64
          case ' ':
×
65
            break;
×
66
        }
67
      }
68

69
      m_diff->m_type =
1✔
70
        (m_diff->m_type == unified_diff::diff_t::UNKNOWN ?
1✔
71
           unified_diff::diff_t::FIRST :
72
           unified_diff::diff_t::OTHER);
73

74
      m_diff->report_diff();
1✔
75
    }
76
  };
4✔
77

78
  // (Skip the first lines)
79
  // The unified output format starts with a two-line header:
80
  // --- from-file from-file-modification-time
81
  // +++ to-file to-file-modification-time
82
  // Next come one or more hunks of differences:
83
  // @@ from-file-line-numbers to-file-line-numbers @@
84
  // line-from-either-file
85
  // line-from-either-file...
86

87
  auto const parser_diff_lines =
3✔
88
    bp::lexeme[+(bp::char_ >> +(bp::char_ - bp::eol))];
89

90
  auto const parser_hunk =
91
    bp::lit("@@") >> bp::repeat(2)[bp::int_ >> ',' >> bp::int_ | bp::int_] >>
3✔
92
    bp::lit("@@") >> bp::lexeme[+(bp::char_ - bp::eol)] >> parser_diff_lines;
3✔
93

94
  auto const parser_diff = bp::lit("--- a/") >> +(bp::char_ - "+++ b/") >>
3✔
95
                           bp::lit("+++ b/") >> +(bp::char_ - "@@") >>
3✔
96
                           +parser_hunk;
3✔
97

98
  auto const parser_skip = bp::omit[*(bp::char_ - "--- a/")];
3✔
99

100
  auto const parser_all = parser_skip >> +parser_diff[action_diff];
3✔
101

102
  if (const auto result = bp::parse(
6!
103
        m_diff->input(),
3✔
104
        parser_all,
105
        bp::ws,
106
        log::get_level() == log::level_t::TRACE ? bp::trace::on :
3✔
107
                                                  bp::trace::off);
108
      result)
109
  {
110
    return true;
1✔
111
  }
112

113
  return false;
2✔
114
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc