I would like to read/write both text and binary data on sockets and
(*stdandard-input* *standard-output*). Are there idioms in Lisp to
mix text and binary ?
············@gmail.com writes:
> I would like to read/write both text and binary data on sockets and
> (*stdandard-input* *standard-output*). Are there idioms in Lisp to
> mix text and binary ?
You already got two answers on this thread. Another is to use
"simple-streams", which is available in Allegro CL, as well as some of
the free lisps (CMUCL, at least). Documentation starts here:
http://www.franz.com/support/documentation/current/doc/streams.htm
--
Duane Rettig ·····@franz.com Franz Inc. http://www.franz.com/
555 12th St., Suite 1450 http://www.555citycenter.com/
Oakland, Ca. 94607 Phone: (510) 452-2000; Fax: (510) 452-0182
Den Fri, 29 Feb 2008 04:40:50 -0800 skrev nicolas.edel:
> I would like to read/write both text and binary data on sockets and
> (*stdandard-input* *standard-output*). Are there idioms in Lisp to mix
> text and binary ?
http://www.cliki.net/Flexi-streams for instance. In CL parlance, such
streams are referred to as "bivalent". There are various mechanisms to
implement them, usually implementation-dependent.
Cheers,
Maciej
············@gmail.com writes:
> I would like to read/write both text and binary data on sockets and
> (*stdandard-input* *standard-output*). Are there idioms in Lisp to
> mix text and binary ?
Use a binary stream and encode and decode explicitely.
(defconstant +ascii-code+ " !\"#$%&'()*+,-./0123456789:;<=>·@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")
(defconstant +ascii-base+ 32)
(defconstant +ascii-linefeed+ 10)
(defun ascii-encode (string)
(map 'vector
(lambda (ch)
(if (char= ch #\newline)
+ascii-linefeed+
(let ((pos (position ch +ascii-code+)))
(if pos
(+ +ascii-base+ pos)
(error "Cannot encode in ASCII the character ~C" ch)))))
string))
(defun ascii-decode (codes)
(map 'string
(lambda (code)
(cond
((= +ascii-linefeed+ code) #\newline)
((<= +ascii-base+ code (+ +ascii-base+ (length +ascii-code+) -1))
(aref +ascii-code+ (- code +ascii-base+)))
((< code 128) (error "The ASCII code ~D doesn't correspond to any character." code))
(t (error "The coed ~D is not an ASCII code." code))))))
Note that most functions you usually apply on strings are actually
defined on vectors or even sequences, so you can use them as well on
code vectors.
(read-sequence buffer)
(cond
((= 5 (mismatch #.(ascii-encode "HELO ") buffer)) (process-helo (subseq buffer 5)))
((= 10 (mismatch #.(ascii-encode "MAIL FROM ") buffer)) (process-mail-from (subseq buffer 10)))
...)
For more complex encoding, you could avoid implementing your own
unicode encode/decode using implementation dependant functions such as
#+clisp ext:convert-string-to-bytes, or dig for some 'portability'
sub-library (eg. there's something in arnesi). But most protocol take
care to specify ASCII for the active strings.
--
__Pascal Bourguignon__
<············@gmail.com> wrote:
+---------------
| I would like to read/write both text and binary data on sockets and
| (*stdandard-input* *standard-output*). Are there idioms in Lisp to
| mix text and binary ?
+---------------
You've already gotten good answers from others, but just in case
you're using CMUCL, the implementation-specific way there is to
add the :CLASS 'BINARY-TEXT-STREAM and :ELEMENT-TYPE :DEFAULT
optional args to the OPEN (or WITH-OPEN-FILE). That will let
you do both text (e.g., READ-CHAR) and binary (e.g. READ-BYTE)
operations on the resulting stream.
In particular, my CMUCL "-script" hack uses it to allow "#!"
scripts of both source files and FASLs, see:
http://rpw3.org/hacks/lisp/site-switch-script.lisp
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607