root/trunk/thirdparty/cl-store_0.8.4/xml-backend.lisp

Revision 2554, 16.7 kB (checked in by ksprotte, 11 months ago)

added cl-store

  • Property svn:executable set to *
Line 
1 ;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;; See the file LICENCE for licence information.
3
4 ;; THIS BACKEND IS DEPRECATED AND WILL NOT WORK
5 ;; ITS PRESENCE IS FOR POSTERITY ONLY
6 (in-package :cl-store-xml)
7
8
9 (defbackend xml :stream-type 'character :extends (resolving-backend))
10
11 ;; The xml backend does not use any type codes
12 ;; we figure it out when we read the tag of each object
13 (defvar *xml-mapping* (make-hash-table :test #'equal))
14 (defun add-xml-mapping (name)
15   (setf (gethash name *xml-mapping*)
16         (intern name :cl-store-xml)))
17
18 (add-xml-mapping "REFERRER")
19 (add-xml-mapping "INTEGER")
20 (add-xml-mapping "FLOAT")
21 (add-xml-mapping "SIMPLE-STRING")
22 (add-xml-mapping "SYMBOL")
23 (add-xml-mapping "CONS")
24 (add-xml-mapping "RATIO")
25 (add-xml-mapping "CHARACTER")
26 (add-xml-mapping "COMPLEX")
27 (add-xml-mapping "PATHNAME")
28 (add-xml-mapping "FUNCTION")
29 (add-xml-mapping "GENERIC-FUNCTION")
30
31 (defmethod get-next-reader ((backend xml) (place list))
32   (or (gethash (car place) *xml-mapping*)
33       (error "Unknown tag ~A" (car place))))
34
35 (defun princ-xml (tag value stream)
36   (format stream "<~A>" tag)
37   (xmls:write-xml value stream)
38   (format stream "</~A>" tag))
39
40 (defun princ-and-store (tag obj stream)
41   (format stream "<~A>" tag)
42   (store-object obj stream)
43   (format stream "</~A>" tag))
44
45 (defmacro with-tag ((tag stream) &body body)
46   `(progn
47     (format ,stream "<~A>" ,tag)
48     ,@body
49     (format ,stream "</~A>" ,tag)))
50
51 (defun first-child (elmt)
52   (first (xmls:node-children elmt)))
53
54 (defun second-child (elmt)
55   (second (xmls:node-children elmt)))
56
57 (defun get-child (name elmt &optional (errorp t))
58   (or (assoc name (xmls:node-children elmt) :test #'equal)
59       (and errorp
60            (restore-error "No child called ~A in xml ~a"
61                           (list name elmt)))))
62
63 (defun get-attr (name elmt)
64   (cadr (assoc name (xmls:node-attrs elmt) :test #'equal)))
65
66 (declaim (inline restore-first))
67 (defun restore-first (place)
68   (restore-object (first-child place)))
69
70 (defmethod store-referrer ((backend xml) (ref t) (stream t))
71   (princ-xml "REFERRER" ref stream))
72
73 (defrestore-xml (referrer place)
74   (make-referrer :val (parse-integer (third place))))
75
76 (defmethod referrerp ((backend xml) (reader t))
77   (eql reader 'referrer))
78
79 ;; override backend restore to parse the incoming stream
80 (defmethod backend-restore ((backend xml) (place stream))
81   (let ((*restore-counter* 0)
82         (*need-to-fix* nil)
83         (*print-circle* nil)
84         (*restored-values* (and *check-for-circs*
85                                 (make-hash-table :test #'eq :size *restore-hash-size*))))
86     (multiple-value-prog1
87         (backend-restore-object backend
88                                 (or (xmls:parse place)
89                                     (restore-error "Invalid xml")))
90       (dolist (fn *need-to-fix*)
91         (force fn)))))
92
93 ;; integer
94 (defstore-xml (obj integer stream)
95   (princ-xml "INTEGER" obj stream))
96
97 (defrestore-xml (integer from)
98   (values (parse-integer (first-child from))))
99
100 ;; floats
101 (defvar *special-floats* nil) ;; setup in custom-xml files
102
103 ;; FIXME: add support for *special-floats*
104 (defstore-xml (obj float stream)
105   (with-tag ("FLOAT" stream) (print obj stream)))
106
107 (defrestore-xml (float from)
108   (cl-l10n:parse-number (first-child from)))
109
110 #|
111 (defstore-xml (obj single-float stream)
112   (store-float "SINGLE-FLOAT" obj stream))
113
114 (defstore-xml (obj double-float stream)
115   (store-float "DOUBLE-FLOAT" obj stream))
116
117 (defun store-float (type obj stream)
118   (block body
119     (let (significand exponent sign)
120       (handler-bind ((simple-error
121                       #'(lambda (err)
122                           (declare (ignore err))
123                           (when-let (type (cdr (assoc obj *special-floats*)))
124                             (output-float-type type stream)
125                             (return-from body)))))
126         (multiple-value-setq (significand exponent sign)
127             (integer-decode-float obj))
128         (with-tag (type stream)
129           (princ-and-store "SIGNIFICAND" significand stream)
130           (princ-and-store "RADIX"(float-radix obj) stream)
131           (princ-and-store "EXPONENT" exponent stream)
132           (princ-and-store "SIGN" sign stream))))))
133 |#
134
135 ; FIXME: restore flaot
136
137 ;; ratio
138 (defstore-xml (obj ratio stream)
139   (with-tag ("RATIO" stream)
140     (princ-and-store "NUMERATOR" (numerator obj) stream)
141     (princ-and-store "DENOMINATOR" (denominator obj) stream)))
142
143 (defrestore-xml (ratio from)
144   (/ (restore-first (get-child "NUMERATOR" from))
145      (restore-first (get-child "DENOMINATOR" from))))
146
147 ;; char
148 (defstore-xml (obj character stream)
149   (princ-and-store "CHARACTER" (char-code obj) stream))
150
151 (defrestore-xml (character from)
152   (code-char (restore-first from)))
153
154
155 ;; complex
156 (defstore-xml (obj complex stream)
157   (with-tag ("COMPLEX" stream)
158     (princ-and-store "REALPART" (realpart obj) stream)
159     (princ-and-store "IMAGPART" (imagpart obj) stream)))
160
161
162 (defrestore-xml (complex from)
163   (complex (restore-first (get-child "REALPART" from))
164            (restore-first (get-child "IMAGPART" from))))
165
166
167 ;; symbols
168 (defstore-xml (obj symbol stream)
169   (with-tag ("SYMBOL" stream)
170     (princ-and-store "NAME" (symbol-name obj) stream)
171     (cl-store::when-let (package (symbol-package obj))
172       (princ-and-store "PACKAGE" (package-name package) stream))))
173
174 (defrestore-xml (symbol from)
175   (let ((name (restore-first (get-child "NAME" from)))
176         (package (when (get-child "PACKAGE" from nil)
177                    (restore-first (get-child "PACKAGE" from)))))
178     (if package
179         (values (intern name package))
180         (make-symbol name))))
181
182 ;; lists
183 (defstore-xml (obj cons stream)
184   (with-tag ("CONS" stream)
185     (princ-and-store "CAR" (car obj) stream)
186     (princ-and-store "CDR" (cdr obj) stream)))
187
188 (defrestore-xml (cons from)
189   (resolving-object (x (cons nil nil))
190     (setting (car x) (restore-first (get-child "CAR" from)))
191     (setting (cdr x) (restore-first (get-child "CDR" from)))))
192
193 ;; simple string
194 (defstore-xml (obj simple-string stream)
195   (princ-xml "SIMPLE-STRING" obj stream))
196
197 (defrestore-xml (simple-string from)
198   (first-child from))
199
200
201 ;; pathnames
202 (defstore-xml (obj pathname stream)
203   (with-tag ("PATHNAME" stream)
204     (princ-and-store "DEVICE" (pathname-device obj) stream)
205     (princ-and-store "DIRECTORY" (pathname-directory obj) stream)
206     (princ-and-store "NAME" (pathname-name obj) stream)
207     (princ-and-store "TYPE" (pathname-type obj) stream)
208     (princ-and-store "VERSION" (pathname-version obj) stream)))
209
210 (defrestore-xml (pathname place)
211   (make-pathname
212    :device (restore-first (get-child "DEVICE" place))
213    :directory (restore-first (get-child "DIRECTORY" place))
214    :name (restore-first (get-child "NAME" place))
215    :type (restore-first (get-child "TYPE" place))
216    :version (restore-first (get-child "VERSION" place))))
217
218
219 ; hash table
220 (defstore-xml (obj hash-table stream)
221   (with-tag ("HASH-TABLE" stream)
222     (princ-and-store "REHASH-SIZE" (hash-table-rehash-size obj) stream)
223     (princ-and-store "REHASH-THRESHOLD" (hash-table-rehash-threshold obj) stream)
224     (princ-and-store "SIZE" (hash-table-size obj) stream)
225     (princ-and-store "TEST" (hash-table-test obj) stream)
226     (with-tag ("ENTRIES" stream)
227       (loop for key being the hash-keys of obj
228             using (hash-value value) do
229             (with-tag ("ENTRY" stream)
230               (princ-and-store "KEY" key stream)
231               (princ-and-store "VALUE" value stream))))))
232
233 ;; FIXME: restore hash tables
234
235 ;; objects and conditions
236
237 (defun xml-dump-type-object (obj stream)
238   (let* ((all-slots (serializable-slots obj)))
239     (with-tag ("SLOTS" stream)
240       (dolist (slot all-slots)
241         (when (slot-boundp obj (slot-definition-name slot))
242           (when (or *store-class-slots*
243                     (eql (slot-definition-allocation slot) :instance))
244             (with-tag ("SLOT" stream)
245               (let ((slot-name (slot-definition-name slot)))
246                 (princ-and-store "NAME" slot-name stream)
247                 (princ-and-store "VALUE" (slot-value obj slot-name) stream)))))))))
248
249 (defstore-xml (obj standard-object stream)
250   (with-tag ("STANDARD-OBJECT" stream)
251     (princ-and-store "CLASS" (type-of obj) stream)
252     (xml-dump-type-object obj stream)))
253
254 (defstore-xml (obj condition stream)
255   (with-tag ("CONDITION" stream)
256     (princ-and-store "CLASS" (type-of obj) stream)
257     (xml-dump-type-object obj stream)))
258
259
260 ;; FIXME: restore objects
261
262
263
264 ;; classes
265
266 ;; FIXME : Write me
267
268 ;; built in classes
269 (defstore-xml (obj built-in-class stream)
270   (princ-and-store "BUILT-IN-CLASS" (class-name obj) stream))
271
272 #-ecl ;; for some reason this doesn't work with ecl
273 (defmethod internal-store-object ((backend xml) (obj (eql (find-class 'hash-table))) stream)
274   (princ-and-store "BUILT-IN-CLASS" 'cl:hash-table stream))
275
276 ;; FIXME: restore built in classes
277
278 ;; arrays and vectors
279 ;; FIXME : Write me
280
281 ;; packages
282 ;; FIXME : Write me
283
284 ;; functions
285 (defstore-xml (obj function stream)
286   (princ-and-store "FUNCTION" (get-function-name obj) stream))
287
288 (defrestore-xml (function from)
289   (fdefinition (restore-first from)))
290
291 ;; generic functions
292 (defstore-xml (obj generic-function stream)
293   (if (generic-function-name obj)
294       (princ-and-store "GENERIC-FUNCTION"
295                        (generic-function-name obj) stream)
296       (store-error "No generic function name for ~A." obj)))
297
298 (defrestore-xml (generic-function from)
299   (fdefinition (restore-first from)))
300
301 (setf *default-backend* (find-backend 'xml))
302
303 #|
304
305 ;; required methods and miscellaneous util functions
306
307
308 (defrestore-xml (hash-table place)
309   (let ((hash1 (make-hash-table
310                 :rehash-size (restore-first (get-child "REHASH-SIZE" place))
311                 :rehash-threshold (restore-first
312                                    (get-child "REHASH-THRESHOLD" place))
313                 :size (restore-first (get-child "SIZE" place))
314                 :test (symbol-function (restore-first (get-child "TEST" place))))))
315     (resolving-object (hash1 hash1)
316       (dolist (entry (xmls:node-children (get-child "ENTRIES" place)))
317         (let* ((key-place (first-child (first-child entry)))
318                (val-place (first-child (second-child entry))))
319           (setting-hash (restore-object key-place)
320                         (restore-object val-place)))))
321     hash1))
322
323
324 (defun restore-xml-type-object (place)
325   (let* ((class (find-class (restore-first (get-child "CLASS" place))))
326          (new-instance (allocate-instance class)))
327     (resolving-object new-instance
328       (dolist (slot (xmls:node-children (get-child "SLOTS" place)))
329         (let ((slot-name (restore-first (get-child "NAME" slot))))
330           (setting (slot-value slot-name)
331                    (restore-first (get-child "VALUE" slot))))))
332     new-instance))
333
334 (defrestore-xml (standard-object place)
335   (restore-xml-type-object place))
336
337 (defrestore-xml (condition place)
338   (restore-xml-type-object place))
339
340 ;; classes
341 (defun store-slot (slot stream)
342   (with-tag ("SLOT" stream)
343     (princ-and-store "NAME" (slot-definition-name slot) stream)
344     (princ-and-store "ALLOCATION" (slot-definition-allocation slot) stream)
345     (princ-and-store "TYPE" (slot-definition-type slot) stream)
346     (with-tag ("INITARGS" stream)
347       (dolist (x (slot-definition-initargs slot))
348         (princ-and-store "INITARG" x stream)))
349     (with-tag ("READERS" stream)
350       (dolist (x (slot-definition-readers slot))
351         (princ-and-store "READER" x stream)))
352     (with-tag ("WRITERS" stream)
353       (dolist (x (slot-definition-writers slot))
354         (princ-and-store "WRITER" x stream)))))
355
356 (defstore-xml (obj standard-class stream)
357   (with-tag ("STANDARD-CLASS" stream)
358     (princ-and-store "NAME" (class-name obj) stream)
359     (with-tag ("SUPERCLASSES" stream)
360       (loop for x in (class-direct-superclasses obj) do
361             (unless (eql x (find-class 'standard-object))
362               (princ-and-store "SUPERCLASS"
363                                (if *store-class-superclasses*
364                                    x
365                                    (class-name x))
366                                stream))))
367     (with-tag ("SLOTS" stream)
368       (dolist (x (class-direct-slots obj))
369         (store-slot x stream)))
370     (princ-and-store "METACLASS" (type-of obj) stream)))
371
372
373
374 (defun xml-add-class (name slots superclasses metaclass)
375   (ensure-class name :direct-slots slots
376                 :direct-superclasses superclasses
377                 :metaclass metaclass)
378   #+clisp(add-methods-for-class name slots))
379
380 (defun get-values (values)
381   (loop for value in (xmls:node-children values)
382         collect (restore-first value)))
383
384 (defun get-slots (slots)
385   (loop for slot in (xmls:node-children slots)
386         collect (list :name (restore-first (get-child "NAME" slot))
387                       :allocation (restore-first (get-child "ALLOCATION" slot))
388                       :type (restore-first (get-child "TYPE" slot))
389                       :initargs (get-values (get-child "INITARGS" slot))
390                       :readers (get-values (get-child "READERS" slot))
391                       :writers (get-values (get-child "WRITERS" slot)))))
392
393 (defun get-superclasses (superclasses)
394   (loop for superclass in (xmls:node-children superclasses)
395         collect (restore-first superclass)))
396        
397 (defrestore-xml (standard-class  place)
398   (let* ((name (restore-first (get-child "NAME" place)))
399          (superclasses (get-superclasses (get-child "SUPERCLASSES" place)))
400          (slots (get-slots (get-child "SLOTS" place)))
401          (metaclass (restore-first (get-child "METACLASS" place))))
402     (cond (*nuke-existing-classes*
403            (xml-add-class name slots superclasses metaclass))
404           (t (aif (find-class name nil)
405                   it
406                   (xml-add-class name slots superclasses metaclass))))))
407
408 ;; built-in-classes
409 (defstore-xml (obj built-in-class stream)
410   (princ-and-store "BUILT-IN-CLASS" (class-name obj) stream))
411
412 (defrestore-xml (built-in-class place)
413   (find-class (restore-first place)))
414
415 ;; I don't know if this really qualifies as a built-in-class but it
416 ;; does make things a bit easier
417 (defmethod internal-store-object ((obj (eql (find-class 'hash-table))) stream
418                                   (backend xml-backend))
419   (princ-and-store "BUILT-IN-CLASS" 'cl:hash-table stream))
420
421
422 ;; Arrays and vectors
423 (defstore-xml (obj array stream)
424   (xml-dump-array obj stream))
425
426 (defun xml-dump-array (obj stream)
427   (with-tag ("ARRAY" stream)
428     (princ-and-store "DIMENSIONS" (array-dimensions obj) stream)
429     (if (and (= (array-rank obj) 1)
430              (array-has-fill-pointer-p obj))
431         (princ-and-store "FILL-POINTER" (fill-pointer obj) stream)
432         (princ-and-store "FILL-POINTER" nil stream))
433     (princ-and-store "ELEMENT-TYPE" (array-element-type obj) stream)
434     (multiple-value-bind (to offset) (array-displacement obj)
435       (princ-and-store "DISPLACED-TO" to stream)
436       (princ-and-store "DISPLACED-OFFSET" offset stream))
437     (princ-and-store "ADJUSTABLE" (adjustable-array-p obj) stream)
438     (with-tag ("VALUES" stream)
439       (loop for x from 0 to (1- (array-total-size obj)) do
440             (princ-and-store "VALUE" (row-major-aref obj x) stream)))))
441
442 (defrestore-xml (array place)
443   (let* ((dimensions (restore-first (get-child "DIMENSIONS" place)))
444          (fill-pointer (restore-first (get-child "FILL-POINTER" place)))
445          (element-type (restore-first (get-child "ELEMENT-TYPE" place)))
446          (displaced-to (restore-first (get-child "DISPLACED-TO" place)))
447          (displaced-offset (restore-first (get-child "DISPLACED-OFFSET"
448                                                      place)))
449          (adjustable (restore-first (get-child "ADJUSTABLE" place)))
450          (res (make-array dimensions 
451                           :element-type element-type
452                           :adjustable adjustable
453                           :fill-pointer fill-pointer)))
454     (when displaced-to
455       (adjust-array res dimensions :displaced-to displaced-to
456                     :displaced-index-offset displaced-offset))
457     (resolving-object res
458       (loop for value in (xmls:node-children (get-child "VALUES" place))
459             for count from 0 do
460             (let ((pos count))
461               (setting (row-major-aref pos)
462                        (restore-first value)))))))
463
464
465 #-(or allegro clisp)
466 (defstore-xml (obj simple-vector stream)
467   (with-tag ("SIMPLE-VECTOR" stream)
468     (princ-and-store "LENGTH" (length obj) stream)
469     (with-tag ("ELEMENTS" stream)
470       (loop for x across obj do
471             (princ-and-store "ELEMENT" x stream)))))
472
473 #-(or allegro clisp)
474 (defrestore-xml (simple-vector place)
475   (let* ((size (restore-first (get-child "LENGTH" place)))
476          (res (make-array size)))
477     (resolving-object res
478       (loop for element in (xmls:node-children (get-child "ELEMENTS" place))
479             for index from 1 do
480             (let ((copy (1- index)))
481               (setting (aref copy)
482                        (restore-first element)))))))
483                                      
484
485 |#
486 ;; EOF
Note: See TracBrowser for help on using the browser.