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

Contents of /FreeELKS/trunk/library/kernel/readable_string_8.e

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.23