git.fiddlerwoaroof.com
Raw Blame History
(in-package :co.fwoar.awkish.lines)

(defclass lines ()
  ((%column-cache :initform (make-hash-table))))
(fw.lu:defclass+ stream-lines (lines)
  ())
(fw.lu:defclass+ string-lines (lines)
  ((%pos :initform 0 :accessor lines-pos)))

(defmethod resolve-column ((client lines) (record cons) (column-designator number))
  (let ((column-designator (1- column-designator)))
    (with-slots (%column-cache) client
      ;; manually tuned
      (if (> column-designator 60)
          (alexandria:ensure-gethash column-designator
                                     %column-cache
                                     (nth column-designator record))
          (nth column-designator record)))))
(defmethod parse-record ((client lines) (raw-record string))
  (serapeum:tokens raw-record))
(defmethod field-count ((client lines) (record list))
  (length record))
(defmethod unpack-binders ((client lines) (record list))
  record)


(defmethod make-client ((client (eql :lines)) (source stream) &key)
  (stream-lines))
(defmethod make-client ((client (eql :lines)) (source string) &key)
  (string-lines))

(defmethod next-record :before ((client lines) (source stream))
  (clrhash (slot-value client '%column-cache)))
(defmethod next-record ((client stream-lines) (source stream))
  (read-line source nil *eof-sentinel*))
(defmethod next-record ((client string-lines) (source string))
  (let ((next-newline (position #\newline source :start (lines-pos client))))
    (if (< (lines-pos client) (length source))
        (prog1 (subseq source (lines-pos client) next-newline)
          (setf (lines-pos client) (if next-newline
                                       (1+ next-newline)
                                       (length source))))
        *eof-sentinel*)))