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

antonvw / wex / 20173039001

12 Dec 2025 04:23PM UTC coverage: 64.268% (-0.1%) from 64.381%
20173039001

push

github

web-flow
1108 changes according to macos instruments (#1109)

* changes according to macos Instruments

* some updates to fix the is_global_command

* more Instrments updates

* fixed lint error

* clear line as well

* one other fix

18559 of 31646 branches covered (58.65%)

Branch coverage included in aggregate %.

14730 of 20151 relevant lines covered (73.1%)

1514.33 hits per line

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

72.73
/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)
68✔
51
{
52
  return i.empty() ? 1 : std::stoi(i);
68✔
53
}
54
} // namespace wex
55

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

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

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

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

70
  m_diffs = 0;
11✔
71
  m_type  = diff_t::UNKNOWN;
11✔
72

73
  while (tok_iter != tokens.end())
34✔
74
  {
75
    // skip first lines
76
    SKIP_LINES;
25!
77

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

82
    m_is_first = true;
14✔
83
    m_is_last  = false;
14✔
84
    m_type     = (m_type == diff_t::UNKNOWN ? diff_t::FIRST : diff_t::OTHER);
14✔
85

86
    // Next come one or more hunks of differences
87
    while (tok_iter != tokens.end())
25✔
88
    {
89
      regex r_hunk("@@ -([0-9]+),?([0-9]*) \\+([0-9]+),?([0-9]*) @@.*");
19✔
90

91
      if (r_hunk.match(*tok_iter) != 4)
19✔
92
      {
93
        log("unified_diff") << *tok_iter << r_hunk.size();
2✔
94
        return false;
2✔
95
      }
96

97
      m_range[0] = wex::stoi(r_hunk[0]);
17✔
98
      m_range[1] = wex::stoi(r_hunk[1]);
17✔
99
      m_range[2] = wex::stoi(r_hunk[2]);
17✔
100
      m_range[3] = wex::stoi(r_hunk[3]);
17✔
101

102
      m_text.fill({});
17✔
103

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

108
      if (!report_diff())
17!
109
      {
110
        return false;
×
111
      }
112

113
      trace("hunk");
17✔
114

115
      m_diffs++;
17✔
116

117
      m_is_first = false;
17✔
118
      m_type     = diff_t::OTHER;
17✔
119

120
      if (++tok_iter != tokens.end() && !(*tok_iter).starts_with("@@"))
17!
121
      {
122
        m_is_last = true;
6✔
123

124
        if (!report_diff())
6!
125
        {
126
          return false;
×
127
        }
128
        trace("last");
6✔
129
        m_diffs++;
6✔
130

131
        break; // this was last hunk, continue with header lines
6✔
132
      }
133
    }
19✔
134
  }
135

136
  m_is_last = true;
8✔
137

138
  if (m_type != diff_t::UNKNOWN)
8✔
139
  {
140
    m_type = diff_t::LAST;
6✔
141
    m_diffs--;
6✔
142
  }
143

144
  report_diff_finish();
8✔
145

146
  trace("finished");
8✔
147

148
  return true;
8✔
149
}
11✔
150

151
bool wex::factory::unified_diff::parse_header(
28✔
152
  const std::string& r,
153
  const std::string& line,
154
  path&              p)
155
{
156
  regex re(r);
28✔
157

158
  if (!re.match(line))
28!
159
  {
160
    log("unified_diff") << line << re.match_data().text();
×
161
    return false;
×
162
  }
163

164
  p = path(re[0]);
28✔
165

166
  return true;
28✔
167
}
28✔
168

169
void wex::factory::unified_diff::trace(const std::string& text) const
36✔
170
{
171
  if (log::get_level() != log::level_t::TRACE)
36!
172
  {
173
    return;
36✔
174
  }
175

176
  using boost::describe::operators::operator<<;
177

178
  std::stringstream str;
×
179
  str << "type: " << boost::describe::enum_to_string(m_type, "none") << " "
×
180
      << *this << " ranges: ";
×
181

182
  std::ranges::for_each(
×
183
    m_range,
×
184
    [this, &str](const auto& it)
×
185
    {
186
      str << std::to_string(it) << ",";
×
187
    });
×
188

189
  str << " text sizes: ";
×
190

191
  std::ranges::for_each(
×
192
    m_text,
×
193
    [this, &str](const auto& it)
×
194
    {
195
      str << it.size() << ",";
×
196
    });
×
197

198
  str << " paths: ";
×
199

200
  std::ranges::for_each(
×
201
    m_path,
×
202
    [this, &str](const auto& it)
×
203
    {
204
      str << it.string() << ",";
×
205
    });
×
206

207
  log::trace("unified_diff::" + text) << str.str();
×
208
}
×
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