Browse code
Support nested providers
fiddlerwoaroof authored on 08/08/2017 01:14:20
Showing 2 changed files
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))))) |