/src/lib/io/basic/binary_file_read.e

http://github.com/tybor/Liberty · Specman e · 352 lines · 272 code · 42 blank · 38 comment · 20 complexity · b17ff3f2b037f84b85c95f846529156d MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. class BINARY_FILE_READ
  5. -- This class allow to read a file on the disk as a binary file
  6. -- (ie. file containing bytes). If you need to read a file which
  7. -- contain text, then consider using TEXT_FILE_READ.
  8. inherit
  9. BINARY_INPUT_STREAM
  10. TERMINAL_INPUT_STREAM
  11. FILE_STREAM
  12. insert
  13. PLATFORM
  14. create {ANY}
  15. make, with_buffer_size, connect_to
  16. feature {ANY}
  17. connect_to (new_path: ABSTRACT_STRING)
  18. -- Open binary file for reading.
  19. -- The stream is positioned at the beginning of the file.
  20. --
  21. -- See also `make', `with_buffer_size'.
  22. do
  23. filtered_stream_pointer := binary_file_read_open(new_path.to_external)
  24. if filtered_stream_pointer.is_not_null then
  25. set_path(new_path)
  26. end_of_input := False
  27. if capacity = 0 then
  28. buffer := buffer.calloc(4096)
  29. capacity := 4096
  30. end
  31. buffer_position := 0
  32. buffer_size := 0
  33. if the_terminal_settings /= Void then
  34. the_terminal_settings.make(filtered_stream_pointer, Current)
  35. end
  36. end
  37. ensure then
  38. is_connected implies not end_of_input
  39. end
  40. disconnect
  41. do
  42. io_fclose(filtered_stream_pointer)
  43. path := Void
  44. end
  45. can_unread_character: BOOLEAN
  46. do
  47. Result := buffer_position > 0
  48. end
  49. read_byte
  50. do
  51. filtered_read_character
  52. end
  53. last_byte: INTEGER
  54. do
  55. Result := filtered_last_character.code
  56. ensure
  57. Result.in_range(Minimum_character_code, Maximum_character_code)
  58. end
  59. read_integer_16_native_endian
  60. local
  61. c1, c2: CHARACTER
  62. do
  63. if buffer_position >= buffer_size then
  64. fill_buffer
  65. end
  66. c1 := buffer.item(buffer_position)
  67. buffer_position := buffer_position + 1
  68. if buffer_position >= buffer_size and then not end_of_input then
  69. fill_buffer
  70. end
  71. c2 := buffer.item(buffer_position)
  72. buffer_position := buffer_position + 1
  73. last_integer_16 := as_16_ne(c1, c2)
  74. end
  75. read_integer_16_big_endian
  76. do
  77. if buffer_position >= buffer_size then
  78. fill_buffer
  79. end
  80. last_integer_16 := buffer.item(buffer_position).code |<< 8
  81. buffer_position := buffer_position + 1
  82. if buffer_position >= buffer_size and then not end_of_input then
  83. fill_buffer
  84. end
  85. last_integer_16 := last_integer_16 | buffer.item(buffer_position).code
  86. buffer_position := buffer_position + 1
  87. end
  88. read_integer_16_little_endian
  89. do
  90. if buffer_position >= buffer_size then
  91. fill_buffer
  92. end
  93. last_integer_16 := buffer.item(buffer_position).code
  94. buffer_position := buffer_position + 1
  95. if buffer_position >= buffer_size and then not end_of_input then
  96. fill_buffer
  97. end
  98. last_integer_16 := last_integer_16 | (buffer.item(buffer_position).code |<< 8)
  99. buffer_position := buffer_position + 1
  100. end
  101. last_integer_16: INTEGER
  102. read_integer_32_native_endian
  103. local
  104. old_integer_16, i1, i2: INTEGER
  105. do
  106. old_integer_16 := last_integer_16
  107. read_integer_16_native_endian
  108. i1 := last_integer_16
  109. read_integer_16_native_endian
  110. i2 := last_integer_16
  111. last_integer_32 := as_32_ne(i1.to_integer_16, i2.to_integer_16)
  112. last_integer_16 := old_integer_16
  113. end
  114. read_integer_32_big_endian
  115. do
  116. if buffer_position >= buffer_size then
  117. fill_buffer
  118. end
  119. last_integer_32 := buffer.item(buffer_position).code.to_integer_32 |<< 24
  120. buffer_position := buffer_position + 1
  121. if buffer_position >= buffer_size and then not end_of_input then
  122. fill_buffer
  123. end
  124. last_integer_32 := last_integer_32 | (buffer.item(buffer_position).code.to_integer_32 |<< 16)
  125. buffer_position := buffer_position + 1
  126. if buffer_position >= buffer_size and then not end_of_input then
  127. fill_buffer
  128. end
  129. last_integer_32 := last_integer_32 | (buffer.item(buffer_position).code |<< 8)
  130. buffer_position := buffer_position + 1
  131. if buffer_position >= buffer_size and then not end_of_input then
  132. fill_buffer
  133. end
  134. last_integer_32 := last_integer_32 | buffer.item(buffer_position).code
  135. buffer_position := buffer_position + 1
  136. end
  137. read_integer_32_little_endian
  138. do
  139. if buffer_position >= buffer_size then
  140. fill_buffer
  141. end
  142. last_integer_32 := buffer.item(buffer_position).code
  143. buffer_position := buffer_position + 1
  144. if buffer_position >= buffer_size and then not end_of_input then
  145. fill_buffer
  146. end
  147. last_integer_32 := last_integer_32 | (buffer.item(buffer_position).code |<< 8)
  148. buffer_position := buffer_position + 1
  149. if buffer_position >= buffer_size and then not end_of_input then
  150. fill_buffer
  151. end
  152. last_integer_32 := last_integer_32 | (buffer.item(buffer_position).code.to_integer_32 |<< 16)
  153. buffer_position := buffer_position + 1
  154. if buffer_position >= buffer_size and then not end_of_input then
  155. fill_buffer
  156. end
  157. last_integer_32 := last_integer_32 | (buffer.item(buffer_position).code.to_integer_32 |<< 24)
  158. buffer_position := buffer_position + 1
  159. end
  160. last_integer_32: INTEGER_32
  161. end_of_input: BOOLEAN
  162. seek (new_offset: INTEGER_64)
  163. -- Next read will start at position `new_offset', counted from
  164. -- the beginning of the file.
  165. --
  166. -- See also `offset'.
  167. require
  168. new_offset >= 0
  169. not is_filtered
  170. local
  171. error: INTEGER
  172. do
  173. error := io_fseek (filtered_stream_pointer, new_offset)
  174. buffer_position := 0
  175. buffer_size := 0
  176. ensure
  177. offset = new_offset
  178. end
  179. offset: INTEGER_64
  180. -- The `offset' that will be used for the next read.
  181. --
  182. -- See also `seek'.
  183. require
  184. not is_filtered
  185. do
  186. Result := io_ftell (filtered_stream_pointer) - buffer_size + buffer_position
  187. end
  188. terminal_settings: TERMINAL_SETTINGS
  189. do
  190. if the_terminal_settings = Void then
  191. create the_terminal_settings.make(filtered_stream_pointer, Current)
  192. end
  193. Result := the_terminal_settings
  194. ensure
  195. valid: Result /= Void
  196. associated: Result.associated_stream = Current
  197. end
  198. feature {FILTER}
  199. filtered_descriptor: INTEGER
  200. do
  201. Result := sequencer_descriptor(filtered_stream_pointer)
  202. end
  203. filtered_has_descriptor: BOOLEAN True
  204. filtered_stream_pointer: POINTER
  205. filtered_has_stream_pointer: BOOLEAN True
  206. feature {FILTER_INPUT_STREAM}
  207. filtered_read_character
  208. do
  209. if buffer_position >= buffer_size then
  210. fill_buffer
  211. end
  212. filtered_last_character := buffer.item(buffer_position)
  213. buffer_position := buffer_position + 1
  214. end
  215. filtered_unread_character
  216. do
  217. end_of_input := False
  218. buffer_position := buffer_position - 1
  219. filtered_last_character := buffer.item(buffer_position)
  220. end
  221. filtered_last_character: CHARACTER
  222. feature {}
  223. buffer: NATIVE_ARRAY[CHARACTER]
  224. buffer_position, buffer_size: INTEGER
  225. capacity: INTEGER
  226. the_terminal_settings: TERMINAL_SETTINGS
  227. fill_buffer
  228. do
  229. buffer_size := io_fread(buffer, capacity, filtered_stream_pointer)
  230. buffer_position := 0
  231. if buffer_size <= 0 then
  232. end_of_input := True --if buffer_size = -1 => exception ?
  233. buffer_size := 1
  234. buffer_position := 1
  235. end
  236. end
  237. make
  238. -- The new created object is not connected. (See also `connect_to'.)
  239. do
  240. ensure
  241. not is_connected
  242. end
  243. with_buffer_size(buffer_capacity: INTEGER)
  244. do
  245. buffer := buffer.calloc(buffer_capacity)
  246. capacity := buffer_capacity
  247. end
  248. binary_file_read_open (path_pointer: POINTER): POINTER
  249. external "plug_in"
  250. alias "{
  251. location: "${sys}/plugins"
  252. module_name: "io"
  253. feature_name: "binary_file_read_open"
  254. }"
  255. end
  256. io_fclose (stream: POINTER)
  257. external "plug_in"
  258. alias "{
  259. location: "${sys}/plugins"
  260. module_name: "io"
  261. feature_name: "io_fclose"
  262. }"
  263. end
  264. io_fseek (path_pointer: POINTER; new_offset: INTEGER_64): INTEGER_32
  265. external "plug_in"
  266. alias "{
  267. location: "${sys}/plugins"
  268. module_name: "io"
  269. feature_name: "io_fseek"
  270. }"
  271. ensure
  272. Result = 0 -- failure otherwise
  273. end
  274. io_ftell (path_pointer: POINTER): INTEGER_64
  275. external "plug_in"
  276. alias "{
  277. location: "${sys}/plugins"
  278. module_name: "io"
  279. feature_name: "io_ftell"
  280. }"
  281. ensure
  282. Result >= 0 -- failure otherwise
  283. end
  284. as_16_ne (c1, c2: CHARACTER): INTEGER_16
  285. external "built_in"
  286. end
  287. as_32_ne (i1, i2: INTEGER_16): INTEGER_32
  288. external "built_in"
  289. end
  290. end -- class BINARY_FILE_READ
  291. --
  292. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  293. --
  294. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  295. -- of this software and associated documentation files (the "Software"), to deal
  296. -- in the Software without restriction, including without limitation the rights
  297. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  298. -- copies of the Software, and to permit persons to whom the Software is
  299. -- furnished to do so, subject to the following conditions:
  300. --
  301. -- The above copyright notice and this permission notice shall be included in
  302. -- all copies or substantial portions of the Software.
  303. --
  304. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  305. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  306. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  307. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  308. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  309. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  310. -- THE SOFTWARE.