class EL_BASE_POWER_2_CONVERTER
Convert binary, octal or hexadecimal strings to NUMERIC types
note
description: "Convert binary, octal or hexadecimal strings to ${NUMERIC} types"
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-25 7:44:01 GMT (Sunday 25th August 2024)"
revision: "12"
deferred class
EL_BASE_POWER_2_CONVERTER
inherit
ANY
EL_SHARED_STRING_8_CURSOR; EL_SHARED_STRING_32_CURSOR
EL_STRING_HANDLER
feature -- Substring conversion
substring_to_integer (str: READABLE_STRING_GENERAL; start_index, end_index: INTEGER): INTEGER
do
Result := substring_to_natural_64 (str, start_index, end_index).to_integer_32
end
substring_to_integer_16 (str: READABLE_STRING_GENERAL; start_index, end_index: INTEGER): INTEGER_16
do
Result := substring_to_natural_64 (str, start_index, end_index).to_integer_16
end
substring_to_integer_64 (str: READABLE_STRING_GENERAL; start_index, end_index: INTEGER): INTEGER_64
do
Result := substring_to_natural_64 (str, start_index, end_index).to_integer_64
end
substring_to_natural_8 (str: READABLE_STRING_GENERAL; start_index, end_index: INTEGER): NATURAL_8
do
Result := substring_to_natural_64 (str, start_index, end_index).to_natural_8
end
substring_to_natural_16 (str: READABLE_STRING_GENERAL; start_index, end_index: INTEGER): NATURAL_16
do
Result := substring_to_natural_64 (str, start_index, end_index).to_natural_16
end
substring_to_natural_32 (str: READABLE_STRING_GENERAL; start_index, end_index: INTEGER): NATURAL
do
Result := substring_to_natural_64 (str, start_index, end_index).to_natural_32
end
substring_to_natural_64 (str: READABLE_STRING_GENERAL; start_index, end_index: INTEGER): NATURAL_64
require
valid_sequence: is_valid_sequence (str, start_index, end_index)
--
local
i, bit_shift, offset: INTEGER; value: NATURAL_64; found: BOOLEAN
l_area: SPECIAL [CHARACTER]
do
if attached character_array (str, start_index, end_index) as array then
offset := array.offset
l_area := array.area
-- Skip 0x00
from i := start_index - 1 until found or i = end_index loop
if is_leading_digit (l_area [i + offset], i - start_index + 2) then
i := i + 1
else
found := True
end
end
from until i = end_index loop
value := to_decimal (l_area [i + offset]).to_natural_64
bit_shift := (end_index - i - 1) * bit_count
Result := Result | (value |<< bit_shift)
i := i + 1
end
end
end
feature -- Conversion
to_decimal (c: CHARACTER): INTEGER_64
do
inspect c
when '0' .. '9' then
Result := (c |-| '0')
when 'a' .. 'z' then
Result := (c |-| 'a') + 10
when 'A' .. 'Z' then
Result := (c |-| 'A') + 10
else
end
end
to_integer (str: READABLE_STRING_GENERAL): INTEGER
--
do
Result := substring_to_integer (str, 1, str.count)
end
to_integer_16 (str: READABLE_STRING_GENERAL): INTEGER_16
--
do
Result := substring_to_integer_16 (str, 1, str.count)
end
to_integer_64 (str: READABLE_STRING_GENERAL): INTEGER_64
--
do
Result := substring_to_integer_64 (str, 1, str.count)
end
to_natural_8 (str: READABLE_STRING_GENERAL): NATURAL_8
--
do
Result := substring_to_natural_8 (str, 1, str.count)
end
to_natural_16 (str: READABLE_STRING_GENERAL): NATURAL_16
--
do
Result := substring_to_natural_16 (str, 1, str.count)
end
to_natural_32 (str: READABLE_STRING_GENERAL): NATURAL
--
do
Result := substring_to_natural_32 (str, 1, str.count)
end
to_natural_64 (str: READABLE_STRING_GENERAL): NATURAL_64
do
Result := substring_to_natural_64 (str, 1, str.count)
end
feature -- Contract Support
is_valid_sequence (str: READABLE_STRING_GENERAL; start_index, end_index: INTEGER): BOOLEAN
local
i: INTEGER; c: CHARACTER; uc: CHARACTER_32
do
Result := True
from i := start_index until not Result or i > end_index loop
uc := str [i]
if uc.is_character_8 then
c := uc.to_character_8
Result := is_valid_digit (c, i - start_index + 1)
else
Result := False
end
i := i + 1
end
end
feature -- Access
bit_count: INTEGER
-- number of bits to encode single binary, octal or hexadecimal digit
deferred
end
feature {NONE} -- Implementation
character_array (
str: READABLE_STRING_GENERAL; start_index, end_index: INTEGER
): TUPLE [area: SPECIAL [CHARACTER]; offset: INTEGER]
do
create Result
inspect string_storage_type (str)
when '1' then
if attached {READABLE_STRING_8} str as str_8
and then attached cursor_8 (str_8) as cursor
then
Result.offset := cursor.area_first_index
Result.area := cursor.area
end
when '4' then
if attached {READABLE_STRING_32} str as str_32
and then attached Buffer.empty as substring
then
cursor_32 (str_32).append_substring_to_string_8 (substring, start_index, end_index)
Result.area := substring.area
end
when 'X' then
if attached {EL_READABLE_ZSTRING} str as zstr then
Result.area := zstr.area
end
end
end
is_leading_digit (c: CHARACTER; index: INTEGER): BOOLEAN
deferred
end
is_valid_digit (c: CHARACTER; index: INTEGER): BOOLEAN
deferred
end
feature {NONE} -- Constants
Buffer: EL_STRING_8_BUFFER
once
create Result
end
end