git.fiddlerwoaroof.com
Browse code

Support nested providers

fiddlerwoaroof authored on 08/08/2017 01:14:20
Showing 2 changed files
... ...
@@ -30,7 +30,10 @@ install:
30 30
     else
31 31
       curl https://raw.githubusercontent.com/luismbo/cl-travis/master/install.sh | sh;
32 32
     fi     
33
-  - 'pushd $HOME/quicklisp/local-projects && git clone http://git.elangley.org/git/u/edwlan/fwoar.lisputils.git && git clone http://git.elangley.org/git/u/edwlan/vector-update-stream.git; popd'
33
+  - 'pushd $HOME/quicklisp/local-projects &&
34
+     git clone http://git.elangley.org/git/u/edwlan/fwoar.lisputils.git &&
35
+     git clone http://git.elangley.org/git/u/edwlan/vector-update-stream.git;
36
+     popd'
34 37
 
35 38
 # this serves as an example of how to use the 'cl' script (provided by
36 39
 # CIM) to test your Lisp project. Here, we're using the RT framework
... ...
@@ -1,13 +1,14 @@
1 1
 (fwoar.sp-user:define-package :stream-provider
2 2
   (:use :fw.lu)
3 3
   (:export #:get-stream-for
4
-	   #:stream-provider
5
-	   #:string-provider
6
-	   #:file-provider
7
-	   #:stream-key
8
-	   #:root
9
-	   #:streams
10
-	   #:with-storage-stream))
4
+           #:stream-provider
5
+           #:string-provider
6
+           #:file-provider
7
+           #:stream-key
8
+           #:root
9
+           #:streams
10
+           #:with-storage-stream
11
+           #:get-nested-provider))
11 12
 (cl:in-package :stream-provider)
12 13
 
13 14
 (defclass stream-provider ()
... ...
@@ -23,6 +24,9 @@ If you override on provider, make sure to CALL-NEXT-METHOD"))
23 24
 (defgeneric get-stream-for (provider streamable &rest extra-args)
24 25
   (:documentation "get a stream for a given streamable object"))
25 26
 
27
+(defgeneric get-nested-provider (provider streamable)
28
+  (:documentation "implement to handle storage of hierarchical data"))
29
+
26 30
 (defgeneric root (provider)
27 31
   (:documentation "get the base path for the streams"))
28 32
 
... ...
@@ -34,19 +38,31 @@ If you override on provider, make sure to CALL-NEXT-METHOD"))
34 38
   #p "/")
35 39
 
36 40
 (defmethod stream-key :around (provider item)
41
+  (declare (optimize (debug 3)))
37 42
   (let ((key (call-next-method)))
38
-    (check-type key (or string pathname))
39
-    (uiop:enough-pathname key (root provider))))
43
+    (check-type key (or cons string pathname))
44
+    (let ((the-pathname
45
+           (ctypecase key
46
+             (pathname key)
47
+             (string (pathname key))
48
+             (cons (uiop:merge-pathnames*
49
+                    (car (last key))
50
+                    (apply 'path-join
51
+                           (mapcar 'uiop:ensure-directory-pathname
52
+                                   (butlast key))))))))
53
+      (uiop:enough-pathname the-pathname
54
+                            (root provider)))))
55
+
40 56
 
41 57
 (defmethod get-stream-for ((provider string-provider) streamable &rest extra-args)
42 58
   (declare (ignore extra-args))
43 59
   (with-accessors* (streams) provider
44 60
     (vector-update-stream:make-update-stream 
45 61
      (setf (gethash (stream-key provider streamable) streams)
46
-	   (make-array 10
47
-		       :element-type 'octet
48
-		       :adjustable t
49
-		       :fill-pointer 0)))))
62
+           (make-array 10
63
+                       :element-type 'octet
64
+                       :adjustable t
65
+                       :fill-pointer 0)))))
50 66
 
51 67
 (defclass file-provider (stream-provider)
52 68
   ((%root :initarg :root :initform (error "need a root for a file-provider") :reader root)
... ...
@@ -56,15 +72,15 @@ If you override on provider, make sure to CALL-NEXT-METHOD"))
56 72
   (declare (ignore extra-args))
57 73
   (with-accessors* (if-exists root) provider
58 74
     (let ((stream-key (merge-pathnames (stream-key provider streamable)
59
-				       root)))
75
+                                       root)))
60 76
       (when (eql if-exists :if-exists)
61
-	(ensure-directories-exist stream-key))
77
+        (ensure-directories-exist stream-key))
62 78
       (open stream-key :direction :output :if-exists if-exists
63
-	    :element-type 'octet))))
79
+            :element-type 'octet))))
64 80
 
65 81
 (defmacro with-storage-stream ((stream-sym object provider &rest extra-args) &body body)
66 82
   (once-only (object)
67 83
     `(let ((,stream-sym (flexi-streams:make-flexi-stream (get-stream-for ,provider ,object ,@extra-args)
68
-							 :external-format :utf-8)))
84
+                                                         :external-format :utf-8)))
69 85
        (unwind-protect (progn ,@body)
70
-	 (close ,stream-sym)))))
86
+         (close ,stream-sym)))))