Skip to content

Commit 02707cb

Browse files
authored
Merge pull request #3030 from tautschnig/format-number-range
Rewrite format_number_range
2 parents 5202f4a + 70d1a85 commit 02707cb

File tree

4 files changed

+82
-89
lines changed

4 files changed

+82
-89
lines changed

src/util/format_number_range.cpp

Lines changed: 43 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -10,107 +10,62 @@ Author: Daniel Kroening, [email protected]
1010
/// Format vector of numbers into a compressed range
1111

1212
#include <algorithm>
13-
#include <cassert>
13+
#include <sstream>
1414
#include <string>
1515

16+
#include "invariant.h"
17+
1618
#include "format_number_range.h"
1719

1820
/// create shorter representation for output
19-
/// \param parameters: vector of numbers
21+
/// \param input_numbers: vector of numbers
2022
/// \return string of compressed number range representation
21-
std::string format_number_range(std::vector<unsigned> &numbers)
23+
std::string format_number_range(const std::vector<unsigned> &input_numbers)
2224
{
23-
std::string number_range;
25+
PRECONDITION(!input_numbers.empty());
26+
27+
std::vector<unsigned> numbers(input_numbers);
2428
std::sort(numbers.begin(), numbers.end());
2529
unsigned end_number=numbers.back();
2630
if(numbers.front()==end_number)
27-
number_range=std::to_string(end_number); // only single number
28-
else
31+
return std::to_string(end_number); // only single number
32+
33+
std::stringstream number_range;
34+
35+
auto start_number = numbers.front();
36+
37+
for(std::vector<unsigned>::const_iterator it = numbers.begin();
38+
it != numbers.end();
39+
++it)
2940
{
30-
bool next=true;
31-
bool first=true;
32-
bool range=false;
33-
unsigned start_number=numbers.front();
34-
unsigned last_number=start_number;
41+
const auto number = *it;
42+
const auto next = std::next(it);
43+
44+
// advance one forward
45+
if(next != numbers.end() && *next <= number + 1)
46+
continue;
47+
48+
// end this block range
49+
if(start_number != numbers.front())
50+
number_range << ',';
3551

36-
for(const auto &number : numbers)
52+
if(number == start_number)
3753
{
38-
if(next)
39-
{
40-
next=false;
41-
start_number=number;
42-
last_number=number;
43-
}
44-
// advance one forward
45-
else
46-
{
47-
if(number==last_number+1 && !(number==end_number))
48-
{
49-
last_number++;
50-
if(last_number>start_number+1)
51-
range=true;
52-
}
53-
// end this block range
54-
else
55-
{
56-
if(first)
57-
first=false;
58-
else
59-
number_range+=",";
60-
if(last_number>start_number)
61-
{
62-
if(range)
63-
{
64-
if(number==end_number && number==last_number+1)
65-
number_range+=
66-
std::to_string(start_number)+"-"+std::to_string(end_number);
67-
else if(number==end_number)
68-
number_range+=
69-
std::to_string(start_number)+"-"+std::to_string(last_number)+
70-
","+std::to_string(end_number);
71-
else
72-
number_range+=
73-
std::to_string(start_number)+"-"+std::to_string(last_number);
74-
}
75-
else
76-
{
77-
if(number!=end_number)
78-
number_range+=
79-
std::to_string(start_number)+","+std::to_string(last_number);
80-
else
81-
{
82-
if(start_number+1==last_number && last_number+1==number)
83-
number_range+=
84-
std::to_string(start_number)+"-"+std::to_string(end_number);
85-
else
86-
number_range+=
87-
std::to_string(start_number)+
88-
","+std::to_string(last_number)+
89-
","+std::to_string(end_number);
90-
}
91-
}
92-
start_number=number;
93-
last_number=number;
94-
range=false;
95-
continue;
96-
}
97-
else
98-
{
99-
if(number!=end_number)
100-
number_range+=std::to_string(start_number);
101-
else
102-
number_range+=std::to_string(start_number)+","+
103-
std::to_string(end_number);
104-
start_number=number;
105-
last_number=number;
106-
range=false;
107-
continue; // already set next start number
108-
}
109-
next=true;
110-
}
111-
}
54+
number_range << number;
11255
}
56+
else if(number == start_number + 1)
57+
{
58+
number_range << start_number << ',' << number;
59+
}
60+
else
61+
{
62+
number_range << start_number << '-' << number;
63+
}
64+
65+
if(next != numbers.end())
66+
start_number = *next;
11367
}
114-
assert(!number_range.empty());
115-
return number_range;
68+
69+
CHECK_RETURN(!number_range.str().empty());
70+
return number_range.str();
11671
}

src/util/format_number_range.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ Author: Daniel Kroening, [email protected]
1515
#include <string>
1616
#include <vector>
1717

18-
std::string format_number_range(std::vector<unsigned> &);
18+
std::string format_number_range(const std::vector<unsigned> &);
1919

2020
#endif // CPROVER_UTIL_FORMAT_NUMBER_RANGE_H

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ SRC += analyses/ai/ai.cpp \
3232
util/expr_cast/expr_cast.cpp \
3333
util/expr.cpp \
3434
util/file_util.cpp \
35+
util/format_number_range.cpp \
3536
util/get_base_name.cpp \
3637
util/graph.cpp \
3738
util/irep.cpp \

unit/util/format_number_range.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*******************************************************************\
2+
3+
Module: format_number_range unit tests
4+
5+
Author: Michael Tautschnig
6+
7+
\*******************************************************************/
8+
9+
#include <testing-utils/catch.hpp>
10+
11+
#include <util/format_number_range.h>
12+
13+
TEST_CASE(
14+
"Format a range of unsigned numbers",
15+
"[core][util][format_number_range]")
16+
{
17+
const std::vector<unsigned> singleton = {1u};
18+
REQUIRE(format_number_range(singleton) == "1");
19+
20+
const std::vector<unsigned> r1 = {0u, 42u};
21+
REQUIRE(format_number_range(r1) == "0,42");
22+
23+
const std::vector<unsigned> r2 = {0u, 1u};
24+
REQUIRE(format_number_range(r2) == "0,1");
25+
26+
const std::vector<unsigned> r3 = {1u, 2u, 3u};
27+
REQUIRE(format_number_range(r3) == "1-3");
28+
29+
const std::vector<unsigned> r4 = {1u, 3u, 4u, 5u};
30+
REQUIRE(format_number_range(r4) == "1,3-5");
31+
32+
const std::vector<unsigned> r5 = {1u, 10u, 11u, 12u, 42u};
33+
REQUIRE(format_number_range(r5) == "1,10-12,42");
34+
35+
const std::vector<unsigned> r6 = {1u, 10u, 11u, 12u, 42u, 43u, 44u};
36+
REQUIRE(format_number_range(r6) == "1,10-12,42-44");
37+
}

0 commit comments

Comments
 (0)