-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfasta_reader.e
241 lines (202 loc) · 4.57 KB
/
fasta_reader.e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
indexing
description: "Reads FASTA formatted files sequentially."
author: "Eser Aygün"
date: "$Date$"
revision: "$Revision$"
class
FASTA_READER
create
make
feature {NONE} -- Initialization
make (s: KI_TEXT_INPUT_STREAM) is
-- Create reader for stream `s'.
local
i: INTEGER
do
input_stream := s
create {CHARACTER_8_SET}allowed_elements.make
from
i := {CHARACTER}.min_value
until
i > {CHARACTER}.max_value
loop
allowed_elements.put (i.to_character_8)
i := i + 1
end
end
feature -- Access
line_number: INTEGER
-- Current line number.
line: STRING
-- Current line.
index: INTEGER
-- Index of current item.
identifier: STRING
-- Identifier of current item.
item: ADVANCED_STRING
-- Sequence of current item.
allowed_elements: SET [CHARACTER]
-- Set of allowed elements.
feature -- Status report
off: BOOLEAN
-- Is there no current item?
feature -- Cursor movement
start is
-- Move to first position if any.
do
index := 0
identifier := Void
item := Void
if not input_stream.end_of_input then
off := False
input_start
forth
else
off := True
end
ensure
first_item: not off implies (index = 1)
end
forth is
-- Move to next position; if no next position,
-- ensure that `off' will be true.
require
not_off: not off
do
index := index + 1
identifier := Void
item := Void
read_identifier
if identifier /= Void then
read_sequence
else
off := True
end
ensure
next_item: index = old index + 1
end
feature -- Element change
set_allowed_elements (v: like allowed_elements) is
-- Let `allowed_elements' be `v'.
require
not_void: v /= Void
do
allowed_elements := v
end
feature {NONE} -- Implementation
input_stream: KI_TEXT_INPUT_STREAM
-- Input stream.
input_off: BOOLEAN is
-- Is input off?
do
Result := input_stream.end_of_input
end
input_start is
-- Go to first position.
do
line_number := 0
-- input_stream.rewind
input_forth
ensure
first_line: not input_off implies (line_number = 1)
end
input_forth is
-- Read a string until new line or end of input.
-- Make result available in `line'.
do
line_number := line_number + 1
line := Void
input_stream.read_line
line := input_stream.last_string
line.left_adjust
line.right_adjust
ensure
next_line: line_number = old line_number + 1
end
read_identifier is
-- Read identifier line.
require
not_off: not off
local
id: STRING
do
from
id := Void
until
(id /= Void) or input_off
loop
-- Skip empty lines and expect a '>' for identifier.
if not line.is_empty then
inspect line @ 1
when '>' then -- Identifier line: set identifier.
id := line.substring (2, line.count)
id.left_adjust
when ';' then -- Comment line: skip.
-- do nothing
else -- Unexpected content.
raise ("Identifier line expected", True, False)
end
end
input_forth
end
if id /= Void then
identifier := id
end
ensure
not_void_or_input_off: (identifier /= Void) or input_off
end
read_sequence is
-- Read item lines.
local
seq: ADVANCED_STRING
done: BOOLEAN
do
from
create seq.make_from_string ("")
until
done or input_off
loop
-- Skip empty lines and read until an identifier line.
if not line.is_empty then
inspect line @ 1
when '>' then -- Identifier line: stop reading.
done := True
when ';' then -- Comment line: skip.
-- do nothing
else -- Sequence line: extend item.
seq.append (line.as_upper)
end
end
if not done then
input_forth
end
end
seq.prune_whitespaces
if seq.is_empty then
raise ("Empty item", True, False)
end
if not seq.all_in (allowed_elements) then
raise ("Invalid element '" + seq.failed_character.out + "'", False, True)
end
item := seq
ensure
not_void: item /= Void
end
raise (m: STRING; include_line: BOOLEAN; include_identifier: BOOLEAN) is
-- Raise an exception with message `m'.
local
s: STRING
ex: DEVELOPER_EXCEPTION
do
s := m
if include_line then
s := s + " at line " + line_number.out
end
if include_identifier then
s := s + " in '" + identifier + "'"
end
create ex
ex.set_message (s)
ex.raise
end
end