class EL_COMPACT_SUBSTRINGS_32_IMPLEMENTATION
Implementation routines for EL_COMPACT_SUBSTRINGS_32
note
description: "Implementation routines for ${EL_COMPACT_SUBSTRINGS_32}"
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: "2024-08-27 7:30:43 GMT (Tuesday 27th August 2024)"
revision: "34"
deferred class
EL_COMPACT_SUBSTRINGS_32_IMPLEMENTATION
inherit
EL_EXTENDABLE_AREA [CHARACTER_32]
EL_STRING_HANDLER
EL_INTERVAL_CONSTANTS
export
{NONE} all
end
EL_SHARED_IMMUTABLE_32_MANAGER
EL_ZCODE_CONVERSION
feature -- Contract Support
contains_all_intervals (interval_list: EL_ARRAYED_INTERVAL_LIST): BOOLEAN
do
if attached interval_list as list then
Result := True
from list.start until not Result or list.after loop
Result := contains_interval (list.item_lower, list.item_upper)
list.forth
end
end
end
contains_interval (lower_A, upper_A: INTEGER): BOOLEAN
local
ir: EL_INTERVAL_ROUTINES; l_area: like area
i, lower_B, upper_B: INTEGER
do
l_area := area
from i := 0 until Result or else i = l_area.count loop
lower_B := l_area [i].code; upper_B := l_area [i + 1].code
Result := ir.overlap_status (lower_A, upper_A, lower_B, upper_B) = B_contains_A
i := i + upper_B - lower_B + 3
end
end
interval_sequence: EL_SEQUENTIAL_INTERVALS
local
i, lower, upper: INTEGER; l_area: like area
do
create Result.make (3)
l_area := area
from i := 0 until i = l_area.count loop
lower := l_area [i].code; upper := l_area [i + 1].code
Result.extend (lower, upper)
i := i + upper - lower + 3
end
end
is_valid: BOOLEAN
-- `True' if all intervals valid and in sequence and consistent with size of `area'
local
i, lower, upper, count, previous_upper, i_final: INTEGER; l_area: like area
do
l_area := area; i_final := l_area.count
Result := True
from i := 0 until not Result or else i = i_final loop
lower := l_area [i].code; upper := l_area [i + 1].code
count := upper - lower + 1
Result := lower <= upper and then lower > previous_upper and then i + count + 2 <= i_final
previous_upper := upper
i := i + count + 2
end
end
substring_list: SPECIAL [STRING_32]
-- Debugging output
local
i, j, lower, upper, count, i_final: INTEGER; l_area: like area
list: ARRAYED_LIST [STRING_32]; string: STRING_32
do
create list.make (10)
l_area := area; i_final := l_area.count
from i := 0 until i = i_final loop
lower := l_area [i].code; upper := l_area [i + 1].code
count := upper - lower + 1
create string.make (count + 8)
string.append_integer (lower)
string.append_character ('-')
string.append_integer (upper)
string.append_string_general (": ")
from j := 1 until j > count loop
string.extend (l_area.item (i + 1 + j).to_character_32)
j := j + 1
end
list.extend (string)
i := i + count + 2
end
Result := list.area_v2
end
feature {NONE} -- Deferred
character_count: INTEGER
deferred
end
feature {NONE} -- Implementation
change_case (as_lower_case: BOOLEAN)
local
i, j, index, count, i_final: INTEGER; l_area: like area
c, new_c: CHARACTER_32
do
l_area := area; i_final := l_area.count
from i := 0 until i = i_final loop
count := section_count (l_area, i)
from j := 1 until j > count loop
index := i + 1 + j
c := l_area.item (index).to_character_32
if as_lower_case then
new_c := c.as_lower
else
new_c := c.as_upper
end
if c /= new_c then
l_area [index] := new_c
end
j := j + 1
end
i := i + count + 2
end
end
empty_buffer: EL_COMPACT_SUBSTRINGS_32_BUFFER
do
Result := Buffer
Result.wipe_out
end
extend_bounds (a_area: like area; lower, upper: INTEGER)
do
a_area.extend (lower.to_character_32)
a_area.extend (upper.to_character_32)
end
extended_enough (a_area: like area; destination_index, lower, upper: INTEGER; uc: CHARACTER_32): like area
local
l_insert: like area
do
l_insert := Unencoded_insert; l_insert.wipe_out
if lower > 0 then
l_insert.extend (lower.to_character_32)
end
if upper > 0 then
l_insert.extend (upper.to_character_32)
end
if uc > '%U' then
l_insert.extend (uc)
end
Result := big_enough (a_area, l_insert.count)
Result.insert_data (l_insert, 0, destination_index, l_insert.count)
end
index_list: ARRAYED_LIST [INTEGER]
local
i, i_final: INTEGER; l_area: like area
do
Result := Once_index_list.emptied
l_area := area; i_final := l_area.count
from i := 0 until i = i_final loop
Result.extend (i)
i := i + section_count (l_area, i) + 2
end
end
index_of_overlapping (a_area: like area; lower_A, upper_A: INTEGER): INTEGER
-- index of first substring overlapping interval `lower_A .. upper_A'
-- or else `a_area.count' if not found
local
found: BOOLEAN; ir: EL_INTERVAL_ROUTINES
i, lower_B, upper_B, overlap_status: INTEGER
do
if a_area.count > 0 and then upper_A >= a_area [0].code then
from i := 0 until found or i = a_area.count loop
lower_B := a_area [i].code; upper_B := a_area [i + 1].code
overlap_status := ir.overlap_status (lower_A, upper_A, lower_B, upper_B)
if ir.is_overlapping (overlap_status) then
found := True
else
i := i + upper_B - lower_B + 3
end
end
else
Result := a_area.count
end
Result := i
end
interval_count (a_area: like area; start_index: INTEGER): INTEGER
do
if a_area.valid_index (start_index) then
Result := a_area [start_index - 1].code - a_area [start_index - 2].code + 1
end
end
null: TYPED_POINTER [INTEGER]
do
end
put_lower (a_area: like area; i, lower: INTEGER)
do
a_area.put (lower.to_character_32, i)
end
put_upper (a_area: like area; i, upper: INTEGER)
do
a_area.put (upper.to_character_32, i + 1)
end
remove_section (a_area: like area; i, lower, upper, start_index, end_index, deleted_count: INTEGER): INTEGER
local
count_to_remove, source_index, destination_index: INTEGER
do
count_to_remove := end_index - start_index + 1
if lower = start_index and then upper = end_index then
destination_index := i
count_to_remove := count_to_remove + 2
else
destination_index := i + 2 + start_index - lower
end
source_index := destination_index + count_to_remove
a_area.overlapping_move (source_index, destination_index, a_area.count - source_index)
a_area.remove_tail (count_to_remove)
if destination_index > i then
if start_index = lower then
-- Remove from start
a_area [i] := (lower + count_to_remove - deleted_count).to_character_32
a_area [i + 1] := (upper - deleted_count).to_character_32
else
a_area [i + 1] := (upper - count_to_remove).to_character_32
end
end
Result := count_to_remove
end
section_count (a_area: like area; i: INTEGER): INTEGER
do
Result := a_area [i + 1].code - a_area [i].code + 1
end
feature {NONE} -- `count_greater_than_zero_flags' values
Both_have_mixed_encoding: INTEGER = 3
Neither: INTEGER = 0
Only_current: INTEGER = 2
Only_other: INTEGER = 1
feature {NONE} -- Constants
Buffer: EL_COMPACT_SUBSTRINGS_32_BUFFER
once
create Result.make
end
Empty_unencoded: SPECIAL [CHARACTER_32]
once
create Result.make_empty (0)
end
Minimum_capacity: INTEGER = 3
Once_index_list: EL_ARRAYED_LIST [INTEGER]
once
create Result.make (5)
end
Unencoded_insert: SPECIAL [CHARACTER_32]
once
create Result.make_empty (3)
end
end