diff --git a/extra/cords/authors.txt b/extra/cords/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/extra/cords/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/extra/cords/cords-tests.factor b/extra/cords/cords-tests.factor new file mode 100644 index 0000000000..0058c8f07a --- /dev/null +++ b/extra/cords/cords-tests.factor @@ -0,0 +1,5 @@ +IN: cords.tests +USING: cords strings tools.test kernel sequences ; + +[ "hello world" ] [ "hello" " world" cord-append dup like ] unit-test +[ "hello world" ] [ { "he" "llo" " world" } cord-concat dup like ] unit-test diff --git a/extra/cords/cords.factor b/extra/cords/cords.factor new file mode 100644 index 0000000000..f5cc89f8d5 --- /dev/null +++ b/extra/cords/cords.factor @@ -0,0 +1,70 @@ +! Copysecond (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors assocs sequences sorting math math.order +arrays combinators kernel ; +IN: cords + +> length ] [ second>> length ] bi + ; + +M: simple-cord virtual-seq first>> ; + +M: simple-cord virtual@ + 2dup first>> length < + [ first>> ] [ [ first>> length - ] [ second>> ] bi ] if ; + +TUPLE: multi-cord count seqs ; + +M: multi-cord length count>> ; + +M: multi-cord virtual@ + dupd + seqs>> [ first <=> ] binsearch* + [ first - ] [ second ] bi ; + +M: multi-cord virtual-seq + seqs>> dup empty? [ drop f ] [ first second ] if ; + +: ( seqs -- cord ) + dup length 2 = [ + first2 simple-cord boa + ] [ + [ 0 [ length + ] accumulate ] keep zip multi-cord boa + ] if ; + +PRIVATE> + +UNION: cord simple-cord multi-cord ; + +INSTANCE: cord virtual-sequence + +INSTANCE: multi-cord virtual-sequence + +: cord-append ( seq1 seq2 -- cord ) + { + { [ over empty? ] [ nip ] } + { [ dup empty? ] [ drop ] } + { [ 2dup [ cord? ] both? ] [ [ seqs>> values ] bi@ append ] } + { [ over cord? ] [ [ seqs>> values ] dip suffix ] } + { [ dup cord? ] [ seqs>> values swap prefix ] } + [ 2array ] + } cond ; + +: cord-concat ( seqs -- cord ) + { + { [ dup empty? ] [ drop f ] } + { [ dup length 1 = ] [ first ] } + [ + [ + { + { [ dup cord? ] [ seqs>> values ] } + { [ dup empty? ] [ drop { } ] } + [ 1array ] + } cond + ] map concat + ] + } cond ; diff --git a/extra/cords/summary.txt b/extra/cords/summary.txt new file mode 100644 index 0000000000..3c69862b71 --- /dev/null +++ b/extra/cords/summary.txt @@ -0,0 +1 @@ +Virtual sequence concatenation diff --git a/extra/cords/tags.txt b/extra/cords/tags.txt new file mode 100644 index 0000000000..42d711b32b --- /dev/null +++ b/extra/cords/tags.txt @@ -0,0 +1 @@ +collections