diff options
author | Mike Montague <mikemon@gmail.com> | 2022-09-06 21:42:16 -0700 |
---|---|---|
committer | Mike Montague <mikemon@gmail.com> | 2022-09-06 21:42:16 -0700 |
commit | 96eb779221be4ddf4bf1d3af48208f7c8ae934fa (patch) | |
tree | 277bb7057b2632ff4b8ee45f4843ca6383e36dee | |
parent | 86afa0639b713b6a9a97b2aeea3b3049fbdb98b0 (diff) |
srfi 207
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | src/base.scm | 9 | ||||
-rw-r--r-- | src/foment.hpp | 2 | ||||
-rw-r--r-- | src/read.cpp | 12 | ||||
-rw-r--r-- | src/srfi-207.scm | 90 | ||||
-rw-r--r-- | src/vectors.cpp | 164 | ||||
-rw-r--r-- | test/srfi.scm | 348 | ||||
-rw-r--r-- | unix/makefile | 6 | ||||
-rw-r--r-- | windows/makefile | 6 |
9 files changed, 452 insertions, 186 deletions
@@ -35,6 +35,7 @@ * SRFI 181: Custom ports (including transcoded ports) * SRFI 192: Port Positioning * SRFI 193: Command line +* SRFI 207: String-notated bytevectors * SRFI 229: Tagged Procedures See [Foment](https://github.com/leftmike/foment/wiki/Foment) for more details. diff --git a/src/base.scm b/src/base.scm index ef9c6fa..e4bc040 100644 --- a/src/base.scm +++ b/src/base.scm @@ -702,7 +702,14 @@ hex-string->bytevector bytevector->base64 base64->bytevector - bytestring->list) + bytestring->list + bytevector=? + bytevector<? + bytevector>? + bytevector<=? + bytevector>=? + read-textual-bytestring + write-textual-bytestring) (cond-expand (unix (export diff --git a/src/foment.hpp b/src/foment.hpp index 994341c..745d5e4 100644 --- a/src/foment.hpp +++ b/src/foment.hpp @@ -10,7 +10,6 @@ To Do: -- SRFI 154: First-class dynamic extents -- SRFI 158: Generators and Accumulators -- SRFI 195: Multiple-value boxes --- SRFI 207: String-notated bytevectors -- IO: FAlive, EnterWait, and LeaveWait -- Allow GC on nested executions @@ -629,6 +628,7 @@ void FoldcasePort(FObject port, long_t fcf); void WantIdentifiersPort(FObject port, long_t wif); FObject Read(FObject port); +FObject ReadBytestring(FObject port); void WriteCh(FObject port, FCh ch); void WriteString(FObject port, FCh * s, ulong_t sl); diff --git a/src/read.cpp b/src/read.cpp index f7232d3..9f18604 100644 --- a/src/read.cpp +++ b/src/read.cpp @@ -237,12 +237,16 @@ Again: UnexpectedEof: if (s != sb) free(s); - RaiseExceptionC(Lexical, "read", bsf ? "unexpected end-of-file reading bytestring" : - "unexpected end-of-file reading string", List(port)); + if (bsf) + RaiseExceptionC(Lexical, "read", BytestringErrorSymbol, + "unexpected end-of-file reading bytestring", List(port)); + else + RaiseExceptionC(Lexical, "read", "unexpected end-of-file reading string", + List(port)); return(NoValueObject); } -static FObject ReadBytestring(FObject port) +FObject ReadBytestring(FObject port) { FObject s = ReadStringLiteral(port, '"', 1); long_t sl = StringLength(s); @@ -250,7 +254,7 @@ static FObject ReadBytestring(FObject port) for (long_t idx = 0; idx < sl; idx += 1) { FCh ch = AsString(s)->String[idx]; - if (ch >= 128 ) + if (ch >= 256) RaiseExceptionC(Lexical, "read", BytestringErrorSymbol, "unexpected character in bytestring", List(MakeCharacter(ch))); AsBytevector(bv)->Vector[idx] = (FByte) ch; diff --git a/src/srfi-207.scm b/src/srfi-207.scm index 9f3dfa6..9f7f45b 100644 --- a/src/srfi-207.scm +++ b/src/srfi-207.scm @@ -15,10 +15,26 @@ bytestring-trim bytestring-trim-right bytestring-trim-both - + bytestring-replace + bytevector=? + bytevector<? + bytevector>? + bytevector<=? + bytevector>=? + (rename bytevector=? bytestring=?) + (rename bytevector<? bytestring<?) + (rename bytevector>? bytestring>?) + (rename bytevector<=? bytestring<=?) + (rename bytevector>=? bytestring>=?) bytestring-index bytestring-index-right - + bytestring-break + bytestring-span + bytestring-join + bytestring-split + read-textual-bytestring + write-textual-bytestring + write-binary-bytestring bytestring-error?) (begin (define (bytestring . args) @@ -62,7 +78,19 @@ (bytevector-copy bv start (+ (bytestring-index-right bv (lambda (n) (not (pred n)))) 1)) #u8()))) - + (define bytestring-replace + (case-lambda + ((bv1 bv2 start1 end1) + (%bytestring-replace bv1 bv2 start1 end1 0 (bytevector-length bv2))) + ((bv1 bv2 start1 end1 start2 end2) + (%bytestring-replace bv1 bv2 start1 end1 start2 end2)))) + (define (%bytestring-replace bv1 bv2 start1 end1 start2 end2) + (let* ((len (+ (- (bytevector-length bv1) (- end1 start1)) (- end2 start2))) + (bv (make-bytevector len))) + (bytevector-copy! bv 0 bv1 0 start1) + (bytevector-copy! bv start1 bv2 start2 end2) + (bytevector-copy! bv (+ start1 (- end2 start2)) bv1 end1 (bytevector-length bv1)) + bv)) (define (%bytestring-index bv pred start end) (if (>= start end) #f @@ -86,7 +114,61 @@ ((bv pred) (%bytestring-index-right bv pred 0 (bytevector-length bv))) ((bv pred start) (%bytestring-index-right bv pred start (bytevector-length bv))) ((bv pred start end) (%bytestring-index-right bv pred start end)))) - + (define (bytestring-break bv pred) + (let ((idx (bytestring-index bv pred))) + (if (not idx) + (values (bytevector-copy bv) (bytevector)) + (values (bytevector-copy bv 0 idx) (bytevector-copy bv idx))))) + (define (bytestring-span bv pred) + (bytestring-break bv (lambda (b) (not (pred b))))) + (define bytestring-join + (case-lambda + ((lst delim) (%bytestring-join lst (bytestring delim) 'infix)) + ((lst delim grammar) (%bytestring-join lst (bytestring delim) grammar)))) + (define (%bytestring-join lst delim grammar) + (if (null? lst) + (if (eq? grammar 'strict-infix) + (full-error 'assertion-violation 'bytestring-join 'bytestring-error + "bytestring-join: list must not be empty with strict-inflix") + (bytevector)) + (let ((port (open-output-bytevector))) + (if (eq? grammar 'prefix) + (write-bytevector delim port)) + (write-bytevector (car lst) port) + (for-each + (lambda (bv) + (write-bytevector delim port) + (write-bytevector bv port)) + (cdr lst)) + (if (eq? grammar 'suffix) + (write-bytevector delim port)) + (get-output-bytevector port)))) + (define bytestring-split + (case-lambda + ((bv delim) + (%bytestring-split bv (if (char? delim) (char->integer delim) delim) 'infix)) + ((bv delim grammar) + (%bytestring-split bv (if (char? delim) (char->integer delim) delim) + grammar)))) + (define (%bytestring-split bv delim grammar) + (let* ((len (bytevector-length bv)) + (len (if (and (eq? grammar 'suffix) + (= (bytevector-u8-ref bv (- len 1)) delim)) + (- len 1) + len))) + (define (split sdx idx) + (if (= idx len) + (list (bytevector-copy bv sdx idx)) + (if (= (bytevector-u8-ref bv idx) delim) + (cons (bytevector-copy bv sdx idx) (split (+ idx 1) (+ idx 1))) + (split sdx (+ idx 1))))) + (if (= len 0) + '() + (if (and (eq? grammar 'prefix) (= (bytevector-u8-ref bv 0) delim)) + (split 1 1) + (split 0 0))))) + (define (write-binary-bytestring port . args) + (write-bytevector (apply bytestring args) port)) (define (bytestring-error? obj) (and (error-object? obj) (eq? (error-object-kind obj) 'bytestring-error))) ) diff --git a/src/vectors.cpp b/src/vectors.cpp index eb4764c..a2afa71 100644 --- a/src/vectors.cpp +++ b/src/vectors.cpp @@ -4,9 +4,17 @@ Foment */ +#ifdef FOMENT_WINDOWS +#include <windows.h> +#endif // FOMENT_WINDOWS +#ifdef FOMENT_UNIX +#include <pthread.h> +#endif // FOMENT_UNIX #include <stdio.h> #include <string.h> #include "foment.hpp" +#include "syncthrd.hpp" +#include "io.hpp" #include "unicode.hpp" // ---- Vectors ---- @@ -1224,6 +1232,153 @@ Define("bytestring->list", BytestringToListPrimitive)(long_t argc, FObject argv[ return(ReverseListModify(lst)); } +static int BytevectorCompare(FObject bv1, FObject bv2) +{ + FAssert(BytevectorP(bv1)); + FAssert(BytevectorP(bv2)); + + ulong_t bvl1 = BytevectorLength(bv1); + ulong_t bvl2 = BytevectorLength(bv2); + + if (bvl1 < bvl2) + { + int ret = memcmp(AsBytevector(bv1)->Vector, AsBytevector(bv2)->Vector, bvl1); + return(ret > 0 ? 1 : -1); + } + else if (bvl1 > bvl2) + { + int ret = memcmp(AsBytevector(bv1)->Vector, AsBytevector(bv2)->Vector, bvl2); + return(ret < 0 ? -1 : 1); + } + return(memcmp(AsBytevector(bv1)->Vector, AsBytevector(bv2)->Vector, bvl1)); +} + +Define("bytevector=?", BytevectorEqualPPrimitive)(long_t argc, FObject argv[]) +{ + TwoArgsCheck("bytevector=?", argc); + BytevectorArgCheck("bytevector=?", argv[0]); + BytevectorArgCheck("bytevector=?", argv[1]); + + return(BytevectorCompare(argv[0], argv[1]) == 0 ? TrueObject : FalseObject); +} + +Define("bytevector<?", BytevectorLessThanPPrimitive)(long_t argc, FObject argv[]) +{ + TwoArgsCheck("bytevector<?", argc); + BytevectorArgCheck("bytevector<?", argv[0]); + BytevectorArgCheck("bytevector<?", argv[1]); + + return(BytevectorCompare(argv[0], argv[1]) < 0 ? TrueObject : FalseObject); +} + +Define("bytevector>?", BytevectorGreaterThanPPrimitive)(long_t argc, FObject argv[]) +{ + TwoArgsCheck("bytevector>?", argc); + BytevectorArgCheck("bytevector>?", argv[0]); + BytevectorArgCheck("bytevector>?", argv[1]); + + return(BytevectorCompare(argv[0], argv[1]) > 0 ? TrueObject : FalseObject); +} + +Define("bytevector<=?", BytevectorLessThanEqualPPrimitive)(long_t argc, FObject argv[]) +{ + TwoArgsCheck("bytevector<=?", argc); + BytevectorArgCheck("bytevector<=?", argv[0]); + BytevectorArgCheck("bytevector<=?", argv[1]); + + return(BytevectorCompare(argv[0], argv[1]) <= 0 ? TrueObject : FalseObject); +} + +Define("bytevector>=?", BytevectorGreaterThanEqualPPrimitive)(long_t argc, FObject argv[]) +{ + TwoArgsCheck("bytevector>=?", argc); + BytevectorArgCheck("bytevector>=?", argv[0]); + BytevectorArgCheck("bytevector>=?", argv[1]); + + return(BytevectorCompare(argv[0], argv[1]) >= 0 ? TrueObject : FalseObject); +} + +static FCh ReadBytestringCh(FObject port) +{ + FCh ch; + if (ReadCh(port, &ch) == 0) + RaiseExceptionC(Lexical, "read-textual-bytestring", BytestringErrorSymbol, + "unexpected end-of-file reading bytestring", List(port)); + + return(ch); +} + +Define("read-textual-bytestring", ReadTextualBytestringPrimitive)(long_t argc, FObject argv[]) +{ + OneOrTwoArgsCheck("read-textual-bytestring", argc); + FObject port = (argc == 2 ? argv[1] : CurrentInputPort()); + TextualInputPortArgCheck("read-textual-bytestring", port); + + if (argv[0] == FalseObject) + { + if (ReadBytestringCh(port) != '"') + RaiseExceptionC(Lexical, "read-textual-bytestring", BytestringErrorSymbol, + "expected \" starting bytestring", List(port)); + } + else + { + if (ReadBytestringCh(port) != '#') + goto MissingPrefix; + if (ReadBytestringCh(port) != 'u') + goto MissingPrefix; + if (ReadBytestringCh(port) != '8') + goto MissingPrefix; + if (ReadBytestringCh(port) != '"') + goto MissingPrefix; + } + + return(ReadBytestring(port)); + +MissingPrefix: + RaiseExceptionC(Lexical, "read-textual-bytestring", BytestringErrorSymbol, + "expected #u8\" starting bytestring", List(port)); + return(NoValueObject); +} + +Define("write-textual-bytestring", WriteTextualBytestringPrimitive)(long_t argc, FObject argv[]) +{ + OneOrTwoArgsCheck("write-textual-bytestring", argc); + BytevectorArgCheck("write-textual-bytestring", argv[0]); + FObject port = (argc == 2 ? argv[1] : CurrentOutputPort()); + TextualOutputPortArgCheck("write-textual-bytestring", port); + + WriteStringC(port, "#u8\""); + for (ulong_t idx = 0; idx < BytevectorLength(argv[0]); idx += 1) + { + FByte b = AsBytevector(argv[0])->Vector[idx]; + switch (b) + { + case 0x07: WriteStringC(port, "\\a"); break; + case 0x08: WriteStringC(port, "\\b"); break; + case 0x09: WriteStringC(port, "\\t"); break; + case 0x0A: WriteStringC(port, "\\n"); break; + case 0x0D: WriteStringC(port, "\\r"); break; + case 0x22: WriteStringC(port, "\\\""); break; + case 0x5C: WriteStringC(port, "\\\\"); break; + case 0x7C: WriteStringC(port, "\\|"); break; + default: + if (b >= 0x20 && b <= 0x7E) + WriteCh(port, b); + else + { + FCh s[4]; + long_t sl = FixnumAsString((long_t) b, s, 16); + + WriteStringC(port, "\\x"); + WriteString(port, s, sl); + WriteCh(port, ';'); + } + } + } + WriteCh(port, '"'); + return(NoValueObject); +} + static FObject Primitives[] = { VectorPPrimitive, @@ -1261,7 +1416,14 @@ static FObject Primitives[] = HexStringToBytevectorPrimitive, BytevectorToBase64Primitive, Base64ToBytevectorPrimitive, - BytestringToListPrimitive + BytestringToListPrimitive, + BytevectorEqualPPrimitive, + BytevectorLessThanPPrimitive, + BytevectorGreaterThanPPrimitive, + BytevectorLessThanEqualPPrimitive, + BytevectorGreaterThanEqualPPrimitive, + ReadTextualBytestringPrimitive, + WriteTextualBytestringPrimitive }; void SetupVectors() diff --git a/test/srfi.scm b/test/srfi.scm index c0dee35..7f232b4 100644 --- a/test/srfi.scm +++ b/test/srfi.scm @@ -3877,7 +3877,6 @@ (check-equal #t (check-read-bytestring "#u8\"\\x100;\"")) (check-equal #t (check-read-bytestring "#u8\"\\x0ABC\"")) (check-equal #t (check-read-bytestring "#u8\"\\xE000;\"")) -(check-equal #t (check-read-bytestring "#u8\"\\x80;\"")) (check-equal #u8(108 111 114 101 109) (bytestring "lo" #\r #x65 #u8(#x6d))) (check-equal #t (equal? (bytestring) (bytevector))) @@ -3894,6 +3893,9 @@ (check-equal #t (check-make-bytestring "abc" #\x80 "efg")) (check-equal #f (check-make-bytestring "abc" #\x10 "efg")) +(check-equal #u8"lorem" (bytestring "lo" #\r #x65 #u8(#x6d))) +(check-equal #u8() (bytestring)) + (check-equal #t (check-make-bytestring "\x3BB;")) (check-equal #t (check-make-bytestring #x100)) @@ -4039,6 +4041,49 @@ (check-equal #u8"lorem" (bytestring-trim-both #u8"lorem" never)) (check-equal #u8(#x72) (bytestring-trim-both #u8"lorem" (lambda (u8) (< u8 #x70)))) +(check-equal #u8"Vogon poetry" (bytestring-replace #u8"Vogon torture" #u8"poetry" 6 13)) + +(check-equal #u8"lists" (bytestring-replace #u8"lorem" (bytestring "mists") 1 5 1 5)) +(check-equal #u8"loaded" (bytestring-replace #u8"lorem" (bytestring "faded") 2 5 1 5)) +(check-equal #u8"lorem" + (bytestring-replace (make-bytevector 5) #u8"lorem" 0 (bytevector-length #u8"lorem"))) +(check-equal #u8"food food" + (let ((bv1 (bytestring "food")) (bv2 (bytestring "od fo"))) + (bytestring-replace bv1 bv2 2 2 0 5))) +(check-equal #u8"food" + (let ((bv1 (bytestring "food food"))) + (bytestring-replace bv1 (bytevector) 2 7 0 0))) + +(check-equal #t (bytestring=? #u8"lorem" #u8"lorem")) +(check-equal #f (bytestring=? #u8"lore" #u8"lorem")) +(check-equal #f (bytestring=? #u8"lorem" #u8"lore")) +(check-equal #f (bytestring=? #u8"abcdef" #u8"ghijklmno")) + +(check-equal #t (bytestring<? #u8"Heart Of Gold" #u8"Heart of Gold")) +(check-equal #f (bytestring<=? #u8(#x81 #x95) #u8(#x80 #xa0))) +(check-equal #t (bytestring>? #u8(1 2 3) #u8(1 2))) + +(define short-bstring (bytestring "lore")) +(define long-bstring (bytestring "lorem ")) +(define mixed-case-bstring (bytestring "loreM")) + +(check-equal #f (bytestring<? #u8"lorem" #u8"lorem")) +(check-equal #t (bytestring<? short-bstring #u8"lorem")) +(check-equal #t (bytestring<? mixed-case-bstring #u8"lorem")) +(check-equal #f (bytestring>? #u8"lorem" #u8"lorem")) +(check-equal #t (bytestring>? #u8"lorem" short-bstring)) +(check-equal #t (bytestring>? #u8"lorem" mixed-case-bstring)) +(check-equal #t (bytestring<=? #u8"lorem" #u8"lorem")) +(check-equal #t (bytestring<=? short-bstring #u8"lorem")) +(check-equal #t (bytestring<=? mixed-case-bstring #u8"lorem")) +(check-equal #f (bytestring<=? #u8"lorem" mixed-case-bstring)) +(check-equal #f (bytestring<=? long-bstring #u8"lorem")) +(check-equal #t (bytestring>=? #u8"lorem" #u8"lorem")) +(check-equal #t (bytestring>=? #u8"lorem" short-bstring)) +(check-equal #t (bytestring>=? #u8"lorem" mixed-case-bstring)) +(check-equal #f (bytestring>=? mixed-case-bstring #u8"lorem")) +(check-equal #f (bytestring>=? short-bstring #u8"lorem")) + (check-equal 2 (bytestring-index #u8(#x65 #x72 #x83 #x6f) (lambda (b) (> b #x7f)))) (check-equal #f (bytestring-index #u8"Beeblebrox" (lambda (b) (> b #x7f)))) (check-equal 4 (bytestring-index-right #u8"Zaphod" odd?)) @@ -4053,173 +4098,134 @@ (check-equal 4 (bytestring-index-right #u8"lorem" always 3)) (check-equal 2 (bytestring-index-right #u8"lorem" eq-r?)) -#| -(define test-bstring (bytestring "lorem")) - -(define (check-replacement) - (print-header "Running bytestring-replace tests...") - - (check (bytestring-replace #u8"lorem" (bytestring "mists") 1 5 1 5) - => (bytestring "lists")) - (check (bytestring-replace #u8"lorem" (bytestring "faded") 2 5 1 5) - => (bytestring "loaded")) - (check (bytestring-replace (make-bytevector 5) - #u8"lorem" - 0 - (bytevector-length #u8"lorem")) - => #u8"lorem") - - (let ((bv1 (bytestring "food")) (bv2 (bytestring "od fo"))) - (check (bytestring-replace bv1 bv2 2 2 0 5) => (bytestring "food food"))) - (let ((bv1 (bytestring "food food"))) - (check (bytestring-replace bv1 (bytevector) 2 7 0 0) - => (bytestring "food"))) -) - -(define (check-comparison) - (define short-bstring (bytestring "lore")) - (define long-bstring (bytestring "lorem ")) - (define mixed-case-bstring (bytestring "loreM")) - (print-header "Runnng comparison tests...") - - (check (bytestring<? #u8"lorem" #u8"lorem") => #f) - (check (bytestring<? short-bstring #u8"lorem") => #t) - (check (bytestring<? mixed-case-bstring #u8"lorem") => #t) - (check (bytestring>? #u8"lorem" #u8"lorem") => #f) - (check (bytestring>? #u8"lorem" short-bstring) => #t) - (check (bytestring>? #u8"lorem" mixed-case-bstring) => #t) - (check (bytestring<=? #u8"lorem" #u8"lorem") => #t) - (check (bytestring<=? short-bstring #u8"lorem") => #t) - (check (bytestring<=? mixed-case-bstring #u8"lorem") => #t) - (check (bytestring<=? #u8"lorem" mixed-case-bstring) => #f) - (check (bytestring<=? long-bstring #u8"lorem") => #f) - (check (bytestring>=? #u8"lorem" #u8"lorem") => #t) - (check (bytestring>=? #u8"lorem" short-bstring) => #t) - (check (bytestring>=? #u8"lorem" mixed-case-bstring) => #t) - (check (bytestring>=? mixed-case-bstring #u8"lorem") => #f) - (check (bytestring>=? short-bstring #u8"lorem") => #f) -) - -(define (check-searching) - (define (eq-r? b) (= b #x72)) - (define (lt-r? b) (< b #x72)) - (print-header "Running search tests...") - - (check (values~>list (bytestring-span #u8"lorem" always)) - => (list #u8"lorem" (bytevector))) - (check (values~>list (bytestring-span #u8"lorem" never)) - => (list (bytevector) #u8"lorem")) - (check (values~>list (bytestring-span #u8"lorem" lt-r?)) - => (list (bytestring "lo") (bytestring "rem"))) - - (check (values~>list (bytestring-break #u8"lorem" always)) - => (list (bytevector) #u8"lorem")) - (check (values~>list (bytestring-break #u8"lorem" never)) - => (list #u8"lorem" (bytevector))) - (check (values~>list (bytestring-break #u8"lorem" eq-r?)) - => (list (bytestring "lo") (bytestring "rem")))) - -(define (check-join-and-split) - (define test-segments '(#u8(1) #u8(2) #u8(3))) - (print-header "Running joining and splitting tests...") - - (check (bytestring-join test-segments #u8(0)) => #u8(1 0 2 0 3)) - (check (bytestring-join test-segments #u8(0) 'prefix) => #u8(0 1 0 2 0 3)) - (check (bytestring-join test-segments #u8(0) 'suffix) => #u8(1 0 2 0 3 0)) - (check (bytestring-join '() #u8(0)) => #u8()) - (check (bytestring-join test-segments #\space) => #u8(1 32 2 32 3)) - (check (bytestring-join test-segments 0) => #u8(1 0 2 0 3)) - (check (bytestring-join test-segments "AB") - => #u8(1 65 66 2 65 66 3)) - (check (bytestring-join test-segments #u8(7 8)) => #u8(1 7 8 2 7 8 3)) - (check (catch-bytestring-error - (bytestring-join test-segments 300)) => 'bytestring-error) - (check (catch-bytestring-error - (bytestring-join test-segments "λ")) => 'bytestring-error) - (check (catch-bytestring-error - (bytestring-join '() #u8(0) 'strict-infix)) => 'bytestring-error) - (check (catch-bytestring-error - (bytestring-join '() #u8(0) 'foofix)) => 'bytestring-error) - - (check (bytestring-split #u8(1 0 2 0 3) 0 'infix) => test-segments) - (check (bytestring-split #u8(0 1 0 2 0 3) 0 'prefix) => test-segments) - (check (bytestring-split #u8(1 0 2 0 3 0) 0 'suffix) => test-segments) - (check (bytestring-split #u8(0 0) 0) => '(#u8() #u8() #u8())) - (check (bytestring-split #u8() 0) => '()) - (check (catch-bytestring-error - (bytestring-split #u8() 0 'foofix)) => 'bytestring-error)) - -(define (check-io) - (print-header "Running I/O tests...") - - (check (%bytestring/IO "lo" #\r #x65 #u8(#x6d)) => #u8"lorem") - (check (%bytestring/IO) => #u8()) - (check (catch-bytestring-error (%bytestring/IO #x100)) => 'bytestring-error) - (check (catch-bytestring-error (%bytestring/IO "λ")) => 'bytestring-error) - - ;;; read-textual-bytestring - - (check (parse-SNB/prefix "#u8\"\"") => #u8()) - (check (parse-SNB/prefix "#u8\"lorem\"") => #u8"lorem") - (check (parse-SNB/prefix "#u8\"\\xde;\\xad;\\xf0;\\x0d;\"") - => (bytevector #xde #xad #xf0 #x0d)) - (check (parse-SNB/prefix "#u8\"\\\"\\\\\\a\\b\\t\\n\\r\\\|\"") - => (bytestring #\" #\\ #\alarm #\backspace #\tab #\newline #\return #\|)) - (check (parse-SNB/prefix "#u8\"lor\\\n\te\\ \r\n\tm\"") - => #u8"lorem") - (check (parse-SNB "\"lorem\"") => #u8"lorem") - - ;; Invalid SNB detection. - (check (catch-bytestring-error (parse-SNB/prefix "#u\"lorem\"")) - => 'bytestring-error) - (check (catch-bytestring-error (parse-SNB/prefix "#u8lorem\"")) - => 'bytestring-error) - (check (catch-bytestring-error (parse-SNB/prefix "#u8\"lorem")) - => 'bytestring-error) - (check (catch-bytestring-error (parse-SNB/prefix "#u8\"lorem")) - => 'bytestring-error) - (check (catch-bytestring-error (parse-SNB/prefix "#u8\"l\\orem\"")) - => 'bytestring-error) - (check (catch-bytestring-error (parse-SNB/prefix "#u8\"l\\ orem\"")) - => 'bytestring-error) - (check (catch-bytestring-error (parse-SNB/prefix "#u8\"l\\x6frem\"")) - => 'bytestring-error) - (check (catch-bytestring-error (parse-SNB/prefix "#u8\"l\\x6z;rem\"")) - => 'bytestring-error) - (check (catch-bytestring-error (parse-SNB/prefix "#u8\"α equivalence\"")) - => 'bytestring-error) - - ;;; write-textual-bytestring - - (check (%bytestring->SNB #u8()) => "#u8\"\"") - (check (%bytestring->SNB #u8"lorem") => "#u8\"lorem\"") - (check (%bytestring->SNB (bytevector #xde #xad #xbe #xef)) - => "#u8\"\\xde;\\xad;\\xbe;\\xef;\"") - (check (%bytestring->SNB - (bytestring #\" #\\ #\alarm #\backspace #\tab #\newline #\return #\|)) - => "#u8\"\\\"\\\\\\a\\b\\t\\n\\r\\\|\"") - - (let ((#u8"lorem"s - '(#u8(124 199 173 212 209 232 249 16 198 32 123 111 130 92 64 155) - #u8(50 133 193 27 177 105 10 186 61 149 177 105 96 70 223 190) - #u8(0 117 226 155 110 0 66 216 27 129 187 81 17 210 71 152) - #u8(123 31 159 25 100 135 246 47 249 137 243 241 45 241 240 221) - #u8(207 186 70 110 118 231 79 195 153 253 93 101 126 198 70 235) - #u8(138 176 92 152 208 107 28 236 198 254 111 37 241 116 191 206) - #u8(221 254 214 90 0 155 132 92 157 246 199 224 224 142 91 114) - #u8(228 216 233 80 142 15 158 54 5 85 174 101 111 75 126 209) - #u8(191 16 83 245 45 98 72 212 148 202 135 19 213 150 141 121) - #u8(41 169 182 96 47 184 16 116 196 251 243 93 81 162 175 140) - #u8(85 49 218 138 132 11 27 11 182 27 120 71 254 169 132 166) - #u8(89 216 175 23 97 10 237 112 208 195 112 80 198 154 241 254) - #u8(187 54 6 57 250 137 129 89 188 19 225 217 168 178 174 129) - #u8(88 164 89 40 175 194 108 56 12 124 109 96 148 149 119 109) - #u8(241 66 32 115 203 71 128 154 240 111 194 137 73 44 146 3) - #u8(177 185 177 233 18 14 178 106 110 109 222 147 111 157 216 208)))) - (check - (every (lambda (bvec) - (equal? bvec (parse-SNB/prefix (%bytestring->SNB bvec)))) - #u8"lorem"s) - => #t)) -) -|# +(check-equal (#u8(#x50 #x4b) #u8(0 0 #x1 #x5)) + (call-with-values (lambda () (bytestring-break #u8(#x50 #x4b 0 0 #x1 #x5) zero?)) list)) + +(check-equal (#u8"ABCD" #u8"efg") + (call-with-values + (lambda () (bytestring-span #u8"ABCDefg" (lambda (b) (and (> b 40) (< b 91))))) + list)) + +(define (eq-r? b) (= b #x72)) +(define (lt-r? b) (< b #x72)) + +(check-equal (#u8"lorem" #u8()) + (call-with-values (lambda () (bytestring-span #u8"lorem" always)) list)) +(check-equal (#u8() #u8"lorem") + (call-with-values (lambda () (bytestring-span #u8"lorem" never)) list)) +(check-equal (#u8"lo" #u8"rem") + (call-with-values (lambda () (bytestring-span #u8"lorem" lt-r?)) list)) + +(check-equal (#u8() #u8"lorem") + (call-with-values (lambda () (bytestring-break #u8"lorem" always)) list)) +(check-equal (#u8"lorem" #u8()) + (call-with-values (lambda () (bytestring-break #u8"lorem" never)) list)) +(check-equal (#u8"lo" #u8"rem") + (call-with-values (lambda () (bytestring-break #u8"lorem" eq-r?)) list)) + +(check-equal #u8"Heart of Gold" (bytestring-join '(#u8"Heart" #u8"of" #u8"Gold") #x20)) +(check-equal #u8(0 #xef #xbb 0 #xbf) (bytestring-join '(#u8(#xef #xbb) #u8(#xbf)) 0 'prefix)) +(check-equal #t + (bytestring-error? (guard (o (else o)) (bytestring-join '() 0 'strict-infix)))) + +(define test-segments '(#u8(1) #u8(2) #u8(3))) +(check-equal #u8(1 0 2 0 3) (bytestring-join test-segments #u8(0))) +(check-equal #u8(0 1 0 2 0 3) (bytestring-join test-segments #u8(0) 'prefix)) +(check-equal #u8(1 0 2 0 3 0) (bytestring-join test-segments #u8(0) 'suffix)) +(check-equal #u8() (bytestring-join '() #u8(0))) +(check-equal #u8(1 32 2 32 3) (bytestring-join test-segments #\space)) +(check-equal #u8(1 0 2 0 3) (bytestring-join test-segments 0)) +(check-equal #u8(1 65 66 2 65 66 3) (bytestring-join test-segments "AB")) +(check-equal #u8(1 7 8 2 7 8 3) (bytestring-join test-segments #u8(7 8))) +(check-equal #t + (bytestring-error? (guard (o (else o)) (bytestring-join test-segments 300)))) +(check-equal #t + (bytestring-error? (guard (o (else o)) (bytestring-join '() #u8(0) 'strict-infix)))) + +(check-equal (#u8"Bee" #u8"le" #u8"rox") (bytestring-split #u8"Beeblebrox" #x62)) +(check-equal (#u8(1) #u8(2)) (bytestring-split #u8(1 0 2 0) 0 'suffix)) +(check-equal (#u8(1) #u8(2) #u8(3)) (bytestring-split #u8(1 0 2 0 3) 0 'infix)) +(check-equal (#u8(1) #u8(2) #u8(3)) (bytestring-split #u8(0 1 0 2 0 3) 0 'prefix)) +(check-equal (#u8(1) #u8(2) #u8(3)) (bytestring-split #u8(1 0 2 0 3 0) 0 'suffix)) +(check-equal (#u8() #u8() #u8()) (bytestring-split #u8(0 0) 0)) +(check-equal () (bytestring-split #u8() 0)) + +(define (read-bs prefix bs) + (call-with-port (open-input-string bs) + (lambda (port) (read-textual-bytestring prefix port)))) + +(check-equal #u8(#x41 #x42 #xad #xf0 #x0d #x43 #x44) + (read-bs #t "#u8\"AB\\xad;\\xf0;\\x0d;CD\"")) +(check-equal #u8() (read-bs #t "#u8\"\"")) +(check-equal #u8"lorem" (read-bs #t "#u8\"lorem\"")) +(check-equal #t + (equal? + (bytevector #xde #xad #xf0 #x0d) + (read-bs #t "#u8\"\\xde;\\xad;\\xf0;\\x0d;\""))) +(check-equal #t + (equal? + (bytestring #\" #\\ #\alarm #\backspace #\tab #\newline #\return #\|) + (read-bs #t "#u8\"\\\"\\\\\\a\\b\\t\\n\\r\\\|\""))) +(check-equal #u8"lorem" (read-bs #t "#u8\"lor\\\n\te\\ \r\n\tm\"")) +(check-equal #u8"lorem" (read-bs #f "\"lorem\"")) + +(check-equal #t + (bytestring-error? (guard (o (else o)) (read-bs #t "#u\"lorem\"")))) +(check-equal #t + (bytestring-error? (guard (o (else o)) (read-bs #t "#u8lorem\"")))) +(check-equal #t + (bytestring-error? (guard (o (else o)) (read-bs #t "#u8\"lorem")))) +(check-equal #t + (bytestring-error? (guard (o (else o)) (read-bs #t "#u8\"l\\orem\"")))) +;(check-equal #t +; (bytestring-error? (guard (o (else o)) (read-bs #t "#u8\"l\\ orem\"")))) +(check-equal #t + (bytestring-error? (guard (o (else o)) (read-bs #t "#u8\"l\\x6frem\"")))) +(check-equal #t + (bytestring-error? (guard (o (else o)) (read-bs #t "#u8\"l\\x6z;rem\"")))) +(check-equal #t + (bytestring-error? (guard (o (else o)) (read-bs #t "#u8\"\x100; equivalence\"")))) + +(define (write-textual-bs bs) + (call-with-port (open-output-string) + (lambda (port) + (write-textual-bytestring bs port) + (get-output-string port)))) + +(check-equal "#u8\"\\tArthur\\n\"" (write-textual-bs #u8(#x9 #x41 #x72 #x74 #x68 #x75 #x72 #xa))) +(check-equal "#u8\"\"" (write-textual-bs #u8())) +(check-equal "#u8\"lorem\"" (write-textual-bs #u8"lorem")) +(check-equal "#u8\"\\xde;\\xad;\\xbe;\\xef;\"" (write-textual-bs (bytevector #xde #xad #xbe #xef))) +(check-equal "#u8\"\\\"\\\\\\a\\b\\t\\n\\r\\\|\"" + (write-textual-bs (bytestring #\" #\\ #\alarm #\backspace #\tab #\newline #\return #\|))) + +(check-equal #t + (let ((lorems + '(#u8(124 199 173 212 209 232 249 16 198 32 123 111 130 92 64 155) + #u8(50 133 193 27 177 105 10 186 61 149 177 105 96 70 223 190) + #u8(0 117 226 155 110 0 66 216 27 129 187 81 17 210 71 152) + #u8(123 31 159 25 100 135 246 47 249 137 243 241 45 241 240 221) + #u8(207 186 70 110 118 231 79 195 153 253 93 101 126 198 70 235) + #u8(138 176 92 152 208 107 28 236 198 254 111 37 241 116 191 206) + #u8(221 254 214 90 0 155 132 92 157 246 199 224 224 142 91 114) + #u8(228 216 233 80 142 15 158 54 5 85 174 101 111 75 126 209) + #u8(191 16 83 245 45 98 72 212 148 202 135 19 213 150 141 121) + #u8(41 169 182 96 47 184 16 116 196 251 243 93 81 162 175 140) + #u8(85 49 218 138 132 11 27 11 182 27 120 71 254 169 132 166) + #u8(89 216 175 23 97 10 237 112 208 195 112 80 198 154 241 254) + #u8(187 54 6 57 250 137 129 89 188 19 225 217 168 178 174 129) + #u8(88 164 89 40 175 194 108 56 12 124 109 96 148 149 119 109) + #u8(241 66 32 115 203 71 128 154 240 111 194 137 73 44 146 3) + #u8(177 185 177 233 18 14 178 106 110 109 222 147 111 157 216 208)))) + (every + (lambda (bvec) + (equal? bvec (read-bs #t (write-textual-bs bvec)))) + lorems))) + +(define (write-binary-bs . args) + (call-with-port (open-output-bytevector) + (lambda (port) + (apply write-binary-bytestring port args) + (get-output-bytevector port)))) + +(check-equal #u8"Zaphod" (write-binary-bs #\Z #x61 #x70 "hod")) diff --git a/unix/makefile b/unix/makefile index 3bab9a5..9f6e0bf 100644 --- a/unix/makefile +++ b/unix/makefile @@ -148,7 +148,8 @@ debug/pairs.o: ../src/pairs.cpp ../src/foment.hpp debug/unicode.o: ../src/unicode.cpp ../src/foment.hpp ../src/unicode.hpp ../src/unicase.hpp debug/chars.o: ../src/chars.cpp ../src/foment.hpp ../src/unicode.hpp debug/strings.o: ../src/strings.cpp ../src/foment.hpp ../src/unicode.hpp -debug/vectors.o: ../src/vectors.cpp ../src/foment.hpp ../src/unicode.hpp +debug/vectors.o: ../src/vectors.cpp ../src/foment.hpp ../src/syncthrd.hpp ../src/io.hpp\ + ../src/unicode.hpp debug/library.o: ../src/library.cpp ../src/foment.hpp ../src/compile.hpp debug/execute.o: ../src/execute.cpp ../src/foment.hpp ../src/execute.hpp ../src/syncthrd.hpp debug/numbers.o: ../src/numbers.cpp ../src/foment.hpp ../src/unicode.hpp ../src/bignums.hpp @@ -181,7 +182,8 @@ release/pairs.o: ../src/pairs.cpp ../src/foment.hpp release/unicode.o: ../src/unicode.cpp ../src/foment.hpp ../src/unicode.hpp ../src/unicase.hpp release/chars.o: ../src/chars.cpp ../src/foment.hpp ../src/unicode.hpp release/strings.o: ../src/strings.cpp ../src/foment.hpp ../src/unicode.hpp -release/vectors.o: ../src/vectors.cpp ../src/foment.hpp ../src/unicode.hpp +release/vectors.o: ../src/vectors.cpp ../src/foment.hpp ../src/syncthrd.hpp ../src/io.hpp\ + ../src/unicode.hpp release/library.o: ../src/library.cpp ../src/foment.hpp ../src/compile.hpp release/execute.o: ../src/execute.cpp ../src/foment.hpp ../src/execute.hpp ../src/syncthrd.hpp release/numbers.o: ../src/numbers.cpp ../src/foment.hpp ../src/unicode.hpp ../src/bignums.hpp diff --git a/windows/makefile b/windows/makefile index 5e3e9a6..8b29b7b 100644 --- a/windows/makefile +++ b/windows/makefile @@ -135,7 +135,8 @@ debug\pairs.obj: ..\src\pairs.cpp ..\src\foment.hpp debug\unicode.obj: ..\src\unicode.cpp ..\src\foment.hpp ..\src\unicode.hpp ..\src\unicase.hpp debug\chars.obj: ..\src\chars.cpp ..\src\foment.hpp ..\src\unicode.hpp debug\strings.obj: ..\src\strings.cpp ..\src\foment.hpp ..\src\unicode.hpp -debug\vectors.obj: ..\src\vectors.cpp ..\src\foment.hpp ..\src\unicode.hpp +debug\vectors.obj: ..\src\vectors.cpp ..\src\foment.hpp ..\src\syncthrd.hpp ..\src\io.hpp\ + ..\src\unicode.hpp debug\library.obj: ..\src\library.cpp ..\src\foment.hpp ..\src\compile.hpp debug\execute.obj: ..\src\execute.cpp ..\src\foment.hpp ..\src\execute.hpp ..\src\syncthrd.hpp debug\numbers.obj: ..\src\numbers.cpp ..\src\foment.hpp ..\src\unicode.hpp ..\src\bignums.hpp @@ -167,7 +168,8 @@ release\pairs.obj: ..\src\pairs.cpp ..\src\foment.hpp release\unicode.obj: ..\src\unicode.cpp ..\src\foment.hpp ..\src\unicode.hpp ..\src\unicase.hpp release\chars.obj: ..\src\chars.cpp ..\src\foment.hpp ..\src\unicode.hpp release\strings.obj: ..\src\strings.cpp ..\src\foment.hpp ..\src\unicode.hpp -release\vectors.obj: ..\src\vectors.cpp ..\src\foment.hpp ..\src\unicode.hpp +release\vectors.obj: ..\src\vectors.cpp ..\src\foment.hpp ..\src\syncthrdhpp ..\src\io.hpp\ + ..\src\unicode.hpp release\library.obj: ..\src\library.cpp ..\src\foment.hpp ..\src\compile.hpp release\execute.obj: ..\src\execute.cpp ..\src\foment.hpp ..\src\execute.hpp ..\src\syncthrd.hpp release\numbers.obj: ..\src\numbers.cpp ..\src\foment.hpp ..\src\unicode.hpp ..\src\bignums.hpp |