Commit 8fe6e63d authored by Gabor Melis's avatar Gabor Melis
Browse files

make it ~30% faster on SBCL x86-64

It's just micro-optimizations: a couple of inline declarations,
and a quicker test for group size 1.

On CLL and Clisp, also on x86-64, it's about 2% and 5% faster,
respectively.
parent 4d427cfb
Loading
Loading
Loading
Loading
+12 −9
Original line number Original line Diff line number Diff line
@@ -23,8 +23,9 @@
  "Calculate the amount of bytes needed to encode a string."
  "Calculate the amount of bytes needed to encode a string."
  (declare (type string string)
  (declare (type string string)
           #'*optimize*)
           #'*optimize*)
  (let ((length (length string))
  (let* ((string (coerce string 'simple-string))
        (string (coerce string 'simple-string)))
         (length (length string)))
    (declare (type fixnum length))
    (loop :for char :across string
    (loop :for char :across string
          :do (let ((code (char-code char)))
          :do (let ((code (char-code char)))
                (when (> code 127)
                (when (> code 127)
@@ -60,11 +61,11 @@ encoded form of that character."
utf-8 representation."
utf-8 representation."
  (declare (type string string)
  (declare (type string string)
           #.*optimize*)
           #.*optimize*)
  (let ((buffer (make-array (+ (the fixnum (utf-8-byte-length string))
  (let* ((string (coerce string 'simple-string))
         (buffer (make-array (+ (the fixnum (utf-8-byte-length string))
                                (if null-terminate 1 0))
                                (if null-terminate 1 0))
                             :element-type '(unsigned-byte 8)))
                             :element-type '(unsigned-byte 8)))
        (position 0)
         (position 0))
        (string (coerce string 'simple-string)))
    (declare (type (array (unsigned-byte 8)) buffer)
    (declare (type (array (unsigned-byte 8)) buffer)
             (type fixnum position))
             (type fixnum position))
    (macrolet ((add-byte (byte)
    (macrolet ((add-byte (byte)
@@ -102,26 +103,28 @@ utf-8 representation."
starting with a given byte."
starting with a given byte."
  (declare (type fixnum byte)
  (declare (type fixnum byte)
           #.*optimize*)
           #.*optimize*)
  (cond ((zerop (logand byte #b10000000)) 1)
  (cond ((not (logtest byte #b10000000)) 1)
        ((= (logand byte #b11100000) #b11000000) 2)
        ((= (logand byte #b11100000) #b11000000) 2)
        ((= (logand byte #b11110000) #b11100000) 3)
        ((= (logand byte #b11110000) #b11100000) 3)
        ((= (logand byte #b11111000) #b11110000) 4)
        ((= (logand byte #b11111000) #b11110000) 4)
        (t (error 'utf-8-decoding-error :byte byte
        (t (error 'utf-8-decoding-error :byte byte
                  :message "Invalid byte at start of character: 0x~X"))))
                  :message "Invalid byte at start of character: 0x~X"))))


(declaim (inline utf-8-string-length))
(defun utf-8-string-length (bytes &key (start 0) (end (length bytes)))
(defun utf-8-string-length (bytes &key (start 0) (end (length bytes)))
  "Calculate the length of the string encoded by the given bytes."
  "Calculate the length of the string encoded by the given bytes."
  (declare (type (simple-array (unsigned-byte 8) (*)) bytes)
  (declare (type (simple-array (unsigned-byte 8) (*)) bytes)
           (type fixnum start end)
           (type fixnum start end)
           #.*optimize*)
           #.*optimize*)
  (loop :with i :of-type fixnum = start
  (loop :with i :of-type fixnum = start
        :with string-length = 0
        :with string-length :of-type fixnum = 0
        :while (< i end)
        :while (< i end)
        :do (progn
        :do (progn
              (incf (the fixnum string-length) 1)
              (incf (the fixnum string-length) 1)
              (incf i (utf-8-group-size (elt bytes i))))
              (incf i (utf-8-group-size (elt bytes i))))
        :finally (return string-length)))
        :finally (return string-length)))


(declaim (inline get-utf-8-character))
(defun get-utf-8-character (bytes group-size &optional (start 0))
(defun get-utf-8-character (bytes group-size &optional (start 0))
  "Given an array of bytes and the amount of bytes to use,
  "Given an array of bytes and the amount of bytes to use,
extract the character starting at the given start position."
extract the character starting at the given start position."