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

antonvw / wex / 19580706205

21 Nov 2025 07:04PM UTC coverage: 64.402% (-0.02%) from 64.42%
19580706205

push

github

web-flow
clang-tidy updates (#1090)

18531 of 31542 branches covered (58.75%)

Branch coverage included in aggregate %.

14692 of 20045 relevant lines covered (73.3%)

1526.51 hits per line

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

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

9
#include <boost/tokenizer.hpp>
10
#include <wex/core/log.h>
11
#include <wex/core/regex.h>
12
#include <wex/factory/frame.h>
13
#include <wex/factory/unified-diff.h>
14

15
#include <iostream>
16
#include <utility>
17

18
#define NEXT_TOKEN                                                             \
19
  if (++tok_iter == tokens.end())                                              \
20
  {                                                                            \
21
    return false;                                                              \
22
  }
23

24
#define CHANGES_LINES(RANGE, TEXT)                                             \
25
  for (int i = 0; i < m_range[RANGE]; i++)                                     \
26
  {                                                                            \
27
    NEXT_TOKEN                                                                 \
28
    m_text[TEXT].push_back((*tok_iter).substr(1));                             \
29
  }
30

31
#define HEADER_LINES(REGEX, INTO)                                              \
32
  if (!parse_header(REGEX, *tok_iter, INTO))                                   \
33
  {                                                                            \
34
    return false;                                                              \
35
  }                                                                            \
36
  NEXT_TOKEN
37

38
#define SKIP_LINES                                                             \
39
  while (tok_iter != tokens.end())                                             \
40
  {                                                                            \
41
    NEXT_TOKEN                                                                 \
42
    if (!tok_iter->starts_with("diff ") && !tok_iter->starts_with("index "))   \
43
    {                                                                          \
44
      break;                                                                   \
45
    }                                                                          \
46
  }
47

48
namespace wex
49
{
50
size_t stoi(const std::string& i)
60✔
51
{
52
  return i.empty() ? 1 : std::stoi(i);
60✔
53
}
54
} // namespace wex
55

56
wex::factory::unified_diff::unified_diff(std::string input)
14✔
57
  : m_input(std::move(input))
14✔
58
{
59
  m_range.fill({0});
14✔
60
}
14✔
61

62
bool wex::factory::unified_diff::parse()
10✔
63
{
64
  using tokenizer = boost::tokenizer<boost::char_separator<char>>;
65

66
  tokenizer tokens(m_input, boost::char_separator<char>("\r\n"));
10✔
67

68
  tokenizer::iterator tok_iter = tokens.begin();
10✔
69

70
  m_diffs = 0;
10✔
71

72
  while (tok_iter != tokens.end())
30✔
73
  {
74
    // skip first lines
75
    SKIP_LINES;
21!
76

77
    // The unified output format starts with a two-line header
78
    HEADER_LINES("--- a/(.*)", m_path[0]);
36!
79
    HEADER_LINES("\\+\\+\\+ b/(.*)", m_path[1]);
36!
80

81
    m_is_first = true;
12✔
82
    m_is_last  = false;
12✔
83

84
    // Next come one or more chunks of differences
85
    while (tok_iter != tokens.end())
22✔
86
    {
87
      regex r_chunk("@@ -([0-9]+),?([0-9]*) \\+([0-9]+),?([0-9]*) @@.*");
17✔
88

89
      if (r_chunk.match(*tok_iter) != 4)
17✔
90
      {
91
        log("unified_diff") << *tok_iter << r_chunk.size();
2✔
92
        return false;
2✔
93
      }
94

95
      m_range[0] = wex::stoi(r_chunk[0]);
15✔
96
      m_range[1] = wex::stoi(r_chunk[1]);
15✔
97
      m_range[2] = wex::stoi(r_chunk[2]);
15✔
98
      m_range[3] = wex::stoi(r_chunk[3]);
15✔
99

100
      m_text.fill({});
15✔
101

102
      // Now get all - lines and all + lines, collect them, and invoke callback.
103
      CHANGES_LINES(1, 0);
29!
104
      CHANGES_LINES(3, 1);
25!
105

106
      if (!report_diff())
15!
107
      {
108
        return false;
×
109
      }
110

111
      m_is_first = false;
15✔
112

113
      if (++tok_iter != tokens.end() && !(*tok_iter).starts_with("@@"))
15!
114
      {
115
        m_is_last = true;
5✔
116
        report_diff();
5✔
117
        break; // this was last chunk, continue with header lines
5✔
118
      }
119
    }
17✔
120
  }
121

122
  m_is_last = true;
7✔
123

124
  report_diff();
7✔
125
  report_diff_finish();
7✔
126

127
  return true;
7✔
128
}
10✔
129

130
bool wex::factory::unified_diff::parse_header(
24✔
131
  const std::string& r,
132
  const std::string& line,
133
  path&              p)
134
{
135
  regex re(r);
24✔
136

137
  if (!re.match(line))
24!
138
  {
139
    log("unified_diff") << line << re.match_data().text();
×
140
    return false;
×
141
  }
142

143
  p = path(re[0]);
24✔
144

145
  return true;
24✔
146
}
24✔
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