PageRenderTime 22ms CodeModel.GetById 12ms app.highlight 4ms RepoModel.GetById 2ms app.codeStats 0ms

/src/lib/io/basic/std_input.e

http://github.com/tybor/Liberty
Specman e | 240 lines | 165 code | 29 blank | 46 comment | 9 complexity | fc79c56c4650202bc778cfb4c06359b3 MD5 | raw file
  1-- This file is part of a Liberty Eiffel library.
  2-- See the full copyright at the end.
  3--
  4class STD_INPUT
  5   --
  6   -- To use the standard input file. As for UNIX, the default standard input is the keyboard.
  7   --
  8   -- Note: only one instance of this class should be necessary.  Access it through ANY.std_input.
  9   --
 10   -- See also STANDARD_STREAMS, STD_INPUT_OUTPUT
 11   --
 12
 13inherit
 14   TERMINAL_INPUT_STREAM
 15      redefine
 16         filtered_read_line_in, dispose
 17      end
 18
 19insert
 20   STRING_HANDLER
 21   REDIRECTION_TOOLS
 22      rename
 23         restore_default as restore_default_input
 24      redefine
 25         restore_default_input
 26      end
 27
 28create {ANY}
 29   make
 30
 31feature {ANY}
 32   is_connected: BOOLEAN True
 33
 34   end_of_input: BOOLEAN
 35
 36   disconnect
 37      do
 38         filter := Void
 39      end
 40
 41feature {}
 42   make
 43      do
 44         buffer := buffer.calloc(4096)
 45         capacity := 4096
 46      end
 47
 48feature {ANY}
 49   can_unread_character: BOOLEAN
 50      do
 51         Result := not unread_character_flag
 52      end
 53
 54feature {FILTER_INPUT_STREAM}
 55   filtered_read_character
 56      do
 57         std_output.flush
 58         unread_character_flag := False
 59         if buffer_position >= buffer_size then
 60            fill_buffer
 61         end
 62         filtered_last_character := buffer.item(buffer_position)
 63         buffer_position := buffer_position + 1
 64         end_of_input := end_reached
 65      end
 66
 67   filtered_unread_character
 68      do
 69         unread_character_flag := True
 70         end_of_input := False
 71         buffer_position := buffer_position - 1
 72      end
 73
 74   filtered_last_character: CHARACTER
 75
 76   filtered_read_line_in (str: STRING)
 77      local
 78         i: INTEGER; stop: BOOLEAN; old_count, new_count: INTEGER; initial_count: INTEGER
 79      do
 80         std_output.flush
 81         from
 82            initial_count := str.count
 83         until
 84            stop
 85         loop
 86            -- search %N in buffer
 87            from
 88               i := buffer_position
 89            until
 90               i >= buffer_size or else buffer.item(i) = '%N'
 91            loop
 92               i := i + 1
 93            end
 94            -- block copy (but copy_slice copies char by char...)
 95            if i > buffer_position then
 96               old_count := str.count
 97               new_count := old_count + i - buffer_position
 98               if str.capacity < new_count then
 99                  str.resize((old_count * 2).max(new_count))
100               end
101               str.storage.slice_copy(old_count, buffer, buffer_position, i - 1)
102               str.set_count(new_count)
103            end
104            -- next buffer if needed
105            if i < buffer_size and then buffer.item(i) = '%N' then
106               stop := True
107               buffer_position := i + 1
108               if str.count > initial_count and then str.last = '%R' then
109                  str.remove_last
110                  -- UNIX uses the Line Feed character (ASCII character 10) to
111                  -- denote the end of a line. DOS uses the Carriage Return
112                  -- followed by the Line Feed character (ASCII character 13
113                  -- & ASCII character 10) instead.
114               end
115            else
116               if not end_reached then
117                  fill_buffer
118               end
119               stop := end_reached
120            end
121         end
122         unread_character_flag := False
123         end_of_input := end_reached
124      end
125
126feature {}
127   buffer: NATIVE_ARRAY[CHARACTER]
128
129   end_reached: BOOLEAN
130
131   buffer_position, buffer_size: INTEGER
132
133   capacity: INTEGER
134
135   unread_character_flag: BOOLEAN
136
137   fill_buffer
138      local
139         last: CHARACTER
140      do
141         if buffer_size > 0 then
142            last := buffer.item(buffer_size - 1)
143         end
144         buffer_size := read_stdin(buffer, 4096)
145         buffer_position := 0
146         if buffer_size <= 0 then
147            end_reached := True
148            buffer.put(last, 0)
149            -- needed for unread_character service
150            --if buffer_size = -1 => exception ?
151            buffer_size := 1
152            buffer_position := 1
153         end
154      end
155
156feature {FILTER}
157   filtered_descriptor: INTEGER
158      do
159         Result := sequencer_descriptor(stdin)
160      end
161
162   filtered_has_descriptor: BOOLEAN True
163
164   filtered_stream_pointer: POINTER
165      do
166         Result := stdin
167      end
168
169   filtered_has_stream_pointer: BOOLEAN True
170
171feature {STREAM_HANDLER}
172   redirect_from (file_name: STRING)
173         -- Redirect standard input to come from `file_name' instead of the default standard input.
174         --
175         -- See also `redirection_succeeded'
176      do
177         redirect(open_descriptor_for_read(file_name.to_external))
178      end
179
180   restore_default_input
181         -- Restore standard input to come from the default standard input.
182      do
183         Precursor
184      end
185
186feature {}
187   flush
188         -- Discard any characters remaining in the input buffer.
189      do
190         buffer_position := buffer_size
191      end
192
193   read_stdin (buf: NATIVE_ARRAY[CHARACTER]; size: INTEGER): INTEGER
194         -- return size read or 0 if end of input (-1 on error => exception ?)
195      external "plug_in"
196      alias "{
197         location: "${sys}/plugins"
198         module_name: "io"
199         feature_name: "read_stdin"
200         }"
201      end
202
203   stdin: POINTER
204      external "plug_in"
205      alias "{
206         location: "${sys}/plugins"
207         module_name: "io"
208         feature_name: "stdin"
209         }"
210      end
211
212   dispose
213      do
214         check
215            std_input = Current
216         end
217         -- Nothing to dispose for `std_input'.
218      end
219
220end -- class STD_INPUT
221--
222-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
223--
224-- Permission is hereby granted, free of charge, to any person obtaining a copy
225-- of this software and associated documentation files (the "Software"), to deal
226-- in the Software without restriction, including without limitation the rights
227-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
228-- copies of the Software, and to permit persons to whom the Software is
229-- furnished to do so, subject to the following conditions:
230--
231-- The above copyright notice and this permission notice shall be included in
232-- all copies or substantial portions of the Software.
233--
234-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
235-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
236-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
237-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
238-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
239-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
240-- THE SOFTWARE.