PageRenderTime 16ms CodeModel.GetById 12ms app.highlight 2ms RepoModel.GetById 1ms app.codeStats 0ms

/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--
  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.