+(defmacro octets-to-string (octets &key (encoding *default-foreign-encoding*))
+ "Converts a vector of octets to a Lisp string."
+ #-(or allegro lispworks openmcl sbcl)
+ (declare (ignore encoding))
+ #-(or allegro lispworks openmcl sbcl)
+ (let ((out (gensym "OUT-"))
+ (code (gensym "CODE-")))
+ `(with-output-to-string (,out)
+ (loop for ,code across ,octets
+ do (write-char (code-char ,code) ,out))))
+
+ #+allegro
+ (let ((fe (gensym "FE-"))
+ (ife (gensym "IFE-"))
+ (oct (gensym "OCTETS-")))
+ `(let* ((,fe ,encoding)
+ (,ife (when ,fe (lookup-foreign-encoding ,fe)))
+ (,oct ,octets))
+ (values
+ (if ,ife
+ (excl:octets-to-string ,oct :external-format ,ife)
+ (excl:octets-to-string ,oct)))))
+
+ #+(or lispworks openmcl)
+ ;; With LW 6.0 and CCL 1.4, writing multibyte character just one octet at a time tests fine
+ (let ((out (gensym "OUT-"))
+ (code (gensym "CODE-")))
+ `(with-output-to-string (,out)
+ (loop for ,code across ,octets
+ do (write-char (code-char ,code) ,out))))
+
+ #+sbcl
+ (let ((fe (gensym "FE-"))
+ (ife (gensym "IFE-"))
+ (oct (gensym "OCTETS-")))
+ `(let* ((,fe ,encoding)
+ (,ife (when ,fe (lookup-foreign-encoding ,fe)))
+ (,oct ,octets))
+ (if ,ife
+ (sb-ext:octets-to-string ,oct :external-format ,ife)
+ (sb-ext:octets-to-string ,oct))))
+
+)
+
+(defun foreign-encoded-octet-count (str &key (encoding *default-foreign-encoding*))
+ "Returns the octets required to represent the string when passed to a ~
+foreign function."
+ ;; AllegroCL 8-bit, CCL, and Lispworks give correct value without converting
+ ;; to external-format. AllegroCL 16-bit, SBCL, and CLISP requires conversion
+ ;; with external-format
+
+ #+(or (and allegro ics) (and sbcl sb-unicode) (and clisp i18n))
+ (length (string-to-octets str :encoding encoding))
+
+ #-(or (and allegro ics) (and sbcl sb-unicode) (and clisp i18n))
+ (declare (ignore encoding))
+ #-(or (and allegro ics) (and sbcl sb-unicode) (and clisp i18n))
+ (length str)
+
+)