r4968: Auto commit for Debian build
[clsql.git] / uffi / clsql-uffi.lisp
1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
5 ;;;; Name:          clsql-uffi.cl
6 ;;;; Purpose:       Common functions for interfaces using UFFI
7 ;;;; Programmers:   Kevin M. Rosenberg
8 ;;;; Date Started:  Mar 2002
9 ;;;;
10 ;;;; $Id: clsql-uffi.lisp,v 1.9 2003/05/16 08:04:02 kevin Exp $
11 ;;;;
12 ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg
13 ;;;;
14 ;;;; CLSQL users are granted the rights to distribute and use this software
15 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
16 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
17 ;;;; *************************************************************************
18
19 (declaim (optimize (debug 3) (speed 3) (safety 1) (compilation-speed 0)))
20 (in-package :clsql-uffi)
21
22
23 (defun canonicalize-type-list (types auto-list)
24   "Ensure a field type list meets expectations"
25   (let ((length-types (length types))
26         (new-types '()))
27     (loop for i from 0 below (length auto-list)
28           do
29           (if (>= i length-types)
30               (push t new-types) ;; types is shorted than num-fields
31               (push
32                (case (nth i types)
33                  (:int
34                   (case (nth i auto-list)
35                     (:int32
36                      :int32)
37                     (:int64
38                      :int64)
39                     (t
40                      t)))
41                  (:double
42                   (case (nth i auto-list)
43                     (:double
44                      :double)
45                     (t
46                      t)))
47                  (:int32
48                   (if (eq :int32 (nth i auto-list))
49                       :int32
50                     t))
51                  (:int64
52                   (if (eq :int64 (nth i auto-list))
53                       :int64
54                     t))
55                  (t
56                   t))
57                new-types)))
58     (nreverse new-types)))
59
60 (uffi:def-function "atoi"
61     ((str (* :unsigned-char)))
62   :returning :int)
63
64 (uffi:def-function "atol"
65     ((str (* :unsigned-char)))
66   :returning :long)
67
68 (uffi:def-function "atof"
69     ((str (* :unsigned-char)))
70   :returning :double)
71
72 (uffi:def-function "atol64"
73     ((str (* :unsigned-char))
74      (high32 (* :int)))
75   :returning :unsigned-int)
76
77 (uffi:def-constant +2^32+ 4294967296)
78 (uffi:def-constant +2^32-1+ (1- +2^32+))
79
80 (defmacro make-64-bit-integer (high32 low32)
81   `(+ ,low32 (* ,high32 +2^32+)))
82
83 (defmacro split-64-bit-integer (int64)
84   `(values (ash ,int64 -32) (logand ,int64 +2^32-1+)))
85
86 (defvar +ascii-N-value+ (char-code #\N))
87 (defvar +ascii-U-value+ (char-code #\U))
88
89 (uffi:def-type char-ptr-def (* :unsigned-char))
90
91 (defun char-ptr-points-to-null (char-ptr)
92   "Returns T if foreign character pointer refers to 'NULL' string. Only called for numeric entries"
93   ;; Uses short cut and returns T if first character is #\N. It should
94   ;; never be non-numeric
95   (declare (type char-ptr-def char-ptr))
96   (let ((char (uffi:ensure-char-character
97                (uffi:deref-pointer char-ptr :char))))
98     (eql char #\N)))
99     
100 (defun convert-raw-field (char-ptr types index)
101   (let ((type (if (listp types)
102                   (nth index types)
103                   types)))
104     (cond
105       ((and (or (eq type :double) (eq type :int32) (eq type :int)
106                 (eq type :int64))
107             (char-ptr-points-to-null char-ptr))
108        nil)
109       (t
110        (case type
111          (:double
112           (atof char-ptr))
113          ((or :int32 :int)
114           (atoi char-ptr))
115          (:int64
116           (uffi:with-foreign-object (high32-ptr :int)
117             (let ((low32 (atol64 char-ptr high32-ptr))
118                   (high32 (uffi:deref-pointer high32-ptr :int)))
119               (if (zerop high32)
120                   low32
121                   (make-64-bit-integer high32 low32)))))
122          (t
123           ;; Choose optimized routine
124           #-(or cmu sbcl)
125           (native-to-string char-ptr)
126           #+(or cmu sbcl)
127           (uffi:convert-from-foreign-string char-ptr)))))))
128   
129
130 (uffi:def-function "strlen"
131     ((str (* :unsigned-char)))
132   :returning :unsigned-int)
133
134 (defun native-to-string (s)
135   (declare (optimize (speed 3) (space 0) (safety 0) (compilation-speed 0))
136            (type char-ptr-def s))
137   (let* ((len (strlen s))
138          (str (make-string len)))
139     (declare (fixnum len)
140              (simple-string str))
141     (do ((i 0))
142         ((= i len))
143       (declare (fixnum i))
144       (setf (schar str i)
145         (code-char (uffi:deref-array s '(:array :unsigned-char) i)))
146       (incf i))
147     str))
148
149 #-allegro
150 (defun native-to-string (s)
151   (declare (optimize (speed 3) (space 0) (safety 0) (compilation-speed 0))
152            (type char-ptr-def s))
153   (let* ((len (strlen s))
154          (str (make-string len)))
155     (declare (fixnum len)
156              (simple-string str))
157     (do ((i 0))
158         ((= i len))
159       (declare (fixnum i))
160       (setf (schar str i)
161         (code-char (uffi:deref-array s '(:array :unsigned-char) i)))
162       (incf i))
163     str))
164
165 #+allegro
166 (excl:ics-target-case
167  (:-ics
168   (defun native-to-string (s)
169     (declare (optimize (speed 3) (space 0) (safety 0) (compilation-speed 0))
170              (type char-ptr-def s))
171     (let* ((len (strlen s))
172            (str (make-string len)))
173       (declare (fixnum len)
174                (simple-string str))
175       (do ((i 0))
176           ((= i len))
177         (declare (fixnum i))
178         (setf (schar str i)
179               (code-char (uffi:deref-array s '(:array :unsigned-char) i)))
180         (incf i))
181     str)))
182  (:+ics
183   (defun native-to-string (s)
184   (declare (optimize (speed 3) (space 0) (safety 0) (compilation-speed 0))
185            (type char-ptr-def s))
186   (let* ((len (strlen s))
187          (str (make-string len)))
188     (declare (fixnum len)
189              (type (simple-array (unsigned-byte 8) (*)) str))
190     (do ((i 0))
191         ((= i len))
192       (declare (fixnum i))
193       (setf (aref str i) (uffi:deref-array s '(:array :unsigned-char) i))
194       (incf i))
195     str))))