PageRenderTime 23ms CodeModel.GetById 14ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lib/string/character.e

http://github.com/tybor/Liberty
Specman e | 401 lines | 295 code | 38 blank | 68 comment | 10 complexity | fd270866d834eda2eb08edabf09232ed MD5 | raw file
  1-- This file is part of a Liberty Eiffel library.
  2-- See the full copyright at the end.
  3--
  4expanded class CHARACTER
  5   --
  6   -- Note: An Eiffel CHARACTER is mapped as a C unsigned char or as a Java Byte.
  7   --
  8
  9insert
 10   HASHABLE
 11      redefine out_in_tagged_out_memory, fill_tagged_out_memory
 12      end
 13   COMPARABLE
 14      redefine out_in_tagged_out_memory, fill_tagged_out_memory, infix ">=", infix "<=", infix ">"
 15      end
 16   PLATFORM
 17      undefine is_equal
 18      redefine out_in_tagged_out_memory, fill_tagged_out_memory
 19      end
 20
 21feature {ANY}
 22   code: INTEGER_16
 23         -- ASCII code of Current. (No Sign-extended conversion.)
 24         --
 25         -- See also `to_integer_8'.
 26      external "built_in"
 27      ensure
 28         Result.in_range(Minimum_character_code, Maximum_character_code)
 29      end
 30
 31   to_integer_8: INTEGER_8
 32         -- Sign-extended conversion.
 33         --
 34         -- See also `code'.
 35      external "built_in"
 36      end
 37
 38   to_integer: INTEGER_8
 39      obsolete "Use `to_integer_8' instead (March 2006)."
 40      do
 41         Result := to_integer_8
 42      end
 43
 44   infix "<" (other: CHARACTER): BOOLEAN
 45         -- Comparison using `code'.
 46      do
 47         Result := code < other.code
 48      ensure then
 49         Result = (code < other.code)
 50      end
 51
 52   infix "<=" (other: CHARACTER): BOOLEAN
 53         -- Comparison using `code'.
 54      do
 55         Result := code <= other.code
 56      end
 57
 58   infix ">" (other: CHARACTER): BOOLEAN
 59         -- Comparison using `code'.
 60      do
 61         Result := code > other.code
 62      end
 63
 64   infix ">=" (other: CHARACTER): BOOLEAN
 65         -- Comparison using `code'.
 66      do
 67         Result := code >= other.code
 68      end
 69
 70   value, decimal_value: INTEGER_8
 71         -- Gives the value of a decimal digit.
 72      require
 73         is_digit
 74      do
 75         Result := code.to_integer_8 - 48
 76      ensure
 77         Result.in_range(0, 9)
 78      end
 79
 80   binary_value: INTEGER_8
 81         -- Gives the value of a binary digit.
 82      require
 83         is_binary_digit
 84      do
 85         Result := code.to_integer_8 - 48
 86      ensure
 87         Result.in_range(0, 1)
 88      end
 89
 90   octal_value: INTEGER_8
 91         -- Gives the value of an octal digit.
 92      require
 93         is_octal_digit
 94      do
 95         Result := code.to_integer_8 - 48
 96      ensure
 97         Result.in_range(0, 7)
 98      end
 99
100   hexadecimal_value: INTEGER_8
101         -- Gives the value of an hexadecimal digit.
102      require
103         is_hexadecimal_digit
104      do
105         Result := code.to_integer_8
106         if code < 'A'.code then
107            Result := Result - 48
108         elseif code < 'a'.code then
109            Result := Result - 55
110         else
111            Result := Result - 87
112         end
113      ensure
114         Result.in_range(0, 15)
115      end
116
117   same_as (other: CHARACTER): BOOLEAN
118         -- Case insensitive comparison.
119         -- No difference between upper/lower case letters.
120      do
121         if Current = other then
122            Result := True
123         else
124            inspect
125               code
126            when 65 .. 90 then
127               Result := code = other.code - 32
128            when 97 .. 122 then
129               Result := code = other.code + 32
130            else
131            end
132         end
133      ensure
134         Result implies to_lower = other or to_upper = other
135      end
136
137   to_upper: CHARACTER
138         -- Conversion to the corresponding upper case.
139      do
140         if code < 97 then
141            Result := Current
142         elseif code > 122 then
143            Result := Current
144         else
145            Result := (code - 32).to_character
146         end
147      end
148
149   to_lower: CHARACTER
150         -- Conversion to the corresponding lower case.
151      do
152         if code < 65 then
153            Result := Current
154         elseif code > 90 then
155            Result := Current
156         else
157            Result := (code + 32).to_character
158         end
159      end
160
161   is_letter: BOOLEAN
162         -- Is it a letter ('a' .. 'z' or 'A' .. 'Z') ?
163      do
164         if Current >= 'a' then
165            Result := Current <= 'z'
166         elseif Current >= 'A' then
167            Result := Current <= 'Z'
168         end
169      ensure
170         Result = in_range('A', 'Z') or in_range('a', 'z')
171      end
172
173   is_digit, is_decimal_digit: BOOLEAN
174         -- Belongs to '0'..'9'.
175         --
176         -- See also `value', `decimal_value'
177      do
178         if Current >= '0' then
179            Result := Current <= '9'
180         end
181      ensure
182         Result = in_range('0', '9')
183      end
184
185   is_binary_digit: BOOLEAN
186         -- Belongs to '0'..'1'.
187      do
188         if Current >= '0' then
189            Result := Current <= '1'
190         end
191      ensure
192         Result = in_range('0', '1')
193      end
194
195   is_octal_digit: BOOLEAN
196         -- Belongs to '0'..'7'.
197      do
198         if Current >= '0' then
199            Result := Current <= '7'
200         end
201      ensure
202         Result = in_range('0', '7')
203      end
204
205   is_hexadecimal_digit: BOOLEAN
206         -- Is it one character of "0123456789abcdefABCDEF" ?
207      do
208         if is_digit then
209            Result := True
210         elseif Current >= 'a' then
211            Result := Current <= 'f'
212         elseif Current >= 'A' then
213            Result := Current <= 'F'
214         end
215      ensure
216         Result = (once "0123456789abcdefABCDEF").has(Current)
217      end
218
219   is_lower: BOOLEAN
220         -- Is it some lowercase letter ('a'..'z')?
221      do
222         inspect
223            Current
224         when 'a' .. 'z' then
225            Result := True
226         else
227         end
228      end
229
230   is_upper: BOOLEAN
231         -- Is it some uppercase letter ('A'..'Z')?
232      do
233         inspect
234            Current
235         when 'A' .. 'Z' then
236            Result := True
237         else
238         end
239      end
240
241   is_separator: BOOLEAN
242         -- True when character is a separator.
243      do
244         inspect
245            Current
246         when ' ', '%T', '%N', '%R', '%U', '%F' then
247            Result := True
248         else
249         end
250      end
251
252   is_letter_or_digit: BOOLEAN
253         -- Is it a letter (see `is_letter') or a digit (see `is_digit') ?
254      do
255         Result := is_letter or else is_digit
256      ensure
257         definition: Result = (is_letter or is_digit)
258      end
259
260   is_ascii: BOOLEAN
261         -- Is character a 8-bit ASCII character?
262      do
263         Result := code < 128
264      end
265
266   is_bit: BOOLEAN
267         -- True for `0' and `1'.
268      do
269         inspect
270            Current
271         when '0', '1' then
272            Result := True
273         else
274         end
275      end
276
277   next: CHARACTER
278         -- Give the next character (the following `code')
279      require
280         code < Maximum_character_code
281      do
282         Result := (code + 1).to_character
283      end
284
285   previous: CHARACTER
286         -- Give the previous character (the `code' before)
287      require
288         code > Minimum_character_code
289      do
290         Result := (code - 1).to_character
291      end
292
293   infix "|..|" (other: CHARACTER): INTEGER_RANGE[CHARACTER]
294      require
295         Current <= other
296      do
297         create Result.make(code.to_integer_32, other.code.to_integer_32, integer_range_itemize, integer_range_indexize)
298      end
299
300feature {}
301   integer_range_itemize: FUNCTION[TUPLE[INTEGER], CHARACTER]
302      once
303         Result := agent (i: INTEGER): CHARACTER do Result := i.to_character end (?)
304      end
305
306   integer_range_indexize: FUNCTION[TUPLE[CHARACTER], INTEGER]
307      once
308         Result := agent (i: CHARACTER): INTEGER do Result := i.code.to_integer_32 end (?)
309      end
310
311feature {ANY} -- Conversions:
312   to_hexadecimal: STRING
313         -- Create a new STRING giving the `code' in hexadecimal.
314         -- For example :
315         --    (255).to_character.to_hexadecimal gives "FF".
316         -- Note: see `to_hexadecimal_in' to save memory.
317      do
318         create Result.make(2)
319         to_hexadecimal_in(Result)
320      ensure
321         Result.count = 2
322      end
323
324   to_hexadecimal_in (str: STRING)
325         -- Append the equivalent of `to_hexadecimal' at the end of
326         -- `str'. Thus you can save memory because no other
327         -- STRING is allocated for the job.
328      local
329         c: INTEGER_16
330      do
331         c := code |>> 4
332         inspect
333            c
334         when 0 .. 9 then
335            str.extend(('0'.code + c).to_character)
336         else
337            str.extend(('A'.code - 10 + c).to_character)
338         end
339         c := code & 0x000F
340         inspect
341            c
342         when 0 .. 9 then
343            str.extend(('0'.code + c).to_character)
344         else
345            str.extend(('A'.code - 10 + c).to_character)
346         end
347      ensure
348         str.count = 2 + old str.count
349      end
350
351   to_string: STRING
352      do
353         create Result.make_filled(Current, 1)
354      ensure
355         Result.count = 1
356         Result.first = Current
357      end
358
359feature {ANY} -- Object Printing:
360   out_in_tagged_out_memory, fill_tagged_out_memory
361      do
362         tagged_out_memory.extend(Current)
363      end
364
365feature {ANY} -- Hashing:
366   hash_code: INTEGER
367      do
368         Result := code
369      end
370
371feature {ANY} -- Miscellaneous:
372   is_alpha: BOOLEAN
373         -- See `is_letter' (yes this is just a call to `is_letter').
374         -- Isn't `is_letter' better English ;-)
375      do
376         Result := is_letter
377      ensure
378         Result = is_letter
379      end
380
381end -- class CHARACTER
382--
383-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
384--
385-- Permission is hereby granted, free of charge, to any person obtaining a copy
386-- of this software and associated documentation files (the "Software"), to deal
387-- in the Software without restriction, including without limitation the rights
388-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
389-- copies of the Software, and to permit persons to whom the Software is
390-- furnished to do so, subject to the following conditions:
391--
392-- The above copyright notice and this permission notice shall be included in
393-- all copies or substantial portions of the Software.
394--
395-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
396-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
397-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
398-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
399-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
400-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
401-- THE SOFTWARE.