1
\$\begingroup\$

I need to handle C style ('\0' delimited) strings from/to a socket and came up with this as a first attempt:

#lang racket
(require racket/tcp)

(define (read-c-str inp)
  (define (read-to-zero acc)
    (define b (read-byte inp))
    (cond 
      [(equal? b 0) (bytes->string/utf-8 (apply bytes (reverse acc)))]
      [else         (read-to-zero (cons b acc))]))
 (read-to-zero null))

(define (write-c-str val p)
  (write-bytes (bytes-append (string->bytes/utf-8 val) (bytes 0)) p)
  (flush-output p))

Writing is pretty simple, but I have the feeling I'm missing a more simple way to handle the accumulator there, and mainly looking for feedback on read-c-str. I'm suspicious of having to reverse, making me think there is a better way.

Here was my second attempt which I'm not convinced is a better way:

(define (blist->string blist)
  (bytes->string/utf-8 (foldr (lambda (inb l) (bytes-append l (bytes inb))) #"" blist)))

(define (read-c-str inp)
  (define (read-to-zero acc)
    (define b (read-byte inp))
    (if (equal? b 0)
        (blist->string acc)
        (read-to-zero (cons b acc))))
  (read-to-zero null))
\$\endgroup\$
1
\$\begingroup\$

I would accumulate bytes instead of integers.

(define (read-c-str inp)
  (define (read-to-zero acc)
    (define b (read-byte inp))
    (if (equal? b 0)
        (blist->string acc)
        (read-to-zero (bytes-append acc (bytes b)))))
  (read-to-zero #""))

And change blist->string accordingly.

Edit: in this case blist->string will become just bytes->string/utf-8 .

\$\endgroup\$
3
  • \$\begingroup\$ can you please point out where specifically I'm using integers? this code appears to be the same, just moved around. edit: nevermind, I see.. \$\endgroup\$
    – user54495
    Oct 7 '14 at 19:39
  • \$\begingroup\$ actually, looking at this again. I'm really not sure. Can you please specify where exactly I'm using an integer? \$\endgroup\$
    – user54495
    Oct 8 '14 at 17:15
  • \$\begingroup\$ You use bytes to convert from number to byte string. And read-byte actually returns numeric representation of the byte read. Try running the following code: (let ([ip (open-input-string "a")])(read-byte ip)) It will return 97, a number. Not a byte string #"a" \$\endgroup\$ Oct 9 '14 at 7:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy