/[eiffelstudio]/FreeELKS/tags/EiffelSoftware/Eiffel_72/library/kernel/readable_string_8.e
ViewVC logotype

Contents of /FreeELKS/tags/EiffelSoftware/Eiffel_72/library/kernel/readable_string_8.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 92171 - (show annotations)
Thu Feb 7 20:27:54 2013 UTC (6 years, 10 months ago) by manus_eiffel
File size: 32588 byte(s)
Merged from rev#747:
Added `item' to READABLE_STRING_GENERAL and proper definition in READABLE_STRING_8 descendans. So that it is easier to migrate from compatible to regular mode.

1 note
2 description: "[
3 Sequences of 8-bit characters, accessible through integer indices
4 in a contiguous range. Read-only interface.
5 ]"
6 library: "Free implementation of ELKS library"
7 copyright: "Copyright (c) 1986-2008, Eiffel Software and others"
8 license: "Eiffel Forum License v2 (see forum.txt)"
9 date: "$Date$"
10 revision: "$Revision$"
11
12 deferred class
13 READABLE_STRING_8
14
15 inherit
16 READABLE_STRING_GENERAL
17 rename
18 same_string as same_string_general,
19 plus as plus_string_general,
20 item as character_32_item
21 redefine
22 copy, is_equal, out
23 end
24
25 convert
26 to_cil: {SYSTEM_STRING},
27 as_string_8: {STRING_8},
28 as_string_32: {READABLE_STRING_32, STRING_32}
29
30 feature {NONE} -- Initialization
31
32 make (n: INTEGER)
33 -- Allocate space for at least `n' characters.
34 require
35 non_negative_size: n >= 0
36 do
37 count := 0
38 internal_hash_code := 0
39 create area.make (n + 1)
40 ensure
41 empty_string: count = 0
42 area_allocated: capacity >= n
43 end
44
45 make_empty
46 -- Create empty string.
47 do
48 make (0)
49 ensure
50 empty: count = 0
51 area_allocated: capacity >= 0
52 end
53
54 make_filled (c: CHARACTER_8; n: INTEGER)
55 -- Create string of length `n' filled with `c'.
56 require
57 valid_count: n >= 0
58 do
59 make (n)
60 fill_character (c)
61 ensure
62 count_set: count = n
63 area_allocated: capacity >= n
64 filled: occurrences (c) = count
65 end
66
67 make_from_string (s: READABLE_STRING_8)
68 -- Initialize from the characters of `s'.
69 require
70 string_exists: s /= Void
71 do
72 area := s.area
73 count := s.count
74 internal_hash_code := 0
75 if Current /= s then
76 create area.make (count + 1)
77 area.copy_data (s.area, s.area_lower, 0, count)
78 end
79 ensure
80 not_shared_implementation: Current /= s implies not shared_with (s)
81 initialized: same_string (s)
82 end
83
84 make_from_c (c_string: POINTER)
85 -- Initialize from contents of `c_string',
86 -- a string created by some C function
87 require
88 c_string_exists: c_string /= default_pointer
89 local
90 l_count: INTEGER
91 do
92 c_string_provider.set_shared_from_pointer (c_string)
93 l_count := c_string_provider.count
94 create area.make (l_count + 1)
95 count := l_count
96 internal_hash_code := 0
97 c_string_provider.read_substring_into_character_8_area (area, 1, l_count)
98 end
99
100 make_from_c_pointer (c_string: POINTER)
101 -- Create new instance from contents of `c_string',
102 -- a string created by some C function
103 obsolete
104 "Use `make_from_c' instead."
105 require
106 c_string_exists: c_string /= default_pointer
107 do
108 make_from_c (c_string)
109 end
110
111 make_from_cil (a_system_string: detachable SYSTEM_STRING)
112 -- Initialize Current with `a_system_string'.
113 require
114 is_dotnet: {PLATFORM}.is_dotnet
115 deferred
116 end
117
118 feature -- Access
119
120 item alias "[]", at alias "@" (i: INTEGER): CHARACTER_8
121 -- Character at position `i'
122 do
123 Result := area.item (i - 1)
124 end
125
126 character_32_item (i: INTEGER): CHARACTER_32
127 -- Character at position `i'
128 do
129 Result := code (i).to_character_32
130 end
131
132 code (i: INTEGER): NATURAL_32
133 -- Numeric code of character at position `i'
134 do
135 Result := area.item (i - 1).code.to_natural_32
136 end
137
138 item_code (i: INTEGER): INTEGER
139 -- Numeric code of character at position `i'
140 require
141 index_small_enough: i <= count
142 index_large_enough: i > 0
143 do
144 Result := area.item (i - 1).code
145 end
146
147 hash_code: INTEGER
148 -- Hash code value
149 local
150 i, nb: INTEGER
151 l_area: like area
152 do
153 Result := internal_hash_code
154 if Result = 0 then
155 -- The magic number `8388593' below is the greatest prime lower than
156 -- 2^23 so that this magic number shifted to the left does not exceed 2^31.
157 from
158 i := 0
159 nb := count
160 l_area := area
161 until
162 i = nb
163 loop
164 Result := ((Result \\ 8388593) |<< 8) + l_area.item (i).code
165 i := i + 1
166 end
167 internal_hash_code := Result
168 end
169 end
170
171 false_constant: STRING_8 = "false"
172 -- Constant string "false"
173
174 true_constant: STRING_8 = "true"
175 -- Constant string "true"
176
177 shared_with (other: READABLE_STRING_8): BOOLEAN
178 -- Does string share the text of `other'?
179 do
180 Result := (other /= Void) and then (area = other.area)
181 end
182
183 index_of (c: CHARACTER_8; start_index: INTEGER): INTEGER
184 -- Position of first occurrence of `c' at or after `start_index';
185 -- 0 if none.
186 require
187 start_large_enough: start_index >= 1
188 start_small_enough: start_index <= count + 1
189 local
190 a: like area
191 i, nb: INTEGER
192 do
193 nb := count
194 if start_index <= nb then
195 from
196 i := start_index - 1
197 a := area
198 until
199 i = nb or else a.item (i) = c
200 loop
201 i := i + 1
202 end
203 if i < nb then
204 -- We add +1 due to the area starting at 0 and not at 1.
205 Result := i + 1
206 end
207 end
208 ensure
209 valid_result: Result = 0 or (start_index <= Result and Result <= count)
210 zero_if_absent: (Result = 0) = not substring (start_index, count).has (c)
211 found_if_present: substring (start_index, count).has (c) implies item (Result) = c
212 none_before: substring (start_index, count).has (c) implies
213 not substring (start_index, Result - 1).has (c)
214 end
215
216 last_index_of (c: CHARACTER_8; start_index_from_end: INTEGER): INTEGER
217 -- Position of last occurrence of `c'.
218 -- 0 if none
219 require
220 start_index_small_enough: start_index_from_end <= count
221 start_index_large_enough: start_index_from_end >= 1
222 local
223 a: like area
224 i: INTEGER
225 do
226 from
227 i := start_index_from_end - 1
228 a := area
229 until
230 i < 0 or else a.item (i) = c
231 loop
232 i := i - 1
233 end
234 -- We add +1 due to the area starting at 0 and not at 1.
235 Result := i + 1
236 ensure
237 last_index_of_non_negative: Result >= 0
238 correct_place: Result > 0 implies item (Result) = c
239 -- forall x : Result..last, item (x) /= c
240 end
241
242 substring_index_in_bounds (other: READABLE_STRING_8; start_pos, end_pos: INTEGER): INTEGER
243 -- Position of first occurrence of `other' at or after `start_pos'
244 -- and to or before `end_pos';
245 -- 0 if none.
246 require
247 other_nonvoid: other /= Void
248 other_notempty: not other.is_empty
249 start_pos_large_enough: start_pos >= 1
250 start_pos_small_enough: start_pos <= count
251 end_pos_large_enough: end_pos >= start_pos
252 end_pos_small_enough: end_pos <= count
253 do
254 Result := string_searcher.substring_index (Current, other, start_pos, end_pos)
255 ensure
256 correct_place: Result > 0 implies other.same_string (substring (Result, Result + other.count - 1))
257 -- forall x : start_pos..Result
258 -- not substring (x, x+other.count -1).is_equal (other)
259 end
260
261 string: STRING_8
262 -- New STRING_8 having same character sequence as `Current'.
263 do
264 create Result.make_from_string (Current)
265 ensure
266 string_not_void: Result /= Void
267 string_type: Result.same_type (create {STRING_8}.make_empty)
268 first_item: count > 0 implies Result.item (1) = item (1)
269 recurse: count > 1 implies Result.substring (2, count) ~ substring (2, count).string
270 end
271
272 string_representation: STRING_8
273 -- Similar to `string' but only create a new object if `Current' is not of dynamic type {STRING_8}
274 do
275 if same_type (create {STRING_8}.make_empty) and then attached {STRING_8} Current as l_s8 then
276 Result := l_s8
277 else
278 Result := string
279 end
280 ensure
281 Result_not_void: Result /= Void
282 correct_type: Result.same_type (create {STRING_8}.make_empty)
283 first_item: count > 0 implies Result.item (1) = item (1)
284 recurse: count > 1 implies Result.substring (2, count) ~ substring (2, count).string
285 end
286
287 substring_index (other: READABLE_STRING_8; start_index: INTEGER): INTEGER
288 -- Index of first occurrence of other at or after start_index;
289 -- 0 if none
290 require
291 other_not_void: other /= Void
292 valid_start_index: start_index >= 1 and start_index <= count + 1
293 do
294 Result := string_searcher.substring_index (Current, other, start_index, count)
295 ensure
296 valid_result: Result = 0 or else
297 (start_index <= Result and Result <= count - other.count + 1)
298 zero_if_absent: (Result = 0) =
299 not substring (start_index, count).has_substring (other)
300 at_this_index: Result >= start_index implies
301 other.same_string (substring (Result, Result + other.count - 1))
302 none_before: Result > start_index implies
303 not substring (start_index, Result + other.count - 2).has_substring (other)
304 end
305
306 fuzzy_index (other: READABLE_STRING_8; start: INTEGER; fuzz: INTEGER): INTEGER
307 -- Position of first occurrence of `other' at or after `start'
308 -- with 0..`fuzz' mismatches between the string and `other'.
309 -- 0 if there are no fuzzy matches
310 require
311 other_exists: other /= Void
312 other_not_empty: not other.is_empty
313 start_large_enough: start >= 1
314 start_small_enough: start <= count
315 acceptable_fuzzy: fuzz <= other.count
316 do
317 Result := string_searcher.fuzzy_index (Current, other, start, count, fuzz)
318 end
319
320 feature -- Measurement
321
322 capacity: INTEGER
323 -- Allocated space
324 do
325 Result := area.count - 1
326 end
327
328 count: INTEGER
329 -- Actual number of characters making up the string
330
331 occurrences (c: CHARACTER_8): INTEGER
332 -- Number of times `c' appears in the string
333 local
334 i, nb: INTEGER
335 a: SPECIAL [CHARACTER_8]
336 do
337 from
338 nb := count
339 a := area
340 until
341 i = nb
342 loop
343 if a.item (i) = c then
344 Result := Result + 1
345 end
346 i := i + 1
347 end
348 ensure then
349 zero_if_empty: count = 0 implies Result = 0
350 recurse_if_not_found_at_first_position:
351 (count > 0 and then item (1) /= c) implies
352 Result = substring (2, count).occurrences (c)
353 recurse_if_found_at_first_position:
354 (count > 0 and then item (1) = c) implies
355 Result = 1 + substring (2, count).occurrences (c)
356 end
357
358 index_set: INTEGER_INTERVAL
359 -- Range of acceptable indexes
360 do
361 create Result.make (1, count)
362 ensure
363 index_set_not_void: Result /= Void
364 index_set_count: Result.count = count
365 end
366
367 feature -- Comparison
368
369 is_equal (other: like Current): BOOLEAN
370 -- Is string made of same character sequence as `other'
371 -- (possibly with a different capacity)?
372 local
373 l_count: INTEGER
374 do
375 if other = Current then
376 Result := True
377 else
378 l_count := count
379 if l_count = other.count then
380 Result := area.same_items (other.area, other.area_lower, area_lower, l_count)
381 end
382 end
383 end
384
385 is_case_insensitive_equal (other: like Current): BOOLEAN
386 -- Is string made of same character sequence as `other' regardless of casing
387 -- (possibly with a different capacity)?
388 require
389 other_not_void: other /= Void
390 local
391 l_area, l_other_area: like area
392 i, j, nb: INTEGER
393 do
394 if other = Current then
395 Result := True
396 else
397 nb := count
398 if nb = other.count then
399 from
400 l_area := area
401 l_other_area := other.area
402 Result := True
403 i := area_lower
404 j := other.area_lower
405 nb := area_lower + nb
406 until
407 i = nb
408 loop
409 if l_area.item (i).as_lower /= l_other_area.item (j).as_lower then
410 Result := False
411 i := nb - 1 -- Jump out of loop
412 end
413 i := i + 1
414 j := j + 1
415 end
416 end
417 end
418 ensure
419 symmetric: Result implies other.is_case_insensitive_equal (Current)
420 consistent: standard_is_equal (other) implies Result
421 valid_result: as_lower ~ other.as_lower implies Result
422 end
423
424 same_string (other: READABLE_STRING_8): BOOLEAN
425 -- Do `Current' and `other' have same character sequence?
426 require
427 other_not_void: other /= Void
428 do
429 if other = Current then
430 Result := True
431 elseif other.count = count then
432 if same_type (other) then
433 Result := area.same_items (other.area, other.area_lower, area_lower, count)
434 else
435 Result := same_string_general (other)
436 end
437 end
438 ensure
439 definition: Result = (string ~ other.string)
440 end
441
442 is_less alias "<" (other: like Current): BOOLEAN
443 -- Is string lexicographically lower than `other'?
444 local
445 other_count: INTEGER
446 current_count: INTEGER
447 do
448 if other /= Current then
449 other_count := other.count
450 current_count := count
451 if other_count = current_count then
452 Result := str_strict_cmp (other.area, area, other.area_lower, area_lower, other_count) > 0
453 else
454 if current_count < other_count then
455 Result := str_strict_cmp (other.area, area, other.area_lower, area_lower, current_count) >= 0
456 else
457 Result := str_strict_cmp (other.area, area, other.area_lower, area_lower, other_count) > 0
458 end
459 end
460 end
461 end
462
463 feature -- Status report
464
465 is_string_8: BOOLEAN = True
466 -- <Precursor>
467
468 is_string_32: BOOLEAN = False
469 -- <Precursor>
470
471 is_valid_as_string_8: BOOLEAN = True
472 -- <Precursor>
473
474 has (c: CHARACTER_8): BOOLEAN
475 -- Does string include `c'?
476 local
477 i, nb: INTEGER
478 l_area: like area
479 do
480 nb := count
481 if nb > 0 then
482 from
483 l_area := area
484 until
485 i = nb or else (l_area.item (i) = c)
486 loop
487 i := i + 1
488 end
489 Result := (i < nb)
490 end
491 ensure then
492 false_if_empty: count = 0 implies not Result
493 true_if_first: count > 0 and then item (1) = c implies Result
494 recurse: (count > 0 and then item (1) /= c) implies
495 (Result = substring (2, count).has (c))
496 end
497
498 has_substring (other: READABLE_STRING_8): BOOLEAN
499 -- Does `Current' contain `other'?
500 require
501 other_not_void: other /= Void
502 do
503 if other = Current then
504 Result := True
505 elseif other.count <= count then
506 Result := substring_index (other, 1) > 0
507 end
508 ensure
509 false_if_too_small: count < other.count implies not Result
510 true_if_initial: (count >= other.count and then
511 other.same_string (substring (1, other.count))) implies Result
512 recurse: (count >= other.count and then
513 not other.same_string (substring (1, other.count))) implies
514 (Result = substring (2, count).has_substring (other))
515 end
516
517 starts_with (s: READABLE_STRING_8): BOOLEAN
518 -- Does string begin with `s'?
519 require
520 argument_not_void: s /= Void
521 local
522 i, j, nb: INTEGER
523 l_area, l_s_area: like area
524 do
525 if Current = s then
526 Result := True
527 else
528 i := s.count
529 if i <= count then
530 from
531 l_area := area
532 l_s_area := s.area
533 j := area_lower + i
534 i := s.area_upper + 1
535 nb := s.area_lower
536 Result := True
537 until
538 i = nb
539 loop
540 i := i - 1
541 j := j - 1
542 if l_area.item (j) /= l_s_area.item (i) then
543 Result := False
544 i := nb -- Jump out of loop
545 end
546 end
547 end
548 end
549 ensure
550 definition: Result = s.same_string (substring (1, s.count))
551 end
552
553 ends_with (s: READABLE_STRING_8): BOOLEAN
554 -- Does string finish with `s'?
555 require
556 argument_not_void: s /= Void
557 local
558 i, j, nb: INTEGER
559 l_area, l_s_area: like area
560 do
561 if Current = s then
562 Result := True
563 else
564 i := s.count
565 j := count
566 if i <= j then
567 from
568 l_area := area
569 l_s_area := s.area
570 j := area_upper + 1
571 i := s.area_upper + 1
572 nb := s.area_lower
573 Result := True
574 until
575 i = nb
576 loop
577 i := i - 1
578 j := j - 1
579 if l_area.item (j) /= l_s_area.item (i) then
580 Result := False
581 i := nb -- Jump out of loop
582 end
583 end
584 end
585 end
586 ensure
587 definition: Result = s.same_string (substring (count - s.count + 1, count))
588 end
589
590 valid_index (i: INTEGER): BOOLEAN
591 -- Is `i' within the bounds of the string?
592 do
593 Result := (i > 0) and (i <= count)
594 ensure then
595 definition: Result = (1 <= i and i <= count)
596 end
597
598 valid_code (v: NATURAL_32): BOOLEAN
599 -- Is `v' a valid code for a CHARACTER_32?
600 do
601 Result := v <= {CHARACTER_8}.max_value.to_natural_32
602 end
603
604 is_number_sequence: BOOLEAN
605 -- Does `Current' represent a number sequence?
606 do
607 Result := is_valid_integer_or_natural ({NUMERIC_INFORMATION}.type_no_limitation)
608 ensure
609 syntax_and_range:
610 -- Result is true if and only if the following two
611 -- conditions are satisfied:
612 --
613 -- In the following BNF grammar, the value of
614 -- Current can be produced by "Integer_literal":
615 --
616 -- Integer_literal = [Space] [Sign] Integer [Space]
617 -- Space = " " | " " Space
618 -- Sign = "+" | "-"
619 -- Integer = Digit | Digit Integer
620 -- Digit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
621 end
622
623 is_real_sequence: BOOLEAN
624 -- Does `Current' represent a real sequence?
625 local
626 l_convertor: like ctor_convertor
627 do
628 l_convertor := ctor_convertor
629 l_convertor.parse_string_with_type (Current, {NUMERIC_INFORMATION}.type_no_limitation)
630 Result := l_convertor.is_integral_double
631 ensure
632 syntax_and_range:
633 -- 'Result' is True if and only if the following condition is satisfied:
634 --
635 -- In the following BNF grammar, the value of
636 -- 'Current' can be produced by "Real_literal":
637 --
638 -- Real_literal = Mantissa [Exponent_part]
639 -- Exponent_part = "E" Exponent
640 -- | "e" Exponent
641 -- Exponent = Integer_literal
642 -- Mantissa = Decimal_literal
643 -- Decimal_literal = Integer_literal ["." [Integer]] | "." Integer
644 -- Integer_literal = [Sign] Integer
645 -- Sign = "+" | "-"
646 -- Integer = Digit | Digit Integer
647 -- Digit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
648 --
649 end
650
651 is_real: BOOLEAN
652 -- Does `Current' represent a REAL?
653 local
654 l_convertor: like ctor_convertor
655 do
656 l_convertor := ctor_convertor
657 l_convertor.parse_string_with_type (Current, {NUMERIC_INFORMATION}.type_real)
658 Result := l_convertor.is_integral_real
659 ensure
660 syntax_and_range:
661 -- 'Result' is True if and only if the following two
662 -- conditions are satisfied:
663 --
664 -- 1. In the following BNF grammar, the value of
665 -- 'Current' can be produced by "Real_literal":
666 --
667 -- Real_literal = Mantissa [Exponent_part]
668 -- Exponent_part = "E" Exponent
669 -- | "e" Exponent
670 -- Exponent = Integer_literal
671 -- Mantissa = Decimal_literal
672 -- Decimal_literal = Integer_literal ["." [Integer]] | "." Integer
673 -- Integer_literal = [Sign] Integer
674 -- Sign = "+" | "-"
675 -- Integer = Digit | Digit Integer
676 -- Digit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
677 --
678 -- 2. The numerical value represented by 'Current'
679 -- is within the range that can be represented
680 -- by an instance of type REAL.
681 end
682
683 is_double: BOOLEAN
684 -- Does `Current' represent a DOUBLE?
685 local
686 l_convertor: like ctor_convertor
687 do
688 l_convertor := ctor_convertor
689 l_convertor.parse_string_with_type (Current, {NUMERIC_INFORMATION}.type_double)
690 Result := l_convertor.is_integral_double
691 ensure
692 syntax_and_range:
693 -- 'Result' is True if and only if the following two
694 -- conditions are satisfied:
695 --
696 -- 1. In the following BNF grammar, the value of
697 -- 'Current' can be produced by "Real_literal":
698 --
699 -- Real_literal = Mantissa [Exponent_part]
700 -- Exponent_part = "E" Exponent
701 -- | "e" Exponent
702 -- Exponent = Integer_literal
703 -- Mantissa = Decimal_literal
704 -- Decimal_literal = Integer_literal ["." [Integer]] | "." Integer
705 -- Integer_literal = [Sign] Integer
706 -- Sign = "+" | "-"
707 -- Integer = Digit | Digit Integer
708 -- Digit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
709 --
710 -- 2. The numerical value represented by 'Current'
711 -- is within the range that can be represented
712 -- by an instance of type DOUBLE.
713 end
714
715 is_boolean: BOOLEAN
716 -- Does `Current' represent a BOOLEAN?
717 local
718 nb: INTEGER
719 l_area: like area
720 do
721 nb := count
722 if nb = 4 then
723 -- Check if this is `true_constant'
724 l_area := area
725 Result := l_area.item (0).lower = 't' and then
726 l_area.item (1).lower = 'r' and then
727 l_area.item (2).lower = 'u' and then
728 l_area.item (3).lower = 'e'
729 elseif nb = 5 then
730 -- Check if this is `false_constant'
731 l_area := area
732 Result := l_area.item (0).lower = 'f' and then
733 l_area.item (1).lower = 'a' and then
734 l_area.item (2).lower = 'l' and then
735 l_area.item (3).lower = 's' and then
736 l_area.item (4).lower = 'e'
737 end
738 ensure
739 is_boolean: Result = (true_constant.same_string (as_lower) or false_constant.same_string (as_lower))
740 end
741
742 is_integer_8: BOOLEAN
743 -- Does `Current' represent an INTEGER_8?
744 do
745 Result := is_valid_integer_or_natural ({NUMERIC_INFORMATION}.type_integer_8)
746 end
747
748 is_integer_16: BOOLEAN
749 -- Does `Current' represent an INTEGER_16?
750 do
751 Result := is_valid_integer_or_natural ({NUMERIC_INFORMATION}.type_integer_16)
752 end
753
754 is_integer, is_integer_32: BOOLEAN
755 -- Does `Current' represent an INTEGER_32?
756 do
757 Result := is_valid_integer_or_natural ({NUMERIC_INFORMATION}.type_integer_32)
758 end
759
760 is_integer_64: BOOLEAN
761 -- Does `Current' represent an INTEGER_64?
762 do
763 Result := is_valid_integer_or_natural ({NUMERIC_INFORMATION}.type_integer_64)
764 end
765
766 is_natural_8: BOOLEAN
767 -- Does `Current' represent a NATURAL_8?
768 do
769 Result := is_valid_integer_or_natural ({NUMERIC_INFORMATION}.type_natural_8)
770 end
771
772 is_natural_16: BOOLEAN
773 -- Does `Current' represent a NATURAL_16?
774
775 do
776 Result := is_valid_integer_or_natural ({NUMERIC_INFORMATION}.type_natural_16)
777 end
778
779 is_natural, is_natural_32: BOOLEAN
780 -- Does `Current' represent a NATURAL_32?
781 do
782 Result := is_valid_integer_or_natural ({NUMERIC_INFORMATION}.type_natural_32)
783 end
784
785 is_natural_64: BOOLEAN
786 -- Does `Current' represent a NATURAL_64?
787 do
788 Result := is_valid_integer_or_natural ({NUMERIC_INFORMATION}.type_natural_64)
789 end
790
791 feature {READABLE_STRING_8} -- Duplication
792
793 copy (other: like Current)
794 -- Reinitialize by copying the characters of `other'.
795 -- (This is also used by `twin'.)
796 local
797 old_area: like area
798 do
799 if other /= Current then
800 old_area := area
801 standard_copy (other)
802 -- Note: <= is needed as all Eiffel string should have an
803 -- extra character to insert null character at the end.
804 if old_area = Void or else old_area.count <= count then
805 area := area.twin
806 else
807 old_area.copy_data (area, 0, 0, count)
808 area := old_area
809 end
810 internal_hash_code := 0
811 end
812 ensure then
813 new_result_count: count = other.count
814 -- same_characters: For every `i' in 1..`count', `item' (`i') = `other'.`item' (`i')
815 end
816
817 feature {NONE} -- Element change
818
819 fill_character (c: CHARACTER_8)
820 -- Fill with `capacity' characters all equal to `c'.
821 local
822 l_cap: like capacity
823 do
824 l_cap := capacity
825 if l_cap /= 0 then
826 area.fill_with (c, 0, l_cap - 1)
827 count := l_cap
828 internal_hash_code := 0
829 end
830 ensure
831 filled: count = capacity
832 same_size: capacity = old capacity
833 -- all_char: For every `i' in 1..`capacity', `item' (`i') = `c'
834 end
835
836 feature -- Element change
837
838 plus alias "+" (s: READABLE_STRING_8): like Current
839 -- Append a copy of 's' at the end of a copy of Current,
840 -- Then return the Result.
841 require
842 argument_not_void: s /= Void
843 deferred
844 ensure
845 Result_exists: Result /= Void
846 new_count: Result.count = count + s.count
847 initial: elks_checking implies Result.substring (1, count) ~ Current
848 final: elks_checking implies Result.substring (count + 1, count + s.count).same_string (s)
849 end
850
851 feature -- Conversion
852
853 as_lower: like Current
854 -- New object with all letters in lower case.
855 deferred
856 ensure
857 as_lower_attached: Result /= Void
858 length: Result.count = count
859 anchor: count > 0 implies Result.item (1) = item (1).as_lower
860 recurse: count > 1 implies Result.substring (2, count) ~ substring (2, count).as_lower
861 end
862
863 as_upper: like Current
864 -- New object with all letters in upper case
865 deferred
866 ensure
867 as_upper_attached: Result /= Void
868 length: Result.count = count
869 anchor: count > 0 implies Result.item (1) = item (1).as_upper
870 recurse: count > 1 implies Result.substring (2, count) ~ substring (2, count).as_upper
871 end
872
873 to_integer_8: INTEGER_8
874 -- 8-bit integer value
875 require
876 is_integer_8: is_integer_8
877 local
878 l_convertor: like ctoi_convertor
879 do
880 l_convertor := ctoi_convertor
881 l_convertor.parse_string_with_type (Current, {NUMERIC_INFORMATION}.type_no_limitation)
882 Result := l_convertor.parsed_integer_8
883 end
884
885 to_integer_16: INTEGER_16
886 -- 16-bit integer value
887 require
888 is_integer_16: is_integer_16
889 local
890 l_convertor: like ctoi_convertor
891 do
892 l_convertor := ctoi_convertor
893 l_convertor.parse_string_with_type (Current, {NUMERIC_INFORMATION}.type_no_limitation)
894 Result := l_convertor.parsed_integer_16
895 end
896
897 to_integer, to_integer_32: INTEGER_32
898 -- 32-bit integer value
899 require
900 is_integer: is_integer_32
901 local
902 l_convertor: like ctoi_convertor
903 do
904 l_convertor := ctoi_convertor
905 l_convertor.parse_string_with_type (Current, {NUMERIC_INFORMATION}.type_no_limitation)
906 Result := l_convertor.parsed_integer
907 end
908
909 to_integer_64: INTEGER_64
910 -- 64-bit integer value
911 require
912 is_integer_64: is_integer_64
913 local
914 l_convertor: like ctoi_convertor
915 do
916 l_convertor := ctoi_convertor
917 l_convertor.parse_string_with_type (Current, {NUMERIC_INFORMATION}.type_no_limitation)
918 Result := l_convertor.parsed_integer_64
919 end
920
921 to_natural_8: NATURAL_8
922 -- 8-bit natural value
923 require
924 is_natural_8: is_natural_8
925 local
926 l_convertor: like ctoi_convertor
927 do
928 l_convertor := ctoi_convertor
929 l_convertor.parse_string_with_type (Current, {NUMERIC_INFORMATION}.type_no_limitation)
930 Result := l_convertor.parsed_natural_8
931 end
932
933 to_natural_16: NATURAL_16
934 -- 16-bit natural value
935 require
936 is_natural_16: is_natural_16
937 local
938 l_convertor: like ctoi_convertor
939 do
940 l_convertor := ctoi_convertor
941 l_convertor.parse_string_with_type (Current, {NUMERIC_INFORMATION}.type_no_limitation)
942 Result := l_convertor.parsed_natural_16
943 end
944
945 to_natural, to_natural_32: NATURAL_32
946 -- 32-bit natural value
947 require
948 is_natural: is_natural_32
949 local
950 l_convertor: like ctoi_convertor
951 do
952 l_convertor := ctoi_convertor
953 l_convertor.parse_string_with_type (Current, {NUMERIC_INFORMATION}.type_no_limitation)
954 Result := l_convertor.parsed_natural_32
955 end
956
957 to_natural_64: NATURAL_64
958 -- 64-bit natural value
959 require
960 is_natural_64: is_natural_64
961 local
962 l_convertor: like ctoi_convertor
963 do
964 l_convertor := ctoi_convertor
965 l_convertor.parse_string_with_type (Current, {NUMERIC_INFORMATION}.type_no_limitation)
966 Result := l_convertor.parsed_natural_64
967 end
968
969 to_real: REAL
970 -- Real value;
971 -- for example, when applied to "123.0", will yield 123.0
972 require
973 represents_a_real: is_real
974 do
975 Result := to_double
976 end
977
978 to_double: DOUBLE
979 -- "Double" value;
980 -- for example, when applied to "123.0", will yield 123.0 (double)
981 require
982 represents_a_double: is_double
983 local
984 l_convertor: like ctor_convertor
985 do
986 l_convertor := ctor_convertor
987 l_convertor.parse_string_with_type (Current, {NUMERIC_INFORMATION}.type_no_limitation)
988 Result := l_convertor.parsed_double
989 end
990
991 to_boolean: BOOLEAN
992 -- Boolean value;
993 -- "True" yields `True', "False" yields `False'
994 -- (case-insensitive)
995 require
996 is_boolean: is_boolean
997 do
998 check true_constant.count = 4 end
999 if count = 4 then
1000 Result := True
1001 end
1002 ensure
1003 to_boolean: (Result = true_constant.same_string (as_lower)) or
1004 (not Result = false_constant.same_string (as_lower))
1005 end
1006
1007 split (a_separator: CHARACTER_8): LIST [like Current]
1008 -- Split on `a_separator'.
1009 local
1010 l_list: ARRAYED_LIST [like Current]
1011 part: like Current
1012 i, j, c: INTEGER
1013 do
1014 c := count
1015 -- Worse case allocation: every character is a separator
1016 create l_list.make (c + 1)
1017 if c > 0 then
1018 from
1019 i := 1
1020 until
1021 i > c
1022 loop
1023 j := index_of (a_separator, i)
1024 if j = 0 then
1025 -- No separator was found, we will
1026 -- simply create a list with a copy of
1027 -- Current in it.
1028 j := c + 1
1029 end
1030 part := substring (i, j - 1)
1031 l_list.extend (part)
1032 i := j + 1
1033 end
1034 if j = c then
1035 check
1036 last_character_is_a_separator: item (j) = a_separator
1037 end
1038 -- A separator was found at the end of the string
1039 l_list.extend (new_string (0))
1040 end
1041 else
1042 -- Extend empty string, since Current is empty.
1043 l_list.extend (new_string (0))
1044 end
1045 Result := l_list
1046 check
1047 l_list.count = occurrences (a_separator) + 1
1048 end
1049 ensure
1050 Result /= Void
1051 end
1052
1053 mirrored: like Current
1054 -- Mirror image of string;
1055 -- Result for "Hello world" is "dlrow olleH".
1056 deferred
1057 ensure
1058 same_count: Result.count = count
1059 -- reversed: For every `i' in 1..`count', `Result'.`item' (`i') = `item' (`count'+1-`i')
1060 end
1061
1062 feature -- Duplication
1063
1064 substring (start_index, end_index: INTEGER): like Current
1065 -- Copy of substring containing all characters at indices
1066 -- between `start_index' and `end_index'
1067 deferred
1068 end
1069
1070 feature -- Output
1071
1072 out: STRING
1073 -- Printable representation
1074 do
1075 create Result.make (count)
1076 Result.append (Current)
1077 ensure then
1078 out_not_void: Result /= Void
1079 same_items: same_type ("") implies Result.same_string (Current)
1080 end
1081
1082 feature {NONE} -- Implementation
1083
1084 new_string (n: INTEGER): like Current
1085 -- New instance of current with space for at least `n' characters.
1086 require
1087 n_non_negative: n >= 0
1088 deferred
1089 ensure
1090 new_string_not_void: Result /= Void
1091 new_string_empty: Result.is_empty
1092 new_string_area_big_enough: Result.capacity >= n
1093 end
1094
1095 is_valid_integer_or_natural (type: INTEGER) : BOOLEAN
1096 -- Is `Current' a valid number according to given `type'?
1097 local
1098 l_convertor: like ctoi_convertor
1099 do
1100 l_convertor := ctoi_convertor
1101 l_convertor.reset (type)
1102 l_convertor.parse_string_with_type (Current, type)
1103 Result := l_convertor.is_integral_integer
1104 end
1105
1106 str_strict_cmp (this, other: like area; this_index, other_index, n: INTEGER): INTEGER
1107 -- Compare `n' characters from `this' starting at `this_index' with
1108 -- `n' characters from and `other' starting at `other_index'.
1109 -- 0 if equal, < 0 if `this' < `other',
1110 -- > 0 if `this' > `other'
1111 require
1112 this_not_void: this /= Void
1113 other_not_void: other /= Void
1114 n_non_negative: n >= 0
1115 n_valid: n <= (this.upper - this_index + 1) and n <= (other.upper - other_index + 1)
1116 local
1117 i, j, nb, l_current_code, l_other_code: INTEGER
1118 do
1119 from
1120 i := this_index
1121 nb := i + n
1122 j := other_index
1123 until
1124 i = nb
1125 loop
1126 l_current_code := this.item (i).code
1127 l_other_code := other.item (j).code
1128 if l_current_code /= l_other_code then
1129 Result := l_current_code - l_other_code
1130 i := nb - 1 -- Jump out of loop
1131 end
1132 i := i + 1
1133 j := j + 1
1134 end
1135 end
1136
1137 to_lower_area (a: like area; start_index, end_index: INTEGER)
1138 -- Replace all characters in `a' between `start_index' and `end_index'
1139 -- with their lower version.
1140 require
1141 a_not_void: a /= Void
1142 start_index_non_negative: start_index >= 0
1143 start_index_not_too_big: start_index <= end_index + 1
1144 end_index_valid: end_index < a.count
1145 local
1146 i: INTEGER
1147 do
1148 from
1149 i := start_index
1150 until
1151 i > end_index
1152 loop
1153 a.put (a.item (i).lower, i)
1154 i := i + 1
1155 end
1156 end
1157
1158 to_upper_area (a: like area; start_index, end_index: INTEGER)
1159 -- Replace all characters in `a' between `start_index' and `end_index'
1160 -- with their upper version.
1161 require
1162 a_not_void: a /= Void
1163 start_index_non_negative: start_index >= 0
1164 start_index_not_too_big: start_index <= end_index + 1
1165 end_index_valid: end_index < a.count
1166 local
1167 i: INTEGER
1168 do
1169 from
1170 i := start_index
1171 until
1172 i > end_index
1173 loop
1174 a.put (a.item (i).upper, i)
1175 i := i + 1
1176 end
1177 end
1178
1179 mirror_area (a: like area; start_index, end_index: INTEGER)
1180 -- Mirror all characters in `a' between `start_index' and `end_index'.
1181 require
1182 a_not_void: a /= Void
1183 start_index_non_negative: start_index >= 0
1184 start_index_not_too_big: start_index <= end_index + 1
1185 end_index_valid: end_index < a.count
1186 local
1187 c: CHARACTER_8
1188 i, j: INTEGER
1189 do
1190 from
1191 i := end_index
1192 until
1193 i <= j
1194 loop
1195 c := a.item (i)
1196 a.put (a.item (j), i)
1197 a.put (c, j)
1198 i := i - 1
1199 j := j + 1
1200 end
1201 end
1202
1203 feature {READABLE_STRING_8, READABLE_STRING_32, HEXADECIMAL_STRING_TO_INTEGER_CONVERTER} -- Implementation
1204
1205 area: SPECIAL [CHARACTER_8]
1206 -- Storage for characters
1207
1208 area_lower: INTEGER
1209 -- Minimum index
1210 do
1211 ensure
1212 area_lower_non_negative: Result >= 0
1213 area_lower_valid: Result <= area.upper
1214 end
1215
1216 area_upper: INTEGER
1217 -- Maximum index
1218 do
1219 Result := area_lower + count - 1
1220 ensure
1221 area_upper_valid: Result <= area.upper
1222 area_upper_in_bound: area_lower <= Result + 1
1223 end
1224
1225 invariant
1226 area_not_void: area /= Void
1227
1228 end

Properties

Name Value
svn:eol-style native
svn:keywords Author Date ID Revision

  ViewVC Help
Powered by ViewVC 1.1.23