note
	description: "Routines that ought to be in class STRING"
	remark: "[
		Unless otherwise specified in their preconditions,
		the features of this class can deal with UC_STRING
		whenever a STRING is expected.
	]"
	library: "Gobo Eiffel Kernel Library"
	copyright: "Copyright (c) 1999-2018, Eric Bezault and others"
	license: "MIT License"
	date: "$Date: 2019-02-07 22:54:15 +0000 (Thu, 07 Feb 2019) $"
	revision: "$Revision: 102807 $"

class interface
	KL_STRING_ROUTINES

create 
	default_create

feature -- Initialization

	make_from_string (s: STRING_8): STRING_8
			-- Initialize from the character sequence of s.
			-- s is considered with its characters which do not fit
			-- in a CHARACTER replaced by a '%U'.
			-- (ELKS 2001 STRING)
			-- Note: Use this routine instead of 'STRING.make_from_string (s)'
			-- when s is of dynamic type other than STRING (e.g. UC_STRING)
			-- because the class STRING provided with the Eiffel compilers
			-- is not necessarily aware of the implementation of UC_STRING
			-- and this may lead to run-time errors or crashes.
		require
			s_not_void: s /= Void
		ensure
			instance_free: class
			string_not_void: Result /= Void
			new_string: Result /= s
			string_type: Any_.same_types (Result, "")
			initialized: elks_same_string (Result, s)

	make_buffer (n: INTEGER_32): STRING_8
			-- Create a new string containing n characters.
			-- (Not in ELKS 2001 STRING)
		require
			non_negative_n: n >= 0
		ensure
			instance_free: class
			string_not_void: Result /= Void
			string_type: Any_.same_types (Result, "")
			count_set: Result.count = n
	
feature -- Status report

	has_substring (a_string, other: STRING_8): BOOLEAN
			-- Does a_string contain other? a_string and other
			-- are considered with their characters which do not fit
			-- in a CHARACTER replaced by a '%U'.
			-- (Extended from ELKS 2001 STRING)
			-- Note: Use this feature instead of 'a_string.has_substring
			-- (other)' when a_string can be of dynamic type STRING and
			-- other of dynamic type other than STRING such as UC_STRING,
			-- because class STRING provided by the Eiffel compilers is
			-- not necessarily aware of the implementation of UC_STRING
			-- and this may lead to run-time errors or crashes.
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
		ensure
			instance_free: class
			false_if_too_small: a_string.count < other.count implies not Result
			true_if_initial: (a_string.count >= other.count and then elks_same_string (other, a_string.substring (1, other.count))) implies Result
			recurse: (a_string.count >= other.count and then not elks_same_string (other, a_string.substring (1, other.count))) implies (Result = has_substring (a_string.substring (2, a_string.count), other))

	is_decimal (a_string: STRING_8): BOOLEAN
			-- Is a_string only made up of characters 0-9?
			-- (Not in ELKS 2001 STRING)
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class

	is_integer_64 (a_string: STRING_8): BOOLEAN
			-- Does a_string represent a positive INTEGER_64?
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class

	is_hexadecimal (a_string: STRING_8): BOOLEAN
			-- Is a string made up of characters 0-9 or A-F or a-f?
			-- (Not in ELKS 2001 STRING)
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class

	is_base64 (a_string: STRING_8): BOOLEAN
			-- Is a string made up of characters +, /, =, XML whitespace, 0-9 or A-Z or a-z?
			-- (Not in ELKS 2001 STRING)
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class
	
feature -- Access

	new_empty_string (a_string: STRING_8; n: INTEGER_32): STRING_8
			-- New empty string with same dynamic type as a_string;
			-- Try to allocate space for at least n characters.
			-- (Not in ELKS 2001 STRING)
		require
			a_string_not_void: a_string /= Void
			non_negative_n: n >= 0
		ensure
			instance_free: class
			new_string_not_void: Result /= Void
			same_type: Any_.same_types (Result, a_string)
			new_string_empty: Result.count = 0

	to_utf16_be (a_string: STRING_8): STRING_8
			-- New STRING made up of bytes corresponding to
			-- the UTF-16BE representation of a_string
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class
			to_utf16_be_not_void: Result /= Void
			string_type: Any_.same_types (Result, "")
			valid_utf16: Utf16.valid_utf16 (Result)

	to_utf16_le (a_string: STRING_8): STRING_8
			-- New STRING made up of bytes corresponding to
			-- the UTF-16LE representation of a_string
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class
			to_utf16_le_not_void: Result /= Void
			string_type: Any_.same_types (Result, "")
			valid_utf16: Utf16.valid_utf16 (Utf16.Bom_le + Result)

	to_utf32_be (a_string: STRING_8): STRING_8
			-- New STRING made up of bytes corresponding to
			-- the UTF-32BE representation of a_string
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class
			to_utf32_be_not_void: Result /= Void
			string_type: Any_.same_types (Result, "")
			valid_utf32: Utf32.valid_utf32 (Result)

	to_utf32_le (a_string: STRING_8): STRING_8
			-- New STRING made up of bytes corresponding to
			-- the UTF-32LE representation of a_string
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class
			to_utf32_le_not_void: Result /= Void
			string_type: Any_.same_types (Result, "")
			valid_utf32: Utf32.valid_utf32 (Utf32.Bom_le + Result)

	substring_index (a_string, other: STRING_8; start_index: INTEGER_32): INTEGER_32
			-- Index of first occurrence of other at or after start_index in
			-- a_string; 0 if none. a_string and other are considered with
			-- their characters which do not fit in a CHARACTER replaced by a '%U'.
			-- (ELKS 2001 STRING)
			-- Note: Use this feature instead of 'a_string.substring_index (other,
			-- start_index)' when a_string can be of dynamic type STRING and
			-- other of dynamic type other than STRING such as UC_STRING, because
			-- class STRING provided by the Eiffel compilers is not necessarily
			-- aware of the implementation of UC_STRING and this may lead to
			-- run-time errors or crashes.
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
			valid_start_index: start_index >= 1 and start_index <= a_string.count + 1
		ensure
			instance_free: class
			valid_result: Result = 0 or else (start_index <= Result and Result <= a_string.count - other.count + 1)
			zero_if_absent: (Result = 0) = not has_substring (a_string.substring (start_index, a_string.count), other)
			at_this_index: Result >= start_index implies elks_same_string (other, a_string.substring (Result, Result + other.count - 1))
			none_before: Result > start_index implies not has_substring (a_string.substring (start_index, Result + other.count - 2), other)

	case_insensitive_hash_code (a_string: STRING_8): INTEGER_32
			-- Hash code value of a_string which doesn't
			-- take case sensitivity into account
			-- (Not in ELKS 2001 STRING)
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class
			hash_code_not_negative: Result >= 0

	concat (a_string, other: STRING_8): STRING_8
			-- New object which contains the characters of a_string
			-- followed by the characters of other; If other is
			-- of dynamic type UC_STRING or one of its descendants and
			-- a_string is not, then the dynamic type of the result
			-- is the same as the dynamic type of other. Otherwise
			-- the result is similar to 'a_string + other';
			-- Note: Use this routine instead of 'a_string + other' or
			-- 'a_string.append_string (other)' when a_string
			-- can be of dynamic type STRING and other of dynamic
			-- type other than STRING such as UC_STRING, because class
			-- STRING provided by the Eiffel compilers is not necessarily
			-- aware of the implementation of UC_STRING and this may
			-- lead to run-time errors or crashes.
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
		ensure
			instance_free: class
			concat_not_void: Result /= Void
			concat_count: Result.count = a_string.count + other.count
			initial: same_string (Result.substring (1, a_string.count), a_string)
			final: same_string (Result.substring (a_string.count + 1, Result.count), other)
	
feature -- Comparison

	elks_same_string (a_string, other: STRING_8): BOOLEAN
			-- Do a_string and other have the same character sequence?
			-- a_string and other are considered with their characters
			-- which do not fit in a CHARACTER replaced by a '%U'.
			-- (Extended from ELKS 2001 STRING)
			-- Note: Use this feature instead of 'a_string.same_string
			-- (other)' when a_string can be of dynamic type STRING and
			-- other of dynamic type other than STRING such as UC_STRING,
			-- because class STRING provided by the Eiffel compilers is
			-- not necessarily aware of the implementation of UC_STRING
			-- and this may lead to run-time errors or crashes.
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
		ensure
			instance_free: class
			definition: Result = a_string.string.is_equal (other.string)

	same_string (a_string, other: STRING_8): BOOLEAN
			-- Do a_string and other have the same unicode character sequence?
			-- (Not in ELKS 2001 STRING)
			-- Note: the difference with elks_same_string is that here the
			-- implementation uses STRING.item_code instead of STRING.item
			-- and hence characters which have different codes are not
			-- considered equal even if they do not fit into a CHARACTER.
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
		ensure
			instance_free: class
			definition: Result = (a_string.count = other.count and then (a_string.count > 0 implies (a_string.item_code (1) = other.item_code (1) and (a_string.count >= 2 implies same_string (a_string.substring (2, a_string.count), other.substring (2, a_string.count))))))
			elks_same_string: Result implies elks_same_string (a_string, other)

	same_case_insensitive (s1, s2: STRING_8): BOOLEAN
			-- Are s1 and s2 made up of the same
			-- characters (case insensitive)?
			-- (Not in ELKS 2001 STRING)
		require
			s1_not_void: s1 /= Void
			s2_not_void: s2 /= Void
		ensure
			instance_free: class

	is_less (a_string, other: STRING_8): BOOLEAN
			-- Is a_string considered less than other?
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
		ensure
			instance_free: class

	three_way_comparison (a_string, other: STRING_8): INTEGER_32
			-- If a_string equal to other, 0;
			-- if smaller, -1; if greater, 1
			-- (ELKS 2001 STRING)
			-- Note: there is a bug in the specification of the
			-- contracts of three_way_comparison from class
			-- COMPARABLE. This routine cannot satisfy its
			-- postconditions if other is not of the same type
			-- as Current because the postcondition uses is_equal
			-- and is_equal has a postcondition inherited from
			-- ANY which says if it returns true then other has
			-- the same type as Current. The current feature
			-- three_way_comparison in class KL_STRING_ROTUINES
			-- solves this problem and make the comparison
			-- polymorphically safe by changing the signature
			-- from 'like Current' to 'STRING' and by using
			-- STRING_.same_string instead of is_equal in
			-- its postcondition.
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
		ensure
			instance_free: class
			equal_zero: (Result = 0) = same_string (a_string, other)

	three_way_case_insensitive_comparison (a_string, other: STRING_8): INTEGER_32
			-- If a_string equal to other, 0; if smaller, -1; if greater, 1
			-- (case insensitive comparison)
			-- (Not in ELKS 2001 STRING)
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
		ensure
			instance_free: class

	three_way_lower_case_comparison (a_string, other: STRING_8): INTEGER_32
			-- If a_string equal to other, 0; if smaller, -1; if greater, 1
			-- (case insensitive comparison, consider letters as lower-case)
			-- (Not in ELKS 2001 STRING)
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
		ensure
			instance_free: class

	three_way_upper_case_comparison (a_string, other: STRING_8): INTEGER_32
			-- If a_string equal to other, 0; if smaller, -1; if greater, 1
			-- (case insensitive comparison, consider letters as upper-case)
			-- (Not in ELKS 2001 STRING)
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
		ensure
			instance_free: class
	
feature -- Duplication

	cloned_string (a_string: STRING_8): STRING_8
			-- Clone of a_string
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class
			cloned_not_void: Result /= Void
			same_type: Any_.same_types (Result, a_string)
			is_equal: Result.is_equal (a_string)
	
feature -- Element change

	appended_string (a_string, other: STRING_8): STRING_8
			-- If the dynamic type of other is UC_STRING or one of
			-- its descendants and a_string is not, then return a
			-- new object with the same dynamic type as other and
			-- which contains the characters of a_string followed
			-- by the characters of other. Otherwise append the
			-- characters of other to a_string and return a_string.
			-- Note: Use this routine instead of 'a_string.append_string (other)'
			-- when a_string can be of dynamic type STRING and other
			-- of dynamic type other than STRING such as UC_STRING, because
			-- class STRING provided by the Eiffel compilers is not necessarily
			-- aware of the implementation of UC_STRING and this may
			-- lead to run-time errors or crashes.
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
		ensure
			instance_free: class
			append_not_void: Result /= Void
			type_if_not_aliased: Result /= a_string implies Any_.same_types (Result, other)
			new_count: Result.count = old a_string.count + old other.count
			initial: same_string (Result.substring (1, old a_string.count), old cloned_string (a_string))
			final: same_string (Result.substring (old a_string.count + 1, Result.count), old cloned_string (other))

	appended_substring (a_string, other: STRING_8; s, e: INTEGER_32): STRING_8
			-- If the dynamic type of other is UC_STRING or one of
			-- its descendants and a_string is not, then return a
			-- new object with the same dynamic type as other and
			-- which contains the characters of a_string followed by
			-- the characters of other between indexes s and e.
			-- Otherwise append the characters of other between s
			-- and e to a_string and return a_string.
			-- Note: Use this routine instead of 'a_string.append_string
			-- (other.substring (s, e)' when a_string can be of dynamic
			-- type STRING and other of dynamic type other than STRING
			-- such as UC_STRING, because class STRING provided by the
			-- Eiffel compilers is not necessarily aware of the
			-- implementation of UC_STRING and this may lead to run-time
			-- errors or crashes.
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
			s_large_enough: s >= 1
			e_small_enough: e <= other.count
			valid_interval: s <= e + 1
		ensure
			instance_free: class
			append_not_void: Result /= Void
			type_if_not_aliased: Result /= a_string implies Any_.same_types (Result, other)
			new_count: Result.count = old a_string.count + e - s + 1
			initial: same_string (Result.substring (1, old a_string.count), old cloned_string (a_string))
			final: same_string (Result.substring (old a_string.count + 1, Result.count), old other.substring (s, e))

	replaced_substring (a_string, other: STRING_8; start_index, end_index: INTEGER_32): STRING_8
			-- If the dynamic type of other is UC_STRING or one of
			-- its descendants and a_string is not, then return a
			-- new object with the same dynamic type as other and
			-- which contains the characters of a_string from which
			-- the substring from start_index to end_index, inclusive,
			-- has been replaced with other. Otherwise replace the
			-- substring from start_index to end_index, inclusive,
			-- in a_string with other and return a_string.
			-- Note: Use this routine instead of 'a_string.replace_substring (other)'
			-- when a_string can be of dynamic type STRING and other
			-- of dynamic type other than STRING such as UC_STRING, because
			-- class STRING provided by the Eiffel compilers is not necessarily
			-- aware of the implementation of UC_STRING and this may
			-- lead to run-time errors or crashes.
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
			valid_start_index: 1 <= start_index
			valid_end_index: end_index <= a_string.count
			meaningful_interval: start_index <= end_index + 1
		ensure
			instance_free: class
			replaced_substring_not_void: Result /= Void
			replaced: same_string (Result, old (appended_string (appended_string (a_string.substring (1, start_index - 1), other), a_string.substring (end_index + 1, a_string.count))))

	append_substring_to_string (a_string: STRING_8; other: STRING_8; s, e: INTEGER_32)
			-- Append substring of other between indexes
			-- s and e at end of a_string.
		require
			a_string_not_void: a_string /= Void
			other_not_void: other /= Void
			same_type: Any_.same_types (other, a_string)
			s_large_enough: s >= 1
			e_small_enough: e <= other.count
			valid_interval: s <= e + 1
		ensure
			instance_free: class
			appended: a_string.is_equal (old cloned_string (a_string) + old other.substring (s, e))

	replaced_all_substrings (a_text, a_old, a_new: STRING_8): STRING_8
			-- Copy of a_text for which each occurrence of a_old has been replaced
			-- by a_new; a_text if no occurrence could be found
		require
			a_text_not_void: a_text /= Void
			a_old_not_void: a_old /= Void
			a_new_not_void: a_new /= Void
		ensure
			instance_free: class
			replaced_all_substrings_not_void: Result /= Void

	replaced_first_substring (a_text: STRING_8; a_old, a_new: STRING_8): STRING_8
			-- Copy of a_text for which first occurrence of a_old has been replaced
			-- by a_new; a_text if no occurrence could be found
		require
			a_text_not_void: a_text /= Void
			a_old_not_void: a_old /= Void
			a_new_not_void: a_new /= Void
		ensure
			instance_free: class
			replaced_first_substring_not_void: Result /= Void
	
feature -- Conversion

	as_string (a_string: STRING_8): STRING_8
			-- String version of a_string;
			-- Return a_string if it is of dynamic type STRING,
			-- return the UTF encoding version if it is a descendant
			-- of UC_STRING, return 'string (a_string)' otherwise.
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class
			as_string_not_void: Result /= Void
			string_type: Any_.same_types (Result, "")
			aliasing: Any_.same_types (a_string, "") implies Result = a_string

	hexadecimal_to_integer (a_string: STRING_8): INTEGER_32
			-- Convert hexadecimal number string to integer;
			-- (Not in ELKS 2001 STRING)
			-- Note: Do not take overflow into account.
		require
			not_void: a_string /= Void
			hexadecimal: is_hexadecimal (a_string)
		ensure
			instance_free: class
	
feature -- Removal

	left_adjust (a_string: STRING_8)
			-- Remove leading whitespace from a_string.
			-- (Not in ELKS 2001 STRING)
			-- Note: SE 1.1 removes the following characters: ' ';
			-- ISE 5.4 removes the following characters: ' ', '%T', '%R', '%N';
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class
			left_adjusted: (a_string.count /= 0) implies ((a_string.item_code (1) /= (' ').code) and (a_string.item_code (1) /= ('%T').code) and (a_string.item_code (1) /= ('%R').code) and (a_string.item_code (1) /= ('%N').code))

	right_adjust (a_string: STRING_8)
			-- Remove trailing whitespace from a_string.
			-- (Not in ELKS 2001 STRING)
			-- Note: SE 1.1 removes the following characters: ' ';
			-- ISE 5.4 removes the following characters: ' ', '%T', '%R', '%N';
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class
			right_adjusted: (a_string.count /= 0) implies ((a_string.item_code (a_string.count) /= (' ').code) and (a_string.item_code (a_string.count) /= ('%T').code) and (a_string.item_code (a_string.count) /= ('%R').code) and (a_string.item_code (a_string.count) /= ('%N').code))

	wipe_out (a_string: STRING_8)
			-- Remove all characters in a_string.
			-- Do not discard allocated memory (i.e. do not
			-- change capacity) when allowed by the underlying
			-- Eiffel compiler.
			-- Note: currently ISE and SE will not change capacity.
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class
			wiped_out: a_string.count = 0

	prune_all_trailing (a_string: STRING_8; c: CHARACTER_8)
			-- Remove all trailing occurrences of c in a_string.
		require
			a_string_not_void: a_string /= Void
		ensure
			instance_free: class
			no_more_trailing: a_string.is_empty or else a_string.item (a_string.count) /= c
	
feature -- Resizing

	resize_buffer (a_string: STRING_8; n: INTEGER_32)
			-- Resize a_string so that it contains n characters.
			-- Do not lose any previously entered characters.
		require
			a_string_not_void: a_string /= Void
			a_string_is_string: Any_.same_types (a_string, "")
			n_large_enough: n >= a_string.count
		ensure
			instance_free: class
			count_set: a_string.count = n
	
feature -- Conversion

	to_integer_64 (a_string: STRING_8): INTEGER_64
			-- a_string as INTEGER_64
		require
			a_string_not_void: a_string /= Void
			integer_64_string: is_integer_64 (a_string)
		ensure
			instance_free: class
	
end -- class KL_STRING_ROUTINES

Generated by ISE EiffelStudio