[bknr-cvs] hans changed trunk/libraries/yason/encode.lisp
BKNR Commits
bknr at bknr.net
Thu Nov 27 14:13:59 UTC 2008
Revision: 4090
Author: hans
URL: http://bknr.net/trac/changeset/4090
Optimize encoder for a 100x speedup. Don't use PRINC unless you know
that you need it.
U trunk/libraries/yason/encode.lisp
Modified: trunk/libraries/yason/encode.lisp
===================================================================
--- trunk/libraries/yason/encode.lisp 2008-11-27 12:18:22 UTC (rev 4089)
+++ trunk/libraries/yason/encode.lisp 2008-11-27 14:13:59 UTC (rev 4090)
@@ -17,99 +17,100 @@
(:documentation "Encode OBJECT to STREAM in JSON format. May be
specialized by applications to perform specific rendering. STREAM
- defaults to *STANDARD-OUTPUT*.")
+ defaults to *STANDARD-OUTPUT*."))
- (:method ((object string) &optional (stream *standard-output*))
- (with-standard-output-to (stream)
- (princ #\")
- (loop
- for char across object
- do (case char
- ((#\\ #\" #\/)
- (princ #\\) (princ char))
- (#\Backspace
- (princ #\\) (princ #\b))
- (#\Page
- (princ #\\) (princ #\f))
- (#\Newline
- (princ #\\) (princ #\n))
- (#\Return
- (princ #\\) (princ #\r))
- (#\Tab
- (princ #\\) (princ #\t))
- (t
- (princ char))))
- (princ #\"))
- object)
+(defparameter *char-replacements*
+ (alexandria:plist-hash-table
+ '(#\\ "\\\\"
+ #\" "\\\""
+ #\/ "\\/"
+ #\Backspace "\\b"
+ #\Page "\\f"
+ #\Newline "\\n"
+ #\Return "\\r"
+ #\Tab "\\t")))
+
- (:method ((object rational) &optional (stream *standard-output*))
- (encode (float object) stream)
- object)
+(defmethod encode ((string string) &optional (stream *standard-output*))
+ (with-standard-output-to (stream)
+ (write-char #\")
+ (dotimes (i (length string))
+ (let* ((char (aref string i))
+ (replacement (gethash char *char-replacements*)))
+ (if replacement
+ (write-string replacement)
+ (write-char char))))
+ (write-char #\")
+ string))
- (:method ((object integer) &optional (stream *standard-output*))
- (princ object stream))
+(defmethod encode ((object rational) &optional (stream *standard-output*))
+ (encode (float object) stream)
+ object)
- (:method ((object hash-table) &optional (stream *standard-output*))
- (with-standard-output-to (stream)
- (princ #\{)
- (let (printed)
- (maphash (lambda (key value)
- (if printed
- (princ #\,)
- (setf printed t))
- (encode key stream)
- (princ #\:)
- (encode value stream))
- object))
- (princ #\}))
- object)
+(defmethod encode ((object integer) &optional (stream *standard-output*))
+ (princ object stream))
- (:method ((object vector) &optional (stream *standard-output*))
- (with-standard-output-to (stream)
- (princ #\[)
- (let (printed)
- (loop
- for value across object
- do
- (when printed
- (princ #\,))
- (setf printed t)
- (encode value stream)))
- (princ #\]))
- object)
+(defmethod encode ((object hash-table) &optional (stream *standard-output*))
+ (with-standard-output-to (stream)
+ (write-char #\{)
+ (let (printed)
+ (maphash (lambda (key value)
+ (if printed
+ (write-char #\,)
+ (setf printed t))
+ (encode key stream)
+ (write-char #\:)
+ (encode value stream))
+ object))
+ (write-char #\}))
+ object)
- (:method ((object list) &optional (stream *standard-output*))
- (with-standard-output-to (stream)
- (princ #\[)
- (let (printed)
- (dolist (value object)
- (if printed
- (princ #\,)
- (setf printed t))
- (encode value stream)))
- (princ #\]))
- object)
+(defmethod encode ((object vector) &optional (stream *standard-output*))
+ (with-standard-output-to (stream)
+ (write-char #\[)
+ (let (printed)
+ (loop
+ for value across object
+ do
+ (when printed
+ (write-char #\,))
+ (setf printed t)
+ (encode value stream)))
+ (write-char #\]))
+ object)
- (:method ((object (eql 'true)) &optional (stream *standard-output*))
- (princ "true" stream)
- object)
+(defmethod encode ((object list) &optional (stream *standard-output*))
+ (with-standard-output-to (stream)
+ (write-char #\[)
+ (let (printed)
+ (dolist (value object)
+ (if printed
+ (write-char #\,)
+ (setf printed t))
+ (encode value stream)))
+ (write-char #\]))
+ object)
- (:method ((object (eql 'false)) &optional (stream *standard-output*))
- (princ "false" stream)
- object)
+(defmethod encode ((object (eql 'true)) &optional (stream *standard-output*))
+ (write-string "true" stream)
+ object)
- (:method ((object (eql 'null)) &optional (stream *standard-output*))
- (princ "null" stream)
- object)
+(defmethod encode ((object (eql 'false)) &optional (stream *standard-output*))
+ (write-string "false" stream)
+ object)
- (:method ((object (eql t)) &optional (stream *standard-output*))
- (princ "true" stream)
- object)
+(defmethod encode ((object (eql 'null)) &optional (stream *standard-output*))
+ (write-string "null" stream)
+ object)
- (:method ((object (eql nil)) &optional (stream *standard-output*))
- (princ "null" stream)
- object))
+(defmethod encode ((object (eql t)) &optional (stream *standard-output*))
+ (write-string "true" stream)
+ object)
+(defmethod encode ((object (eql nil)) &optional (stream *standard-output*))
+ (write-string "null" stream)
+ object)
+
(defclass json-output-stream ()
((output-stream :reader output-stream
:initarg :output-stream)
@@ -119,7 +120,7 @@
(defun next-aggregate-element ()
(if (car (stack *json-output*))
- (princ (car (stack *json-output*)) (output-stream *json-output*))
+ (write-char (car (stack *json-output*)) (output-stream *json-output*))
(setf (car (stack *json-output*)) #\,)))
(defmacro with-output ((stream) &body body)
@@ -147,12 +148,12 @@
(error 'no-json-output-context))
(when (stack *json-output*)
(next-aggregate-element))
- (princ ,begin-char (output-stream *json-output*))
+ (write-char ,begin-char (output-stream *json-output*))
(push nil (stack *json-output*))
(prog1
(progn , at body)
(pop (stack *json-output*))
- (princ ,end-char (output-stream *json-output*)))))
+ (write-char ,end-char (output-stream *json-output*)))))
(defmacro with-array (() &body body)
"Open a JSON array, then run BODY. Inside the body,
@@ -188,7 +189,7 @@
type for which an ENCODE method is defined."
(next-aggregate-element)
(encode key (output-stream *json-output*))
- (princ #\: (output-stream *json-output*))
+ (write-char #\: (output-stream *json-output*))
(encode value (output-stream *json-output*))
value)
More information about the Bknr-cvs
mailing list