Merge branch 'master' of git://git.b9.com/clsql
[clsql/s11.git] / uffi / clsql-uffi.lisp
blob4f9479d0b1c0f97025ce05a0a7142492757d502b
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$
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 ;;;; *************************************************************************
19 (in-package #:clsql-uffi)
22 (defun canonicalize-type-list (types auto-list)
23 "Ensure a field type list meets expectations"
24 (declare (optimize (speed 3) (safety 0)))
25 (do ((i 0 (1+ i))
26 (new-types '())
27 (length-types (length types))
28 (length-auto-list (length auto-list)))
29 ((= i length-auto-list)
30 (nreverse new-types))
31 (declare (fixnum length-types length-auto-list i))
32 (if (>= i length-types)
33 (push t new-types) ;; types is shorter than num-fields
34 (push
35 (case (nth i types)
36 (:int
37 (case (nth i auto-list)
38 (:int32
39 :int32)
40 (:int64
41 :int64)
43 t)))
44 (:double
45 (case (nth i auto-list)
46 (:double
47 :double)
49 t)))
50 (:int32
51 (if (eq :int32 (nth i auto-list))
52 :int32
53 t))
54 (:int64
55 (if (eq :int64 (nth i auto-list))
56 :int64
57 t))
58 (:blob
59 :blob)
60 (:uint
61 :uint)
63 t))
64 new-types))))
66 (uffi:def-function "atoi"
67 ((str (* :unsigned-char)))
68 :returning :int)
70 (uffi:def-function ("strtoul" c-strtoul)
71 ((str (* :unsigned-char))
72 (endptr (* :unsigned-char))
73 (radix :int))
74 :returning :unsigned-long)
76 (uffi:def-function "atol"
77 ((str (* :unsigned-char)))
78 :returning :long)
80 (uffi:def-function "atof"
81 ((str (* :unsigned-char)))
82 :returning :double)
84 (uffi:def-function "atol64"
85 ((str (* :unsigned-char))
86 (high32 (* :unsigned-int)))
87 :module "clsql-uffi"
88 :returning :unsigned-int)
90 (uffi:def-constant +2^32+ 4294967296)
91 (uffi:def-constant +2^64+ 18446744073709551616)
92 (uffi:def-constant +2^32-1+ (1- +2^32+))
94 (defmacro make-64-bit-integer (high32 low32)
95 `(if (zerop (ldb (byte 1 31) ,high32))
96 (+ ,low32 (ash ,high32 32))
97 (- (+ ,low32 (ash ,high32 32)) +2^64+)))
99 ;; From high to low ints
100 (defmacro make-128-bit-integer (a b c d)
101 `(+ ,d (ash ,c 32) (ash ,b 64) (ash ,a 96)))
103 (defmacro split-64-bit-integer (int64)
104 `(values (ash ,int64 -32) (logand ,int64 +2^32-1+)))
106 (uffi:def-type char-ptr-def (* :unsigned-char))
108 (defun strtoul (char-ptr)
109 (declare (optimize (speed 3) (safety 0) (space 0))
110 (type char-ptr-def char-ptr))
111 (c-strtoul char-ptr uffi:+null-cstring-pointer+ 10))
113 (defun convert-raw-field (char-ptr types index &optional length)
114 (declare (optimize (speed 3) (safety 0) (space 0))
115 (type char-ptr-def char-ptr))
116 (let ((type (if (consp types)
117 (nth index types)
118 types)))
119 (cond
120 ((uffi:null-pointer-p char-ptr)
121 nil)
123 (case type
124 (:double
125 (atof char-ptr))
126 (:int
127 (atol char-ptr))
128 (:int32
129 (atoi char-ptr))
130 (:uint32
131 (strtoul char-ptr))
132 (:uint
133 (strtoul char-ptr))
134 ((:int64 :uint64)
135 (uffi:with-foreign-object (high32-ptr :unsigned-int)
136 (let ((low32 (atol64 char-ptr high32-ptr))
137 (high32 (uffi:deref-pointer high32-ptr :unsigned-int)))
138 (if (zerop high32)
139 low32
140 (make-64-bit-integer high32 low32)))))
141 (:blob
142 (if length
143 (uffi:convert-from-foreign-usb8 char-ptr length)
144 (error "Can't return blob since length is not specified.")))
146 ;; sb-unicode still broken with converting with length, assume
147 ;; that string is null terminated
148 #+sb-unicode
149 (uffi:convert-from-foreign-string char-ptr :locale :none)
150 #-sb-unicode
151 (if length
152 (uffi:convert-from-foreign-string char-ptr :locale :none
153 :null-terminated-p nil
154 :length length)
155 (uffi:convert-from-foreign-string char-ptr :locale :none))))))))