/[eiffelstudio]/FreeELKS/trunk/library/kernel/string_32.e
ViewVC logotype

Annotation of /FreeELKS/trunk/library/kernel/string_32.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 91639 - (hide annotations)
Thu Nov 6 13:22:41 2008 UTC (11 years, 3 months ago) by kwaxer
File size: 43233 byte(s)
Added new features to separate creation of an object and its modification that allows to avoid errors related to initialization of attributes in void-safe mode.
1 manus_eiffel 91539 indexing
2     description: "[
3 manus_eiffel 91608 Sequences of 32-bit characters, accessible through integer indices
4 manus_eiffel 91539 in a contiguous range.
5     ]"
6     library: "Free implementation of ELKS library"
7 manus_eiffel 91592 copyright: "Copyright (c) 1986-2008, Eiffel Software and others"
8 manus_eiffel 91539 license: "Eiffel Forum License v2 (see forum.txt)"
9     date: "$Date: $"
10     revision: "$Revision: $"
11    
12     class
13     STRING_32
14    
15     inherit
16 manus_eiffel 91608
17     READABLE_STRING_32
18     export
19 manus_eiffel 91615 {ANY} make, make_empty, make_filled, make_from_c, make_from_string, fill_character
20 manus_eiffel 91608 redefine
21     item, infix "@", area
22     end
23    
24 manus_eiffel 91539 STRING_GENERAL
25     rename
26 manus_eiffel 91615 append as append_string_general,
27     same_string as same_string_general
28 manus_eiffel 91608 undefine
29     copy, is_equal, out
30 manus_eiffel 91539 redefine
31 manus_eiffel 91608 append_string_general
32 manus_eiffel 91539 end
33    
34     INDEXABLE [CHARACTER_32, INTEGER]
35     rename
36     item as item
37 manus_eiffel 91608 undefine
38     copy, is_equal, out
39 manus_eiffel 91539 redefine
40 manus_eiffel 91608 prune_all,
41 manus_eiffel 91539 changeable_comparison_criterion
42     end
43    
44     RESIZABLE [CHARACTER_32]
45 manus_eiffel 91608 undefine
46     copy, is_equal, out
47 manus_eiffel 91539 redefine
48     changeable_comparison_criterion
49     end
50    
51     TO_SPECIAL [CHARACTER_32]
52     rename
53     item as item
54 manus_eiffel 91608 undefine
55     copy, is_equal, out, item, infix "@", put, valid_index
56 manus_eiffel 91539 redefine
57 manus_eiffel 91608 area
58 manus_eiffel 91539 end
59    
60     MISMATCH_CORRECTOR
61 manus_eiffel 91608 undefine
62     copy, is_equal, out
63 manus_eiffel 91539 redefine
64 manus_eiffel 91608 correct_mismatch
65 manus_eiffel 91539 end
66    
67     create
68     make,
69     make_empty,
70     make_filled,
71     make_from_string,
72 kwaxer 91639 make_from_other_string,
73 manus_eiffel 91539 make_from_c,
74 kwaxer 91639 make_from_c_pointer,
75 manus_eiffel 91539 make_from_cil
76    
77     convert
78     to_cil: {SYSTEM_STRING},
79     make_from_cil ({SYSTEM_STRING}),
80 kwaxer 91639 as_string_8: {READABLE_STRING_8, STRING_8, ?STRING_8}
81 manus_eiffel 91539
82     feature -- Initialization
83    
84 manus_eiffel 91608 make_from_cil (a_system_string: SYSTEM_STRING)
85 manus_eiffel 91539 -- Initialize Current with `a_system_string'.
86     local
87     l_count: INTEGER
88     do
89     if a_system_string /= Void then
90     l_count := a_system_string.length
91 kwaxer 91628 end
92     make (l_count)
93     if l_count > 0 then
94 manus_eiffel 91638 set_count (l_count)
95 manus_eiffel 91539 dotnet_convertor.read_system_string_into (a_system_string, Current)
96     end
97     end
98    
99 manus_eiffel 91608 from_c (c_string: POINTER)
100 manus_eiffel 91539 -- Reset contents of string from contents of `c_string',
101     -- a string created by some C function.
102     require
103     c_string_exists: c_string /= default_pointer
104     local
105     l_count: INTEGER
106     do
107     c_string_provider.share_from_pointer (c_string)
108     -- Resize string in case it is not big enough
109     l_count := c_string_provider.count
110     resize (l_count + 1)
111     count := l_count
112     internal_hash_code := 0
113     c_string_provider.read_string_into (Current)
114     ensure
115     no_zero_byte: not has ('%/0/')
116     -- characters: for all i in 1..count, item (i) equals
117     -- ASCII character at address c_string + (i - 1)
118     -- correct_count: the ASCII character at address c_string + count
119     -- is NULL
120     end
121    
122 manus_eiffel 91608 from_c_substring (c_string: POINTER; start_pos, end_pos: INTEGER)
123 manus_eiffel 91539 -- Reset contents of string from substring of `c_string',
124     -- a string created by some C function.
125     require
126     c_string_exists: c_string /= default_pointer
127     start_position_big_enough: start_pos >= 1
128     end_position_big_enough: start_pos <= end_pos + 1
129     local
130     l_count: INTEGER
131     do
132     l_count := end_pos - start_pos + 1
133     c_string_provider.share_from_pointer_and_count (c_string + (start_pos - 1), l_count)
134     -- Resize string in case it is not big enough
135     resize (l_count + 1)
136     count := l_count
137     internal_hash_code := 0
138     c_string_provider.read_substring_into (Current, 1, l_count)
139     ensure
140     valid_count: count = end_pos - start_pos + 1
141     -- characters: for all i in 1..count, item (i) equals
142     -- ASCII character at address c_string + (i - 1)
143     end
144    
145 manus_eiffel 91608 adapt (s: STRING_32): like Current
146 manus_eiffel 91539 -- Object of a type conforming to the type of `s',
147     -- initialized with attributes from `s'
148     do
149     Result := new_string (0)
150     Result.share (s)
151     ensure
152     adapt_not_void: Result /= Void
153     shared_implementation: Result.shared_with (s)
154     end
155    
156     remake (n: INTEGER) is
157     -- Allocate space for at least `n' characters.
158     obsolete
159     "Use `make' instead"
160     require
161     non_negative_size: n >= 0
162     do
163     make (n)
164     ensure
165     empty_string: count = 0
166     area_allocated: capacity >= n
167     end
168    
169     feature -- Access
170    
171 manus_eiffel 91608 item, infix "@" (i: INTEGER): CHARACTER_32 assign put
172 manus_eiffel 91539 -- Character at position `i'
173     do
174     Result := area.item (i - 1)
175     end
176    
177 manus_eiffel 91608 area: SPECIAL [CHARACTER_32]
178     -- Storage for characters
179 manus_eiffel 91539
180     feature -- Status report
181    
182     extendible: BOOLEAN is True
183     -- May new items be added? (Answer: yes.)
184    
185     prunable: BOOLEAN is
186     -- May items be removed? (Answer: yes.)
187     do
188     Result := True
189     end
190    
191     changeable_comparison_criterion: BOOLEAN is False
192    
193     feature -- Element change
194    
195 manus_eiffel 91608 set (t: like Current; n1, n2: INTEGER)
196 manus_eiffel 91539 -- Set current string to substring of `t' from indices `n1'
197     -- to `n2', or to empty string if no such substring.
198     require
199     argument_not_void: t /= Void
200     local
201     s: STRING_32
202     do
203     s := t.substring (n1, n2)
204     area := s.area
205     count := s.count
206     internal_hash_code := 0
207     ensure
208     is_substring: is_equal (t.substring (n1, n2))
209     end
210    
211 manus_eiffel 91608 subcopy (other: like Current; start_pos, end_pos, index_pos: INTEGER)
212 manus_eiffel 91539 -- Copy characters of `other' within bounds `start_pos' and
213     -- `end_pos' to current string starting at index `index_pos'.
214     require
215     other_not_void: other /= Void
216     valid_start_pos: other.valid_index (start_pos)
217     valid_end_pos: other.valid_index (end_pos)
218     valid_bounds: (start_pos <= end_pos) or (start_pos = end_pos + 1)
219     valid_index_pos: valid_index (index_pos)
220     enough_space: (count - index_pos) >= (end_pos - start_pos)
221     local
222     l_other_area, l_area: like area
223     do
224     l_other_area := other.area
225     l_area := area
226     if end_pos >= start_pos then
227     if l_area /= l_other_area then
228     l_area.copy_data (l_other_area, start_pos - 1, index_pos - 1,
229     end_pos - start_pos + 1)
230     else
231     l_area.overlapping_move (start_pos - 1, index_pos - 1,
232     end_pos - start_pos + 1)
233     end
234     internal_hash_code := 0
235     end
236     ensure
237     same_count: count = old count
238     copied: elks_checking implies
239     (is_equal (old substring (1, index_pos - 1) +
240     old other.substring (start_pos, end_pos) +
241     old substring (index_pos + (end_pos - start_pos + 1), count)))
242     end
243    
244 manus_eiffel 91608 replace_substring (s: READABLE_STRING_32; start_index, end_index: INTEGER)
245 manus_eiffel 91539 -- Replace characters from `start_index' to `end_index' with `s'.
246     require
247     string_not_void: s /= Void
248     valid_start_index: 1 <= start_index
249     valid_end_index: end_index <= count
250     meaningfull_interval: start_index <= end_index + 1
251     local
252     new_size: INTEGER
253     diff: INTEGER
254     l_area: like area
255     s_count: INTEGER
256     old_count: INTEGER
257     do
258     s_count := s.count
259     old_count := count
260     diff := s_count - (end_index - start_index + 1)
261     new_size := diff + old_count
262     if diff > 0 then
263     -- We need to resize the string.
264     grow (new_size)
265     end
266    
267     l_area := area
268     --| We move the end of the string forward (if diff is > 0), backward (if diff < 0),
269     --| and nothing otherwise.
270     if diff /= 0 then
271     l_area.overlapping_move (end_index, end_index + diff, old_count - end_index)
272     end
273     --| Set new count
274     set_count (new_size)
275     --| We copy the substring.
276     l_area.copy_data (s.area, 0, start_index - 1, s_count)
277     ensure
278     new_count: count = old count + old s.count - end_index + start_index - 1
279     replaced: elks_checking implies
280     (is_equal (old (substring (1, start_index - 1) +
281     s + substring (end_index + 1, count))))
282     end
283    
284     replace_substring_all (original, new: like Current) is
285     -- Replace every occurrence of `original' with `new'.
286     require
287     original_exists: original /= Void
288     new_exists: new /= Void
289     original_not_empty: not original.is_empty
290     original_is_valid_as_string_8: original.is_valid_as_string_8
291     local
292     l_first_pos, l_next_pos: INTEGER
293     l_orig_count, l_new_count, l_count: INTEGER
294     l_area, l_new_area: like area
295     l_offset: INTEGER
296     l_string_searcher: like string_searcher
297     do
298     if not is_empty then
299     l_count := count
300     l_string_searcher := string_searcher
301     l_string_searcher.initialize_deltas (original)
302     l_first_pos := l_string_searcher.substring_index_with_deltas (Current, original, 1, l_count)
303     if l_first_pos > 0 then
304     l_orig_count := original.count
305     l_new_count := new.count
306     if l_orig_count = l_new_count then
307     -- String will not be resized, simply perform character substitution
308     from
309     l_area := area
310     l_new_area := new.area
311     until
312     l_first_pos = 0
313     loop
314     l_area.copy_data (l_new_area, 0, l_first_pos - 1, l_new_count)
315     if l_first_pos + l_new_count <= l_count then
316     l_first_pos := l_string_searcher.substring_index_with_deltas (Current, original, l_first_pos + l_new_count, l_count)
317     else
318     l_first_pos := 0
319     end
320     end
321     elseif l_orig_count > l_new_count then
322     -- New string is smaller than previous string, we can optimize
323     -- substitution by only moving block between two occurrences of `orginal'.
324     from
325     l_next_pos := l_string_searcher.substring_index_with_deltas (Current, original, l_first_pos + l_orig_count, l_count)
326     l_area := area
327     l_new_area := new.area
328     until
329     l_next_pos = 0
330     loop
331     -- Copy new string into Current
332     l_area.copy_data (l_new_area, 0, l_first_pos - 1 - l_offset, l_new_count)
333     -- Shift characters between `l_first_pos' and `l_next_pos'
334     l_area.overlapping_move (l_first_pos + l_orig_count - 1,
335     l_first_pos + l_new_count - 1 - l_offset, l_next_pos - l_first_pos - l_orig_count)
336     l_first_pos := l_next_pos
337     l_offset := l_offset + (l_orig_count - l_new_count)
338     if l_first_pos + l_new_count <= l_count then
339     l_next_pos := l_string_searcher.substring_index_with_deltas (Current, original, l_first_pos + l_orig_count, l_count)
340     else
341     l_next_pos := 0
342     end
343     end
344     -- Perform final substitution:
345     -- Copy new string into Current
346     l_area.copy_data (l_new_area, 0, l_first_pos - 1 - l_offset, l_new_count)
347     -- Shift characters between `l_first_pos' and the end of the string
348     l_area.overlapping_move (l_first_pos + l_orig_count - 1,
349     l_first_pos + l_new_count - 1 - l_offset, l_count + 1 - l_first_pos - l_orig_count)
350     -- Perform last substitution
351     l_offset := l_offset + (l_orig_count - l_new_count)
352    
353     -- Update `count'
354     set_count (l_count - l_offset)
355     else
356     -- Optimization is harder as we don't know how many times we need to resize
357     -- the string. For now, we do like we did in our previous implementation
358     from
359     until
360     l_first_pos = 0
361     loop
362     replace_substring (new, l_first_pos, l_first_pos + l_orig_count - 1)
363     l_count := count
364     if l_first_pos + l_new_count <= l_count then
365     l_first_pos := l_string_searcher.substring_index_with_deltas (Current, original, l_first_pos + l_new_count, l_count)
366     else
367     l_first_pos := 0
368     end
369     end
370     end
371     internal_hash_code := 0
372     end
373     end
374     end
375    
376 manus_eiffel 91608 replace_blank
377 manus_eiffel 91539 -- Replace all current characters with blanks.
378     do
379     fill_with (' ')
380     ensure
381     same_size: (count = old count) and (capacity >= old capacity)
382     all_blank: elks_checking implies occurrences (' ') = count
383     end
384    
385 manus_eiffel 91608 fill_blank
386 manus_eiffel 91539 -- Fill with `capacity' blank characters.
387     do
388     fill_character (' ')
389     ensure
390     filled: full
391     same_size: (count = capacity) and (capacity = old capacity)
392     -- all_blank: For every `i' in `count'..`capacity', `item' (`i') = `Blank'
393     end
394    
395 manus_eiffel 91608 fill_with (c: CHARACTER_32)
396 manus_eiffel 91539 -- Replace every character with `c'.
397     local
398     l_count: INTEGER
399     do
400     l_count := count
401     if l_count /= 0 then
402     area.fill_with (c, 0, count - 1)
403     internal_hash_code := 0
404     end
405     ensure
406     same_count: (count = old count) and (capacity >= old capacity)
407     filled: elks_checking implies occurrences (c) = count
408     end
409    
410 manus_eiffel 91608 replace_character (c: CHARACTER_32)
411 manus_eiffel 91539 -- Replace every character with `c'.
412     obsolete
413     "ELKS 2001: use `fill_with' instead'"
414     do
415     fill_with (c)
416     ensure
417     same_count: (count = old count) and (capacity >= old capacity)
418     filled: elks_checking implies occurrences (c) = count
419     end
420    
421 manus_eiffel 91608 head (n: INTEGER)
422 manus_eiffel 91539 -- Remove all characters except for the first `n';
423     -- do nothing if `n' >= `count'.
424     obsolete
425     "ELKS 2001: use `keep_head' instead'"
426     require
427     non_negative_argument: n >= 0
428     do
429     keep_head (n)
430     ensure
431     new_count: count = n.min (old count)
432     kept: elks_checking implies is_equal (old substring (1, n.min (count)))
433     end
434    
435 manus_eiffel 91608 keep_head (n: INTEGER)
436 manus_eiffel 91539 -- Remove all characters except for the first `n';
437     -- do nothing if `n' >= `count'.
438     require
439     non_negative_argument: n >= 0
440     do
441     if n < count then
442     count := n
443     internal_hash_code := 0
444     end
445     ensure
446     new_count: count = n.min (old count)
447     kept: elks_checking implies is_equal (old substring (1, n.min (count)))
448     end
449    
450 manus_eiffel 91608 tail (n: INTEGER)
451 manus_eiffel 91539 -- Remove all characters except for the last `n';
452     -- do nothing if `n' >= `count'.
453     obsolete
454     "ELKS 2001: use `keep_tail' instead'"
455     require
456     non_negative_argument: n >= 0
457     do
458     keep_tail (n)
459     ensure
460     new_count: count = n.min (old count)
461     kept: elks_checking implies is_equal (old substring (count - n.min(count) + 1, count))
462     end
463    
464 manus_eiffel 91608 keep_tail (n: INTEGER)
465 manus_eiffel 91539 -- Remove all characters except for the last `n';
466     -- do nothing if `n' >= `count'.
467     require
468     non_negative_argument: n >= 0
469     local
470     nb: like count
471     do
472     nb := count
473     if n < nb then
474     area.overlapping_move (nb - n, 0, n)
475     count := n
476     internal_hash_code := 0
477     end
478     ensure
479     new_count: count = n.min (old count)
480     kept: elks_checking implies is_equal (old substring (count - n.min(count) + 1, count))
481     end
482    
483 manus_eiffel 91608 left_adjust
484 manus_eiffel 91539 -- Remove leading whitespace.
485     require
486     is_valid_as_string_8: is_valid_as_string_8
487     local
488     nb, nb_space: INTEGER
489     l_area: like area
490     do
491     -- Compute number of spaces at the left of current string.
492     from
493     nb := count - 1
494     l_area := area
495     until
496     nb_space > nb or else not l_area.item (nb_space).is_space
497     loop
498     nb_space := nb_space + 1
499     end
500    
501     if nb_space > 0 then
502     -- Set new count value.
503     nb := nb + 1 - nb_space
504     -- Shift characters to the left.
505     l_area.overlapping_move (nb_space, 0, nb)
506     -- Set new count.
507     count := nb
508     internal_hash_code := 0
509     end
510     ensure
511     valid_count: count <= old count
512     new_count: not is_empty implies not item (1).is_space
513     kept: elks_checking implies is_equal ((old twin).substring (old count - count + 1, old count))
514     end
515    
516 manus_eiffel 91608 right_adjust
517 manus_eiffel 91539 -- Remove trailing whitespace.
518     require
519     is_valid_as_string_8: is_valid_as_string_8
520     local
521     i, nb: INTEGER
522     nb_space: INTEGER
523     l_area: like area
524     do
525     -- Compute number of spaces at the right of current string.
526     from
527     nb := count - 1
528     i := nb
529     l_area := area
530     until
531     i < 0 or else not l_area.item (i).is_space
532     loop
533     nb_space := nb_space + 1
534     i := i - 1
535     end
536    
537     if nb_space > 0 then
538     -- Set new count.
539     count := nb + 1 - nb_space
540     internal_hash_code := 0
541     end
542     ensure
543     valid_count: count <= old count
544     new_count: (count /= 0) implies
545     ((item (count) /= ' ') and
546     (item (count) /= '%T') and
547     (item (count) /= '%R') and
548     (item (count) /= '%N'))
549     kept: elks_checking implies is_equal ((old twin).substring (1, count))
550     end
551    
552 manus_eiffel 91608 share (other: STRING_32)
553 manus_eiffel 91539 -- Make current string share the text of `other'.
554     -- Subsequent changes to the characters of current string
555     -- will also affect `other', and conversely.
556     require
557     argument_not_void: other /= Void
558     do
559     area := other.area
560     count := other.count
561     internal_hash_code := 0
562     ensure
563     shared_count: other.count = count
564     shared_area: other.area = area
565     end
566    
567 manus_eiffel 91608 put (c: CHARACTER_32; i: INTEGER)
568 manus_eiffel 91539 -- Replace character at position `i' by `c'.
569     do
570     area.put (c, i - 1)
571     internal_hash_code := 0
572     ensure then
573     stable_count: count = old count
574     stable_before_i: elks_checking implies substring (1, i - 1).is_equal (old substring (1, i - 1))
575     stable_after_i: elks_checking implies substring (i + 1, count).is_equal (old substring (i + 1, count))
576     end
577    
578 manus_eiffel 91608 put_code (v: NATURAL_32; i: INTEGER)
579 manus_eiffel 91539 -- Replace character at position `i' by character of code `v'.
580     do
581     area.put (v.to_character_32, i - 1)
582     internal_hash_code := 0
583     end
584    
585 manus_eiffel 91608 precede, prepend_character (c: CHARACTER_32)
586 manus_eiffel 91539 -- Add `c' at front.
587     local
588     l_area: like area
589     do
590     if count = capacity then
591     resize (count + additional_space)
592     end
593     l_area := area
594     l_area.overlapping_move (0, 1, count)
595     l_area.put (c, 0)
596     count := count + 1
597     internal_hash_code := 0
598     ensure
599     new_count: count = old count + 1
600     end
601    
602 manus_eiffel 91608 prepend (s: READABLE_STRING_32)
603 manus_eiffel 91539 -- Prepend a copy of `s' at front.
604     require
605     argument_not_void: s /= Void
606     do
607     insert_string (s, 1)
608     ensure
609     new_count: count = old (count + s.count)
610 manus_eiffel 91608 inserted: elks_checking implies string.is_equal (old (s.twin.as_string_32) + old substring (1, count))
611 manus_eiffel 91539 end
612    
613 manus_eiffel 91608 prepend_boolean (b: BOOLEAN)
614 manus_eiffel 91539 -- Prepend the string representation of `b' at front.
615     do
616     prepend (b.out)
617     end
618    
619 manus_eiffel 91608 prepend_double (d: DOUBLE)
620 manus_eiffel 91539 -- Prepend the string representation of `d' at front.
621     do
622     prepend (d.out)
623     end
624    
625 manus_eiffel 91608 prepend_integer (i: INTEGER)
626 manus_eiffel 91539 -- Prepend the string representation of `i' at front.
627     do
628     prepend (i.out)
629     end
630    
631 manus_eiffel 91608 prepend_real (r: REAL)
632 manus_eiffel 91539 -- Prepend the string representation of `r' at front.
633     do
634     prepend (r.out)
635     end
636    
637 manus_eiffel 91608 prepend_string (s: READABLE_STRING_32)
638 manus_eiffel 91539 -- Prepend a copy of `s', if not void, at front.
639     do
640     if s /= Void then
641     prepend (s)
642     end
643     end
644    
645 manus_eiffel 91608 append_string_general (s: READABLE_STRING_GENERAL)
646 manus_eiffel 91539 -- Append a copy of `s' at end.
647     do
648 manus_eiffel 91608 if {l_s32: READABLE_STRING_32} s then
649 manus_eiffel 91539 append (l_s32)
650     else
651     Precursor {STRING_GENERAL} (s)
652     end
653     end
654    
655 manus_eiffel 91608 append (s: READABLE_STRING_32)
656 manus_eiffel 91539 -- Append a copy of `s' at end.
657     require
658     argument_not_void: s /= Void
659     local
660     l_count, l_s_count, l_new_size: INTEGER
661     do
662     l_s_count := s.count
663     if l_s_count > 0 then
664     l_count := count
665     l_new_size := l_s_count + l_count
666     if l_new_size > capacity then
667     resize (l_new_size + additional_space)
668     end
669     area.copy_data (s.area, 0, l_count, l_s_count)
670     count := l_new_size
671     internal_hash_code := 0
672     end
673     ensure
674     new_count: count = old count + old s.count
675     appended: elks_checking implies is_equal (old twin + old s.twin)
676     end
677    
678 manus_eiffel 91608 infix "+" (s: READABLE_STRING_32): like Current
679 manus_eiffel 91539 -- Append a copy of 's' at the end of a copy of Current,
680     -- Then return the Result.
681     do
682     Result := new_string (count + s.count)
683     Result.append (Current)
684     Result.append (s)
685     end
686    
687 manus_eiffel 91608 append_string (s: READABLE_STRING_32)
688 manus_eiffel 91539 -- Append a copy of `s', if not void, at end.
689     do
690     if s /= Void then
691     append (s)
692     end
693     ensure
694     appended: s /= Void implies
695     (elks_checking implies is_equal (old twin + old s.twin))
696     end
697    
698 manus_eiffel 91608 append_integer (i: INTEGER)
699 manus_eiffel 91539 -- Append the string representation of `i' at end.
700     local
701     l_value: INTEGER
702     l_starting_index, l_ending_index: INTEGER
703     l_temp: CHARACTER_32
704     l_area: like area
705     do
706     if i = 0 then
707     append_character ('0')
708     else
709     -- Extract integer value digit by digit from right to left.
710     from
711     l_starting_index := count
712     if i < 0 then
713     append_character ('-')
714     l_starting_index := l_starting_index + 1
715     -- Special case for minimum integer value as negating it
716     -- as no effect.
717     if i = {INTEGER}.Min_value then
718     append_character ('8')
719     l_value := -(i // 10)
720     else
721     l_value := -i
722     end
723     else
724     l_value := i
725     end
726     until
727     l_value = 0
728     loop
729     append_character (((l_value \\ 10)+ 48).to_character_32)
730     l_value := l_value // 10
731     end
732    
733     -- Now put digits in correct order from left to right.
734     from
735     l_ending_index := count - 1
736     l_area := area
737     until
738     l_starting_index >= l_ending_index
739     loop
740     l_temp := l_area.item (l_starting_index)
741     l_area.put (l_area.item (l_ending_index), l_starting_index)
742     l_area.put (l_temp, l_ending_index)
743     l_ending_index := l_ending_index - 1
744     l_starting_index := l_starting_index + 1
745     end
746     end
747     end
748    
749 manus_eiffel 91608 append_integer_8 (i: INTEGER_8)
750 manus_eiffel 91539 -- Append the string representation of `i' at end.
751     local
752     l_value: INTEGER_8
753     l_starting_index, l_ending_index: INTEGER
754     l_temp: CHARACTER_32
755     l_area: like area
756     do
757     if i = 0 then
758     append_character ('0')
759     else
760     -- Extract integer value digit by digit from right to left.
761     from
762     l_starting_index := count
763     if i < 0 then
764     append_character ('-')
765     l_starting_index := l_starting_index + 1
766     -- Special case for minimum integer value as negating it
767     -- as no effect.
768     if i = {INTEGER_8}.Min_value then
769     append_character ('8')
770     l_value := -(i // 10)
771     else
772     l_value := -i
773     end
774     else
775     l_value := i
776     end
777     until
778     l_value = 0
779     loop
780     append_character (((l_value \\ 10)+ 48).to_character_32)
781     l_value := l_value // 10
782     end
783    
784     -- Now put digits in correct order from left to right.
785     from
786     l_ending_index := count - 1
787     l_area := area
788     until
789     l_starting_index >= l_ending_index
790     loop
791     l_temp := l_area.item (l_starting_index)
792     l_area.put (l_area.item (l_ending_index), l_starting_index)
793     l_area.put (l_temp, l_ending_index)
794     l_ending_index := l_ending_index - 1
795     l_starting_index := l_starting_index + 1
796     end
797     end
798     end
799    
800 manus_eiffel 91608 append_integer_16 (i: INTEGER_16)
801 manus_eiffel 91539 -- Append the string representation of `i' at end.
802     local
803     l_value: INTEGER_16
804     l_starting_index, l_ending_index: INTEGER
805     l_temp: CHARACTER_32
806     l_area: like area
807     do
808     if i = 0 then
809     append_character ('0')
810     else
811     -- Extract integer value digit by digit from right to left.
812     from
813     l_starting_index := count
814     if i < 0 then
815     append_character ('-')
816     l_starting_index := l_starting_index + 1
817     -- Special case for minimum integer value as negating it
818     -- as no effect.
819     if i = {INTEGER_16}.Min_value then
820     append_character ('8')
821     l_value := -(i // 10)
822     else
823     l_value := -i
824     end
825     else
826     l_value := i
827     end
828     until
829     l_value = 0
830     loop
831     append_character (((l_value \\ 10)+ 48).to_character_32)
832     l_value := l_value // 10
833     end
834    
835     -- Now put digits in correct order from left to right.
836     from
837     l_ending_index := count - 1
838     l_area := area
839     until
840     l_starting_index >= l_ending_index
841     loop
842     l_temp := l_area.item (l_starting_index)
843     l_area.put (l_area.item (l_ending_index), l_starting_index)
844     l_area.put (l_temp, l_ending_index)
845     l_ending_index := l_ending_index - 1
846     l_starting_index := l_starting_index + 1
847     end
848     end
849     end
850    
851 manus_eiffel 91608 append_integer_64 (i: INTEGER_64)
852 manus_eiffel 91539 -- Append the string representation of `i' at end.
853     local
854     l_value: INTEGER_64
855     l_starting_index, l_ending_index: INTEGER
856     l_temp: CHARACTER_32
857     l_area: like area
858     do
859     if i = 0 then
860     append_character ('0')
861     else
862     -- Extract integer value digit by digit from right to left.
863     from
864     l_starting_index := count
865     if i < 0 then
866     append_character ('-')
867     l_starting_index := l_starting_index + 1
868     -- Special case for minimum integer value as negating it
869     -- as no effect.
870     if i = {INTEGER_64}.Min_value then
871     append_character ('8')
872     l_value := -(i // 10)
873     else
874     l_value := -i
875     end
876     else
877     l_value := i
878     end
879     until
880     l_value = 0
881     loop
882     append_character (((l_value \\ 10)+ 48).to_character_32)
883     l_value := l_value // 10
884     end
885    
886     -- Now put digits in correct order from left to right.
887     from
888     l_ending_index := count - 1
889     l_area := area
890     until
891     l_starting_index >= l_ending_index
892     loop
893     l_temp := l_area.item (l_starting_index)
894     l_area.put (l_area.item (l_ending_index), l_starting_index)
895     l_area.put (l_temp, l_ending_index)
896     l_ending_index := l_ending_index - 1
897     l_starting_index := l_starting_index + 1
898     end
899     end
900     end
901    
902 manus_eiffel 91608 append_natural_8 (i: NATURAL_8)
903 manus_eiffel 91539 -- Append the string representation of `i' at end.
904     local
905     l_value: NATURAL_8
906     l_starting_index, l_ending_index: INTEGER
907     l_temp: CHARACTER_32
908     l_area: like area
909     do
910     if i = 0 then
911     append_character ('0')
912     else
913     -- Extract integer value digit by digit from right to left.
914     from
915     l_starting_index := count
916     l_value := i
917     until
918     l_value = 0
919     loop
920     append_character (((l_value \\ 10)+ 48).to_character_32)
921     l_value := l_value // 10
922     end
923    
924     -- Now put digits in correct order from left to right.
925     from
926     l_ending_index := count - 1
927     l_area := area
928     until
929     l_starting_index >= l_ending_index
930     loop
931     l_temp := l_area.item (l_starting_index)
932     l_area.put (l_area.item (l_ending_index), l_starting_index)
933     l_area.put (l_temp, l_ending_index)
934     l_ending_index := l_ending_index - 1
935     l_starting_index := l_starting_index + 1
936     end
937     end
938     end
939    
940 manus_eiffel 91608 append_natural_16 (i: NATURAL_16)
941 manus_eiffel 91539 -- Append the string representation of `i' at end.
942     local
943     l_value: NATURAL_16
944     l_starting_index, l_ending_index: INTEGER
945     l_temp: CHARACTER_32
946     l_area: like area
947     do
948     if i = 0 then
949     append_character ('0')
950     else
951     -- Extract integer value digit by digit from right to left.
952     from
953     l_starting_index := count
954     l_value := i
955     until
956     l_value = 0
957     loop
958     append_character (((l_value \\ 10)+ 48).to_character_32)
959     l_value := l_value // 10
960     end
961    
962     -- Now put digits in correct order from left to right.
963     from
964     l_ending_index := count - 1
965     l_area := area
966     until
967     l_starting_index >= l_ending_index
968     loop
969     l_temp := l_area.item (l_starting_index)
970     l_area.put (l_area.item (l_ending_index), l_starting_index)
971     l_area.put (l_temp, l_ending_index)
972     l_ending_index := l_ending_index - 1
973     l_starting_index := l_starting_index + 1
974     end
975     end
976     end
977    
978 manus_eiffel 91608 append_natural_32 (i: NATURAL_32)
979 manus_eiffel 91539 -- Append the string representation of `i' at end.
980     local
981     l_value: NATURAL_32
982     l_starting_index, l_ending_index: INTEGER
983     l_temp: CHARACTER_32
984     l_area: like area
985     do
986     if i = 0 then
987     append_character ('0')
988     else
989     -- Extract integer value digit by digit from right to left.
990     from
991     l_starting_index := count
992     l_value := i
993     until
994     l_value = 0
995     loop
996     append_character (((l_value \\ 10)+ 48).to_character_32)
997     l_value := l_value // 10
998     end
999    
1000     -- Now put digits in correct order from left to right.
1001     from
1002     l_ending_index := count - 1
1003     l_area := area
1004     until
1005     l_starting_index >= l_ending_index
1006     loop
1007     l_temp := l_area.item (l_starting_index)
1008     l_area.put (l_area.item (l_ending_index), l_starting_index)
1009     l_area.put (l_temp, l_ending_index)
1010     l_ending_index := l_ending_index - 1
1011     l_starting_index := l_starting_index + 1
1012     end
1013     end
1014     end
1015    
1016 manus_eiffel 91608 append_natural_64 (i: NATURAL_64)
1017 manus_eiffel 91539 -- Append the string representation of `i' at end.
1018     local
1019     l_value: NATURAL_64
1020     l_starting_index, l_ending_index: INTEGER
1021     l_temp: CHARACTER_32
1022     l_area: like area
1023     do
1024     if i = 0 then
1025     append_character ('0')
1026     else
1027     -- Extract integer value digit by digit from right to left.
1028     from
1029     l_starting_index := count
1030     l_value := i
1031     until
1032     l_value = 0
1033     loop
1034     append_character (((l_value \\ 10)+ 48).to_character_32)
1035     l_value := l_value // 10
1036     end
1037    
1038     -- Now put digits in correct order from left to right.
1039     from
1040     l_ending_index := count - 1
1041     l_area := area
1042     until
1043     l_starting_index >= l_ending_index
1044     loop
1045     l_temp := l_area.item (l_starting_index)
1046     l_area.put (l_area.item (l_ending_index), l_starting_index)
1047     l_area.put (l_temp, l_ending_index)
1048     l_ending_index := l_ending_index - 1
1049     l_starting_index := l_starting_index + 1
1050     end
1051     end
1052     end
1053    
1054 manus_eiffel 91608 append_real (r: REAL)
1055 manus_eiffel 91539 -- Append the string representation of `r' at end.
1056     do
1057     append (r.out)
1058     end
1059    
1060 manus_eiffel 91608 append_double (d: DOUBLE)
1061 manus_eiffel 91539 -- Append the string representation of `d' at end.
1062     do
1063     append (d.out)
1064     end
1065    
1066 manus_eiffel 91608 append_character, extend (c: CHARACTER_32)
1067 manus_eiffel 91539 -- Append `c' at end.
1068     local
1069     current_count: INTEGER
1070     do
1071     current_count := count
1072     if current_count = capacity then
1073     resize (current_count + additional_space)
1074     end
1075     area.put (c, current_count)
1076     count := current_count + 1
1077     internal_hash_code := 0
1078     ensure then
1079     item_inserted: item (count) = c
1080     new_count: count = old count + 1
1081     stable_before: elks_checking implies substring (1, count - 1).is_equal (old twin)
1082     end
1083    
1084 manus_eiffel 91608 append_boolean (b: BOOLEAN)
1085 manus_eiffel 91539 -- Append the string representation of `b' at end.
1086     do
1087     append (b.out)
1088     end
1089    
1090 manus_eiffel 91608 insert (s: READABLE_STRING_32; i: INTEGER)
1091 manus_eiffel 91539 -- Add `s' to left of position `i' in current string.
1092     obsolete
1093     "ELKS 2001: use `insert_string' instead"
1094     require
1095     string_exists: s /= Void
1096     index_small_enough: i <= count + 1
1097     index_large_enough: i > 0
1098     do
1099     insert_string (s, i)
1100     ensure
1101     inserted: elks_checking implies
1102     (is_equal (old substring (1, i - 1) + old (s.twin) + old substring (i, count)))
1103     end
1104    
1105 manus_eiffel 91608 insert_string (s: READABLE_STRING_32; i: INTEGER)
1106 manus_eiffel 91539 -- Insert `s' at index `i', shifting characters between ranks
1107     -- `i' and `count' rightwards.
1108     require
1109     string_exists: s /= Void
1110     valid_insertion_index: 1 <= i and i <= count + 1
1111     local
1112     pos, new_size: INTEGER
1113     l_s_count: INTEGER
1114     l_area: like area
1115     do
1116     -- Insert `s' if `s' is not empty, otherwise is useless.
1117     l_s_count := s.count
1118     if l_s_count /= 0 then
1119     -- Resize Current if necessary.
1120     new_size := l_s_count + count
1121     if new_size > capacity then
1122     resize (new_size + additional_space)
1123     end
1124    
1125     -- Perform all operations using a zero based arrays.
1126     l_area := area
1127     pos := i - 1
1128    
1129     -- First shift from `s.count' position all characters starting at index `pos'.
1130     l_area.overlapping_move (pos, pos + l_s_count, count - pos)
1131    
1132     -- Copy string `s' at index `pos'.
1133     l_area.copy_data (s.area, 0, pos, l_s_count)
1134    
1135     count := new_size
1136     internal_hash_code := 0
1137     end
1138     ensure
1139     inserted: elks_checking implies
1140     (is_equal (old substring (1, i - 1) + old (s.twin) + old substring (i, count)))
1141     end
1142    
1143 manus_eiffel 91608 insert_character (c: CHARACTER_32; i: INTEGER)
1144 manus_eiffel 91539 -- Insert `c' at index `i', shifting characters between ranks
1145     -- `i' and `count' rightwards.
1146     require
1147     valid_insertion_index: 1 <= i and i <= count + 1
1148     local
1149     pos, new_size: INTEGER
1150     l_area: like area
1151     do
1152     -- Resize Current if necessary.
1153     new_size := 1 + count
1154     if new_size > capacity then
1155     resize (new_size + additional_space)
1156     end
1157    
1158     -- Perform all operations using a zero based arrays.
1159     pos := i - 1
1160     l_area := area
1161    
1162     -- First shift from `s.count' position all characters starting at index `pos'.
1163     l_area.overlapping_move (pos, pos + 1, count - pos)
1164    
1165     -- Insert new character
1166     l_area.put (c, pos)
1167    
1168     count := new_size
1169     internal_hash_code := 0
1170     ensure
1171     one_more_character: count = old count + 1
1172     inserted: item (i) = c
1173     stable_before_i: elks_checking implies substring (1, i - 1).is_equal (old substring (1, i - 1))
1174     stable_after_i: elks_checking implies substring (i + 1, count).is_equal (old substring (i, count))
1175     end
1176    
1177     feature -- Removal
1178    
1179 manus_eiffel 91608 remove (i: INTEGER)
1180 manus_eiffel 91539 -- Remove `i'-th character.
1181     local
1182     l_count: INTEGER
1183     do
1184     l_count := count
1185     -- Shift characters to the left.
1186     area.overlapping_move (i, i - 1, l_count - i)
1187     -- Update content.
1188     count := l_count - 1
1189     internal_hash_code := 0
1190     end
1191    
1192 manus_eiffel 91608 remove_head (n: INTEGER)
1193 manus_eiffel 91539 -- Remove first `n' characters;
1194     -- if `n' > `count', remove all.
1195     require
1196     n_non_negative: n >= 0
1197     do
1198     if n > count then
1199     count := 0
1200     internal_hash_code := 0
1201     else
1202     keep_tail (count - n)
1203     end
1204     ensure
1205     removed: elks_checking implies is_equal (old substring (n.min (count) + 1, count))
1206     end
1207    
1208 manus_eiffel 91608 remove_substring (start_index, end_index: INTEGER)
1209 manus_eiffel 91539 -- Remove all characters from `start_index'
1210     -- to `end_index' inclusive.
1211     require
1212     valid_start_index: 1 <= start_index
1213     valid_end_index: end_index <= count
1214     meaningful_interval: start_index <= end_index + 1
1215     local
1216     l_count, nb_removed: INTEGER
1217     do
1218     nb_removed := end_index - start_index + 1
1219     if nb_removed > 0 then
1220     l_count := count
1221     area.overlapping_move (start_index + nb_removed - 1, start_index - 1, l_count - end_index)
1222     count := l_count - nb_removed
1223     end
1224     ensure
1225     removed: elks_checking implies
1226     is_equal (old substring (1, start_index - 1) + old substring (end_index + 1, count))
1227     end
1228    
1229 manus_eiffel 91608 remove_tail (n: INTEGER)
1230 manus_eiffel 91539 -- Remove last `n' characters;
1231     -- if `n' > `count', remove all.
1232     require
1233     n_non_negative: n >= 0
1234     local
1235     l_count: INTEGER
1236     do
1237     l_count := count
1238     if n > l_count then
1239     count := 0
1240     internal_hash_code := 0
1241     else
1242     keep_head (l_count - n)
1243     end
1244     ensure
1245     removed: elks_checking implies is_equal (old substring (1, count - n.min (count)))
1246     end
1247    
1248 manus_eiffel 91608 prune (c: CHARACTER_32)
1249 manus_eiffel 91539 -- Remove first occurrence of `c', if any.
1250     require else
1251     True
1252     local
1253     counter: INTEGER
1254     do
1255     from
1256     counter := 1
1257     until
1258     counter > count or else (item (counter) = c)
1259     loop
1260     counter := counter + 1
1261     end
1262     if counter <= count then
1263     remove (counter)
1264     end
1265     end
1266    
1267 manus_eiffel 91608 prune_all (c: CHARACTER_32)
1268 manus_eiffel 91539 -- Remove all occurrences of `c'.
1269     require else
1270     True
1271     local
1272     i, j, nb: INTEGER
1273     l_area: like area
1274     l_char: CHARACTER_32
1275     do
1276     -- Traverse string and shift characters to the left
1277     -- each time we find an occurrence of `c'.
1278     from
1279     l_area := area
1280     nb := count
1281     until
1282     i = nb
1283     loop
1284     l_char := l_area.item (i)
1285     if l_char /= c then
1286     l_area.put (l_char, j)
1287     j := j + 1
1288     end
1289     i := i + 1
1290     end
1291     count := j
1292     internal_hash_code := 0
1293     ensure then
1294     changed_count: count = (old count) - (old occurrences (c))
1295     -- removed: For every `i' in 1..`count', `item' (`i') /= `c'
1296     end
1297    
1298 manus_eiffel 91608 prune_all_leading (c: CHARACTER_32)
1299 manus_eiffel 91539 -- Remove all leading occurrences of `c'.
1300     do
1301     from
1302     until
1303     is_empty or else item (1) /= c
1304     loop
1305     remove (1)
1306     end
1307     end
1308    
1309 manus_eiffel 91608 prune_all_trailing (c: CHARACTER_32)
1310 manus_eiffel 91539 -- Remove all trailing occurrences of `c'.
1311     do
1312     from
1313     until
1314     is_empty or else item (count) /= c
1315     loop
1316     remove (count)
1317     end
1318     end
1319    
1320 manus_eiffel 91608 wipe_out
1321 manus_eiffel 91539 -- Remove all characters.
1322     do
1323     create area.make (1)
1324     count := 0
1325     internal_hash_code := 0
1326     ensure then
1327     is_empty: count = 0
1328     empty_capacity: capacity = 0
1329     end
1330    
1331 manus_eiffel 91608 clear_all
1332 manus_eiffel 91539 -- Reset all characters.
1333     do
1334     count := 0
1335     internal_hash_code := 0
1336     ensure
1337     is_empty: count = 0
1338     same_capacity: capacity = old capacity
1339     end
1340    
1341     feature -- Resizing
1342    
1343 manus_eiffel 91608 adapt_size
1344 manus_eiffel 91539 -- Adapt the size to accommodate `count' characters.
1345     do
1346     resize (count)
1347     end
1348    
1349 manus_eiffel 91608 resize (newsize: INTEGER)
1350 manus_eiffel 91539 -- Rearrange string so that it can accommodate
1351     -- at least `newsize' characters.
1352     -- Do not lose any previously entered character.
1353     local
1354     area_count: INTEGER
1355     do
1356     area_count := area.count
1357     if newsize >= area_count then
1358     area := area.aliased_resized_area (newsize + 1)
1359     end
1360     end
1361    
1362 manus_eiffel 91608 grow (newsize: INTEGER)
1363 manus_eiffel 91539 -- Ensure that the capacity is at least `newsize'.
1364     do
1365     if newsize > capacity then
1366     resize (newsize)
1367     end
1368     end
1369    
1370     feature -- Conversion
1371    
1372 manus_eiffel 91608 as_lower: like Current
1373 manus_eiffel 91539 -- New object with all letters in lower case.
1374     do
1375     Result := twin
1376     Result.to_lower
1377     end
1378    
1379 manus_eiffel 91608 as_upper: like Current
1380 manus_eiffel 91539 -- New object with all letters in upper case
1381     do
1382     Result := twin
1383     Result.to_upper
1384     end
1385    
1386 manus_eiffel 91608 left_justify
1387 manus_eiffel 91539 -- Left justify Current using `count' as witdth.
1388     local
1389     i, nb: INTEGER
1390     l_area: like area
1391     do
1392     -- Remove leading white spaces.
1393     nb := count
1394     left_adjust
1395    
1396     -- Get new count
1397     i := count
1398     if i < nb then
1399     -- `left_adjust' did remove some characters, so we need to add
1400     -- some white spaces at the end of the string.
1401     from
1402     l_area := area
1403     until
1404     i = nb
1405     loop
1406     l_area.put (' ', i)
1407     i := i + 1
1408     end
1409     -- Restore `count'
1410     count := nb
1411     internal_hash_code := 0
1412     end
1413     end
1414    
1415 manus_eiffel 91608 center_justify
1416 manus_eiffel 91539 -- Center justify Current using `count' as width.
1417     require
1418     is_valid_as_string_8: is_valid_as_string_8
1419     local
1420     i, nb, l_offset: INTEGER
1421     left_nb_space, right_nb_space: INTEGER
1422     l_area: like area
1423     do
1424     -- Compute number of spaces at the left of current string.
1425     from
1426     nb := count
1427     l_area := area
1428     until
1429     left_nb_space = nb or else not l_area.item (left_nb_space).is_space
1430     loop
1431     left_nb_space := left_nb_space + 1
1432     end
1433    
1434     -- Compute number of spaces at the right of current string.
1435     from
1436     i := nb - 1
1437     l_area := area
1438     until
1439     i = -1 or else not l_area.item (i).is_space
1440     loop
1441     right_nb_space := right_nb_space + 1
1442     i := i - 1
1443     end
1444    
1445     -- We encourage that more spaces will be put to the left, when
1446     -- number of spaces is not even.
1447     l_offset := left_nb_space + right_nb_space
1448     if l_offset \\ 2 = 0 then
1449     l_offset := left_nb_space - l_offset // 2
1450     else
1451     l_offset := left_nb_space - l_offset // 2 - 1
1452     end
1453     if l_offset = 0 then
1454     -- Nothing to be done.
1455     else
1456     -- Shift characters to the right or left (depending on sign of
1457     -- `l_offset' by `l_offset' position.
1458     l_area.move_data (left_nb_space, left_nb_space - l_offset,
1459     nb - left_nb_space - right_nb_space)
1460    
1461     if l_offset < 0 then
1462     -- Fill left part with spaces.
1463     l_area.fill_with (' ', left_nb_space, left_nb_space - l_offset - 1)
1464     else
1465     -- Fill right part with spaces.
1466     l_area.fill_with (' ', nb - right_nb_space - l_offset, nb - 1)
1467     end
1468     internal_hash_code := 0
1469     end
1470     end
1471    
1472 manus_eiffel 91608 right_justify
1473 manus_eiffel 91539 -- Right justify Current using `count' as width.
1474     local
1475     i, nb: INTEGER
1476     nb_space: INTEGER
1477     l_area: like area
1478     do
1479     nb := count
1480     right_adjust
1481     i := count
1482     nb_space := nb - i
1483     if nb_space > 0 then
1484     -- Shift characters to the right.
1485     from
1486     l_area := area
1487     until
1488     i = 0
1489     loop
1490     i := i - 1
1491     l_area.put (l_area.item (i), i + nb_space)
1492 manus_eiffel 91615 variant
1493     i + 1
1494 manus_eiffel 91539 end
1495    
1496     -- Fill left part with spaces.
1497     from
1498     until
1499     nb_space = 0
1500     loop
1501     nb_space := nb_space - 1
1502     l_area.put (' ', nb_space)
1503 manus_eiffel 91615 variant
1504     nb_space + 1
1505 manus_eiffel 91539 end
1506     -- Restore `count'
1507     count := nb
1508     internal_hash_code := 0
1509     end
1510     ensure
1511     same_count: count = old count
1512     end
1513    
1514 manus_eiffel 91608 character_justify (pivot: CHARACTER_32; position: INTEGER)
1515 manus_eiffel 91539 -- Justify a string based on a `pivot'
1516     -- and the `position' it needs to be in
1517     -- the final string.
1518     -- This will grow the string if necessary
1519     -- to get the pivot in the correct place.
1520     require
1521     valid_position: position <= capacity
1522     positive_position: position >= 1
1523     pivot_not_space: pivot /= ' '
1524     not_empty: not is_empty
1525     local
1526     l_index_of_pivot, l_new_size: INTEGER
1527     l_area: like area
1528     do
1529     l_index_of_pivot := index_of (pivot, 1)
1530     if l_index_of_pivot /= 0 then
1531     if l_index_of_pivot < position then
1532     -- We need to resize Current so that we can shift Current by
1533     -- `l_index_of_pivot - position'.
1534     l_new_size := count + position - l_index_of_pivot
1535     grow (l_new_size)
1536     l_area := area
1537     l_area.move_data (0, position - l_index_of_pivot, count)
1538     l_area.fill_with (' ', 0, position - l_index_of_pivot - 1)
1539     count := l_new_size
1540     else
1541     -- Simply shift content to the left and reset trailing with spaces.
1542     l_area := area
1543     l_area.move_data (l_index_of_pivot - position, 0, count - l_index_of_pivot + position)
1544     l_area.fill_with (' ', count - l_index_of_pivot + position, count - 1)
1545     end
1546     internal_hash_code := 0
1547     end
1548     end
1549    
1550 manus_eiffel 91608 to_lower
1551 manus_eiffel 91539 -- Convert to lower case.
1552     require
1553     is_valid_as_string_8: is_valid_as_string_8
1554     local
1555     i: INTEGER
1556     a: like area
1557     do
1558     from
1559     i := count - 1
1560     a := area
1561     until
1562     i < 0
1563     loop
1564     a.put (a.item (i).lower, i)
1565     i := i - 1
1566     end
1567     internal_hash_code := 0
1568     ensure
1569 manus_eiffel 91615 length_and_content: elks_checking implies is_equal (old as_lower)
1570 manus_eiffel 91539 end
1571    
1572 manus_eiffel 91608 to_upper
1573 manus_eiffel 91539 -- Convert to upper case.
1574     require
1575     is_valid_as_string_8: is_valid_as_string_8
1576     local
1577     i: INTEGER
1578     a: like area
1579     do
1580     from
1581     i := count - 1
1582     a := area
1583     until
1584     i < 0
1585     loop
1586     a.put (a.item (i).upper, i)
1587     i := i - 1
1588     end
1589     internal_hash_code := 0
1590     ensure
1591 manus_eiffel 91615 length_and_content: elks_checking implies is_equal (old as_upper)
1592 manus_eiffel 91539 end
1593    
1594 manus_eiffel 91608 linear_representation: LINEAR [CHARACTER_32]
1595 manus_eiffel 91539 -- Representation as a linear structure
1596     local
1597     temp: ARRAYED_LIST [CHARACTER_32]
1598     i: INTEGER
1599     do
1600     create temp.make (capacity)
1601     from
1602     i := 1
1603     until
1604     i > count
1605     loop
1606     temp.extend (item (i))
1607     i := i + 1
1608     end
1609     Result := temp
1610     end
1611    
1612 manus_eiffel 91608 frozen to_c: ANY
1613 manus_eiffel 91539 -- A reference to a C form of current string.
1614     -- Useful only for interfacing with C software.
1615     require
1616     not_is_dotnet: not {PLATFORM}.is_dotnet
1617     local
1618     l_area: like area
1619     do
1620     l_area := area
1621     l_area.put ('%U', count)
1622     Result := l_area
1623     end
1624    
1625 manus_eiffel 91608 mirrored: like Current
1626 manus_eiffel 91539 -- Mirror image of string;
1627     -- Result for "Hello world" is "dlrow olleH".
1628     do
1629     Result := twin
1630     if count > 0 then
1631     Result.mirror
1632     end
1633     end
1634    
1635 manus_eiffel 91608 mirror
1636 manus_eiffel 91539 -- Reverse the order of characters.
1637     -- "Hello world" -> "dlrow olleH".
1638     local
1639     a: like area
1640     c: CHARACTER_32
1641     i, j: INTEGER
1642     do
1643     if count > 0 then
1644     from
1645     i := count - 1
1646     a := area
1647     until
1648     i <= j
1649     loop
1650     c := a.item (i)
1651     a.put (a.item (j), i)
1652     a.put (c, j)
1653     i := i - 1
1654     j := j + 1
1655     end
1656     internal_hash_code := 0
1657     end
1658     ensure
1659     same_count: count = old count
1660     -- reversed: For every `i' in 1..`count', `item' (`i') = old `item' (`count'+1-`i')
1661     end
1662    
1663     feature -- Duplication
1664    
1665 manus_eiffel 91608 substring (start_index, end_index: INTEGER): like Current
1666 manus_eiffel 91539 -- Copy of substring containing all characters at indices
1667     -- between `start_index' and `end_index'
1668     do
1669     if (1 <= start_index) and (start_index <= end_index) and (end_index <= count) then
1670     Result := new_string (end_index - start_index + 1)
1671     Result.area.copy_data (area, start_index - 1, 0, end_index - start_index + 1)
1672     Result.set_count (end_index - start_index + 1)
1673     else
1674     Result := new_string (0)
1675     end
1676     end
1677    
1678 manus_eiffel 91608 multiply (n: INTEGER)
1679 manus_eiffel 91539 -- Duplicate a string within itself
1680     -- ("hello").multiply(3) => "hellohellohello"
1681     require
1682     meaningful_multiplier: n >= 1
1683     local
1684     s: like Current
1685     i: INTEGER
1686     do
1687     s := twin
1688     grow (n * count)
1689     from
1690     i := n
1691     until
1692     i = 1
1693     loop
1694     append (s)
1695     i := i - 1
1696     end
1697     end
1698    
1699     feature {STRING_HANDLER} -- Implementation
1700    
1701 manus_eiffel 91608 frozen set_count (number: INTEGER)
1702 manus_eiffel 91539 -- Set `count' to `number' of characters.
1703     do
1704     count := number
1705     internal_hash_code := 0
1706     end
1707    
1708     feature {NONE} -- Implementation
1709    
1710 manus_eiffel 91608 new_string (n: INTEGER): like Current
1711 manus_eiffel 91539 -- New instance of current with space for at least `n' characters.
1712     do
1713     create Result.make (n)
1714     end
1715    
1716     feature -- Transformation
1717    
1718 manus_eiffel 91608 correct_mismatch
1719 manus_eiffel 91539 -- Attempt to correct object mismatch during retrieve using `mismatch_information'.
1720     do
1721     -- Nothing to be done because we only added `internal_hash_code' that will
1722     -- be recomputed next time we query `hash_code'.
1723     end
1724    
1725     invariant
1726     extendible: extendible
1727     compare_character: not object_comparison
1728    
1729     end

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.23