class EL_REPEATED_NUMERIC_LIST
Client examples: BASE_AUTOTEST_APP
Object that uses run length encoding to data compress a sequence of numeric values that tend to repeat a lot.
note
description: "[
Object that uses run length encoding to data compress a sequence of numeric values that tend to repeat a lot.
]"
author: "Finnian Reilly"
copyright: "Copyright (c) 2001-2022 Finnian Reilly"
contact: "finnian at eiffel hyphen loop dot com"
license: "MIT license (See: en.wikipedia.org/wiki/MIT_License)"
date: "2022-11-15 19:56:04 GMT (Tuesday 15th November 2022)"
revision: "4"
class
EL_REPEATED_NUMERIC_LIST [G -> NUMERIC]
inherit
LIST [G]
export
{NONE} all
{ANY} item, readable, off, before, after, go_i_th, valid_cursor_index
redefine
start, finish, go_i_th, move
end
create
make
feature {NONE} -- Initialization
make (repeated_item_count: INTEGER)
-- Create an empty list.
do
create compact_list.make (repeated_item_count)
end
feature -- Access
item: G
-- Current item
do
Result := compact_list.item.value
end
index: INTEGER
count: INTEGER
compact_count: INTEGER
--
do
Result := compact_list.count
end
feature -- Status report
extendible: BOOLEAN
-- May new items be added? (Answer: yes.)
do
Result := true
end
prunable: BOOLEAN
-- May items be removed? (Answer: yes.)
do
Result := False
end
full: BOOLEAN = False
feature -- Cursor movement
start
-- Move cursor to first position.
-- (No effect if empty)
do
if not compact_list.is_empty then
compact_list.start
index := 1
repeat_offset := 1
end
end
finish
-- Move cursor to last position.
-- (No effect if empty)
do
if not compact_list.is_empty then
index := count
compact_list.finish
repeat_offset := compact_list.item.count
end
end
back
--
do
if not compact_list.off then
repeat_offset := repeat_offset - 1
index := index - 1
if repeat_offset = 0 then
compact_list.back
if not compact_list.before then
repeat_offset := compact_list.item.count
end
end
end
end
forth
--
do
if not compact_list.off then
repeat_offset := repeat_offset + 1
index := index + 1
if repeat_offset > compact_list.item.count then
compact_list.forth
if not compact_list.after then
repeat_offset := 1
end
end
end
end
go_i_th (i: INTEGER_32)
--
do
if index = 0 or i = 1 then
start
end
if i > 1 then
Precursor (i)
end
end
move (i: INTEGER)
-- Move cursor `i' positions. The cursor
-- may end up `off' if the absolute value of `i'
-- is too big.
local
delta: INTEGER
do
if i > 0 then
from
delta := i
until
compact_list.after or else delta <= (compact_list.item.count - repeat_offset)
loop
delta := delta - (compact_list.item.count - repeat_offset + 1)
index := index + (compact_list.item.count - repeat_offset + 1)
compact_list.forth
repeat_offset := 1
end
Precursor (delta)
elseif i < 0 then
from
delta := i.abs
until
compact_list.before or else delta < repeat_offset
loop
delta := delta - repeat_offset
index := index - repeat_offset
compact_list.back
if not compact_list.before then
repeat_offset := compact_list.count
end
end
Precursor (-delta)
if index < 0 then
index := 0
end
end
end
feature -- Iteration
repeated_numerics_do_all (action: PROCEDURE [EL_REPEATED_NUMERIC [G]])
--
do
compact_list.do_all (action)
end
feature -- Element change
extend (v: like item)
-- Add `v' to end.
-- Do not move cursor.
do
if not compact_list.is_empty and then v = compact_list.last.value and then
not compact_list.last.maximum_reached
then
compact_list.last.increment
else
compact_list.extend (create {EL_REPEATED_NUMERIC [G]}.make (v))
end
count := count + 1
end
extend_repeated_numeric (repeated_numeric: EL_REPEATED_NUMERIC [G])
--
do
compact_list.extend (repeated_numeric)
count := count + repeated_numeric.count
end
wipe_out
-- Remove all items.
do
compact_list.wipe_out
count := 0
repeat_offset := 0
index := 0
end
feature {NONE} -- Unused
valid_cursor (p: CURSOR): BOOLEAN
--
do
end
cursor: CURSOR
replace (v: like item)
-- Replace current item by `v'.
do
end
duplicate (n: INTEGER): like Current
--
do
end
go_to (p: CURSOR)
--
do
end
feature {NONE} -- Implementation
repeat_offset: INTEGER
compact_list: ARRAYED_LIST [EL_REPEATED_NUMERIC [G]]
end