Browse code
Restore originial emitter interface. Whitespace cleanup (tabs to spaces).
Jason Melbye authored on 23/12/2016 23:36:12
Showing 6 changed files
Showing 6 changed files
... | ... |
@@ -8,7 +8,6 @@ |
8 | 8 |
:allocate-emitter |
9 | 9 |
:emitter-initialize |
10 | 10 |
:emitter-delete |
11 |
- :emit |
|
12 | 11 |
:set-output |
13 | 12 |
:stream-start-event-initialize |
14 | 13 |
:stream-end-event-initialize |
... | ... |
@@ -25,7 +24,12 @@ |
25 | 24 |
(:import-from :libyaml.write-handler |
26 | 25 |
:*write-handler-callback* |
27 | 26 |
:*write-handler-stream*) |
28 |
- (:export :stream-start-event |
|
27 |
+ (:export ;; Original interface |
|
28 |
+ :emit |
|
29 |
+ :emit-to-string |
|
30 |
+ :encode |
|
31 |
+ ;; libyaml based interface |
|
32 |
+ :stream-start-event |
|
29 | 33 |
:stream-end-event |
30 | 34 |
:document-start-event |
31 | 35 |
:document-end-event |
... | ... |
@@ -46,6 +50,68 @@ |
46 | 50 |
(:documentation "The YAML emitter.")) |
47 | 51 |
(in-package :yaml.emitter) |
48 | 52 |
|
53 |
+;;; Encoder functions |
|
54 |
+ |
|
55 |
+(defgeneric encode (value stream) |
|
56 |
+ (:documentation "Write the YAML corresponding to value to a stream.")) |
|
57 |
+ |
|
58 |
+(defmethod encode ((true (eql 't)) stream) |
|
59 |
+ "Encode true." |
|
60 |
+ (write-string "true" stream)) |
|
61 |
+ |
|
62 |
+(defmethod encode ((true (eql 'nil)) stream) |
|
63 |
+ "Encode false." |
|
64 |
+ (write-string "false" stream)) |
|
65 |
+ |
|
66 |
+(defmethod encode ((integer integer) stream) |
|
67 |
+ "Encode an integer." |
|
68 |
+ (princ integer stream)) |
|
69 |
+ |
|
70 |
+(defmethod encode ((float float) stream) |
|
71 |
+ "Encode a float." |
|
72 |
+ (princ float stream)) |
|
73 |
+ |
|
74 |
+(defmethod encode ((string string) stream) |
|
75 |
+ "Encode a string." |
|
76 |
+ ;; (write-string string stream) |
|
77 |
+ (format stream "~s" string)) |
|
78 |
+ |
|
79 |
+(defmethod encode ((list list) stream) |
|
80 |
+ "Encode a list." |
|
81 |
+ (write-string "[" stream) |
|
82 |
+ (loop for sublist on list do |
|
83 |
+ (encode (first sublist) stream) |
|
84 |
+ (when (rest sublist) |
|
85 |
+ (write-string ", " stream))) |
|
86 |
+ (write-string "]" stream)) |
|
87 |
+ |
|
88 |
+(defmethod encode ((vector vector) stream) |
|
89 |
+ "Encode a vector." |
|
90 |
+ (encode (loop for elem across vector collecting elem) stream)) |
|
91 |
+ |
|
92 |
+(defmethod encode ((table hash-table) stream) |
|
93 |
+ "Encode a hash table." |
|
94 |
+ (write-string "{ " stream) |
|
95 |
+ (loop for sublist on (alexandria:hash-table-keys table) do |
|
96 |
+ (let ((key (first sublist))) |
|
97 |
+ (encode key stream) |
|
98 |
+ (write-string ": " stream) |
|
99 |
+ (encode (gethash key table) stream) |
|
100 |
+ (when (rest sublist) |
|
101 |
+ (write-string ", " stream)))) |
|
102 |
+ (write-string " }" stream)) |
|
103 |
+ |
|
104 |
+;;; Interface |
|
105 |
+ |
|
106 |
+(defun emit (value stream) |
|
107 |
+ "Emit a value to a stream." |
|
108 |
+ (encode value stream)) |
|
109 |
+ |
|
110 |
+(defun emit-to-string (value) |
|
111 |
+ "Emit a value to string." |
|
112 |
+ (with-output-to-string (stream) |
|
113 |
+(emit value stream))) |
|
114 |
+ |
|
49 | 115 |
;;; Wrappers around cl-libyaml event interface with defaults and keyword args |
50 | 116 |
|
51 | 117 |
(defun stream-start-event (event &key (encoding :utf8-encoding)) |
... | ... |
@@ -141,7 +207,7 @@ |
141 | 207 |
&key version-directive |
142 | 208 |
tag-directive-start |
143 | 209 |
tag-directive-end |
144 |
- (implicit 0)) &body body) |
|
210 |
+ (implicit nil)) &body body) |
|
145 | 211 |
(declare (ignorable version-directive tag-directive-start |
146 | 212 |
tag-directive-end implicit)) |
147 | 213 |
(let ((emitter-value (gensym "EMITTER")) |
... | ... |
@@ -194,7 +260,7 @@ |
194 | 260 |
(let ((printed-value (print-scalar value))) |
195 | 261 |
(apply #'scalar-event (foreign-event emitter) |
196 | 262 |
printed-value (length printed-value) rest) |
197 |
- (emit (foreign-emitter emitter) (foreign-event emitter)))) |
|
263 |
+ (libyaml.emitter:emit (foreign-emitter emitter) (foreign-event emitter)))) |
|
198 | 264 |
|
199 | 265 |
(defgeneric print-scalar (scalar) |
200 | 266 |
(:documentation "Convert a scalar object into its printed representation")) |
... | ... |
@@ -222,7 +288,18 @@ |
222 | 288 |
(let ((*read-default-float-format* 'double-float)) |
223 | 289 |
(princ-to-string scalar))) |
224 | 290 |
|
225 |
-;;; Interface |
|
226 |
- |
|
227 | 291 |
(defgeneric emit-object (emitter obj) |
228 | 292 |
(:documentation "Emit YAML representation of obj")) |
293 |
+ |
|
294 |
+(defmethod emit-object (emitter (obj symbol)) |
|
295 |
+ (emit-scalar emitter obj)) |
|
296 |
+ |
|
297 |
+(defmethod emit-object (emitter (obj string)) |
|
298 |
+ (emit-scalar emitter obj)) |
|
299 |
+ |
|
300 |
+(defmethod emit-object (emitter (obj integer)) |
|
301 |
+ (emit-scalar emitter obj)) |
|
302 |
+ |
|
303 |
+(defmethod emit-object (emitter (obj float)) |
|
304 |
+ (emit-scalar emitter obj)) |
|
305 |
+ |
... | ... |
@@ -2,10 +2,21 @@ |
2 | 2 |
(defpackage cl-yaml |
3 | 3 |
(:use :cl) |
4 | 4 |
(:nicknames :yaml) |
5 |
+ (:import-from :yaml.parser |
|
6 |
+ :register-scalar-converter |
|
7 |
+ :register-sequence-converter |
|
8 |
+ :register-mapping-converter) |
|
9 |
+ (:import-from :yaml.emitter |
|
10 |
+ :emit-object |
|
11 |
+ :print-scalar) |
|
5 | 12 |
(:export :parse |
6 |
- ;:emit |
|
7 |
- ;:emit-to-string |
|
8 |
- ) |
|
13 |
+ :emit |
|
14 |
+ :emit-to-string |
|
15 |
+ :register-scalar-converter |
|
16 |
+ :register-sequence-converter |
|
17 |
+ :register-mapping-converter |
|
18 |
+ :emit-object |
|
19 |
+ :print-scalar) |
|
9 | 20 |
(:documentation "The main YAML interface.")) |
10 | 21 |
(in-package :yaml) |
11 | 22 |
|
... | ... |
@@ -23,8 +34,8 @@ |
23 | 34 |
(parse (uiop:read-file-string input) |
24 | 35 |
:multi-document-p multi-document-p)) |
25 | 36 |
|
26 |
-;; (defun emit (value stream) |
|
27 |
-;; (yaml.emitter:emit value stream)) |
|
37 |
+(defun emit (value stream) |
|
38 |
+ (yaml.emitter:emit value stream)) |
|
28 | 39 |
|
29 |
-;; (defun emit-to-string (value) |
|
30 |
-;; (yaml.emitter:emit-to-string value)) |
|
40 |
+(defun emit-to-string (value) |
|
41 |
+ (yaml.emitter:emit-to-string value)) |
... | ... |
@@ -10,6 +10,7 @@ |
10 | 10 |
(run! 'cl-yaml-test.scalar:scalar) |
11 | 11 |
(run! 'cl-yaml-test.parser:parser) |
12 | 12 |
(run! 'cl-yaml-test.emitter:emitter) |
13 |
+ (run! 'cl-yaml-test.emitter2:emitter2) |
|
13 | 14 |
(run! 'cl-yaml-test.round-trip:round-trip) |
14 | 15 |
(run! 'cl-yaml-test.spec:spec) |
15 | 16 |
(run! 'cl-yaml-test.bench:bench)) |
... | ... |
@@ -1,80 +1,67 @@ |
1 | 1 |
(in-package :cl-user) |
2 | 2 |
(defpackage cl-yaml-test.emitter |
3 | 3 |
(:use :cl :fiveam) |
4 |
+ (:import-from :alexandria |
|
5 |
+ :alist-hash-table) |
|
4 | 6 |
(:export :emitter) |
5 | 7 |
(:documentation "Emitter tests.")) |
6 | 8 |
(in-package :cl-yaml-test.emitter) |
7 | 9 |
|
10 |
+;;; Macros |
|
11 |
+ |
|
8 | 12 |
(defmacro define-test-cases ((name) &rest pairs) |
9 | 13 |
`(test ,name |
10 | 14 |
,@(loop for (form string) in pairs collecting |
11 |
- `(is (equal (yaml.emitter:with-emitter-to-string (emitter) |
|
12 |
- (yaml.emitter:emit-stream (emitter) |
|
13 |
- (yaml.emitter:emit-document (emitter :implicit t) |
|
14 |
- (yaml.emitter:emit-scalar emitter ,form)))) |
|
15 |
- ,(format nil "~a~%...~%" string)))))) ;; Document end marker |
|
16 |
- ;; is libyaml behavior |
|
17 |
- |
|
18 |
-(defun test-emit-sequence (sequence style) |
|
19 |
- (yaml.emitter:with-emitter-to-string (emitter) |
|
20 |
- (yaml.emitter:emit-stream (emitter) |
|
21 |
- (yaml.emitter:emit-document (emitter :implicit t) |
|
22 |
- (yaml.emitter:emit-sequence (emitter :style style) |
|
23 |
- (mapcar (lambda (element) (yaml.emitter:emit-scalar emitter element)) |
|
24 |
- sequence)))))) |
|
15 |
+ `(is (equal (yaml.emitter:emit-to-string ,form) |
|
16 |
+ ,string))))) |
|
25 | 17 |
|
26 |
-(defun test-emit-mapping (mapping style) |
|
27 |
- (yaml.emitter:with-emitter-to-string (emitter) |
|
28 |
- (yaml.emitter:emit-stream (emitter) |
|
29 |
- (yaml.emitter:emit-document (emitter :implicit t) |
|
30 |
- (yaml.emitter:emit-mapping (emitter :style style) |
|
31 |
- (mapcar (lambda (pair) |
|
32 |
- (yaml.emitter:emit-scalar emitter (car pair)) |
|
33 |
- (yaml.emitter:emit-scalar emitter (cdr pair))) |
|
34 |
- mapping)))))) |
|
18 |
+;;; Tests |
|
35 | 19 |
|
36 | 20 |
(def-suite emitter |
37 |
- :description "YAML emitter tests.") |
|
21 |
+ :description "YAML emitter tests.") |
|
38 | 22 |
(in-suite emitter) |
39 | 23 |
|
40 | 24 |
(define-test-cases (boolean) |
41 |
- (t "true") |
|
42 |
- (nil "false")) |
|
25 |
+ (t |
|
26 |
+ "true") |
|
27 |
+ (nil |
|
28 |
+ "false")) |
|
43 | 29 |
|
44 | 30 |
(define-test-cases (integers) |
45 |
- (1 "1") |
|
46 |
- (123 "123") |
|
47 |
- (+123 "123") |
|
48 |
- (-123 "-123")) |
|
31 |
+ (1 |
|
32 |
+ "1") |
|
33 |
+ (123 |
|
34 |
+ "123") |
|
35 |
+ (+123 |
|
36 |
+ "123") |
|
37 |
+ (-123 |
|
38 |
+ "-123")) |
|
49 | 39 |
|
50 | 40 |
(define-test-cases (floats) |
51 |
- (1.23 "1.23") |
|
52 |
- (6.62607e-34 "6.62607e-34")) |
|
53 |
- |
|
54 |
-(test flow-sequence |
|
55 |
- (is (equal (test-emit-sequence '(1 "a" 3.14f0 3.14d0) :flow-sequence-style) |
|
56 |
- "[1, a, 3.14, 3.14] |
|
57 |
-"))) |
|
58 |
- |
|
59 |
-(test block-sequence |
|
60 |
- (is (equal (test-emit-sequence '(1 "a" 3.14f0 3.14d0) :block-sequence-style) |
|
61 |
- "- 1 |
|
62 |
-- a |
|
63 |
-- 3.14 |
|
64 |
-- 3.14 |
|
65 |
-"))) |
|
41 |
+ (1.23 |
|
42 |
+ "1.23") |
|
43 |
+ (6.62607e-34 |
|
44 |
+ "6.62607e-34")) |
|
66 | 45 |
|
67 |
-(test flow-mapping |
|
68 |
- (is (equal (test-emit-mapping '(("integer" . 1) ("string" . "test") ("bool" . nil)) |
|
69 |
- :flow-mapping-style) |
|
70 |
- "{integer: 1, string: test, bool: false} |
|
71 |
-"))) |
|
46 |
+(define-test-cases (lists) |
|
47 |
+ ((list 1 2 3) |
|
48 |
+ "[1, 2, 3]") |
|
49 |
+ ((vector 1 2 3) |
|
50 |
+ "[1, 2, 3]")) |
|
72 | 51 |
|
73 |
-(test block-mapping |
|
74 |
- (is (equal (test-emit-mapping '(("integer" . 1) ("string" . "test") ("bool" . nil)) |
|
75 |
- :block-mapping-style) |
|
76 |
- "integer: 1 |
|
77 |
-string: test |
|
78 |
-bool: false |
|
79 |
-"))) |
|
52 |
+(test hash-tables |
|
53 |
+ (let ((table (alexandria:alist-hash-table |
|
54 |
+ (list (cons "a" 1) |
|
55 |
+ (cons "b" 2))))) |
|
56 |
+ (is |
|
57 |
+ (equal (yaml:emit-to-string table) |
|
58 |
+ "{ \"b\": 2, \"a\": 1 }")))) |
|
80 | 59 |
|
60 |
+(test toplevel-function |
|
61 |
+ (is |
|
62 |
+ (equal (yaml:emit-to-string 1) |
|
63 |
+ "1")) |
|
64 |
+ (is |
|
65 |
+ (equal (with-output-to-string (stream) |
|
66 |
+ (yaml:emit 1 stream)) |
|
67 |
+ "1"))) |
81 | 68 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,79 @@ |
1 |
+(in-package :cl-user) |
|
2 |
+(defpackage cl-yaml-test.emitter2 |
|
3 |
+ (:use :cl :fiveam) |
|
4 |
+ (:export :emitter2) |
|
5 |
+ (:documentation "Emitter tests - libyaml-based emitter.")) |
|
6 |
+(in-package :cl-yaml-test.emitter2) |
|
7 |
+ |
|
8 |
+(defmacro define-test-cases ((name) &rest pairs) |
|
9 |
+ `(test ,name |
|
10 |
+ ,@(loop for (form string) in pairs collecting |
|
11 |
+ `(is (equal (yaml.emitter:with-emitter-to-string (emitter) |
|
12 |
+ (yaml.emitter:emit-stream (emitter) |
|
13 |
+ (yaml.emitter:emit-document (emitter :implicit t) |
|
14 |
+ (yaml.emitter:emit-scalar emitter ,form)))) |
|
15 |
+ ,(format nil "~a~%...~%" string)))))) ;; Document end marker |
|
16 |
+ ;; is libyaml behavior |
|
17 |
+ |
|
18 |
+(defun test-emit-sequence (sequence style) |
|
19 |
+ (yaml.emitter:with-emitter-to-string (emitter) |
|
20 |
+ (yaml.emitter:emit-stream (emitter) |
|
21 |
+ (yaml.emitter:emit-document (emitter :implicit t) |
|
22 |
+ (yaml.emitter:emit-sequence (emitter :style style) |
|
23 |
+ (mapcar (lambda (element) (yaml.emitter:emit-scalar emitter element)) |
|
24 |
+ sequence)))))) |
|
25 |
+ |
|
26 |
+(defun test-emit-mapping (mapping style) |
|
27 |
+ (yaml.emitter:with-emitter-to-string (emitter) |
|
28 |
+ (yaml.emitter:emit-stream (emitter) |
|
29 |
+ (yaml.emitter:emit-document (emitter :implicit t) |
|
30 |
+ (yaml.emitter:emit-mapping (emitter :style style) |
|
31 |
+ (mapcar (lambda (pair) |
|
32 |
+ (yaml.emitter:emit-scalar emitter (car pair)) |
|
33 |
+ (yaml.emitter:emit-scalar emitter (cdr pair))) |
|
34 |
+ mapping)))))) |
|
35 |
+ |
|
36 |
+(def-suite emitter2 |
|
37 |
+ :description "YAML libyaml-based emitter tests.") |
|
38 |
+(in-suite emitter2) |
|
39 |
+ |
|
40 |
+(define-test-cases (boolean) |
|
41 |
+ (t "true") |
|
42 |
+ (nil "false")) |
|
43 |
+ |
|
44 |
+(define-test-cases (integers) |
|
45 |
+ (1 "1") |
|
46 |
+ (123 "123") |
|
47 |
+ (+123 "123") |
|
48 |
+ (-123 "-123")) |
|
49 |
+ |
|
50 |
+(define-test-cases (floats) |
|
51 |
+ (1.23 "1.23") |
|
52 |
+ (6.62607e-34 "6.62607e-34")) |
|
53 |
+ |
|
54 |
+(test flow-sequence |
|
55 |
+ (is (equal (test-emit-sequence '(1 "a" 3.14f0 3.14d0) :flow-sequence-style) |
|
56 |
+ "[1, a, 3.14, 3.14] |
|
57 |
+"))) |
|
58 |
+ |
|
59 |
+(test block-sequence |
|
60 |
+ (is (equal (test-emit-sequence '(1 "a" 3.14f0 3.14d0) :block-sequence-style) |
|
61 |
+ "- 1 |
|
62 |
+- a |
|
63 |
+- 3.14 |
|
64 |
+- 3.14 |
|
65 |
+"))) |
|
66 |
+ |
|
67 |
+(test flow-mapping |
|
68 |
+ (is (equal (test-emit-mapping '(("integer" . 1) ("string" . "test") ("bool" . nil)) |
|
69 |
+ :flow-mapping-style) |
|
70 |
+ "{integer: 1, string: test, bool: false} |
|
71 |
+"))) |
|
72 |
+ |
|
73 |
+(test block-mapping |
|
74 |
+ (is (equal (test-emit-mapping '(("integer" . 1) ("string" . "test") ("bool" . nil)) |
|
75 |
+ :block-mapping-style) |
|
76 |
+ "integer: 1 |
|
77 |
+string: test |
|
78 |
+bool: false |
|
79 |
+"))) |