r11859: Canonicalize whitespace
[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$
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 (in-package #:clsql-uffi)
20
21
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)
42               (t
43                t)))
44            (:double
45             (case (nth i auto-list)
46               (:double
47                :double)
48               (t
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)
62            (t
63             t))
64          new-types))))
65
66 (uffi:def-function "atoi"
67     ((str (* :unsigned-char)))
68   :returning :int)
69
70 (uffi:def-function ("strtoul" c-strtoul)
71     ((str (* :unsigned-char))
72      (endptr (* :unsigned-char))
73      (radix :int))
74   :returning :unsigned-long)
75
76 (uffi:def-function "atol"
77     ((str (* :unsigned-char)))
78   :returning :long)
79
80 (uffi:def-function "atof"
81     ((str (* :unsigned-char)))
82   :returning :double)
83
84 (uffi:def-function "atol64"
85     ((str (* :unsigned-char))
86      (high32 (* :unsigned-int)))
87   :module "clsql-uffi"
88   :returning :unsigned-int)
89
90 (uffi:def-constant +2^32+ 4294967296)
91 (uffi:def-constant +2^64+ 18446744073709551616)
92 (uffi:def-constant +2^32-1+ (1- +2^32+))
93
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+)))
98
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)))
102
103 (defmacro split-64-bit-integer (int64)
104   `(values (ash ,int64 -32) (logand ,int64 +2^32-1+)))
105
106 (uffi:def-type char-ptr-def (* :unsigned-char))
107
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))
112
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)
122       (t
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.")))
145          (t
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))))))))
156