! Copyright (C) 2005, 2009 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: arrays kernel math sbufs sequences sequences.private strings ; IN: splitting : ?head ( seq begin -- newseq ? ) [ head? ] [ tail ] ?chomp ; : ?head-slice ( seq begin -- newseq ? ) [ head? ] [ tail-slice ] ?chomp ; : ?tail ( seq end -- newseq ? ) [ tail? ] [ head* ] ?chomp ; : ?tail-slice ( seq end -- newseq ? ) [ tail? ] [ head-slice* ] ?chomp ; : subseq-range ( seq subseq -- from/f to/f ) tuck subseq-index [ dup rot length + ] [ drop f f ] if* ; : ?snip ( from/f to/f seq -- before after ) over [ snip ] [ 2nip f ] if ; inline : ?snip-slice ( from/f to/f seq -- before after ) over [ snip-slice ] [ 2nip f ] if ; inline : split1 ( seq subseq -- before after ) [ subseq-range ] keepd ?snip ; inline : split1-slice ( seq subseq -- before-slice after-slice ) [ subseq-range ] keepd ?snip-slice ; inline : split-subseq ( seq subseq -- seqs ) [ 1array ] [ [ dup ] swap [ split1-slice swap ] curry produce nip ] if-empty ; : replace ( seq old new -- new-seq ) pick [ [ split-subseq ] dip ] dip join-as ; : split1-when ( ... seq quot: ( ... elt -- ... ? ) -- ... before after ) [ find drop ] keepd swap [ dup 1 + rot snip ] [ f ] if* ; inline : split1-when-slice ( ... seq quot: ( ... elt -- ... ? ) -- ... before-slice after-slice ) [ find drop ] keepd swap [ dup 1 + rot snip-slice ] [ f ] if* ; inline : split1-last ( seq subseq -- before after ) [ ] bi@ split1 [ reverse ] bi@ dup [ swap ] when ; : split1-last-slice ( seq subseq -- before-slice after-slice ) [ ] bi@ split1-slice [ ] bi@ [ f ] [ swap ] if-empty ; : split-when ( ... seq quot: ( ... elt -- ... ? ) -- ... pieces ) [ subseq-unsafe ] (split) ; inline : split-when-slice ( ... seq quot: ( ... elt -- ... ? ) -- ... pieces ) [ ] (split) ; inline : split ( seq separators -- pieces ) [ member? ] curry split-when ; inline : split-slice ( seq separators -- pieces ) [ member? ] curry split-when-slice ; inline : split-indices ( seq indices -- pieces ) over length suffix 0 swap [ [ pick subseq ] keep swap ] map 2nip ; ! split-lines uses string-nth-fast which is 50% faster over ! nth-unsafe. be careful when changing the definition so that ! you don't unoptimize it. GENERIC: split-lines ( seq -- seq' ) ALIAS: string-lines split-lines M: string split-lines [ V{ } clone 0 ] dip [ 2dup bounds-check? ] [ 2dup [ "\r\n" member? ] find-from swapd [ over [ [ nip length ] keep ] unless [ "" subseq-as suffix! ] 2keep [ 1 + ] dip ] dip CHAR: \r eq? [ 2dup ?nth CHAR: \n eq? [ [ 1 + ] dip ] when ] when ] while 2drop { } like ; M: sbuf split-lines "" like split-lines ; : join-lines-as ( seq exemplar -- seq ) "\n" swap join-as ; inline : join-lines ( seq -- seq ) "" join-lines-as ; inline : split-words ( seq -- seq ) " " split ; inline : join-words-as ( seq exemplar -- seq ) " " swap join-as ; inline : join-words ( seq -- seq ) " " join-words-as ; inline