61 lines
2.4 KiB
Text
61 lines
2.4 KiB
Text
Rebol [
|
|
title: "Rosetta code: FASTA format"
|
|
file: %FASTA_format.r3
|
|
url: https://rosettacode.org/wiki/FASTA_format
|
|
]
|
|
;; Parses a FASTA-format file in chunks, returning a flat block of [header sequence] pairs.
|
|
;; FASTA format alternates between header lines (starting with ">") and sequence data lines.
|
|
decode-fasta: function [
|
|
source [file! url!] "Source file or URL to read from"
|
|
chunk-size [integer!] "Number of bytes to read per iteration"
|
|
][
|
|
out: copy []
|
|
port: open/read source ;; open the source as a streaming read port
|
|
|
|
;; Stream through the file chunk by chunk to avoid loading it all into memory
|
|
while [not empty? data: read/string/part port chunk-size][
|
|
|
|
;; If the previous iteration had an incomplete (trailing) line, prepend it
|
|
;; to the current chunk so it is parsed as a whole line this time
|
|
if rest [insert data rest]
|
|
|
|
parse data [
|
|
any [
|
|
;; Match everything up to the next newline as one line, then skip the LF
|
|
copy line: to LF skip (
|
|
either line/1 == #">" [
|
|
;; Header line - strip the leading ">" and add a new entry to out;
|
|
;; also capture the new 'val' reference for subsequent sequence appends
|
|
repend out [remove line val: copy ""]
|
|
][
|
|
;; Sequence line - append its content to the current entry's value
|
|
append val line
|
|
]
|
|
)
|
|
]
|
|
;; Capture any trailing bytes that did not end with LF (incomplete line);
|
|
;; 'rest' will be prepended to the next chunk at the top of the loop
|
|
copy rest: to end
|
|
]
|
|
]
|
|
close port ;; Be nice and close the port when done reading
|
|
|
|
;; The final trailing bytes are part of the last value
|
|
if all [val rest] [append val rest]
|
|
|
|
;; Insert a new-line marker before every other element (i.e. before each header),
|
|
;; making the flat block easier to read when printed with 'probe'
|
|
new-line/skip out true 2
|
|
]
|
|
|
|
;; Prepare a test file
|
|
write %data.fasta
|
|
{>Rosetta_Example_1
|
|
THERECANBENOSPACE
|
|
>Rosetta_Example_2
|
|
THERECANBESEVERAL
|
|
LINESBUTTHEYALLMUST
|
|
BECONCATENATED}
|
|
|
|
;; Run the decoder on a local FASTA file, reading 10 bytes at a time, and print the result
|
|
probe decode-fasta %data.fasta 10
|