guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [code] Quoted-printable decoding.


From: Ludovic Courtès
Subject: Re: [code] Quoted-printable decoding.
Date: Sat, 17 Aug 2013 14:50:29 +0200
User-agent: Gnus/5.130007 (Ma Gnus v0.7) Emacs/24.3 (gnu/linux)

Dmitry Bogatov <address@hidden> skribis:

> Today I faced the need to decode quoted-printable message, and for fun,
> learning and love to scheme implemented it myself rather than use any
> other language. I found no existing implementation in Guile or Guile
> Lib.
>
> I would like to share code and ready to work and discuss to make it part
> of Guile. If it possible, I would like to put my code to public domain
> to avoid legal issues.

That’s something that could perhaps end up in a (web ...) module, Andy?

> (use-modules (ice-9 iconv))
> (use-modules (rnrs bytevectors))
> (use-modules (rnrs io ports))
> (use-modules (ice-9 receive))
> (use-modules (ice-9 binary-ports))

Several modules can be listed in a single ‘use-modules’.

> (define (newline? ch) (or (char=? ch #\newline)
>                         (char=? ch #\return)))
>
> (define (hex-char? ch)
>     (define (in-range low high)
>       (and (char<=? low ch)
>            (char<=? ch high)))
>     (or (in-range #\0 #\9)
>       (in-range #\A #\F)
>       (in-range #\a #\f)))

Use SRFI-14 character sets instead.

> (define* (decode str #:key (enc "utf-8"))
>     (define (char-ref index) (string-ref str index))
>     (define length (string-length str))
>     (define index 0)
>     (receive [bv-port bv-get-content]
>            [open-bytevector-output-port]
>            (while (not (= index length))
>                   (let ([char (char-ref index)])
>                       (if (char=? char #\=)
>                           (let ([char+  (char-ref (+ 1 index))]
>                                 [char++ (char-ref (+ 2 index))])
>                               (cond
>                                [[hex-char? char+]
>                                 (put-u8 bv-port
>                                         (string->number
>                                          (string char+ char++) 16))
>                                           (inc! index 2)]
>                                [[newline? char++] (inc! index 2)]
>                                [else (inc! index)]))
>                           (put-u8 bv-port (char->integer char))))
>                   (inc! index))
>            (bytevector->string (bv-get-content) enc
>                                'substitute)))

I think this function is not robust against malformed input (it could
lead to out-of-bounds references).

Stylistic note: some of us (ahem) prefer a functional style.  I would
write the loop as a recursive function, and pass the index value as an
argument:

  (let loop ((index 0))
    ...
    (loop (+ 1 index)))

Ludo’.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]