class EL_STRING_8

(source code)

Client examples: STRING_TEST_SET

description

Capabilities of STRING_8 extended with routines from EL_EXTENDED_READABLE_STRING_I and EL_EXTENDED_STRING_GENERAL.

note
	description: "[
		Capabilities of ${STRING_8} extended with routines from ${EL_EXTENDED_READABLE_STRING_I} and
		${EL_EXTENDED_STRING_GENERAL}.
	]"

	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: "2025-04-17 14:55:44 GMT (Thursday 17th April 2025)"
	revision: "42"

class
	EL_STRING_8

inherit
	STRING_8
		rename
			replace_character as replace_every_character,
			set_count as set_string_count,
			split as split_list
		export
			{EL_STRING_8_CONSTANTS} String_searcher
			{EL_TYPE_CONVERSION_HANDLER}
				Ctoi_convertor, Ctor_convertor, is_valid_integer_or_natural
		undefine
			same_string
		redefine
			append_string_general, make, resize, share, trim
		end

	EL_EXTENDED_STRING_8
		rename
			set_target as share
		undefine
			count, has, is_valid_as_string_8, occurrences, valid_index
		end

	EL_SHARED_STRING_8_BUFFER_POOL

create
	make_from_zstring, make_empty, make, make_from_string

feature {NONE} -- Initialization

	make (n: INTEGER)
		do
			Precursor (n)
			shared_string := Current
		end

	make_from_zstring (zstr: EL_ZSTRING_CHARACTER_8_BASE)
		do
			set_area_and_count (zstr.area, zstr.count)
		end

feature -- Staus query

	has_padding: BOOLEAN
		-- `True' if `leading_white_count > 0' or `trailing_white_count > 0'
		do
			if count > 0 and then attached area as l_area then
				Result := l_area [0].is_space or else l_area [count - 1].is_space
			end
		end

feature -- Comparison

	same_strings (a, b: READABLE_STRING_8): BOOLEAN
		-- work around for bug in `{SPECIAL}.same_items' affecting `{IMMUTABLE_STRING_8}.same_string'
		do
			if a.count = b.count then
				Result := same_area_items (a.area, b.area, a.area_lower, b.area_lower, a.count)
			end
		end

feature -- Basic operations

	append_adjusted_to (str: STRING)
		local
			n, i, start_index, end_index, offset: INTEGER
			l_area, o_area: like area
		do
			end_index := count - trailing_white_count
			if end_index.to_boolean then
				start_index := leading_white_count + 1
			else
				start_index := 1
			end
			n := end_index - start_index + 1
			offset := str.count
			str.grow (offset + n)
			str.set_count (offset + n)
			l_area := area; o_area := str.area
			from i := 0 until i = n loop
				o_area [i + offset] := l_area [i + start_index - 1]
				i := i + 1
			end
		end

feature -- Element change

	append_count_from_c (c_string: POINTER; a_count: INTEGER)
		local
			c: like C_string_provider
		do
			c := C_string_provider
			c.set_shared_from_pointer_and_count (c_string, a_count)
			grow (count + a_count + 1)
			c.managed_data.read_into_special_character_8 (area, 0, count, a_count)
			count := count + a_count
			internal_hash_code := 0
		end

	append_from_c (c_string: POINTER)
		local
			c: like C_string_provider
		do
			c := C_string_provider
			c.set_shared_from_pointer (c_string)
			grow (count + c.count + 1)
			c.managed_data.read_into_special_character_8 (area, 0, count, c.count)
			count := count + c.count
			internal_hash_code := 0
		end

	append_string_general (str: READABLE_STRING_GENERAL)
		do
			if conforms_to_zstring (str) and then attached {ZSTRING} str as z_str then
				z_str.append_to_string_8 (Current)
			else
				Precursor (str)
			end
		end

	set_area_and_count (a_area: like area; a_count: INTEGER)
		do
			area := a_area; count := a_count
			internal_hash_code := 0
		end

	set_from_c (c_string: POINTER)
		local
			c: like C_string_provider
		do
			c := C_string_provider
			c.set_shared_from_pointer (c_string)
			grow (c.count + 1)
			c.managed_data.read_into_special_character_8 (area, 0, 0, c.count)
			count := c.count
			internal_hash_code := 0
		end

	set_from_c_with_count (c_string: POINTER; a_count: INTEGER)
		local
			c: like C_string_provider
		do
			c := C_string_provider
			c.set_shared_from_pointer_and_count (c_string, a_count)
			grow (a_count + 1)
			c.managed_data.read_into_special_character_8 (area, 0, 0, a_count)
			count := a_count
			internal_hash_code := 0
		end

	share (other: STRING_8)
			-- Make current string share the text of `other'.
			-- Subsequent changes to the characters of current string
			-- will also affect `other', and conversely.
		do
			Precursor (other)
			shared_string := other
		end

	unescape (unescaper: EL_STRING_8_UNESCAPER)
		local
			uc: CHARACTER_32
		do
			uc := unescaper.escape_code.to_character_32
			if uc.is_character_8 and then has (uc.to_character_8) then
				if attached String_8_pool.borrowed_item as borrowed then
					if attached borrowed.empty as str then
						unescaper.unescape_into (Current, str)
						wipe_out
						append (str)
					end
					borrowed.return
				end
			end
		end

feature -- Duplication

	enclosed (left, right: CHARACTER_8): STRING_8
		-- copy of target with `left' and `right' character prepended and appended
		do
			create Result.make (count + 2)
			Result.append_character (left)
			Result.append_string (shared_string)
			Result.append_character (right)
		end

	filled (c: CHARACTER_8; n: INTEGER): STRING_8
		-- shared string filled with `n' number of `c' characters repeated
		do
			Result := Character_string_8_table.item (c, n)
		end

	pruned (c: CHARACTER_8): STRING_8
		do
			create Result.make_from_string (Current)
			Result.prune_all (c)
		end

	shared_leading (end_index: INTEGER): STRING_8
		-- leading substring of `shared_string' from 1 to `end_index'
		do
			create Result.make_empty
			Result.share (shared_string)
			Result.set_count (end_index)
		end

feature {NONE} -- Implementation

	copy_area_32_data (a_area: like area; source: SPECIAL [CHARACTER_32])
		local
			i, i_upper, offset: INTEGER; uc: CHARACTER_32
		do
			i_upper := source.count - 1; offset := count
			from i := 0 until i > i_upper loop
				uc := source [i]
				if uc.is_character_8 then
					a_area [i + offset] := uc.to_character_8
				else
					a_area [i + offset] := '%/26/'
				end
				i := i + 1
			end
		end

	new_readable: EL_STRING_8
		do
			create Result.make_empty
		end

	new_substring (start_index, end_index: INTEGER): STRING_8
		do
			create Result.make_empty
			Result.share (substring (start_index, end_index))
		end

	other_area (other: READABLE_STRING_8): like area
		do
			Result := other.area
		end

	other_index_lower (other: READABLE_STRING_8): INTEGER
		do
			Result := other.area_lower
		end

	resize (newsize: INTEGER)
		-- Rearrange string so that it can accommodate at least `newsize' characters.
		do
			Precursor (newsize)
			if shared_string /= Current then
				shared_string.share (Current)
			end
		end

	set_count (n: INTEGER)
		do
			set_string_count (n)
			if shared_string /= Current then
				shared_string.set_count (n)
			end
		end

	trim
		 -- reallocate to new size
		do
			if attached area as l_area then
				Precursor
				if l_area /= area and then shared_string /= Current then
					shared_string.share (Current)
				end
			end
		end

feature {NONE} -- Internal attributes

	shared_string: STRING_8

end