X-Git-Url: http://git.kpe.io/?a=blobdiff_plain;f=src%2Fmcl%2Fstrings.cl;fp=src%2Fmcl%2Fstrings.cl;h=ed311a20dac068dce734e367c855b9858191290d;hb=93d37518cbd27aa8b7f313bb89b9523d5a40ec88;hp=0000000000000000000000000000000000000000;hpb=6aca6ef38f1f406c9e7987e46cbaca3299c487fb;p=uffi.git diff --git a/src/mcl/strings.cl b/src/mcl/strings.cl new file mode 100644 index 0000000..ed311a2 --- /dev/null +++ b/src/mcl/strings.cl @@ -0,0 +1,198 @@ +;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: UFFI -*- +;;;; ************************************************************************* +;;;; FILE IDENTIFICATION +;;;; +;;;; Name: strings.cl +;;;; Purpose: UFFI source to handle strings, cstring and foreigns +;;;; Programmers: Kevin M. Rosenberg and John DeSoi +;;;; Date Started: Feb 2002 +;;;; +;;;; $Id: strings.cl,v 1.5 2002/08/23 15:28:11 kevin Exp $ +;;;; +;;;; This file, part of UFFI, is Copyright (c) 2002 by Kevin M. Rosenberg +;;;; and John DeSoi +;;;; +;;;; UFFI users are granted the rights to distribute and use this software +;;;; as governed by the terms of the Lisp Lesser GNU Public License +;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. +;;;; ************************************************************************* + +(declaim (optimize (debug 3) (speed 3) (safety 1) (compilation-speed 0))) +(in-package :uffi) + + +(defvar +null-cstring-pointer+ (ccl:%null-ptr)) + +(defmacro convert-from-cstring (obj) + "Converts a string from a c-call. Same as convert-from-foreign-string, except +that CMU automatically converts strings from c-calls." + #+cmu obj + #+lispworks + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (fli:null-pointer-p ,stored) + nil + (fli:convert-from-foreign-string ,stored)))) + #+allegro + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (zerop ,stored) + nil + (values (excl:native-to-string ,stored))))) + #+mcl + (let ((stored (gensym))) + `(let ((,stored ,obj)) + (if (ccl:%null-ptr-p ,stored) + nil + (values (ccl:%get-cstring ,stored))))) + + + ) + +(defmacro convert-to-cstring (obj) + #+lispworks + `(if (null ,obj) + +null-cstring-pointer+ + (fli:convert-to-foreign-string ,obj)) + #+allegro + `(if (null ,obj) + 0 + (values (excl:string-to-native ,obj))) + #+cmu + (declare (ignore obj)) + #+mcl + `(if (null ,obj) + +null-cstring-pointer+ + (let ((ptr (new-ptr (1+ (length ,obj))))) + (ccl:%put-cstring ptr ,obj) + ptr)) + ) + +(defmacro free-cstring (obj) + #+lispworks + `(unless (fli:null-pointer-p ,obj) + (fli:free-foreign-object ,obj)) + #+allegro + `(unless (zerop obj) + (ff:free-fobject ,obj)) + #+cmu + (declare (ignore obj)) + #+mcl + `(unless (ccl:%null-ptr-p ,obj) + (dispose-ptr ,obj)) + + ) + +;; Either length or null-terminated-p must be non-nil +(defmacro convert-from-foreign-string (obj &key + length + (null-terminated-p t)) + #+allegro + `(if (zerop ,obj) + nil + (values (excl:native-to-string + ,obj + ,@(if length (list :length length) (values)) + :truncate (not ,null-terminated-p)))) + #+lispworks + `(if (fli:null-pointer-p ,obj) + nil + (fli:convert-from-foreign-string + ,obj + ,@(if length (list :length length) (values)) + :null-terminated-p ,null-terminated-p + :external-format '(:latin-1 :eol-style :lf))) + #+cmu + `(cmucl-naturalize-cstring (alien:alien-sap ,obj) + :length ,length + :null-terminated-p ,null-terminated-p) + #+mcl + (declare (ignore null-terminated-p)) + #+mcl + `(if (ccl:%null-ptr-p ,obj) + nil + (ccl:%get-cstring ,obj 0 ,@(if length (list length) nil))) + ) + +(defmacro convert-to-foreign-string (obj) + #+lispworks + `(if (null ,obj) + +null-cstring-pointer+ + (fli:convert-to-foreign-string ,obj)) + #+allegro + `(if (null ,obj) + 0 + (values (excl:string-to-native ,obj))) + #+cmu + (let ((size (gensym)) + (storage (gensym)) + (i (gensym))) + `(when (stringp ,obj) + (let* ((,size (length ,obj)) + (,storage (alien:make-alien char (1+ ,size)))) + (setq ,storage (alien:cast ,storage (* char))) + (dotimes (,i ,size) + (declare (fixnum ,i) + (optimize (speed 3) (safety 0))) + (setf (alien:deref ,storage ,i) (char-code (char ,obj ,i)))) + (setf (alien:deref ,storage ,size) 0) + ,storage))) + #+mcl + `(if (null ,obj) + +null-cstring-pointer+ + (let ((ptr (new-ptr (1+ (length ,obj))))) + (ccl:%put-cstring ptr ,obj) + ptr)) + ) + + +(defmacro allocate-foreign-string (size &key (unsigned t)) + #+cmu + (let ((array-def (gensym))) + `(let ((,array-def (list 'alien:array 'c-call:char ,size))) + (eval `(alien:cast (alien:make-alien ,,array-def) + ,(if ,unsigned + '(* (alien:unsigned 8)) + '(* (alien:signed 8))))))) + #+lispworks + `(fli:allocate-foreign-object :type + ,(if unsigned + ''(:unsigned :char) + :char) + :nelems ,size) + #+allegro + (declare (ignore unsigned)) + #+allegro + `(ff:allocate-fobject :char :c ,size) + #+mcl + (declare (ignore unsigned)) + #+mcl + `(new-ptr ,size) + + ) + + +; I'm sure there must be a better way to write this... +(defmacro with-cstring ((foreign-string lisp-string) &body body) + `(if (stringp ,lisp-string) + (ccl:with-cstrs ((,foreign-string ,lisp-string)) + ,@body) + (let ((,foreign-string +null-cstring-pointer+)) + ,@body))) + + +#| Works but, supposedly the built in method is better +(defmacro with-cstring ((foreign-string lisp-string) &body body) + (let ((result (gensym))) + `(let* ((,foreign-string (convert-to-cstring ,lisp-string)) + (,result ,@body)) + (dispose-ptr ,foreign-string) + ,result)) + ) + +|# + + + + +