Skip to content

Instantly share code, notes, and snippets.

@vyzo
Created October 25, 2019 09:01
Show Gist options
  • Save vyzo/e9d33f1ed117ac2500bc06b5ec1d1c25 to your computer and use it in GitHub Desktop.
Save vyzo/e9d33f1ed117ac2500bc06b5ec1d1c25 to your computer and use it in GitHub Desktop.
wc with raw fd output
(import :std/net/bio
:std/net/bio/output
:std/net/bio/file
:std/os/fdio
:std/sort
:std/srfi/1)
(export main)
(declare (not safe))
;; shim to use an output buffer on raw file descriptors
(def (fd-output-drain! buf need)
(fd-output-write (&output-buffer-e buf) 0 (&output-buffer-wlo buf) buf)
(set! (&output-buffer-wlo buf) 0))
(def (fd-output-write bytes start end buf)
(let ((fd (&file-output-buffer-fd buf))
(bytes (&output-buffer-e buf)))
(_write fd bytes start end)))
(def (open-stdout-buffer (bufsz 4096))
(make-file-output-buffer (make-u8vector bufsz) 0 bufsz
fd-output-drain!
fd-output-write
1))
(def (read-next-word buf)
(let lp ((chars []))
(let (next (bio-read-char buf))
(cond
((eof-object? next)
(if (null? chars)
next
(list->string (reverse! chars))))
((or (eq? next #\space) (eq? next #\newline))
(list->string (reverse! chars)))
(else
(lp (cons next chars)))))))
(def (main path)
(let ((words (make-hash-table size: 1000000))
(buf (open-file-input-buffer path 8192)))
(let lp ()
(let (word (read-next-word buf))
(unless (eof-object? word)
(hash-update! words word fx1+ 0)
(lp))))
(let (obuf (open-stdout-buffer 8192))
(for-each (lambda (x)
(bio-write-string (car x) obuf)
(bio-write-char #\space obuf)
(bio-write-string (number->string (cdr x)) obuf)
(bio-write-char #\newline obuf))
(sort! (hash->list words)
(lambda (a b) (> (cdr a) (cdr b)))))
(bio-force-output obuf))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment