1 #include "common.h"
2 
3 #include <common/test_assert.h>
4 
5 static char *
add_char(char * s,SQLWCHAR ch)6 add_char(char *s, SQLWCHAR ch)
7 {
8 	if (ch == '\\')
9 		s += sprintf(s, "\\\\");
10 	else if (ch == '\t')
11 		s += sprintf(s, "\\t");
12 	else if (ch == '\r')
13 		s += sprintf(s, "\\r");
14 	else if (ch == '\n')
15 		s += sprintf(s, "\\n");
16 	else if ((unsigned int) ch < 32u)
17 		s += sprintf(s, "\\x%02x", (unsigned int) ch);
18 	else if ((unsigned int) ch < 256u)
19 		s += sprintf(s, "%c", (char) ch);
20 	else
21 		s += sprintf(s, "\\u%04x", (unsigned int) ch);
22 	return s;
23 }
24 
25 void
odbc_c2string(char * out,SQLSMALLINT out_c_type,const void * in,size_t in_len)26 odbc_c2string(char *out, SQLSMALLINT out_c_type, const void *in, size_t in_len)
27 {
28 	typedef union {
29 		unsigned char bin[256];
30 		char s[256];
31 		SQLWCHAR ws[256/sizeof(SQLWCHAR)];
32 		SQLINTEGER i;
33 		SQLBIGINT bi;
34 		SQLSMALLINT si;
35 		SQL_NUMERIC_STRUCT num;
36 		SQL_TIMESTAMP_STRUCT ts;
37 	} buf_t;
38 #undef IN
39 #define IN (*((const buf_t*) in))
40         size_t i;
41 	const SQL_NUMERIC_STRUCT *num;
42 	char *s;
43 
44 	out[0] = 0;
45 	s = out;
46 	switch (out_c_type) {
47 	case SQL_C_NUMERIC:
48 		num = &IN.num;
49 		s += sprintf(s, "%d %d %d ", num->precision, num->scale, num->sign);
50 		i = SQL_MAX_NUMERIC_LEN;
51 		for (; i > 0 && !num->val[--i];)
52 			continue;
53                 for (; (int)i >= 0; --i)
54 			s += sprintf(s, "%02X", num->val[i]);
55 		break;
56 	case SQL_C_BINARY:
57 		assert(in_len >= 0);
58 		for (i = 0; i < in_len; ++i)
59 			s += sprintf(s, "%02X", IN.bin[i]);
60 		break;
61 	case SQL_C_CHAR:
62 		assert(IN.s[in_len] == 0);
63 		s += sprintf(s, "%u ", (unsigned int) in_len);
64 		for (i = 0; i < in_len; ++i)
65 			s = add_char(s, (unsigned char) IN.s[i]);
66 		*s = 0;
67 		break;
68 	case SQL_C_WCHAR:
69 		assert(in_len >=0 && (in_len % sizeof(SQLWCHAR)) == 0);
70 		s += sprintf(s, "%u ", (unsigned int) (in_len / sizeof(SQLWCHAR)));
71 		for (i = 0; i < in_len / sizeof(SQLWCHAR); ++i)
72 			s = add_char(s, IN.ws[i]);
73 		*s = 0;
74 		break;
75 	case SQL_C_LONG:
76 		assert(in_len == sizeof(SQLINTEGER));
77 		sprintf(s, "%ld", (long int) IN.i);
78 		break;
79 	case SQL_C_SBIGINT:
80 		assert(in_len == sizeof(SQLBIGINT));
81                 sprintf(s, "%" PRId64, (tds_sysdep_int64_type) IN.bi);
82 		break;
83 	case SQL_C_SHORT:
84 		assert(in_len == sizeof(SQLSMALLINT));
85 		sprintf(s, "%d", (int) IN.si);
86 		break;
87 	case SQL_C_TIMESTAMP:
88 		sprintf(s, "%04d-%02u-%02u %02u:%02u:%02u.%03u",
89 			IN.ts.year, IN.ts.month, IN.ts.day,
90 			IN.ts.hour, IN.ts.minute, IN.ts.second,
91 			(unsigned) (IN.ts.fraction / 1000000u));
92 		break;
93 	default:
94 		/* not supported */
95 		assert(0);
96 		break;
97 	}
98 }
99