Skip to content

Commit 9da2c85

Browse files
committed
Merge branch 'master' into develop
2 parents 719fea7 + ee34494 commit 9da2c85

9 files changed

Lines changed: 201 additions & 167 deletions

src/base/humanize.cc

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ try_from(const string_fragment& sf)
5656
};
5757

5858
static const auto code = lnav::pcre2pp::code::from_const(
59-
R"(^\s*(?:([\-\+]?\d+)|([\-\+]?\d+\.\d+(?:[eE][\-\+]\d+)?)|([\-\+]?\d+(?:\.\d+)?\s*[KMGTPE]?[Bb](?:ps)?)|([\-\+]?\d+(?:\.\d+)?\s*[munpf]?)s|(\d{1,2}:\d{2}:\d{2}(?:\.\d{1,6})?)|(\d{1,2}:\d{2}(?:\.\d{1,6})?))\s*$)");
59+
R"(^\s*(?:([\-\+]?\d+)|([\-\+]?\d+\.\d+(?:[eE][\-\+]\d+)?)|([\-\+]?\d+(?:\.\d+)?\s*(?:[KMGTPE]i?)?[Bb](?:ps)?)|([\-\+]?\d+(?:\.\d+)?\s*[munpf]?)s|(\d{1,2}:\d{2}:\d{2}(?:\.\d{1,6})?)|(\d{1,2}:\d{2}(?:\.\d{1,6})?))\s*$)");
6060
thread_local auto md = lnav::pcre2pp::match_data::unitialized();
6161

6262
if (!code.capture_from(sf).into(md).found_p()) {
@@ -92,19 +92,25 @@ try_from(const string_fragment& sf)
9292
while (isspace(unit_range[start])) {
9393
start += 1;
9494
}
95+
// IEC `KiB`/`MiB`/... use 1024-multipliers; the bare
96+
// `KB`/`MB`/... forms use the strict SI 1000-multipliers.
97+
const double mult
98+
= (start + 1 < unit_range.size() && unit_range[start + 1] == 'i')
99+
? 1024.0
100+
: 1000.0;
95101
switch (unit_range[start]) {
96102
case 'E':
97-
retval *= 1024.0;
103+
retval *= mult;
98104
case 'P':
99-
retval *= 1024.0;
105+
retval *= mult;
100106
case 'T':
101-
retval *= 1024.0;
107+
retval *= mult;
102108
case 'G':
103-
retval *= 1024.0;
109+
retval *= mult;
104110
case 'M':
105-
retval *= 1024.0;
111+
retval *= mult;
106112
case 'K':
107-
retval *= 1024.0;
113+
retval *= mult;
108114
break;
109115
}
110116
}
@@ -161,7 +167,7 @@ try_from(const string_fragment& sf)
161167
std::string
162168
file_size(file_ssize_t value, alignment align)
163169
{
164-
static const double LN1024 = std::log(1024.0);
170+
static const double LN1000 = std::log(1000.0);
165171
static constexpr std::array<const char*, 7> UNITS = {
166172
" ",
167173
"K",
@@ -186,8 +192,8 @@ file_size(file_ssize_t value, alignment align)
186192
}
187193

188194
const auto exp
189-
= floor(std::min(log(value) / LN1024, (double) (UNITS.size() - 1)));
190-
const auto divisor = pow(1024, exp);
195+
= floor(std::min(log(value) / LN1000, (double) (UNITS.size() - 1)));
196+
const auto divisor = pow(1000, exp);
191197

192198
if (align == alignment::none && divisor <= 1) {
193199
return fmt::format(FMT_STRING("{}B"), value);

src/base/humanize.file_size.tests.cc

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,15 @@ TEST_CASE("humanize::file_size")
3838
{
3939
CHECK(humanize::file_size(0, humanize::alignment::columnar) == "0.0 B");
4040
CHECK(humanize::file_size(1, humanize::alignment::columnar) == "1.0 B");
41-
CHECK(humanize::file_size(1024, humanize::alignment::columnar) == "1.0KB");
41+
CHECK(humanize::file_size(1000, humanize::alignment::columnar) == "1.0KB");
4242
CHECK(humanize::file_size(1500, humanize::alignment::columnar) == "1.5KB");
43-
CHECK(humanize::file_size(55LL * 784LL * 1024LL * 1024LL,
44-
humanize::alignment::columnar)
43+
CHECK(humanize::file_size(42100000000LL, humanize::alignment::columnar)
4544
== "42.1GB");
4645
CHECK(humanize::file_size(-1LL, humanize::alignment::columnar)
4746
== "Unknown");
4847
CHECK(humanize::file_size(std::numeric_limits<int64_t>::max(),
4948
humanize::alignment::columnar)
50-
== "8.0EB");
49+
== "9.2EB");
5150
}
5251

5352
TEST_CASE("humanize::try_from")
@@ -67,18 +66,50 @@ TEST_CASE("humanize::try_from")
6766
CHECK(try_res.value() == 123.456);
6867
}
6968
{
69+
// SI prefix forms now use strict 1000-multipliers.
7070
auto file_size = string_fragment::from_const(" 123.4GB");
7171
auto try_res = humanize::try_from<double>(file_size);
7272

7373
CHECK(try_res.has_value());
74-
CHECK(try_res.value() == 123.4 * 1024 * 1024 * 1024);
74+
CHECK(try_res.value() == 123.4 * 1000 * 1000 * 1000);
7575
}
7676
{
7777
auto file_size = string_fragment::from_const(" 123.4 GB");
7878
auto try_res = humanize::try_from<double>(file_size);
7979

8080
CHECK(try_res.has_value());
81-
CHECK(try_res.value() == 123.4 * 1024 * 1024 * 1024);
81+
CHECK(try_res.value() == 123.4 * 1000 * 1000 * 1000);
82+
}
83+
{
84+
// IEC "bibyte" prefixes should parse to the same numeric value
85+
// as the informal K/M/G/T/P/E spellings already supported.
86+
auto file_size = string_fragment::from_const("4KiB");
87+
auto try_res = humanize::try_from<double>(file_size);
88+
89+
CHECK(try_res.has_value());
90+
CHECK(try_res.value() == 4.0 * 1024);
91+
}
92+
{
93+
auto file_size = string_fragment::from_const(" 2.5 MiB");
94+
auto try_res = humanize::try_from<double>(file_size);
95+
96+
CHECK(try_res.has_value());
97+
CHECK(try_res.value() == 2.5 * 1024 * 1024);
98+
}
99+
{
100+
auto file_size = string_fragment::from_const("1 GiB");
101+
auto try_res = humanize::try_from<double>(file_size);
102+
103+
CHECK(try_res.has_value());
104+
CHECK(try_res.value() == 1.0 * 1024 * 1024 * 1024);
105+
}
106+
{
107+
// "iB" alone (with no prefix letter) should not parse as a
108+
// size — the `i` marker is only meaningful after K/M/G/T/P/E.
109+
auto bad = string_fragment::from_const("5iB");
110+
auto try_res = humanize::try_from<double>(bad);
111+
112+
CHECK(!try_res.has_value());
82113
}
83114
{
84115
auto secs = string_fragment::from_const("1.2s");

src/internals/sql-ref.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1777,7 +1777,7 @@ humanize_file_size(*value*)
17771777
.. code-block:: custsqlite
17781778

17791779
;SELECT humanize_file_size(10 * 1024 * 1024)
1780-
10.0MB
1780+
10.5MB
17811781

17821782
**See Also**
17831783
:ref:`anonymize`, :ref:`char`, :ref:`charindex`, :ref:`concat_ws`, :ref:`concat`, :ref:`decode`, :ref:`encode`, :ref:`endswith`, :ref:`extract`, :ref:`fuzzy_match`, :ref:`group_concat`, :ref:`group_spooky_hash_agg`, :ref:`gunzip`, :ref:`gzip`, :ref:`humanize_duration`, :ref:`humanize_id`, :ref:`instr`, :ref:`leftstr`, :ref:`length`, :ref:`logfmt2json`, :ref:`lower`, :ref:`ltrim`, :ref:`padc`, :ref:`padl`, :ref:`padr`, :ref:`parse_url`, :ref:`pretty_print`, :ref:`printf`, :ref:`proper`, :ref:`regexp_capture_into_json`, :ref:`regexp_capture`, :ref:`regexp_match`, :ref:`regexp_replace`, :ref:`replace`, :ref:`replicate`, :ref:`reverse`, :ref:`rightstr`, :ref:`rtrim`, :ref:`sparkline`, :ref:`spooky_hash`, :ref:`startswith`, :ref:`strfilter`, :ref:`substr`, :ref:`timezone`, :ref:`trim`, :ref:`unhex`, :ref:`unicode`, :ref:`unparse_url`, :ref:`upper`, :ref:`xpath`

src/line_buffer.cc

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,6 @@ line_buffer::fill_range(file_off_t start,
820820
scan_direction dir)
821821
{
822822
auto retval = false;
823-
auto got_preload = false;
824823

825824
require(start >= 0);
826825

@@ -871,11 +870,9 @@ line_buffer::fill_range(file_off_t start,
871870
this->lb_stats.s_used_preloads += 1;
872871
this->lb_next_line_start_index = 0;
873872
this->lb_next_buffer_offset = 0;
874-
got_preload = true;
875873
}
876874
if (this->in_range(start)
877-
&& (got_preload || max_length == 0
878-
|| this->in_range(start + max_length - 1)))
875+
&& (max_length == 0 || this->in_range(start + max_length - 1)))
879876
{
880877
// log_debug("fd(%d) cached!", this->lb_fd.get());
881878
/* Cache already has the data, nothing to do. */

test/expected/test_cmds.sh_b6a3bb78e9d60e5e1f5ce5b18e40d2f1662707ab.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3160,7 +3160,7 @@ For support questions, email:
31603160
Example
31613161
#1 To format an amount:
31623162
;SELECT humanize_file_size(10 * 1024 * 1024) 
3163-
10.0MB
3163+
10.5MB
31643164

31653165

31663166
humanize_id(id)

0 commit comments

Comments
 (0)