Email list hosting service & mailing list manager


ASCII character routines Lassi Kortela 13 Sep 2019 15:47 UTC

Here's a simple library for dealing only with ASCII characters,
instead of the full Unicode range with all its complexities. I've
several times wished for one like this. The procedures take either
char or integer arguments; if you get bytes from a bytevector, you can
pass them directly to these procedures without converting to a char
first, which can be convenient.

Should I submit a SRFI about this or just publish as a library in
Snow? This would be easy to add to implementations, some of them might
want to implement it in C, and I'd personally love to have these out
of the box when installing an implementation. But if it's too trivial
I'm happy with the Snow library.

----------------------------------------------------------------------

(define ascii-digit "0123456789")
(define ascii-lower "abcdefghijklmnopqrstuvwxyz")
(define ascii-upper "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
(define ascii-punct "!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~")

(define (ensure-int x)
   (if (char? x) (char->integer x) x))

(define (ascii-char? x)
   (and (char? x) (< (char->integer x) #x80)))

(define (ascii-control? x)
   (let ((cc (ensure-int x)))
     (or (< cc #x20) (= cc #x7f))))

(define (ascii-printable? x)
   (let ((cc (ensure-int x)))
     (<= #x20 cc #x7e)))

(define (ascii-whitespace? x)
   (let ((cc (ensure-int x)))
     (cond ((< cc #x09) #f)
           ((< cc #x0e) #t)
           (else (= x #x20)))))

(define (ascii-upper-case? x)
   (let ((cc (ensure-int x)))
     (<= #x41 cc #x5a)))

(define (ascii-lower-case? x)
   (let ((cc (ensure-int x)))
     (<= #x61 cc #x7a)))

(define (ascii-alphabetic? x)
   (let ((cc (ensure-int x)))
     (or (<= #x41 cc #x5a)
         (<= #x61 cc #x7a))))

(define (ascii-alphanumeric? x)
   (let ((cc (ensure-int x)))
     (or (<= #x30 cc #x39)
         (<= #x41 cc #x5a)
         (<= #x61 cc #x7a))))

(define (ascii-digit-value x radix)
   (let ((cc (ensure-int x)))
     (and (<= 2 radix 36)
          (or (and (<= #x30 cc (+ #x30 (min radix 9)))
                   (- cc #x30))
              (and (> radix 10)
                   (let ((letters (- radix 10)))
                     (or (and (<= #x41 cc (+ #x41 letters))
                              (- cc #x41 -10))
                         (and (<= #x61 cc (+ #x61 letters))
                              (- cc #x61 -10)))))))))

(define (ascii-numeric? x radix)
   (not (not (ascii-digit-value x radix))))

(define (ascii-upcase x)
   (cond ((char? x) (integer->char (ascii-upcase (char->integer x))))
         ((<= #x61 x #x7a) (- x #x20))
         (else x)))

(define (ascii-downcase x)
   (cond ((char? x) (integer->char (ascii-downcase (char->integer x))))
         ((<= #x41 x #x5a) (+ x #x20))
         (else x)))