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 + -
显示快捷键?