Shammer's Philosophy

My private adversaria

ClozureCL で文字のバイト数を判定

ClozureCLでマルチバイト文字のバイト数を判定する - Shammerismでは、encode-string-to-octets を使用したが、mutiple-value-bind を使用しないといけないなど、面倒な点があったので、純粋に文字のバイト数をカウントする処理を実装。UTF-8 のみに対応という状態だが。

(defun utf-8-string-byte-size (s)
  (if (stringp s)
      (let ((char-array (coerce s 'list))
	    (length 0))
	(dolist (x char-array)
	  (setf x (char-code x))
	  (cond ((equal x 10)
		 (setf length (+ length 2)))
		((or (<= x #x7f) (equal x #xa0))
		 (setf length (+ length 1)))
		((and (>= x #x80) (<= x #x7ff))
		 (setf length (+ length 2)))
		((and (>= x #x800) (<= x #xffff))
		 (setf length (+ length 3)))
		((and (>= x #x10000) (<= x #x1fffff))
		 (setf length (+ length 4)))
		((and (>= x #x200000) (<= x #x3ffffff))
		 (setf length (+ length 5)))
		((and (>= x #x4000000) (<= x #x7fffffff))
		 (setf length (+ length 6)))))
	length)
      0))

とりあえず、文字だったら問答無用で UTF-8 とみなして判定する。0x80 とかは、#x80 という感じにすることでヘキサで扱えるようだ。
以下、実行結果。

? (utf-8-string-byte-size "あいうえおabcdefg")
22
? (encode-string-to-octets "あいうえおabcdefg" :external-format :utf-8)
#(227 129 130 227 129 132 227 129 134 227 129 136 227 129 138 97 98 99 100 101 102 103)
22
?