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\$
  • \$\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\$ – Dexter Haslem 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\$ – Dexter Haslem 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\$ – Danil Gaponov 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

Not the answer you're looking for? Browse other questions tagged or ask your own question.