/src/lib/string/character.e
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.