changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/lib/io/xsubseq.lisp

changeset 448: a37b1d3371fc
parent: 7c1383c08493
author: Richard Westhaver <ellis@rwest.io>
date: Sat, 15 Jun 2024 19:34:10 -0400
permissions: -rw-r--r--
description: fasl tweaks
1 ;;; io/xsubseq.lisp --- Subseq Optimizations
2 
3 ;; This is ported from Fukamachi's XSUBSEQ
4 
5 ;;; Code:
6 (require :sb-cltl2)
7 (defpackage io/xsubseq
8  (:use :cl)
9  (:import-from :sb-cltl2 :variable-information)
10  (:import-from :std/type :octet-vector)
11  (:export :xsubseq
12  :octet-xsubseq
13  :string-xsubseq
14  :concatenated-xsubseqs
15  :null-concatenated-xsubseqs
16  :octet-concatenated-xsubseqs
17  :string-concatenated-xsubseqs
18  :make-concatenated-xsubseqs
19  :xlength
20  :xnconc
21  :xnconcf
22  :coerce-to-sequence
23  :coerce-to-string
24  :with-xsubseqs))
25 (in-package :io/xsubseq)
26 
27 (defstruct (xsubseq (:constructor make-xsubseq (data start &optional (end (length data))
28  &aux (len (- end start)))))
29  (data nil)
30  (start 0 :type integer)
31  (end 0 :type integer)
32  (len 0 :type integer))
33 
34 (defstruct (octet-xsubseq (:include xsubseq)
35  (:constructor make-octet-xsubseq (data start &optional (end (length data))
36  &aux (len (- end start))))))
37 
38 (defstruct (string-xsubseq (:include xsubseq)
39  (:constructor make-string-xsubseq (data start &optional (end (length data))
40  &aux (len (- end start))))))
41 
42 (defstruct (concatenated-xsubseqs (:constructor %make-concatenated-xsubseqs))
43  (len 0 :type integer)
44  (last nil :type list)
45  (children nil :type list))
46 
47 (defun make-concatenated-xsubseqs (&rest children)
48  (if (null children)
49  (make-null-concatenated-xsubseqs)
50  (%make-concatenated-xsubseqs :children children
51  :last (last children)
52  :len (reduce #'+
53  children
54  :key #'xsubseq-len
55  :initial-value 0))))
56 
57 (defstruct (null-concatenated-xsubseqs (:include concatenated-xsubseqs)))
58 
59 (defstruct (octet-concatenated-xsubseqs (:include concatenated-xsubseqs)))
60 
61 (defstruct (string-concatenated-xsubseqs (:include concatenated-xsubseqs)))
62 
63 (defun xsubseq (data start &optional (end (length data)))
64  (typecase data
65  (octet-vector (make-octet-xsubseq data start end))
66  (string (make-string-xsubseq data start end))
67  (t (make-xsubseq data start end))))
68 
69 #+(or sbcl openmcl cmu allegro)
70 (define-compiler-macro xsubseq (&whole form &environment env data start &optional end)
71  (let ((type (cond
72  ((constantp data) (type-of data))
73  ((and (symbolp data)
74  (assoc 'type (nth-value 2 (variable-information data env)))))
75  ((and (listp data)
76  (eq (car data) 'make-string))
77  'string)
78  ((and (listp data)
79  (eq (car data) 'the)
80  (cadr data)))
81  ((and (listp data)
82  (eq (car data) 'make-array)
83  (null (cadr (member :adjustable data)))
84  (null (cadr (member :fill-pointer data)))
85  (cadr (member :element-type data))))))
86  (g-data (gensym "DATA")))
87  (if (null type)
88  form
89  (cond
90  ((subtypep type 'octet-vector) `(let ((,g-data ,data))
91  (make-octet-xsubseq ,g-data ,start ,(or end `(length ,g-data)))))
92  ((subtypep type 'string) `(let ((,g-data ,data))
93  (make-string-xsubseq ,g-data ,start ,(or end `(length ,g-data)))))
94  (t form)))))
95 
96 (defun %xnconc2 (seq1 seq2)
97  (flet ((seq-values (seq)
98  (if (concatenated-xsubseqs-p seq)
99  (values (concatenated-xsubseqs-children seq)
100  (concatenated-xsubseqs-last seq)
101  (concatenated-xsubseqs-len seq))
102  (let ((children (list seq)))
103  (values children children
104  (xsubseq-len seq))))))
105  (macrolet ((make-concatenated (type seq1 seq2)
106  `(multiple-value-bind (children last len)
107  (seq-values ,seq2)
108  (,(cond
109  ((eq type 'octet-vector) 'make-octet-concatenated-xsubseqs)
110  ((eq type 'string) 'make-string-concatenated-xsubseqs)
111  (t '%make-concatenated-xsubseqs))
112  :len (+ (xsubseq-len ,seq1) len)
113  :children (cons ,seq1 children)
114  :last last))))
115  (etypecase seq1
116  (null-concatenated-xsubseqs seq2)
117  (concatenated-xsubseqs
118  (multiple-value-bind (children last len)
119  (seq-values seq2)
120  (if (concatenated-xsubseqs-last seq1)
121  (progn
122  (rplacd (concatenated-xsubseqs-last seq1)
123  children)
124  (setf (concatenated-xsubseqs-last seq1) last)
125  (incf (concatenated-xsubseqs-len seq1) len))
126  ;; empty concatenated-xsubseqs
127  (progn
128  (setf (concatenated-xsubseqs-children seq1) children
129  (concatenated-xsubseqs-len seq1) len
130  (concatenated-xsubseqs-last seq1) last)))
131  seq1))
132  (octet-xsubseq
133  (make-concatenated octet-vector seq1 seq2))
134  (string-xsubseq
135  (make-concatenated string seq1 seq2))
136  (xsubseq (make-concatenated t seq1 seq2))))))
137 
138 (defun xnconc (subseq &rest more-subseqs)
139  (reduce #'%xnconc2 more-subseqs :initial-value subseq))
140 
141 (define-modify-macro xnconcf (subseq &rest more-subseqs) xnconc)
142 
143 (defun xlength (seq)
144  (etypecase seq
145  (xsubseq (xsubseq-len seq))
146  (concatenated-xsubseqs (concatenated-xsubseqs-len seq))))
147 
148 (defun coerce-to-sequence (seq)
149  (etypecase seq
150  (octet-concatenated-xsubseqs (octet-concatenated-xsubseqs-to-sequence seq))
151  (string-concatenated-xsubseqs (string-concatenated-xsubseqs-to-sequence seq))
152  (concatenated-xsubseqs (concatenated-xsubseqs-to-sequence seq))
153  (xsubseq (xsubseq-to-sequence seq))))
154 
155 #+(or sbcl openmcl cmu allegro)
156 (define-compiler-macro coerce-to-sequence (&whole form &environment env seq)
157  (let ((type (cond
158  ((constantp seq) (type-of seq))
159  ((and (symbolp seq)
160  (assoc 'type (nth-value 2 (variable-information seq env)))))
161  ((and (listp seq)
162  (eq (car seq) 'the)
163  (cadr seq))))))
164  (if (null type)
165  form
166  (cond
167  ((subtypep type 'octet-concatenated-xsubseqs) `(octet-concatenated-xsubseqs-to-sequence ,seq))
168  ((subtypep type 'string-concatenated-xsubseqs) `(string-concatenated-xsubseqs-to-sequence ,seq))
169  ((subtypep type 'concatenated-xsubseqs) `(concatenated-xsubseqs-to-sequence ,seq))
170  ((subtypep type 'xsubseq) `(xsubseq-to-sequence ,seq))
171  (t form)))))
172 
173 (defun coerce-to-string (seq)
174  (etypecase seq
175  (null-concatenated-xsubseqs "")
176  (octet-concatenated-xsubseqs (octet-concatenated-xsubseqs-to-string seq))
177  (string-concatenated-xsubseqs (string-concatenated-xsubseqs-to-sequence seq))
178  (octet-xsubseq (octet-xsubseq-to-string seq))
179  (string-xsubseq (xsubseq-to-sequence seq))))
180 
181 #+(or sbcl openmcl cmu allegro)
182 (define-compiler-macro coerce-to-string (&whole form &environment env seq)
183  (let ((type (cond
184  ((constantp seq) (type-of seq))
185  ((and (symbolp seq)
186  (assoc 'type (nth-value 2 (variable-information seq env)))))
187  ((and (listp seq)
188  (eq (car seq) 'the)
189  (cadr seq))))))
190  (if (null type)
191  form
192  (cond
193  ((subtypep type 'octet-concatenated-xsubseqs) `(octet-concatenated-xsubseqs-to-string ,seq))
194  ((subtypep type 'string-concatenated-xsubseqs) `(string-concatenated-xsubseqs-to-sequence ,seq))
195  ((subtypep type 'octet-xsubseq) `(octet-xsubseq-to-string ,seq))
196  ((subtypep type 'string-xsubseq) `(xsubseq-to-sequence ,seq))
197  (t form)))))
198 
199 (defun xsubseq-to-sequence (seq)
200  (let ((result (make-array (xsubseq-len seq)
201  :element-type
202  (array-element-type (xsubseq-data seq)))))
203  (replace result (xsubseq-data seq)
204  :start2 (xsubseq-start seq)
205  :end2 (xsubseq-end seq))
206  result))
207 
208 (defun octet-xsubseq-to-string (seq)
209  (let ((result (make-array (xsubseq-len seq)
210  :element-type 'character)))
211  (declare (type simple-string result))
212  (let ((data (xsubseq-data seq))
213  (end (xsubseq-end seq)))
214  (do ((i (xsubseq-start seq) (1+ i))
215  (j 0 (1+ j)))
216  ((= i end) result)
217  (setf (aref result j)
218  (code-char
219  (the (unsigned-byte 8)
220  (aref (the octet-vector data) i))))))))
221 
222 (defun concatenated-xsubseqs-to-sequence (seq)
223  (let ((result (make-array (concatenated-xsubseqs-len seq)
224  :element-type
225  (array-element-type (xsubseq-data (car (concatenated-xsubseqs-children seq)))))))
226  (loop with current-pos = 0
227  for seq in (concatenated-xsubseqs-children seq)
228  do (replace result (xsubseq-data seq)
229  :start1 current-pos
230  :start2 (xsubseq-start seq)
231  :end2 (xsubseq-end seq))
232  (incf current-pos
233  (xsubseq-len seq)))
234  result))
235 
236 (defun octet-concatenated-xsubseqs-to-sequence (seq)
237  (let ((result (make-array (concatenated-xsubseqs-len seq)
238  :element-type '(unsigned-byte 8))))
239  (declare (type octet-vector result))
240  (loop with current-pos of-type integer = 0
241  for seq in (concatenated-xsubseqs-children seq)
242  do (replace result (the octet-vector (xsubseq-data seq))
243  :start1 current-pos
244  :start2 (xsubseq-start seq)
245  :end2 (xsubseq-end seq))
246  (incf current-pos
247  (xsubseq-len seq)))
248  result))
249 
250 (defun octet-concatenated-xsubseqs-to-string (seq)
251  (let ((result (make-array (concatenated-xsubseqs-len seq)
252  :element-type 'character)))
253  (declare (type simple-string result))
254  (loop with current-pos = 0
255  for seq in (concatenated-xsubseqs-children seq)
256  do (do ((i (xsubseq-start seq) (1+ i))
257  (j current-pos (1+ j)))
258  ((= i (xsubseq-end seq))
259  (setf current-pos j))
260  (setf (aref result j)
261  (code-char
262  (the (unsigned-byte 8)
263  (aref (the octet-vector (xsubseq-data seq)) i))))))
264  result))
265 
266 (defun string-concatenated-xsubseqs-to-sequence (seq)
267  (let ((result (make-string (concatenated-xsubseqs-len seq))))
268  (declare (type simple-string result))
269  (loop with current-pos of-type integer = 0
270  for seq in (concatenated-xsubseqs-children seq)
271  do (replace result (the simple-string (xsubseq-data seq))
272  :start1 current-pos
273  :start2 (xsubseq-start seq)
274  :end2 (xsubseq-end seq))
275  (incf current-pos
276  (xsubseq-len seq)))
277  result))
278 
279 (defmacro with-xsubseqs ((xsubseqs &key initial-value) &body body)
280  `(let ((,xsubseqs ,(or initial-value
281  `(make-null-concatenated-xsubseqs))))
282  ,@body
283 
284  (typecase ,xsubseqs
285  (null-concatenated-xsubseqs nil)
286  (xsubseq (xsubseq-to-sequence ,xsubseqs))
287  (t (concatenated-xsubseqs-to-sequence ,xsubseqs)))))