class EL_COMPACT_SUBSTRINGS_32_ITERATION
Client examples: COMPACT_SUBSTRINGS_32_C_EXTERNAL ; COMPACT_SUBSTRINGS_32_ITERATION_COMPARISON ; ZSTRING_UNICODE_TO_Z_CODE
Stateless character iteration over SPECIAL area in EL_COMPACT_SUBSTRINGS_32
For performance efficiency state is mantained externally in a local INTEGER_32 variable. The state is referenced by the routine argument block_index_ptr: POINTER.
note
description: "[
Stateless character iteration over ${SPECIAL} area in ${EL_COMPACT_SUBSTRINGS_32}
]"
notes: "[
For performance efficiency state is mantained externally in a local ${INTEGER_32} variable.
The state is referenced by the routine argument `block_index_ptr: POINTER'.
]"
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-01-20 19:18:25 GMT (Saturday 20th January 2024)"
revision: "13"
expanded class
EL_COMPACT_SUBSTRINGS_32_ITERATION
inherit
EL_POINTER_ROUTINES
export
{NONE} all
end
EL_ZCODE_CONVERSION
EL_SHARED_IMMUTABLE_32_MANAGER
feature -- Access
code (block_index_ptr: TYPED_POINTER [INTEGER]; area: SPECIAL [CHARACTER_32]; i: INTEGER): NATURAL
do
Result := item (block_index_ptr, area, i).natural_32_code
end
i_th_z_code (
block_index_ptr: TYPED_POINTER [INTEGER]; area: SPECIAL [CHARACTER]
unencoded_area: SPECIAL [CHARACTER_32]; i: INTEGER
): NATURAL
local
c_i: CHARACTER
do
c_i := area [i]
inspect c_i
when Substitute then
Result := item (block_index_ptr, unencoded_area, i + 1).natural_32_code
Result := unicode_to_z_code (Result)
else
Result := c_i.natural_32_code
end
end
index_of (
block_index_ptr: TYPED_POINTER [INTEGER]; area: SPECIAL [CHARACTER_32]; uc: CHARACTER_32; start_index: INTEGER
): INTEGER
-- index of `unicode' starting from `start_index'
local
lower, upper, i, j: INTEGER; found: BOOLEAN
do
i := read_integer_32 (block_index_ptr)
lower := area [i].code
if start_index < lower then
put_integer_32 (0, block_index_ptr)
i := 0
end
from until found or else i = area.count loop
upper := area [i + 1].code
if start_index <= upper then
found := True
else
i := i + upper - area [i].code + 3
end
end
if found then
from until Result > 0 or else i = area.count loop
lower := area [i].code; upper := area [i + 1].code
from j := lower.max (start_index) until Result > 0 or else j > upper loop
if area [i + 2 + j - lower] = uc then
Result := j
end
j := j + 1
end
if Result = 0 then
i := i + upper - lower + 3
end
end
if i = area.count then
put_integer_32 (0, block_index_ptr)
else
put_integer_32 (i, block_index_ptr)
end
end
ensure
valid_result: Result > 0 implies item (block_index_ptr, area, Result) = uc
end
item (block_index_ptr: TYPED_POINTER [INTEGER]; area: SPECIAL [CHARACTER_32]; index: INTEGER): CHARACTER_32
require
at_least_one_block: area.count >= 3
local
i, lower, upper, block_index: INTEGER; found: BOOLEAN
do
block_index := read_integer_32 (block_index_ptr)
lower := area [block_index].code
-- reset to beginning if `index' is prior to current block
if index < lower then
block_index := 0
lower := area [block_index].code
end
upper := area [block_index + 1].code
if index > upper then
i := block_index + upper - lower + 3
from until found or else i = area.count loop
lower := area [i].code; upper := area [i + 1].code
if lower <= index and index <= upper then
block_index := i
found := True
else
i := i + upper - lower + 3
end
end
-- write new block index back to calling routine local
put_integer_32 (block_index, block_index_ptr)
end
Result := area [block_index + 2 + index - lower]
end
block_string (block_index: INTEGER; area: SPECIAL [CHARACTER_32]): IMMUTABLE_STRING_32
-- Shared sub string from `area' at block index pointed to by `block_index_ptr',
-- Returns empty string if block index out of bounds of `area'
require
at_least_one_block: area.count >= 3
local
count, lower, upper: INTEGER
do
if block_index >= area.count then
create Result.make_empty
else
lower := area [block_index].code
upper := area [block_index + 1].code
count := upper - lower + 1
Immutable_32.set_item (area, block_index + 2, count)
Result := Immutable_32.item
end
end
next_index (block_index: INTEGER; str: IMMUTABLE_STRING_32): INTEGER
-- next `block_index' for string returned by `block_string'
do
Result := block_index + 2 + str.count
end
feature -- Comparison
same_caseless_characters (
block_index_ptr: TYPED_POINTER [INTEGER]; area, other_area: SPECIAL [CHARACTER_32]
i, other_i, comparison_count: INTEGER
): BOOLEAN
local
lower, block_index: INTEGER; c32: EL_CHARACTER_32_ROUTINES
do
-- `block_index_ptr' is set as side effect of calling `item'
if c32.to_lower (item (block_index_ptr, area, i)) = c32.to_lower (other_area [other_i]) then
block_index := read_integer_32 (block_index_ptr)
lower := area [block_index].code
Result := c32.same_caseless_sub_array (
area, other_area, block_index + 2 + i - lower, other_i, comparison_count
)
end
end
same_characters (
block_index_ptr: TYPED_POINTER [INTEGER]; area, other_area: SPECIAL [CHARACTER_32]
i, other_i, comparison_count: INTEGER
): BOOLEAN
local
block_index, lower: INTEGER
do
-- `block_index_ptr' is set as side effect of calling `item'
if item (block_index_ptr, area, i) = other_area [other_i] then
block_index := read_integer_32 (block_index_ptr)
lower := area [block_index].code
Result := area.same_items (other_area, other_i, block_index + 2 + i - lower, comparison_count)
end
end
feature -- Contract Support
block_has (area: SPECIAL [CHARACTER_32]; block_index, index: INTEGER): BOOLEAN
-- `True' if `index' is inside the substring interval referenced by `block_index_ptr'
require
area_has_at_least_one_block: area.count >= 3
local
upper, lower: INTEGER
do
lower := area [block_index].code; upper := area [block_index + 1].code
Result := lower <= index and index <= upper
end
feature -- Basic operations
put (area: SPECIAL [CHARACTER_32]; uc: CHARACTER_32; block_index, index: INTEGER)
-- set character at `index' in block referenced by `block_index_ptr'
require
valid_block_reference: block_has (area, block_index, index)
local
lower: INTEGER
do
lower := area [block_index].code
area [block_index + 2 + index - lower] := uc
ensure
character_set: item ($block_index, area, index) = uc
end
end