/runtime/string.lisp

https://github.com/froggey/Mezzano · Lisp · 219 lines · 196 code · 15 blank · 8 comment · 0 complexity · ddae5dcf4cf3bff89caf48f4691d6568 MD5 · raw file

  1. ;;;; Low-level support functions for strings and characters.
  2. (in-package :mezzano.runtime)
  3. (defun wiredp (object)
  4. (< (sys.int::lisp-object-address object) #x8000000000))
  5. ;; Hardcoded string accessor, the support stuff for arrays doesn't function at this point.
  6. (defun char (string index)
  7. (check-type index integer)
  8. (cond ((sys.int::character-array-p string)
  9. (let ((data (sys.int::%complex-array-storage string)))
  10. (assert (and (<= 0 index)
  11. (< index (sys.int::%object-header-data data)))
  12. (string index))
  13. (sys.int::%%assemble-value
  14. (logior
  15. (ash (ecase (sys.int::%object-tag data)
  16. (#.sys.int::+object-tag-array-unsigned-byte-8+
  17. (sys.int::%object-ref-unsigned-byte-8 data index))
  18. (#.sys.int::+object-tag-array-unsigned-byte-16+
  19. (sys.int::%object-ref-unsigned-byte-16 data index))
  20. (#.sys.int::+object-tag-array-unsigned-byte-32+
  21. (sys.int::%object-ref-unsigned-byte-32 data index)))
  22. (+ (byte-position sys.int::+immediate-tag+)
  23. (byte-size sys.int::+immediate-tag+)))
  24. (dpb sys.int::+immediate-tag-character+
  25. sys.int::+immediate-tag+
  26. 0))
  27. sys.int::+tag-immediate+)))
  28. (t
  29. ;; Possibly a displaced string.
  30. (check-type string string)
  31. (aref string index))))
  32. (defun resize-string-storage (old-storage new-tag)
  33. (let* ((old-tag (sys.int::%object-tag old-storage))
  34. (elt-size (ecase new-tag
  35. ((nil) old-tag)
  36. (#.sys.int::+object-tag-array-unsigned-byte-8+
  37. 1)
  38. (#.sys.int::+object-tag-array-unsigned-byte-16+
  39. 2)
  40. (#.sys.int::+object-tag-array-unsigned-byte-32+
  41. 4)))
  42. (len (sys.int::%object-header-data old-storage))
  43. (new-storage (mezzano.runtime::%allocate-object
  44. new-tag
  45. len
  46. (ceiling (* len elt-size) 8)
  47. (if (wiredp old-storage) :wired nil))))
  48. (dotimes (i len)
  49. (let ((val (ecase old-tag
  50. (#.sys.int::+object-tag-array-unsigned-byte-8+
  51. (sys.int::%object-ref-unsigned-byte-8 old-storage i))
  52. (#.sys.int::+object-tag-array-unsigned-byte-16+
  53. (sys.int::%object-ref-unsigned-byte-16 old-storage i))
  54. (#.sys.int::+object-tag-array-unsigned-byte-32+
  55. (sys.int::%object-ref-unsigned-byte-32 old-storage i)))))
  56. (ecase new-tag
  57. (#.sys.int::+object-tag-array-unsigned-byte-8+
  58. (setf (sys.int::%object-ref-unsigned-byte-8 new-storage i) val))
  59. (#.sys.int::+object-tag-array-unsigned-byte-16+
  60. (setf (sys.int::%object-ref-unsigned-byte-16 new-storage i) val))
  61. (#.sys.int::+object-tag-array-unsigned-byte-32+
  62. (setf (sys.int::%object-ref-unsigned-byte-32 new-storage i) val)))))
  63. new-storage))
  64. (defun ensure-string-wide-enough (character string)
  65. (let* ((int-value (char-int character))
  66. (min-len (cond ((<= int-value #xFF)
  67. sys.int::+object-tag-array-unsigned-byte-8+)
  68. ((<= int-value #xFFFF)
  69. sys.int::+object-tag-array-unsigned-byte-16+)
  70. (t
  71. sys.int::+object-tag-array-unsigned-byte-32+)))
  72. (backing-type (sys.int::%object-tag (sys.int::%complex-array-storage string))))
  73. (when (< backing-type min-len)
  74. ;; Promote the storage array to fit the character.
  75. (setf (sys.int::%complex-array-storage string)
  76. (resize-string-storage (sys.int::%complex-array-storage string)
  77. min-len)))))
  78. (defun (setf char) (value string index)
  79. (check-type index integer)
  80. (check-type value character)
  81. (cond ((sys.int::character-array-p string)
  82. (ensure-string-wide-enough value string)
  83. (let ((int-value (char-int value))
  84. (data (sys.int::%complex-array-storage string)))
  85. (assert (and (<= 0 index)
  86. (< index (sys.int::%object-header-data data)))
  87. (string index))
  88. (ecase (sys.int::%object-tag data)
  89. (#.sys.int::+object-tag-array-unsigned-byte-8+
  90. (setf (sys.int::%object-ref-unsigned-byte-8 data index) int-value))
  91. (#.sys.int::+object-tag-array-unsigned-byte-16+
  92. (setf (sys.int::%object-ref-unsigned-byte-16 data index) int-value))
  93. (#.sys.int::+object-tag-array-unsigned-byte-32+
  94. (setf (sys.int::%object-ref-unsigned-byte-32 data index) int-value)))
  95. value))
  96. (t
  97. ;; Possibly a displaced string.
  98. (check-type string string)
  99. (setf (aref string index) value))))
  100. (defun schar (string index)
  101. (check-type string string)
  102. (char string index))
  103. (defun (setf schar) (value string index)
  104. (check-type string string)
  105. (setf (char string index) value))
  106. (defun copy-string-in-area (string &optional area)
  107. (cond ((sys.int::character-array-p string)
  108. (let* ((data (sys.int::%complex-array-storage string))
  109. (len (or (sys.int::%complex-array-fill-pointer string)
  110. (sys.int::%object-header-data data)))
  111. (tag (sys.int::%object-tag data))
  112. (elt-size (ecase tag
  113. (#.sys.int::+object-tag-array-unsigned-byte-8+
  114. 1)
  115. (#.sys.int::+object-tag-array-unsigned-byte-16+
  116. 2)
  117. (#.sys.int::+object-tag-array-unsigned-byte-32+
  118. 4)))
  119. (new-data (mezzano.runtime::%allocate-object
  120. tag
  121. len
  122. (ceiling (* len elt-size) 8)
  123. area))
  124. (new-header (mezzano.runtime::%allocate-object
  125. sys.int::+object-tag-simple-string+
  126. 1
  127. (+ 3 1)
  128. area)))
  129. (setf (sys.int::%complex-array-storage new-header) new-data
  130. (sys.int::%complex-array-fill-pointer new-header) nil
  131. (sys.int::%complex-array-info new-header) nil
  132. (sys.int::%complex-array-dimension new-header 0) len)
  133. (dotimes (i len)
  134. (let ((val (ecase tag
  135. (#.sys.int::+object-tag-array-unsigned-byte-8+
  136. (sys.int::%object-ref-unsigned-byte-8 data i))
  137. (#.sys.int::+object-tag-array-unsigned-byte-16+
  138. (sys.int::%object-ref-unsigned-byte-16 data i))
  139. (#.sys.int::+object-tag-array-unsigned-byte-32+
  140. (sys.int::%object-ref-unsigned-byte-32 data i)))))
  141. (ecase tag
  142. (#.sys.int::+object-tag-array-unsigned-byte-8+
  143. (setf (sys.int::%object-ref-unsigned-byte-8 new-data i) val))
  144. (#.sys.int::+object-tag-array-unsigned-byte-16+
  145. (setf (sys.int::%object-ref-unsigned-byte-16 new-data i) val))
  146. (#.sys.int::+object-tag-array-unsigned-byte-32+
  147. (setf (sys.int::%object-ref-unsigned-byte-32 new-data i) val)))))
  148. new-header))
  149. (t
  150. (error "TODO: copy non-character-array strings"))))
  151. (defun make-wired-string (len &key fullwidth)
  152. (let* ((tag (if fullwidth
  153. #.sys.int::+object-tag-array-unsigned-byte-32+
  154. #.sys.int::+object-tag-array-unsigned-byte-8+))
  155. (elt-size (if fullwidth
  156. 4
  157. 1))
  158. (data (mezzano.runtime::%allocate-object
  159. tag
  160. len
  161. (ceiling (* len elt-size) 8)
  162. :wired))
  163. (header (mezzano.runtime::%allocate-object
  164. sys.int::+object-tag-simple-string+
  165. 1
  166. (+ 3 1)
  167. :wired)))
  168. (setf (sys.int::%complex-array-storage header) data
  169. (sys.int::%complex-array-fill-pointer header) nil
  170. (sys.int::%complex-array-info header) nil
  171. (sys.int::%complex-array-dimension header 0) len)
  172. header))
  173. (declaim (inline sys.int::%%make-character))
  174. (defun sys.int::%%make-character (code &optional bits)
  175. (sys.int::%%assemble-value
  176. (if bits
  177. (logior (dpb code sys.int::+char-code+ 0)
  178. (dpb bits sys.int::+char-bits+ 0))
  179. (dpb code sys.int::+char-code+ 0))
  180. (dpb sys.int::+immediate-tag-character+
  181. sys.int::+immediate-tag+
  182. sys.int::+tag-immediate+)))
  183. (defun sys.int::%make-character (code &optional bits)
  184. (check-type code (integer 0 #x0010FFFF)
  185. "a unicode code-point")
  186. (check-type bits (or null (integer 0 15)))
  187. (if (or (<= #xD800 code #xDFFF) ; UTF-16 surrogates.
  188. ;; Noncharacters.
  189. (<= #xFDD0 code #xFDEF)
  190. ;; The final two code points in each plane are noncharacters.
  191. (eql (logand code #xFFFE) #xFFFE))
  192. nil
  193. (sys.int::%%make-character code bits)))
  194. (defun char-code (character)
  195. (check-type character character)
  196. (ldb sys.int::+char-code+ (sys.int::lisp-object-address character)))
  197. (defun char-int (character)
  198. (check-type character character)
  199. ;; Strip tag & immediate tag.
  200. (ash (sys.int::lisp-object-address character)
  201. (- (+ (byte-position sys.int::+immediate-tag+)
  202. (byte-size sys.int::+immediate-tag+)))))
  203. (defun code-char (code)
  204. (sys.int::%make-character code))