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

antonvw / wex / 20412704571

21 Dec 2025 04:32PM UTC coverage: 64.359% (-0.01%) from 64.372%
20412704571

push

github

antonvw
implemented some actions

18627 of 31704 branches covered (58.75%)

Branch coverage included in aggregate %.

14790 of 20219 relevant lines covered (73.15%)

1510.16 hits per line

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

72.73
/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
enum line_action_t
18
{
19
  ACTION_DEL,
20
  ACTION_ADD,
21
  ACTION_BOTH,
22
  ACTION_UNKNOWN,
23
};
24

25
struct diff
26
{
27
  std::string path_a, path_b;
28

29
  std::vector<std::vector<std::variant<std::pair<int, int>, int>>> hunks;
30

31
  std::vector<std::string> files;
32
};
33

34
wex::factory::unified_diff_parser::unified_diff_parser(unified_diff* diff)
3✔
35
  : m_diff(diff)
3✔
36
{
37
  m_diff->m_diffs = 0;
3✔
38
  m_diff->m_type  = unified_diff::diff_t::UNKNOWN;
3✔
39
}
3✔
40

41
bool wex::factory::unified_diff_parser::parse()
3✔
42
{
43
  bp::symbols<int> const line_actions = {
44
    {"-", ACTION_DEL},
×
45
    {"+", ACTION_ADD},
×
46
    {" ", ACTION_BOTH}};
3✔
47

48
  int action = ACTION_UNKNOWN;
3✔
49

50
  auto const action_diff = [this](const auto& ctx)
1✔
51
  {
52
    auto tpl          = _attr(ctx);
1✔
53
    m_diff->m_path[0] = wex::path(std::get<0>(tpl));
1✔
54
    m_diff->m_path[1] = wex::path(std::get<1>(tpl));
1✔
55

56
    log::debug("unified_diff_parser") << "action_diff" << m_diff->m_path[0];
1✔
57
    diff x;
1✔
58

59
    for (const auto& hunk : x.hunks)
1!
60
    {
61
      int index = 0;
×
62

63
      for (const auto& number : hunk)
×
64
      {
65
        if (const auto* val = std::get_if<std::pair<int, int>>(&number); val)
×
66
        {
67
          m_diff->m_range[index]     = val->first;
×
68
          m_diff->m_range[index + 1] = val->second;
×
69
        }
70
        else
71
        {
72
          m_diff->m_range[index]     = std::get<int>(number);
×
73
          m_diff->m_range[index + 1] = 1;
×
74
        }
75

76
        index += 2;
×
77
      }
78

79
      m_diff->m_type =
×
80
        (m_diff->m_type == unified_diff::diff_t::UNKNOWN ?
×
81
           unified_diff::diff_t::FIRST :
82
           unified_diff::diff_t::OTHER);
83

84
      m_diff->report_diff();
×
85
    }
86
  };
4✔
87

88
  auto action_set = [&action](auto& ctx)
1✔
89
  {
90
    action = _attr(ctx);
1✔
91
    log::debug("unified_diff_parser") << "action_set" << action;
1✔
92
  };
4✔
93

94
  // (Skip the first lines)
95
  // The unified output format starts with a two-line header:
96
  // --- from-file from-file-modification-time
97
  // +++ to-file to-file-modification-time
98
  // Next come one or more hunks of differences:
99
  // @@ from-file-line-numbers to-file-line-numbers @@
100
  // line-from-either-file
101
  // line-from-either-file...
102

103
  auto const parser_diff_lines =
104
    bp::lexeme[+(line_actions[action_set] >> +(bp::char_ - bp::eol))];
3✔
105

106
  auto const parser_hunk =
107
    bp::lit("@@") >> bp::repeat(2)[bp::int_ >> ',' >> bp::int_ | bp::int_] >>
3✔
108
    bp::lit("@@") >> bp::lexeme[+(bp::char_ - bp::eol)] >> parser_diff_lines;
3✔
109

110
  auto const parser_diff = bp::lit("--- a/") >> +(bp::char_ - "+++ b/") >>
3✔
111
                           bp::lit("+++ b/") >> +(bp::char_ - "@@") >>
3✔
112
                           +parser_hunk;
3✔
113

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

116
  auto const parser_all = parser_skip >> +parser_diff[action_diff];
3✔
117

118
  if (const auto result = bp::parse(
6!
119
        m_diff->input(),
3✔
120
        parser_all,
121
        bp::ws,
122
        log::get_level() == log::level_t::TRACE ? bp::trace::on :
3✔
123
                                                  bp::trace::off);
124
      result)
125
  {
126
    return true;
1✔
127
  }
128

129
  return false;
2✔
130
}
3✔
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