/src/lib/io/filter/base64_input_stream.e

http://github.com/tybor/Liberty · Specman e · 201 lines · 154 code · 21 blank · 26 comment · 9 complexity · 3863600f80e1a4c02ea555e81c664601 MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. class BASE64_INPUT_STREAM
  5. --
  6. -- A Base64 decoder. Plug it onto a Base64-encoded stream.
  7. --
  8. inherit
  9. FILTER_INPUT_STREAM
  10. redefine can_unread_character, end_of_input
  11. end
  12. create {ANY}
  13. connect_to
  14. feature {ANY}
  15. can_unread_character: BOOLEAN
  16. do
  17. Result := flags.bit_test(can_unread_character_flag)
  18. end
  19. end_of_input: BOOLEAN
  20. do
  21. Result := end_of_base64 or else Precursor
  22. end
  23. feature {}
  24. local_can_disconnect: BOOLEAN True
  25. feature {FILTER_INPUT_STREAM}
  26. filtered_read_character
  27. local
  28. c: INTEGER
  29. do
  30. if has_unread_character then
  31. set_has_unread_character(False)
  32. swap_unread_buffer
  33. else
  34. unread_buffer := filtered_last_character
  35. from
  36. stream.filtered_read_character
  37. until
  38. stream.end_of_input or else stream.filtered_last_character /= '%N'
  39. loop
  40. stream.filtered_read_character
  41. end
  42. if not stream.end_of_input then
  43. c := b2t(stream.filtered_last_character)
  44. inspect
  45. state
  46. when 0 then
  47. accu := c |<< 2
  48. stream.filtered_read_character
  49. if not stream.end_of_input then
  50. c := b2t(stream.filtered_last_character)
  51. accu := accu | (c |>> 4)
  52. filtered_last_character := accu.to_character
  53. accu := c & 15 |<< 4
  54. state := 1
  55. end
  56. when 1 then
  57. accu := accu | (c |>> 2)
  58. filtered_last_character := accu.to_character
  59. accu := c & 3 |<< 6
  60. state := 2
  61. when 2 then
  62. accu := accu | c
  63. filtered_last_character := accu.to_character
  64. state := 0
  65. end
  66. end
  67. end
  68. set_can_unread_character(not end_of_input)
  69. end
  70. filtered_unread_character
  71. do
  72. set_has_unread_character(True)
  73. set_can_unread_character(False)
  74. swap_unread_buffer
  75. end
  76. filtered_last_character: CHARACTER
  77. feature {}
  78. state: INTEGER
  79. accu: INTEGER
  80. unread_buffer: CHARACTER
  81. swap_unread_buffer
  82. local
  83. tmp_buffer: CHARACTER
  84. do
  85. tmp_buffer := unread_buffer
  86. unread_buffer := filtered_last_character
  87. filtered_last_character := tmp_buffer
  88. ensure
  89. unread_buffer = old filtered_last_character
  90. filtered_last_character = old unread_buffer
  91. end
  92. set_can_unread_character (value: BOOLEAN)
  93. do
  94. if value then
  95. flags := flags.bit_set(can_unread_character_flag)
  96. else
  97. flags := flags.bit_reset(can_unread_character_flag)
  98. end
  99. ensure
  100. can_unread_character = value
  101. end
  102. has_unread_character: BOOLEAN
  103. do
  104. Result := flags.bit_test(has_unread_character_flag)
  105. end
  106. set_has_unread_character (value: BOOLEAN)
  107. do
  108. if value then
  109. flags := flags.bit_set(has_unread_character_flag)
  110. else
  111. flags := flags.bit_reset(has_unread_character_flag)
  112. end
  113. ensure
  114. has_unread_character = value
  115. end
  116. end_of_base64: BOOLEAN
  117. do
  118. Result := flags.bit_test(end_of_base64_flag)
  119. end
  120. set_end_of_base64 (value: BOOLEAN)
  121. do
  122. if value then
  123. flags := flags.bit_set(end_of_base64_flag)
  124. else
  125. flags := flags.bit_reset(end_of_base64_flag)
  126. end
  127. ensure
  128. end_of_base64 = value
  129. end
  130. flags: INTEGER
  131. can_unread_character_flag: INTEGER_8 0
  132. has_unread_character_flag: INTEGER_8 1
  133. end_of_base64_flag: INTEGER_8 2
  134. feature {}
  135. alphabet: STRING "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
  136. b2t (c: CHARACTER): INTEGER
  137. require
  138. c = '=' or else alphabet.has(c)
  139. do
  140. inspect
  141. c
  142. when '=' then
  143. set_end_of_base64(True)
  144. when 'A' .. 'Z' then
  145. Result := c.code - 'A'.code
  146. when 'a' .. 'z' then
  147. Result := c.code - ('a'.code - 26)
  148. when '0' .. '9' then
  149. Result := c.code - ('0'.code - 52)
  150. when '+' then
  151. Result := 62
  152. when '/' then
  153. Result := 63
  154. end
  155. ensure
  156. Result >= 0 and then Result < 64
  157. c /= '=' implies alphabet.item(Result + 1) = c
  158. c = '=' implies Result = 0
  159. end
  160. end -- class BASE64_INPUT_STREAM
  161. --
  162. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  163. --
  164. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  165. -- of this software and associated documentation files (the "Software"), to deal
  166. -- in the Software without restriction, including without limitation the rights
  167. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  168. -- copies of the Software, and to permit persons to whom the Software is
  169. -- furnished to do so, subject to the following conditions:
  170. --
  171. -- The above copyright notice and this permission notice shall be included in
  172. -- all copies or substantial portions of the Software.
  173. --
  174. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  175. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  176. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  177. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  178. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  179. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  180. -- THE SOFTWARE.