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