odbcutil.c

来自「这个是内存数据库的客户端」· C语言 代码 · 共 462 行 · 第 1/2 页

C
462
字号
/* * The contents of this file are subject to the MonetDB Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://monetdb.cwi.nl/Legal/MonetDBLicense-1.1.html * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Original Code is the MonetDB Database System. * * The Initial Developer of the Original Code is CWI. * Portions created by CWI are Copyright (C) 1997-2007 CWI. * All Rights Reserved. *//* * This code was created by Peter Harvey (mostly during Christmas 98/99). * This code is LGPL. Please ensure that this message remains in future * distributions and uses of this code (thats about all I get out of it). * - Peter Harvey pharvey@codebydesign.com *  * This file has been modified for the MonetDB project.  See the file * Copyright in this directory for more information. *//********************************************** * ODBCUtil.c * * Description: * This file contains utility functions for * the ODBC driver implementation. * * Author: Martin van Dinther * Date  : 30 aug 2002 * **********************************************/#include "ODBCUtil.h"#include <float.h>#ifdef WIN32/* Windows seems to need this */BOOL WINAPIDllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved){#ifdef ODBCDEBUG	ODBCLOG("DllMain %ld\n", (long) reason);#endif	(void) hinstDLL;	(void) reason;	(void) reserved;	return TRUE;}#endif/* * Utility function to duplicate an ODBC string (with a length * specified, may not be null terminated) to a normal C string (null * terminated). * * Precondition: inStr != NULL * Postcondition: returns a newly allocated null terminated string. */char *dupODBCstring(const SQLCHAR *inStr, size_t length){	char *tmp = (char *) malloc((length + 1) * sizeof(char));	assert(tmp);	strncpy(tmp, (char *) inStr, length);	tmp[length] = '\0';	/* make it null terminated */	return tmp;}#ifdef WITH_WCHAR/* Conversion to and from SQLWCHAR */static int utf8chkmsk[] = {	0x0000007f,	0x00000780,	0x0000f800,	0x001f0000,	0x03e00000,	0x7c000000};#define LEAD_OFFSET		(0xD800 - (0x10000 >> 10))#define SURROGATE_OFFSET	(0x10000 - (0xD800 << 10) - 0xDC00)/* Convert a SQLWCHAR (UTF-16 encoded string) to UTF-8.  On success,   clears the location pointed to by errmsg and returns NULL or a   newly allocated buffer.  On error, assigns a string with an error   message to the location pointed to by errmsg and returns NULL.   The first two arguments describe the input string in the normal   ODBC fashion.*/SQLCHAR *ODBCwchar2utf8(const SQLWCHAR *s, SQLINTEGER length, char **errmsg){	const SQLWCHAR *s1;	unsigned long c;	SQLCHAR *buf, *p;	int i, l, n;	if (errmsg)		*errmsg = NULL;	if (s == NULL)		return NULL;	if (length == SQL_NTS)		for (s1 = s, length = 0; *s1; s1++)			length++;	else if (length == SQL_NULL_DATA)		return NULL;	else if (length < 0) {		if (errmsg)			*errmsg = "Invalid length parameter";		return NULL;	}	/* count necessary length */	l = 1;			/* space for NULL byte */	for (s1 = s, i = 0; i < length; s1++, i++) {		c = *s1;		if (0xD800 <= c && c <= 0xDBFF) {			/* high surrogate, must be followed by low surrogate */			s1++;			i++;			if (i >= length || *s1 < 0xDC00 || *s1 > 0xDFFF) {				if (errmsg)					*errmsg = "High surrogate not followed by low surrogate";				return NULL;			}			c = (c << 10) + *s1 + SURROGATE_OFFSET;		} else if (0xDC00 <= c && c <= 0xDFFF) {			/* low surrogate--illegal */			if (errmsg)				*errmsg = "Low surrogate not preceded by high surrogate";			return NULL;		}		for (n = 5; n > 0; n--)			if (c & utf8chkmsk[n])				break;		l += n + 1;	}	/* convert */	buf = (SQLCHAR *) malloc(l);	for (s1 = s, p = buf, i = 0; i < length; s1++, i++) {		c = *s1;		if (0xD800 <= c && c <= 0xDBFF) {			/* high surrogate followed by low surrogate */			s1++;			i++;			c = (c << 10) + *s1 + SURROGATE_OFFSET;		}		for (n = 5; n > 0; n--)			if (c & utf8chkmsk[n])				break;		if (n == 0)			*p++ = (SQLCHAR) c;		else {			*p++ = (SQLCHAR) (((c >> (n * 6)) | (0x1F80 >> n)) & 0xFF);			while (--n >= 0)				*p++ = (SQLCHAR) (((c >> (n * 6)) & 0x3F) | 0x80);		}	}	*p = 0;	return buf;}/* Convert a UTF-8 encoded string to UTF-16 (SQLWCHAR).  On success   returns NULL, on error returns a string with an error message.  The   first two arguments describe the input, the last three arguments   describe the output, both in the normal ODBC fashion. */char *ODBCutf82wchar(const SQLCHAR *s, SQLINTEGER length, SQLWCHAR * buf, SQLINTEGER buflen, SQLSMALLINT *buflenout){	SQLWCHAR *p;	int i, m, n;	unsigned int c;	if (buflenout)		*buflenout = 0;	if (s == NULL || length == SQL_NULL_DATA || buf == NULL) {		if (buf && buflen > 0)			*buf = 0;		return NULL;	}	if (length == SQL_NTS)		length = (SQLINTEGER) strlen((const char *) s);	else if (length < 0)		return "Invalid length parameter";	for (p = buf, i = 0; i < length; i++) {		c = *s++;		if ((c & 0x80) != 0) {			for (n = 0, m = 0x40; c & m; n++, m >>= 1) ;			/* n now is number of 10xxxxxx bytes that			 * should follow */			c &= ~(0xFFC0) >> n;			while (--n >= 0) {				i++;				c <<= 6;				c |= *s++ & 0x3F;			}		}		if ((c & 0xF8) == 0xD8) {			/* UTF-8 encoded high or low surrogate */			free(buf);			return "Illegal code point";		}		if (c > 0x10FFFF) {			/* cannot encode as UTF-16 */			free(buf);			return "Codepoint too large to be representable in UTF-16";		}		if (c <= 0xFFFF) {			if (--buflen > 0)				*p++ = c;			if (buflenout)				(*buflenout)++;		} else {			if ((buflen -= 2) > 0) {				*p++ = LEAD_OFFSET + (c >> 10);				*p++ = 0xDC00 + (c & 0x3FF);			}			if (buflenout)				*buflenout += 2;		}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?