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