Packages
ra
2.16.7
3.1.9
3.1.8
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.2
3.0.1
3.0.0
3.0.0-beta.1
2.17.3
2.17.2
2.17.1
2.17.0
2.16.13
2.16.12
2.16.11
2.16.10
2.16.9
2.16.8
2.16.7
2.16.6
2.16.5
2.16.4
2.16.3
2.16.2
2.16.1
2.16.0
2.16.0-pre.12
2.16.0-pre.11
2.16.0-pre.10
2.16.0-pre.9
2.16.0-pre.8
2.16.0-pre.7
2.16.0-pre.6
2.16.0-pre.5
2.16.0-pre.4
2.16.0-pre.3
2.16.0-pre.2
2.16.0-pre.1
2.15.4
2.15.3
2.15.2
2.15.1
2.15.0
2.14.0
2.13.6
2.13.5
2.13.4
2.13.3
2.13.2
2.13.1
2.13.0
2.13.0-pre.1
2.12.0
2.11.0
2.11.0-pre.1
2.10.2-pre.2
2.10.2-pre.1
2.10.1
2.10.0
2.10.0-pre.3
2.10.0-pre.2
2.10.0-pre.1
2.9.10-pre.1
2.9.1
2.9.1-pre.2
2.9.1-pre.1
2.9.0
2.8.0
retired
2.7.3
2.7.2
2.7.1
2.7.0
2.7.0-pre.3
2.7.0-pre.2
2.7.0-pre.1
2.6.3
2.6.2
2.6.1
2.6.0-pre.1
2.5.1
2.5.1-pre.1
2.5.0
2.4.9
2.4.8
2.4.7
2.4.6
2.4.5
2.4.4
2.4.3
2.4.2
retired
2.4.1
2.4.0
2.3.0
2.2.0
2.1.0
2.0.13
2.0.12
2.0.11
2.0.10
2.0.9
2.0.8
2.0.7
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.9.6
0.9.5
0.9.4
0.9.2
0.3.3
retired
0.3.2
retired
0.3.1
retired
Raft library
Current section
Files
Jump to
Current section
Files
src/ra_range.erl
%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
%%
%% Copyright (c) 2017-2023 Broadcom. All Rights Reserved. The term Broadcom refers to Broadcom Inc. and/or its subsidiaries.
%%
%% @hidden
-module(ra_range).
-export([
new/1,
new/2,
add/2,
in/2,
extend/2,
limit/2,
truncate/2,
size/1,
overlap/2,
subtract/2
]).
-type range() :: undefined | {ra:index(), ra:index()}.
-export_type([range/0]).
-spec new(ra:index()) -> range().
new(Start) when is_integer(Start) ->
{Start, Start}.
-spec new(ra:index(), ra:index()) -> range().
new(Start, End)
when is_integer(Start) andalso
is_integer(End) andalso
Start =< End ->
{Start, End};
new(_Start, _End) ->
undefined.
-spec add(AddRange :: range(), CurRange :: range()) -> range().
add(undefined, Range) ->
Range;
add({AddStart, AddEnd}, {Start, End})
when Start =< AddEnd + 1 andalso
End + 1 >= AddStart ->
{min(AddStart, Start), max(AddEnd, End)};
add(AddRange, _Range) ->
%% no overlap, return add range
AddRange.
-spec in(ra:index(), range()) -> boolean().
in(_Idx, undefined) ->
false;
in(Idx, {Start, End}) ->
Idx >= Start andalso Idx =< End.
-spec limit(ra:index(), range()) -> range().
limit(CeilExcl, {Start, _End})
when is_integer(CeilExcl) andalso
CeilExcl =< Start ->
undefined;
limit(CeilExcl, {Start, End})
when is_integer(CeilExcl) andalso
CeilExcl =< End ->
{Start, CeilExcl - 1};
limit(CeilExcl, Range)
when is_integer(CeilExcl) ->
Range.
-spec truncate(ra:index(), range()) -> range().
truncate(UpToIncl, {_Start, End})
when is_integer(UpToIncl) andalso
UpToIncl >= End ->
undefined;
truncate(UpToIncl, {Start, End})
when is_integer(UpToIncl) andalso
UpToIncl >= Start ->
{UpToIncl + 1, End};
truncate(UpToIncl, Range)
when is_integer(UpToIncl) ->
Range.
size(undefined) ->
0;
size({Start, End}) ->
End - Start + 1.
-spec extend(ra:index(), range()) -> range().
extend(Idx, {Start, End})
when Idx == End + 1 ->
{Start, Idx};
extend(Idx, undefined) when is_integer(Idx) ->
ra_range:new(Idx);
extend(Idx, Range) ->
error({cannot_extend, Idx, Range}).
-spec overlap(range(), range()) -> range().
overlap({ReqStart, ReqEnd}, {Start, End}) ->
new(max(ReqStart, Start), min(ReqEnd, End));
overlap(_Range1, _Range2) ->
undefined.
%% @doc subtracts the range in the first argument
%% from that of the range in the second arg.
%% Returns a list of remaining ranges
%% @end
-spec subtract(range(), range()) -> [range()].
subtract(_Range1, undefined) ->
[];
subtract(undefined, Range) ->
[Range];
subtract({_SubStart, _SubEnd} = SubRange, {Start, End} = Range) ->
case overlap(SubRange, Range) of
undefined ->
[Range];
{OStart, OEnd} ->
[R || {_, _} = R <- [new(Start, OStart -1),
new(OEnd + 1, End)]]
end.
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
subtract_test() ->
?assertEqual([], subtract({1, 10}, undefined)),
?assertEqual([{1, 10}], subtract(undefined, {1, 10})),
?assertEqual([], subtract({1, 10}, {1, 10})),
?assertEqual([], subtract({1, 10}, {4, 6})),
?assertEqual([{4, 6}], subtract({8, 10}, {4, 6})),
?assertEqual([{11, 20}], subtract({1, 10}, {1, 20})),
?assertEqual([{1, 1}, {11, 20}], subtract({2, 10}, {1, 20})),
?assertEqual([{1, 9}], subtract({10, 20}, {1, 20})),
ok.
overlap_test() ->
?assertEqual(undefined, overlap({1, 10}, undefined)),
?assertEqual(undefined, overlap(undefined, {1, 10})),
?assertEqual(undefined, overlap({1, 10}, {11, 15})),
?assertEqual(undefined, overlap({16, 20}, {11, 15})),
?assertEqual({11, 11}, overlap({1, 11}, {11, 15})),
?assertEqual({14, 15}, overlap({14, 20}, {11, 15})),
?assertEqual({12, 14}, overlap({12, 14}, {11, 15})),
?assertEqual({11, 15}, overlap({1, 20}, {11, 15})),
ok.
add_test() ->
?assertEqual(undefined, add(undefined, undefined)),
?assertEqual({1, 10}, add(undefined, {1, 10})),
?assertEqual({1, 10}, add({1, 10}, undefined)),
?assertEqual({1, 20}, add({1, 10}, {11, 20})),
?assertEqual({1, 20}, add({1, 10}, {5, 20})),
?assertEqual({1, 10}, add({1, 10}, {5, 9})),
?assertEqual({5, 10}, add({6, 10}, {5, 9})),
?assertEqual({1, 10}, add({6, 10}, {1, 5})),
%% when the add range is smaller than the prior range
%% return the additional range
?assertEqual({1, 3}, add({1, 3}, {6, 10})),
?assertEqual({1, 10}, add({6, 10}, {1, 7})),
ok.
truncate_test() ->
?assertEqual(undefined, truncate(9, undefined)),
?assertEqual({6, 10}, truncate(5, {1, 10})),
?assertEqual(undefined, truncate(11, {1, 10})),
?assertEqual({10, 20}, truncate(9, {10, 20})),
ok.
limit_test() ->
?assertEqual(undefined, limit(9, undefined)),
?assertEqual({1, 4}, limit(5, {1, 10})),
?assertEqual({1, 10}, limit(11, {1, 10})),
?assertEqual(undefined, limit(10, {10, 20})),
?assertEqual(undefined, limit(1, {10, 20})),
ok.
in_test() ->
?assertEqual(false, in(9, undefined)),
?assertEqual(true, in(5, {1, 10})),
?assertEqual(true, in(10, {1, 10})),
?assertEqual(true, in(1, {1, 10})),
?assertEqual(false, in(11, {1, 10})),
?assertEqual(false, in(0, {1, 10})),
ok.
extend_test() ->
?assertEqual({9, 9}, extend(9, undefined)),
?assertEqual({1, 11}, extend(11, {1, 10})),
?assertError({cannot_extend, 1, {5, 10}}, extend(1, {5, 10})),
?assertError({cannot_extend, 12, {1, 10}}, extend(12, {1, 10})),
ok.
-endif.