Update of /project/cl-store/cvsroot/cl-store
In directory common-lisp.net:/tmp/cvs-serv11891
Modified Files:
ChangeLog backends.lisp circularities.lisp cl-store.asd
default-backend.lisp package.lisp plumbing.lisp tests.lisp
utils.lisp
Log Message:
Changelog 2005-02-11
Date: Fri Feb 11 13:00:31 2005
Author: sross
Index: cl-store/ChangeLog
diff -u cl-store/ChangeLog:1.19 cl-store/ChangeLog:1.20
--- cl-store/ChangeLog:1.19 Thu Feb 3 12:55:13 2005
+++ cl-store/ChangeLog Fri Feb 11 13:00:30 2005
@@ -1,3 +1,29 @@
+2005-02-11 Sean Ross <sross(a)common-lisp.net>
+ New Magic Number for cl-store-backend.
+ * default-backend.lisp, acl/custom.lisp, lispworks/custom.lisp
+ * sbcl/custom.lisp, cmucl/custom.lisp:
+ Changed storing of floats to be compatible between implementations
+ while ensuring that NaN floats and friends are still serializable.
+ * backends.lisp, plumbing.lisp:
+ Added concept of backend designators which can be a
+ symbol (the backend name) or the backend itself. These are
+ acceptable replacements for a backend object
+ to store, restore and with-backend.
+ Completely changed argument order for generic functions
+ to ensure that backends are the first argument.
+ * ecl/mop.lisp: Added support for ecl.
+ * plumbing.lisp: Removed multiple-value-store (I don't really
+ see the point of it).
+ * backends.lisp: Changed the working of object restoration
+ from functions in a hash-table (restorer-funs of a backend)
+ to generic functions specialized on backend and a symbol,
+ removed find-function-for-type.
+ * plumbing.lisp: Changed the handling of the stream-type
+ of backends to be any legal type designator since it's
+ only used when opening files.
+ * backends.lisp: Both defstore-? and defrestore-?
+ can take an optional qualifer argument.
+
2005-02-03 Sean Ross <sross(a)common-lisp.net>
* default-backend.lisp: Fixed hash-table restoration,
it no longer assumes that the result of hash-table-test
@@ -10,7 +36,7 @@
argument-precedence-order from various gf's, added the
start of support for ecl, renamed fix-clisp.lisp file to
mop.lisp, and changed resolving-object and setting
- to use delays allowing get-setf-place and *postfix-setter*
+ to use delays allowing get-setf-place and *postfix-setters*
to be removed.
2004-12-02 Sean Ross <sross(a)common-lisp.net>
@@ -151,7 +177,7 @@
2004-05-21 Sean Ross <sross(a)common-lisp.net>
* store.lisp, fix-clisp.lisp, circularities.lisp, package.lisp,
- tests.lisp, utils.lisp, cl-store.asd:
+ * tests.lisp, utils.lisp, cl-store.asd:
Added ability to specify the type code of an object
when using defstore. Added code to autogenerate the
accessor methods for CLISP when restoring classes.
Index: cl-store/backends.lisp
diff -u cl-store/backends.lisp:1.7 cl-store/backends.lisp:1.8
--- cl-store/backends.lisp:1.7 Tue Feb 1 09:27:26 2005
+++ cl-store/backends.lisp Fri Feb 11 13:00:31 2005
@@ -7,8 +7,6 @@
;; in default-backend.lisp and xml-backend.lisp
(in-package :cl-store)
-;(declaim (optimize (speed 3) (safety 1) (debug 0)))
-
(defun required-arg (name)
(error "~A is a required argument" name))
@@ -19,103 +17,93 @@
(old-magic-numbers :accessor old-magic-numbers :initarg :old-magic-numbers
:type integer)
(stream-type :accessor stream-type :initarg :stream-type :type symbol
- :initform (required-arg "stream-type"))
- (restorer-funs :accessor restorer-funs :initform (make-hash-table)
- :initarg :restorer-funs :type hash-table))
+ :initform (required-arg "stream-type")))
(:documentation "Core class which custom backends must extend"))
+(deftype backend-designator ()
+ `(or symbol backend))
+
(defparameter *registered-backends* nil
"An assoc list mapping backend-names to the backend objects")
-(defun mkstr (&rest args)
- (with-output-to-string (s)
- (dolist (x args)
- (princ x s))))
-
-(defun symbolicate (&rest syms)
- "Concatenate all symbol names into one big symbol"
- (values (intern (apply #'mkstr syms))))
+(defun find-backend (name)
+ (declare (type symbol name))
+ "Return backup called NAME or NIL if not found."
+ (cdr (assoc name *registered-backends*)))
+
+(defun backend-designator->backend (designator)
+ (check-type designator backend-designator)
+ (etypecase designator
+ (symbol (or (find-backend designator)
+ (error "~A does not designate a backend." designator)))
+ (backend designator)))
-(defun get-store-macro (name class-name)
+(defun get-store-macro (name)
"Return the defstore-? macro which will be used by a custom backend"
(let ((macro-name (symbolicate 'defstore- name)))
- `(defmacro ,macro-name ((var type stream &key qualifier)
+ `(defmacro ,macro-name ((var type stream &optional qualifier)
&body body)
- `(defmethod internal-store-object ,@(if qualifier (list qualifier) nil)
- ((,var ,type) ,stream (backend ,',class-name))
- ,(format nil "Definition for storing an object of type ~A with ~
-backend ~A" type ',name)
- ,@body))))
+ (with-gensyms (gbackend)
+ `(defmethod internal-store-object ,@(if qualifier (list qualifier) nil)
+ ((,gbackend ,',name) (,var ,type) ,stream)
+ ,(format nil "Definition for storing an object of type ~A with ~
+ backend ~A" type ',name)
+ (declare (ignorable ,gbackend))
+ ,@body)))))
(defun get-restore-macro (name)
"Return the defrestore-? macro which will be used by a custom backend"
(let ((macro-name (symbolicate 'defrestore- name)))
- `(defmacro ,macro-name ((type place) &body body)
- (let ((fn-name (gensym (symbol-name (symbolicate ',name '- type)))))
- `(flet ((,fn-name (,place)
- ,@body))
- (let* ((backend (find-backend ',',name))
- (restorers (restorer-funs backend)))
- (when (gethash ',type restorers)
- (warn "Redefining restorer ~A for backend ~(~A~)"
- ',type (name backend)))
- (setf (gethash ',type restorers)
- #',fn-name)))))))
-
-(defun real-stream-type (value)
- (ecase value
- (char 'character)
- (binary 'integer)))
+ `(defmacro ,macro-name ((type place &optional qualifier) &body body)
+ (with-gensyms (gbackend gtype)
+ `(defmethod internal-restore-object ,@(if qualifier (list qualifier) nil)
+ ((,gbackend ,',name) (,gtype (eql ',type)) (,place t))
+ (declare (ignorable ,gbackend ,gtype))
+ ,@body)))))
(defun register-backend (name class magic-number stream-type old-magic-numbers)
(declare (type symbol name))
- (assert (member stream-type '(char binary)))
(let ((instance (make-instance class
:name name
:magic-number magic-number
:old-magic-numbers old-magic-numbers
- :stream-type (real-stream-type stream-type))))
+ :stream-type stream-type)))
(if (assoc name *registered-backends*)
- (cerror "Redefine backend" "Backend is already defined ~A" name)
+ (cerror "Redefine backend" "Backend ~A is already defined." name)
(push (cons name instance) *registered-backends*))
instance))
-(defun find-backend (name)
- (declare (type symbol name))
- "Return backup called NAME or NIL if not found."
- (cdr (assoc name *registered-backends*)))
(defun get-class-form (name fields extends)
- `(defclass ,name (,extends)
+ `(defclass ,name ,extends
,fields
(:documentation ,(format nil "Autogenerated cl-store class for backend ~(~A~)."
name))))
-(defmacro defbackend (name &key (stream-type (required-arg "stream-type"))
- (magic-number nil) fields (extends 'backend)
- (old-magic-numbers nil))
+(defmacro defbackend (name &key (stream-type ''(unsigned-byte 8))
+ (magic-number nil) fields (extends '(backend))
+ (old-magic-numbers nil))
"Defines a new backend called NAME. Stream type must be either 'char or 'binary.
FIELDS is a list of legal slots for defclass. MAGIC-NUMBER, when supplied, will
be written down stream as verification and checked on restoration.
EXTENDS is a class to extend, which must be backend or a class which extends
backend"
(assert (symbolp name))
- (let ((class-name (symbolicate name '-backend)))
- `(eval-when (:compile-toplevel :load-toplevel :execute)
- (prog2
- ,(get-class-form class-name fields extends)
- (register-backend ',name ',class-name ,magic-number
- ,stream-type ',old-magic-numbers)
- ,(get-store-macro name class-name)
- ,(get-restore-macro name)))))
-
+ `(eval-when (:load-toplevel :execute)
+ (eval-when (:compile-toplevel :load-toplevel :execute)
+ ,(get-class-form name fields extends)
+ ,(get-store-macro name)
+ ,(get-restore-macro name))
+ (register-backend ',name ',name ,magic-number
+ ,stream-type ',old-magic-numbers)))
(defmacro with-backend (backend &body body)
"Run BODY with *default-backend* bound to BACKEND"
- `(let ((*default-backend* (or (and (typep ,backend 'backend)
- ,backend)
- (error "~A is not a legal backend"
- ,backend))))
- ,@body))
+ (with-gensyms (gbackend)
+ `(let* ((,gbackend ,backend)
+ (*default-backend* (or (backend-designator->backend ,gbackend)
+ (error "~A is not a legal backend"
+ ,gbackend))))
+ ,@body)))
-;; EOF
\ No newline at end of file
+;; EOF
Index: cl-store/circularities.lisp
diff -u cl-store/circularities.lisp:1.14 cl-store/circularities.lisp:1.15
--- cl-store/circularities.lisp:1.14 Tue Feb 1 09:27:26 2005
+++ cl-store/circularities.lisp Fri Feb 11 13:00:31 2005
@@ -19,8 +19,6 @@
;; programs according to the Hyperspec(notes in EQ).
(in-package :cl-store)
-;(declaim (optimize (speed 3) (safety 1) (debug 1)))
-
(defvar *check-for-circs* t)
@@ -42,14 +40,16 @@
"Resolve the possible referring object retrieved by GET and
set it into PLACE. Only usable within a resolving-object form."
(declare (ignore place get))
- (error "setting can only be used inside a resolving-object form."))
+ #+ecl nil
+ #-ecl (error "setting can only be used inside a resolving-object form."))
(defmacro setting-hash (getting-key getting-value)
"Insert the value retrieved by GETTING-VALUE with the key
retrieved by GETTING-KEY, resolving possible circularities.
Only usable within a resolving-object form."
(declare (ignore getting-key getting-value))
- (error "setting-hash can only be used inside a resolving-object form."))
+ #+ecl nil
+ #-ecl (error "setting-hash can only be used inside a resolving-object form."))
(defmacro resolving-object ((var create) &body body)
"Execute body attempting to resolve circularities found in
@@ -76,8 +76,7 @@
,@body
,var))))
-(defstruct referrer
- val)
+(defstruct referrer val)
(defun referred-value (referrer hash)
"Return the value REFERRER is meant to be by looking in HASH."
@@ -100,7 +99,7 @@
(let ((*stored-counter* 0)
(*stored-values* (make-hash-table :test #'eq :size *store-hash-size*)))
(store-backend-code backend place)
- (backend-store-object obj place backend)
+ (backend-store-object backend obj place)
obj))
(defun seen (obj)
@@ -122,9 +121,9 @@
"Do we need to check if this object has been stored before?"
(not (typep obj 'not-circ)))
-(defgeneric store-referrer (obj place backend)
+(defgeneric store-referrer (backend obj place)
(:documentation "Store the number OBJ into PLACE as a referrer for BACKEND.")
- (:method ((obj t) (place t) (backend resolving-backend))
+ (:method ((backend resolving-backend) (obj t) (place t))
(store-error "store-referrer must be specialized for backend ~(~A~)."
(name backend))))
@@ -136,12 +135,12 @@
(update-seen obj))
nil))
-(defmethod backend-store-object ((obj t) (place t) (backend resolving-backend))
+(defmethod backend-store-object ((backend resolving-backend) (obj t) (place t))
"Store object if we have not seen this object before, otherwise retrieve
the referrer object for it and store that using store-referrer."
(aif (and *check-for-circs* (get-ref obj))
- (store-referrer it place backend)
- (internal-store-object obj place backend)))
+ (store-referrer backend it place)
+ (internal-store-object backend obj place)))
;; Restoration.
(declaim (type (or fixnum null) *restore-counter*))
@@ -158,53 +157,36 @@
(*restored-values* (make-hash-table :test #'eq :size *restore-hash-size*)))
(check-magic-number backend place)
(multiple-value-prog1
- (backend-restore-object place backend)
+ (backend-restore-object backend place)
(dolist (fn *need-to-fix*)
(force fn)))))
(defun update-restored (spot val)
(setf (gethash spot *restored-values*) val))
-(defun all-vals (reader place)
- (declare (type function reader))
- (multiple-value-list (funcall reader place)))
-
-(defun get-vals (reader place)
- (declare (type function reader))
- (mapcar #'new-val (all-vals reader place)))
-
-(defun handle-values (reader place)
+(defun handle-normal (backend reader place)
(let ((spot (incf *restore-counter*))
- (vals (get-vals reader place)))
- (update-restored spot (car vals))
- (values-list vals)))
-
-(defun call-it (reader place)
- (funcall (the function reader) place))
-
-(defun handle-normal (reader place)
- (let ((spot (incf *restore-counter*))
- (vals (new-val (call-it reader place))))
+ (vals (new-val (internal-restore-object backend reader place))))
(update-restored spot vals)
vals))
+(defgeneric referrerp (backend reader))
+
(defun handle-restore (place backend)
- (multiple-value-bind (reader sym) (find-function-for-type place backend)
- (declare (type function reader) (type symbol sym))
- (cond ((eql sym 'values-object)
- (handle-values reader place))
- ((eql sym 'referrer)
+ (multiple-value-bind (reader) (get-next-reader backend place)
+ (declare (type symbol reader))
+ (cond ((referrerp backend reader)
(incf *restore-counter*)
- (new-val (call-it reader place)))
- ((not (int-sym-or-char-p backend sym))
- (handle-normal reader place))
- (t (new-val (funcall reader place))))))
+ (new-val (internal-restore-object backend reader place)))
+ ((not (int-sym-or-char-p backend reader))
+ (handle-normal backend reader place))
+ (t (new-val (internal-restore-object backend reader place))))))
-(defmethod backend-restore-object ((place stream) (backend resolving-backend))
+(defmethod backend-restore-object ((backend resolving-backend) (place stream))
"Retrieve a object from PLACE, does housekeeping for circularity fixing."
(if *check-for-circs*
(handle-restore place backend)
- (funcall (the function (find-function-for-type place backend)) place)))
+ (call-next-method)))
(defgeneric int-sym-or-char-p (backend fn)
(:method ((backend backend) (fn symbol))
@@ -220,5 +202,4 @@
val)
val))
-
-;; EOF
\ No newline at end of file
+;; EOF
Index: cl-store/cl-store.asd
diff -u cl-store/cl-store.asd:1.18 cl-store/cl-store.asd:1.19
--- cl-store/cl-store.asd:1.18 Thu Feb 3 12:59:12 2005
+++ cl-store/cl-store.asd Fri Feb 11 13:00:31 2005
@@ -40,7 +40,7 @@
:name "CL-STORE"
:author "Sean Ross <sdr(a)jhb.ucs.co.za>"
:maintainer "Sean Ross <sdr(a)jhb.ucs.co.za>"
- :version "0.4.6"
+ :version "0.4.13"
:description "Serialization package"
:long-description "Portable CL Package to serialize data types"
:licence "MIT"
@@ -65,9 +65,7 @@
:components ((:file "tests")))
(defmethod perform ((op test-op) (sys (eql (find-system :cl-store-tests))))
- (or (funcall (find-symbol "RUN-TESTS" "CL-STORE-TESTS")
- (symbol-value (find-symbol "*CL-STORE-BACKEND*" "CL-STORE")))
- (error "Test-op Failed.")))
-
+ (funcall (find-symbol "RUN-TESTS" "CL-STORE-TESTS")
+ (find-symbol "CL-STORE" "CL-STORE")))
;; EOF
Index: cl-store/default-backend.lisp
diff -u cl-store/default-backend.lisp:1.17 cl-store/default-backend.lisp:1.18
--- cl-store/default-backend.lisp:1.17 Thu Feb 3 12:55:13 2005
+++ cl-store/default-backend.lisp Fri Feb 11 13:00:31 2005
@@ -2,66 +2,68 @@
;; See the file LICENCE for licence information.
;; The cl-store backend.
-
(in-package :cl-store)
-(eval-when (:compile-toplevel :load-toplevel :execute)
- (defvar *cl-store-backend*
- (defbackend cl-store :magic-number 1886611820
- :stream-type 'binary
- :old-magic-numbers (1912923 1886611788 1347635532
- 1884506444 1347643724 1349732684)
- :extends resolving-backend
- :fields ((restorers :accessor restorers
- :initform (make-hash-table :size 100)))))
- (defun register-code (code name &optional (errorp t))
- (aif (and (gethash code (restorers *cl-store-backend*)) errorp)
- (error "Code ~A is already defined for ~A." code name)
- (setf (gethash code (restorers *cl-store-backend*))
- name))
- code))
+(defbackend cl-store :magic-number 1349740876
+ :stream-type '(unsigned-byte 8)
+ :old-magic-numbers (1912923 1886611788 1347635532 1886611820
+ 1884506444 1347643724 1349732684)
+ :extends (resolving-backend)
+ :fields ((restorers :accessor restorers
+ :initform (make-hash-table :size 100))))
+
+(defun register-code (code name &optional (errorp t))
+ (aif (and (gethash code (restorers (find-backend 'cl-store))) errorp)
+ (error "Code ~A is already defined for ~A." code name)
+ (setf (gethash code (restorers (find-backend 'cl-store)))
+ name))
+ code)
;; Type code constants
-(defconstant +referrer-code+ (register-code 1 'referrer nil))
-(defconstant +values-code+ (register-code 2 'values-object nil))
-(defconstant +unicode-string-code+ (register-code 3 'unicode-string nil))
-(defconstant +integer-code+ (register-code 4 'integer nil))
-(defconstant +simple-string-code+ (register-code 5 'simple-string nil))
-(defconstant +float-code+ (register-code 6 'float nil))
-(defconstant +ratio-code+ (register-code 7 'ratio nil))
-(defconstant +character-code+ (register-code 8 'character nil))
-(defconstant +complex-code+ (register-code 9 'complex nil))
-(defconstant +symbol-code+ (register-code 10 'symbol nil))
-(defconstant +cons-code+ (register-code 11 'cons nil))
-(defconstant +pathname-code+ (register-code 12 'pathname nil))
-(defconstant +hash-table-code+ (register-code 13 'hash-table nil))
-(defconstant +standard-object-code+ (register-code 14 'standard-object nil))
-(defconstant +condition-code+ (register-code 15 'condition nil))
-(defconstant +structure-object-code+ (register-code 16 'structure-object nil))
-(defconstant +standard-class-code+ (register-code 17 'standard-class nil))
-(defconstant +built-in-class-code+ (register-code 18 'built-in-class nil))
-(defconstant +array-code+ (register-code 19 'array nil))
-(defconstant +simple-vector-code+ (register-code 20 'simple-vector nil))
-(defconstant +package-code+ (register-code 21 'package nil))
+(defvar +referrer-code+ (register-code 1 'referrer nil))
+;(defvar +values-code+ (register-code 2 'values-object nil))
+(defvar +unicode-string-code+ (register-code 3 'unicode-string nil))
+(defvar +integer-code+ (register-code 4 'integer nil))
+(defvar +simple-string-code+ (register-code 5 'simple-string nil))
+(defvar +float-code+ (register-code 6 'float nil))
+(defvar +ratio-code+ (register-code 7 'ratio nil))
+(defvar +character-code+ (register-code 8 'character nil))
+(defvar +complex-code+ (register-code 9 'complex nil))
+(defvar +symbol-code+ (register-code 10 'symbol nil))
+(defvar +cons-code+ (register-code 11 'cons nil))
+(defvar +pathname-code+ (register-code 12 'pathname nil))
+(defvar +hash-table-code+ (register-code 13 'hash-table nil))
+(defvar +standard-object-code+ (register-code 14 'standard-object nil))
+(defvar +condition-code+ (register-code 15 'condition nil))
+(defvar +structure-object-code+ (register-code 16 'structure-object nil))
+(defvar +standard-class-code+ (register-code 17 'standard-class nil))
+(defvar +built-in-class-code+ (register-code 18 'built-in-class nil))
+(defvar +array-code+ (register-code 19 'array nil))
+(defvar +simple-vector-code+ (register-code 20 'simple-vector nil))
+(defvar +package-code+ (register-code 21 'package nil))
;; Used by lispworks
-(defconstant +positive-infinity-code+ (register-code 22 'positive-infinity nil))
-(defconstant +negative-infinity-code+ (register-code 23 'negative-infinity nil))
+(defvar +positive-infinity-code+ (register-code 22 'positive-infinity nil))
+(defvar +negative-infinity-code+ (register-code 23 'negative-infinity nil))
;; new storing for 32 bit ints
-(defconstant +32-bit-integer-code+ (register-code 24 '32-bit-integer nil))
+(defvar +32-bit-integer-code+ (register-code 24 '32-bit-integer nil))
;; More for lispworks
-(defconstant +float-nan-code+ (register-code 25 'nan-float nil))
+(defvar +float-nan-code+ (register-code 25 'nan-float nil))
-(defconstant +function-code+ (register-code 26 'function nil))
-(defconstant +gf-code+ (register-code 27 'generic-function nil))
+(defvar +function-code+ (register-code 26 'function nil))
+(defvar +gf-code+ (register-code 27 'generic-function nil))
;; Used by SBCL and CMUCL.
-(defconstant +structure-class-code+ (register-code 28 'structure-class nil))
-(defconstant +struct-def-code+ (register-code 29 'struct-def nil))
+(defvar +structure-class-code+ (register-code 28 'structure-class nil))
+(defvar +struct-def-code+ (register-code 29 'struct-def nil))
+
+(defvar +gensym-code+ (register-code 30 'gensym nil))
-(defconstant +gensym-code+ (register-code 30 'gensym nil))
+(defvar +positive-double-infinity-code+ (register-code 31 'positive-double-infinity nil))
+(defvar +negative-double-infinity-code+ (register-code 32 'negative-double-infinity nil))
+(defvar +float-double-nan-code+ (register-code 33 'float-double-nan nil))
;; setups for type code mapping
(defun output-type-code (code stream)
@@ -71,24 +73,25 @@
(defun read-type-code (stream)
(read-byte stream))
-(defvar *restorers* (restorers *cl-store-backend*))
+(defmethod referrerp ((backend cl-store) (reader t))
+ (eql reader 'referrer))
+
+(defvar *restorers* (restorers (find-backend 'cl-store)))
+
;; get-next-reader needs to return a symbol which will be used by the
;; backend to lookup the function that was defined by
;; defrestore-cl-store to restore it, or nil if not found.
-
(defun lookup-code (code)
(gethash code *restorers*))
-(defmethod get-next-reader ((stream stream) (backend cl-store-backend))
- (declare (ignore backend))
+(defmethod get-next-reader ((backend cl-store) (stream stream))
(let ((type-code (read-type-code stream)))
- (or (lookup-code type-code) ;(gethash type-code *restorers*)
- (values nil (format nil "Type ~A" type-code)))))
+ (or (lookup-code type-code)
+ (error "Type code ~A is not registered." type-code))))
;; referrer, Required for a resolving backend
-(defmethod store-referrer (ref stream (backend cl-store-backend))
- (declare (ignore backend))
+(defmethod store-referrer ((backend cl-store) (ref t) (stream t))
(output-type-code +referrer-code+ stream)
(dump-int ref stream))
@@ -101,8 +104,7 @@
;; so we we have a little optimization for it
;; We need this for circularity stuff.
-(defmethod int-sym-or-char-p ((backend cl-store-backend) (fn symbol))
- (declare (ignore backend))
+(defmethod int-sym-or-char-p ((backend cl-store) (fn symbol))
(find fn '(integer character 32-bit-integer symbol)))
(defstore-cl-store (obj integer stream)
@@ -162,29 +164,63 @@
(- result)
result)))
-;; Floats
-;; SBCL and CMUCL use a different mechanism for dealing
-;; with floats which supports infinities.
-;; Lispworks uses a slightly different version as well
-;; manually handling negative and positive infinity
-;; Allegro uses excl:double-float-to-shorts and friends
-#-(or lispworks cmu sbcl allegro)
+;; Floats (*special-floats* are setup in the custom.lisp files)
+(defvar *special-floats* nil)
+
(defstore-cl-store (obj float stream)
- (output-type-code +float-code+ stream)
- (multiple-value-bind (significand exponent sign)
- (integer-decode-float obj)
- (write-byte (float-type obj) stream)
- (store-object significand stream)
- (store-object exponent stream)
- (store-object sign stream)))
+ (block body
+ (let (significand exponent sign)
+ (handler-bind ((simple-error
+ #'(lambda (err)
+ (declare (ignore err))
+ (awhen (cdr (assoc obj *special-floats*))
+ (output-type-code it stream)
+ (return-from body)))))
+ (multiple-value-setq (significand exponent sign)
+ (integer-decode-float obj))
+ (output-type-code +float-code+ stream)
+ (write-byte (float-type obj) stream)
+ (store-object significand stream)
+ (store-object (float-radix obj) stream)
+ (store-object exponent stream)
+ (store-object sign stream)))))
-#-(or cmu sbcl allegro)
(defrestore-cl-store (float stream)
(float (* (get-float-type (read-byte stream))
(* (restore-object stream)
- (expt 2 (restore-object stream)))
+ (expt (restore-object stream)
+ (restore-object stream)))
(restore-object stream))))
+(defun handle-special-float (code name)
+ (aif (rassoc code *special-floats*)
+ (car it)
+ (store-error "~A Cannot be represented." name)))
+
+(defrestore-cl-store (negative-infinity stream)
+ (handle-special-float +negative-infinity-code+
+ "Single Float Negative Infinity"))
+
+(defrestore-cl-store (positive-infinity stream)
+ (handle-special-float +positive-infinity-code+
+ "Single Float Positive Infinity"))
+
+(defrestore-cl-store (nan-float stream)
+ (handle-special-float +float-nan-code+ "Single Float NaN"))
+
+(defrestore-cl-store (negative-double-infinity stream)
+ (handle-special-float +negative-double-infinity-code+
+ "Double Float Negative Infinity"))
+
+(defrestore-cl-store (positive-double-infinity stream)
+ (handle-special-float +positive-double-infinity-code+
+ "Double Float Positive Infinity"))
+
+(defrestore-cl-store (float-double-nan stream)
+ (handle-special-float +float-double-nan-code+
+ "Double Float NaN"))
+
+
;; ratio
(defstore-cl-store (obj ratio stream)
(output-type-code +ratio-code+ stream)
@@ -231,7 +267,7 @@
(defrestore-cl-store (gensym stream)
(make-symbol (restore-object stream)))
-
+
;; lists
(defstore-cl-store (obj cons stream)
(output-type-code +cons-code+ stream)
@@ -245,6 +281,7 @@
(setting (car x) (restore-object stream))
(setting (cdr x) (restore-object stream))))
+
;; pathnames
(defstore-cl-store (obj pathname stream)
(output-type-code +pathname-code+ stream)
@@ -297,7 +334,6 @@
(restore-object stream))))
hash)))
-
;; Object and Conditions
(defun store-type-object (obj stream)
(let* ((all-slots (remove-if-not (lambda (x)
@@ -321,7 +357,6 @@
(output-type-code +standard-object-code+ stream)
(store-type-object obj stream))
-#-lispworks
(defstore-cl-store (obj condition stream)
(output-type-code +condition-code+ stream)
(store-type-object obj stream))
@@ -339,11 +374,10 @@
(setting (slot-value obj slot-name) (restore-object stream)))))
new-instance))
-#-lispworks
-(defrestore-cl-store (condition stream)
+(defrestore-cl-store (standard-object stream)
(restore-type-object stream))
-(defrestore-cl-store (standard-object stream)
+(defrestore-cl-store (condition stream)
(restore-type-object stream))
@@ -377,12 +411,14 @@
#+clisp (add-methods-for-class class slots)))))
;; built in classes
+
(defstore-cl-store (obj built-in-class stream)
(output-type-code +built-in-class-code+ stream)
(store-object (class-name obj) stream))
+#-ecl ;; for some reason this doesn't work with ecl
(defmethod internal-store-object ((obj (eql (find-class 'hash-table))) stream
- (backend cl-store-backend))
+ (backend cl-store))
(output-type-code +built-in-class-code+ stream)
(store-object 'cl:hash-table stream))
@@ -505,17 +541,6 @@
(find-package (restore-object stream)))
-;; multiple values
-
-(defstore-cl-store (obj values-object stream)
- (output-type-code +values-code+ stream)
- (store-object (vals obj) stream))
-
-(defrestore-cl-store (values-object stream)
- (apply #'values (restore-object stream)))
-
-
-
;; Function storing hack.
;; This just stores the function name if we can find it
;; or signal a store-error.
@@ -570,6 +595,7 @@
(defrestore-cl-store (generic-function stream)
(fdefinition (restore-object stream)))
+
(setf *default-backend* (find-backend 'cl-store))
Index: cl-store/package.lisp
diff -u cl-store/package.lisp:1.16 cl-store/package.lisp:1.17
--- cl-store/package.lisp:1.16 Tue Feb 1 09:27:26 2005
+++ cl-store/package.lisp Fri Feb 11 13:00:31 2005
@@ -1,33 +1,28 @@
;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
;; See the file LICENCE for licence information.
-
+(in-package :cl-store.system)
(defpackage #:cl-store
(:use #:cl)
- (:export #:backend #:magic-number #:stream-type #:restorer-funs
+ (:export #:backend #:magic-number #:stream-type
#:restorers #:resolving-backend #:find-backend #:defbackend
#:*restore-counter* #:*need-to-fix* #:*restored-values*
#:with-backend #:fix-circularities #:*default-backend*
- #:*cl-store-backend* #:*current-backend* #:*store-class-slots*
+ #:*current-backend* #:*store-class-slots*
#:*nuke-existing-classes* #:*store-class-superclasses*
#:cl-store-error #:store-error #:restore-error #:store
#:restore #:backend-store #:store-backend-code #:store-object
#:backend-store-object #:get-class-details #:get-array-values
- #:restore #:backend-restore
+ #:restore #:backend-restore #:cl-store #:referrerp
#:check-magic-number #:get-next-reader #:int-sym-or-char-p
#:restore-object #:backend-restore-object
#:defstore-cl-store #:defrestore-cl-store #:register-code
#:output-type-code #:store-referrer #:resolving-object
#:internal-store-object #:setting #:simple-standard-string
- #:float-type #:get-float-type #:compute-slots
- #:slot-definition-allocation #:slot-definition-name
- #:slot-definition-type #:slot-definition-initargs
- #:slot-definition-readers #:slot-definition-writers
- #:class-direct-superclasses #:class-direct-slots
- #:ensure-class #:make-referrer #:setting-hash
+ #:float-type #:get-float-type #:make-referrer #:setting-hash
#:multiple-value-store #:*postfix-setters* #:caused-by
#:store-32-bit #:read-32-bit #:*check-for-circs*
#:*store-hash-size* #:*restore-hash-size*)
-
+
#+sbcl (:import-from #:sb-mop
#:generic-function-name
#:slot-definition-name
Index: cl-store/plumbing.lisp
diff -u cl-store/plumbing.lisp:1.9 cl-store/plumbing.lisp:1.10
--- cl-store/plumbing.lisp:1.9 Tue Feb 1 09:27:26 2005
+++ cl-store/plumbing.lisp Fri Feb 11 13:00:31 2005
@@ -53,25 +53,21 @@
(error 'restore-error :format-string format-string :format-args args))
-
-
;; entry points
(defun store-to-file (obj place backend)
(declare (type backend backend))
- (let* ((backend-type (stream-type backend))
- (element-type (ecase backend-type
- (character 'character)
- (integer '(unsigned-byte 8)))))
+ (let* ((element-type (stream-type backend)))
(with-open-file (s place :element-type element-type
:direction :output :if-exists :supersede)
(backend-store backend s obj))))
-(defgeneric store (obj place &optional backend)
+(defgeneric store (obj place &optional designator)
(:documentation "Entry Point for storing objects.")
- (:method ((obj t) (place t) &optional (backend *default-backend*))
+ (:method ((obj t) (place t) &optional (designator *default-backend*))
"Store OBJ into Stream PLACE using backend BACKEND."
- (let ((*current-backend* backend)
- (*read-eval* nil))
+ (let* ((backend (backend-designator->backend designator))
+ (*current-backend* backend)
+ (*read-eval* nil))
(handler-bind ((error (lambda (c)
(signal (make-condition 'store-error
:caused-by c)))))
@@ -104,20 +100,20 @@
(defun store-object (obj stream &optional (backend *current-backend*))
"Store OBJ into STREAM. Not meant to be overridden,
use backend-store-object instead"
- (backend-store-object obj stream backend))
+ (backend-store-object backend obj stream))
-(defgeneric backend-store-object (obj stream backend)
+(defgeneric backend-store-object (backend obj stream)
(:documentation
"Wrapped by store-object, override this to do custom storing
(see circularities.lisp for an example).")
- (:method ((obj t) (stream t) (backend backend))
+ (:method ((backend backend) (obj t) (stream t))
"The default, just calls internal-store-object."
- (internal-store-object obj stream backend)))
+ (internal-store-object backend obj stream)))
-(defgeneric internal-store-object (obj place backend)
+(defgeneric internal-store-object (backend obj place)
(:documentation "Method which is specialized by defstore-? macros.")
- (:method ((obj t) (place t) (backend backend))
+ (:method ((backend backend) (obj t) (place t))
"If call falls back here then OBJ cannot be serialized with BACKEND."
(store-error "Cannot store objects of type ~A with backend ~(~A~)."
(type-of obj) (name backend))))
@@ -127,10 +123,11 @@
(:documentation
"Restore and object FROM PLACE using BACKEND. Not meant to be
overridden, use backend-restore instead")
- (:method (place &optional (backend *default-backend*))
+ (:method (place &optional (designator *default-backend*))
"Entry point for restoring objects (setfable)."
- (let ((*current-backend* backend)
- (*read-eval* nil))
+ (let* ((backend (backend-designator->backend designator))
+ (*current-backend* backend)
+ (*read-eval* nil))
(handler-bind ((error (lambda (c)
(signal (make-condition 'restore-error
:caused-by c)))))
@@ -143,7 +140,7 @@
"Restore the object found in stream PLACE using backend BACKEND.
Checks the magic-number and invokes backend-restore-object"
(check-magic-number backend place)
- (backend-restore-object place backend))
+ (backend-restore-object backend place))
(:method ((backend backend) (place string))
"Restore the object found in file designator PLACE using backend BACKEND."
(restore-from-file place backend))
@@ -152,10 +149,7 @@
(restore-from-file place backend)))
(defun restore-from-file (place backend)
- (let* ((backend-type (stream-type backend))
- (element-type (ecase backend-type
- (character 'character)
- (integer '(unsigned-byte 8)))))
+ (let* ((element-type (stream-type backend)))
(with-open-file (s place :element-type element-type :direction :input)
(backend-restore backend s))))
@@ -164,18 +158,10 @@
(:documentation "Backends supporting multiple return values
should define a custom storer and restorer for this class"));
-(defmacro multiple-value-store (values-form place
- &optional (backend '*default-backend*))
- "Store all values returned from VALUES-FORM into PLACE"
- `(let ((vals (multiple-value-list ,values-form)))
- (store (make-instance 'values-object :vals vals)
- ,place ,backend)
- (apply #'values vals)))
-
(defun (setf restore) (new-val place)
(store new-val place))
-(defgeneric check-magic-number (stream backend)
+(defgeneric check-magic-number (backend stream)
(:method ((backend backend) (stream t))
(let ((magic-number (magic-number backend)))
(declare (type (or null ub32) magic-number))
@@ -195,47 +181,33 @@
(defun lookup-reader (val readers)
(gethash val readers))
-(defgeneric get-next-reader (place backend)
+(defgeneric get-next-reader (backend place)
(:documentation
"Method which must be specialized for BACKEND to return
the next function to restore an object from PLACE.
If no reader is found return a second value which will be included
in the error.")
- (:method ((place t) (backend backend))
+ (:method ((backend backend) (place t))
+ (declare (ignore place))
"The default, throw an error."
(restore-error "get-next-reader must be specialized for backend ~(~A~)."
(name backend))))
-(defun find-function-for-type (place backend)
- (declare (type backend backend))
-;; (:documentation
-;; "Return a function registered with defrestore-? which knows
-;; how to retrieve an object from PLACE, uses get-next-reader.")
-;; (:method ((place t) (backend backend))
- (multiple-value-bind (val info) (get-next-reader place backend)
- (let ((reader (lookup-reader val (restorer-funs backend))))
- (cond ((and val reader) (values reader val))
- ((not val)
- (restore-error "~A is not registered with backend ~(~A~)."
- (or info "Unknown Type") (name backend)))
- ((not reader)
- (restore-error "No restorer defined for ~A in backend ~(~A~)."
- val (name backend)))))))
-
;; Wrapper for backend-restore-object so we don't have to pass
;; a backend object around all the time
(declaim (inline restore-object))
(defun restore-object (place &optional (backend *current-backend*))
"Restore the object in PLACE using BACKEND"
- (backend-restore-object place backend))
-
+ (backend-restore-object backend place))
-(defgeneric backend-restore-object (place backend)
+(defgeneric backend-restore-object (backend place)
(:documentation
"Find the next function to call with BACKEND and invoke it with PLACE.")
- (:method ((place t) (backend backend))
+ (:method ((backend backend) (place t))
"The default"
- (funcall (the function (find-function-for-type place backend)) place)))
+ (internal-restore-object backend (get-next-reader backend place) place)))
+
+(defgeneric internal-restore-object (backend type place))
;; EOF
Index: cl-store/tests.lisp
diff -u cl-store/tests.lisp:1.13 cl-store/tests.lisp:1.14
--- cl-store/tests.lisp:1.13 Tue Feb 1 09:27:26 2005
+++ cl-store/tests.lisp Fri Feb 11 13:00:31 2005
@@ -172,15 +172,20 @@
;; hash tables
+; for some reason (make-hash-table) is not equalp
+; to (make-hash-table) with ecl.
+
+#-ecl
(deftestit hash.1 (make-hash-table))
-(deftestit hash.2
- (let ((val #.(let ((in (make-hash-table :test #'equal
+#-ecl
+(defvar *hash* (let ((in (make-hash-table :test #'equal
:rehash-threshold 0.4 :size 20
:rehash-size 40)))
(dotimes (x 1000) (setf (gethash (format nil "~R" x) in) x))
- in)))
- val))
+ in))
+#-ecl
+(deftestit hash.2 *hash*)
;; packages
@@ -211,7 +216,7 @@
(deftest standard-object.2
(let ((val (store (make-instance 'bar
:x (list 1 "foo" 1.0)
- :y (make-hash-table :test #'equal))
+ :y #(1 2 3 4))
*test-file*)))
(let ((ret (restore *test-file*)))
(and (equalp (get-x val) (get-x ret))
@@ -467,22 +472,10 @@
t)
-(deftest values.1
- (progn (multiple-value-store (values 1 2 3) *test-file*)
- (multiple-value-list (restore *test-file*)))
- (1 2 3))
-
-(deftest values.2
- (let ((string "foo"))
- (multiple-value-store (values string string) *test-file*)
- (let ((val (multiple-value-list (restore *test-file*))))
- (eq (car val) (cadr val))))
- t)
-
(deftestit function.1 #'restores)
(deftestit function.2 #'car)
-#-(or clisp lispworks allegro openmcl)
+#-(or clisp lispworks allegro openmcl ecl)
(deftestit function.3 #'(setf car))
(deftestit gfunction.1 #'cl-store:restore)
Index: cl-store/utils.lisp
diff -u cl-store/utils.lisp:1.10 cl-store/utils.lisp:1.11
--- cl-store/utils.lisp:1.10 Thu Feb 3 12:55:13 2005
+++ cl-store/utils.lisp Fri Feb 11 13:00:31 2005
@@ -94,5 +94,13 @@
(defun kwd (name)
(values (intern (string-upcase name) :keyword)))
+(defun mkstr (&rest args)
+ (with-output-to-string (s)
+ (dolist (x args)
+ (princ x s))))
+
+(defun symbolicate (&rest syms)
+ "Concatenate all symbol names into one big symbol"
+ (values (intern (apply #'mkstr syms))))
;; EOF