PR# 19830 '{STRING}.left_adjust' error
Problem Report Summary
Submitter: hcater
Category: EiffelBase
Priority: Medium
Date: 2022/01/14
Class: Bug
Severity: Serious
Number: 19830
Release: 21.11
Confidential: No
Status: Closed
Responsible:
Environment: win
Synopsis: '{STRING}.left_adjust' error
Description
There is an issue with 'left_adjust' please see the screenshots of before and after. Then what happens when I use 'twin' where the string loses the null character entirely after, because of the issue initiated originally with 'left_adjust'
To Reproduce
Problem Report Interactions
For the record, here is the answer sent by mail: Alexander Kogtenkov from EiffelSoftware is also suggesting to replace this code: create string_array.make_from_special(string.as_string_32.area) create natural_16_array.make_filled (0, string_array.lower, string_array.upper) from i := string_array.lower until i > string_array.upper loop integer := string_array.item(i).code natural_16_array.put(integer.as_natural_16, i) -- forth i := i + 1 end a_string := natural_16_array.to_c with a_string := {UTF_CONVERTER}.string_32_to_utf_16_0 (string.as_string32) This code will make sure that a_string is 0-terminated Unicode code points above 0xFFFF (for examples, for emoji) are correctly translated into UTF-16 surrogate pairs it is more efficient than the original If string is in UTF-32, even simpler (and even more efficient code) is possible: a_string := {UTF_CONVERTER}.utf_32_string_to_utf_16_0 (string) Note that in that case, th .... Output truncated, Click download to get the full message
With the provided solution sent by Jocelyn in an email message, shall we close this report?
Hi Hubert, Sorry for the delay. There are many other features in STRING_32 (and other variants, including STRING_8) that do not ensure that there is null at the end, keep_head as an example. On the other hand, there is a feature to_c that makes sure that there is null at the end. I guess, users should be using to_c and do not expect that using area directly guarantees 0-terminated sequence of characters. In addition your suggestion would slow down Eiffel code. For C code, there is a dedicated mechanism already. So for now, I would suggest adapting your code that interfaces with C code, to either ensure you use the feature "to_c" , and avoid using string's area directly. Or eventually call directly " s.area.put ('%U', s.count) " if you really need a null character ending C memory for the associated SPECIAL object.
Dear Hubert, We are looking at the suggestion, and run our test suite.
This fixes a similar issue with 'remove_substring' in both STRING_32 and STRING_8 remove_substring (start_index, end_index: INTEGER) -- Remove all characters from `start_index' -- to `end_index' inclusive. local l_count, nb_removed: INTEGER do nb_removed := end_index - start_index + 1 if nb_removed > 0 then l_count := count area.overlapping_move (start_index + nb_removed - 1, start_index - 1, l_count - end_index + 1) area.remove_tail (nb_removed) count := l_count - nb_removed reset_hash_codes end end
Here are my changes which seem to resolve the issues in both 'left_adjust' and 'right_adjust' when it comes to adjusting the length and properly repositioning the null character '%U' left_adjust -- Remove leading whitespace. local nb, nb_space: INTEGER l_area: like area l_prop: like character_properties do l_prop := character_properties -- Compute number of spaces at the left of current string. from nb := count - 1 l_area := area until nb_space > nb or else not l_prop.is_space (l_area.item (nb_space)) loop nb_space := nb_space + 1 end if nb_space > 0 then -- Set new count value. nb := nb + 1 - nb_space -- Shift characters to the left. l_area.overlapping_move (nb_space, 0, nb + 1) l_area.remove_tail (nb_space) -- Set new count. count := nb reset_hash_codes end end right_adjust -- Remove trailing whitespace. local i, nb: INTEGER nb_space: INTEGER l_area: like are .... Output truncated, Click download to get the full message
Attachments for problem report #19830