summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--buf.c29
-rw-r--r--buf.h1
-rw-r--r--tests/012/buf.tl24
-rw-r--r--txr.126
4 files changed, 77 insertions, 3 deletions
diff --git a/buf.c b/buf.c
index dd5abda9..c36d1c0c 100644
--- a/buf.c
+++ b/buf.c
@@ -1561,6 +1561,34 @@ val buf_and(val bufa, val bufb)
}
}
+val buf_test(val bufa, val bufb)
+{
+ val self = lit("buf-test");
+ struct buf *ab = buf_handle(bufa, self);
+ struct buf *bb = buf_handle(bufb, self);
+ ucnum la = c_unum(ab->len, self);
+ ucnum lb = c_unum(bb->len, self);
+
+ if (la == 0 || lb == 0 ) {
+ return nil;
+ } else if (la < lb) {
+ return buf_test(bufb, bufa);
+ } else if (la == convert(ucnum, -1)) {
+ err_oflow(self);
+ abort();
+ } else {
+ ucnum delta = la - lb;
+ ucnum i;
+
+ for (i = 0; i < lb; i++) {
+ if ((ab->data[i + delta] & bb->data[i]) != 0)
+ return t;
+ }
+
+ return nil;
+ }
+}
+
val buf_or(val bufa, val bufb)
{
val self = lit("buf-or");
@@ -1843,6 +1871,7 @@ void buf_init(void)
reg_fun(intern(lit("buf-ash"), user_package), func_n2(buf_ash));
reg_fun(intern(lit("buf-fash"), user_package), func_n2(buf_fash));
reg_fun(intern(lit("buf-and"), user_package), func_n2(buf_and));
+ reg_fun(intern(lit("buf-test"), user_package), func_n2(buf_test));
reg_fun(intern(lit("buf-or"), user_package), func_n2(buf_or));
reg_fun(intern(lit("buf-xor"), user_package), func_n2(buf_xor));
reg_fun(intern(lit("buf-not"), user_package), func_n1(buf_not));
diff --git a/buf.h b/buf.h
index c134b43b..2a599339 100644
--- a/buf.h
+++ b/buf.h
@@ -127,6 +127,7 @@ void buf_swap32(val buf);
val buf_ash(val buf, val bits);
val buf_fash(val buf, val bits);
val buf_and(val bufa, val bufb);
+val buf_test(val bufa, val bufb);
val buf_or(val bufa, val bufb);
val buf_xor(val bufa, val bufb);
val buf_not(val buf);
diff --git a/tests/012/buf.tl b/tests/012/buf.tl
index 77018647..173522ce 100644
--- a/tests/012/buf.tl
+++ b/tests/012/buf.tl
@@ -275,6 +275,30 @@
(buf-xor #b'ff00ff0f' #b'1baddeadbeef') #b'1bad21ad41e0')
(mtest
+ (buf-test #b'' #b'') nil
+ (buf-test #b'' #b'00') nil
+ (buf-test #b'' #b'11') nil
+ (buf-test #b'00' #b'00') nil
+ (buf-test #b'ff' #b'00') nil
+ (buf-test #b'00' #b'ff') nil
+ (buf-test #b'aa' #b'ff') t
+ (buf-test #b'ff' #b'aa') t
+ (buf-test #b'ff55' #b'aa') nil
+ (buf-test #b'ff00' #b'00') nil
+ (buf-test #b'ffff' #b'00') nil
+ (buf-test #b'ff00' #b'ff') nil
+ (buf-test #b'ffaa' #b'ff') t
+ (buf-test #b'ffff' #b'aa') t
+ (buf-test #b'ff55' #b'aa') nil
+ (buf-test #b'00' #b'ff00') nil
+ (buf-test #b'ff' #b'ff00') nil
+ (buf-test #b'00' #b'ffff') nil
+ (buf-test #b'aa' #b'ffff') t
+ (buf-test #b'ff' #b'ffaa') t
+ (buf-test #b'ff00ff0f' #b'1baddeadbeef') t)
+
+
+(mtest
(buf-not #b'') #b''
(buf-not #b'00') #b'ff'
(buf-not #b'aa') #b'55'
diff --git a/txr.1 b/txr.1
index 57173cdf..df6c3aaa 100644
--- a/txr.1
+++ b/txr.1
@@ -30273,11 +30273,12 @@ length is equal to that of
Shifting an empty buffer by any number of bits results in
an empty buffer.
-.coNP Functions @, buf-and @ buf-or and @ buf-xor
+.coNP Functions @, buf-and @, buf-or @ buf-xor and @ buf-test
.synb
.mets (buf-and < buf1 << buf2 )
.mets (buf-or < buf1 << buf2 )
.mets (buf-xor < buf1 << buf2 )
+.mets (buf-test < buf1 << buf2 )
.syne
.desc
The functions
@@ -30286,7 +30287,12 @@ The functions
or
.code buf-xor
perform common bitwise Boolean operations on a pair of buffers,
-returning the result as a buffer.
+returning the result as a buffer. The function
+.code buf-test
+returns a Boolean result,
+.code t
+or
+.codn nil .
If the input operands
.meta buf1
@@ -30307,7 +30313,7 @@ or
then that input buffer itself may be returned.
The
-code buf-and
+.code buf-and
function calculates the bitwise Boolean "and" operation between
corresponding bytes of the two operands;
.code buf-or
@@ -30316,6 +30322,20 @@ and
.code buf-xor
calculates the bitwise Boolean exclusive "or".
+The
+.code buf-test
+calculates the bitwise Boolean "and", in the same manner as
+.codn buf-and .
+However, rather than returning the result of that operation,
+.code buf-test
+returns an indication whether any nonzero bits occur in the result.
+
+Thus
+.code "(buf-test x y)"
+is equivalent to
+.code "(not (buf-zero-p (x y)))"
+except that a buffer need not be calculated and separately tested for zero.
+
.coNP Function @ buf-not
.synb
.mets (buf-not << buf )