File: file-backed-table-container.lisp

package info (click to toggle)
cl-containers 20170403-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 1,072 kB
  • ctags: 1,387
  • sloc: lisp: 8,341; makefile: 14
file content (93 lines) | stat: -rw-r--r-- 2,902 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
(in-package #:containers)

(defclass* file-backed-table-container (table-container)
  ((pathspec nil ir)
   (size 0 a)
   (require-write (make-container 'list-container) r)
   )
  (:documentation "This is a very half-assed class that pretends to store a
table on disk. It doesn't support updating.")
  (:export-p t))


(defmethod save-row (column-names row out)
  (format out "~&\(~{~S ~}\)" 
          (collect-elements 
           column-names
           :transform (lambda (name)
                        (slot-value row name)))))

  
(defmethod save-table-header ((container file-backed-table-container) 
                              stream)
  (format stream "~&\(:prototype-name ~S :columns ~S\)"
          (class-name (prototype container))
          (column-names container)))


(defmethod load-table-header ((container file-backed-table-container) 
                              line)
  ;;?? STUB
  (values t))


(defmethod check-table-header ((container file-backed-table-container) 
                               line)
  ;;?? STUB
  (values t))


(defmethod save-changes ((container file-backed-table-container)) 
  (let ((column-names (column-names container))
        (write-header? nil))
    (if (probe-file (pathspec container))
      (check-table-header container (pathspec container))
      (setf write-header? t))
    
    (with-open-file (out (pathspec container)
                         :if-exists :append
                         :direction :output
                         :if-does-not-exist :create)
      (let ((*print-right-margin* most-positive-fixnum))
        (when write-header?
          (save-table-header container out))
        (iterate-elements
         (require-write container)
         (lambda (row)
           (save-row column-names row out))))))
  (empty! (require-write container)))


(defmethod insert-record ((table file-backed-table-container) object)
  (insert-item (require-write table) object)
  (incf (size table))
  (maybe-save-changes table))


(defmethod maybe-save-changes ((table file-backed-table-container))
  (when (> (size (require-write table)) 10)
    (save-changes table)))


(defmethod iterate-container ((container file-backed-table-container) fn)
  (save-changes container)
  (let ((first? t)
        (column-names (column-names container)))
    (u:map-lines-in-file 
     (lambda (line)
       (if first?
         ;; skip header row
         (setf first? nil)
       
         ;; create element and call fn on it
         (funcall fn (create-record container column-names line))))
     (pathspec container))))


(defmethod create-record ((container file-backed-table-container) 
                          (column-names list) (line string))
  (let ((it (allocate-instance (prototype container))))
    (loop for datum in (read-from-string line)
          for column in column-names do
          (setf (slot-value it column) datum))
    it))