class EL_C_STRING

(source code)

description

C string

note
	description: "C string"

	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-07 11:11:09 GMT (Sunday 7th January 2024)"
	revision: "17"

deferred class
	EL_C_STRING

inherit
	MANAGED_POINTER
		rename
			item as base_address,
			count as byte_count,
			make as make_buffer,
			append as append_buffer
		export
			{NONE} all
			{ANY} base_address
		redefine
			default_create
		end

	EL_MEMORY_ROUTINES undefine copy, default_create, is_equal end

	EL_BIT_COUNTABLE

	EL_SHARED_IMMUTABLE_32_MANAGER

feature {NONE} -- Initialization

	make_owned (c_ptr: POINTER)
			--
		do
			make_with_ownership (c_ptr, True)
		end

	make_owned_of_size (c_ptr: POINTER; size: INTEGER)
			--
		do
			make_with_size_and_ownership (c_ptr, size, True)
		end

	make_shared (c_ptr: POINTER)
			-- make shared
		do
			make_with_ownership (c_ptr, False)
		end

	make_shared_of_size (c_ptr: POINTER; size: INTEGER)
			-- make shared
		do
			make_with_size_and_ownership (c_ptr, size, False)
		end

feature {NONE} -- Initialization

	default_create
			--
		do
			make (0)
		end

	make (a_count: INTEGER)
			--
		do
			count := a_count
			capacity := a_count
			if count > 0 then
				make_buffer ((count + 1) * width)
				put_item (0, count + 1)
			else
				base_address := Default_pointer
				is_shared := true
			end
		end

	make_from_string (string: READABLE_STRING_GENERAL)
			--
		local
			i: INTEGER
		do
			count := string.count
			capacity := count + 1
			make_buffer (capacity * width)
			from i := 1 until i > count loop
				put_item (string.code (i), i)
				i := i + 1
			end
			put_item (0, i)
		end

	make_with_ownership (c_ptr: POINTER; owned: BOOLEAN)
			--
		do
			if is_attached (c_ptr) then
				make_with_size_and_ownership (c_ptr, c_string_length (c_ptr, width), owned)
			else
				make_with_size_and_ownership (c_ptr, 0, owned)
			end
		end

	make_with_size_and_ownership (c_ptr: POINTER; size: INTEGER; owned: BOOLEAN)
			--
		do
			if is_attached (base_address) then
				dispose
			end
			count := size; capacity := size + 1
			if owned then
				own_from_pointer (c_ptr, capacity * width)
			else
				share_from_pointer (c_ptr, capacity * width)
			end
		ensure
			correct_sized_buffer: byte_count // width = capacity
		end

feature -- Measurement

	capacity: INTEGER

	count: INTEGER

feature -- Access

	code (index: INTEGER): NATURAL_32
			--
		require
			valid_index: index >= 1 and index <= count
		deferred
		end

	item (index: INTEGER): CHARACTER_32
			--
		require
			valid_index: index >= 1 and index <= count
		do
			Result := code (index).to_character_32
		end

feature -- Conversion

	to_boolean: BOOLEAN
		do
			if count = 4 then
				Result := code (1).to_character_32.as_upper = 'T'
			end
		end

feature -- Element change	

	append (string: READABLE_STRING_GENERAL)
			--
		local
			new_string: STRING_32
		do
			if not is_attached (base_address) and is_shared then
				is_shared := false -- to satisfy precondition in MANAGED_POINTER make
				make_from_string (string)

			else
				new_string := as_string_32
				new_string.append_string_general (string)
				dispose
				make_from_string (new_string)
			end
		end

	put_item (value: NATURAL_32; index: INTEGER)
			--
		require
			valid_index: index >= 1 and index <= count + 1
			value_small_enough: is_value_small_enough (value)
		deferred
		end

	set_count (new_count: INTEGER)
			--
		require
			valid_new_count: new_count >= 0 and new_count <= capacity
		do
			count := new_count
		end

	set_owned_from_c (c_ptr: POINTER)
			--
		do
			make_with_ownership (c_ptr, True)
		end

	set_owned_from_c_of_size (c_ptr: POINTER; size: INTEGER)
			--
		do
			make_with_size_and_ownership (c_ptr, size, True)
		end

	set_shared_from_c (c_ptr: POINTER)
			-- make shared
		do
			make_with_ownership (c_ptr, False)
		end

	set_shared_from_c_of_size (c_ptr: POINTER; size: INTEGER)
			-- make shared
		do
			make_with_size_and_ownership (c_ptr, size, False)
		end

feature -- Set external strings

	fill_string (string: STRING_GENERAL)
			-- Fill string argument with all characters
		local
			i, l_count: INTEGER
		do
			l_count := count
			from i := 1 until i > l_count loop
				string.append_code (code (i))
				i := i + 1
			end
		end

feature -- Removal

	wipe_out
			--
		do
			dispose
			count := 0
			byte_count := 0
			is_shared := true
		end

feature -- Status query

	is_empty: BOOLEAN
			--
		do
			Result := count = 0 or else count = 1 and code (1) = 0
		end

	is_owned: BOOLEAN
			--
		do
			Result := not is_shared
		end

	is_value_small_enough (value: NATURAL_32): BOOLEAN
		--
		do
			Result := width < Natural_32_bytes implies value.bit_shift_right (width * 8) = 0
		end

feature -- Conversion

	as_array: SPECIAL [CHARACTER_32]
		-- character array with terminating NULL character
		local
			i, l_count: INTEGER
		do
			l_count := count
			create Result.make_empty (l_count + 1)
			from i := 1 until i > l_count loop
				Result.extend (code (i).to_character_32)
				i := i + 1
			end
			Result.extend ('%U')
		end

	as_immutable_32: IMMUTABLE_STRING_32
			--
		do
			Result := shared_immutable_32.twin
		end

	as_string: ZSTRING
			--
		do
			create Result.make_from_general (shared_immutable_32)
		end

	as_string_32: STRING_32
			--
		do
			create Result.make_from_string (shared_immutable_32)
		end

	as_string_8: STRING
			--
		do
			Result := shared_immutable_32.to_string_8
		end

feature {NONE} -- Implementation

	shared_immutable_32: IMMUTABLE_STRING_32
			--
		do
			Immutable_32.set_item (as_array, 0, count)
			Result := Immutable_32.item
		end

feature {NONE} -- Deferred

	width: INTEGER
			-- character width in bytes
		deferred
		end


end