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