Merge commit 'origin/master'
[versaplex.git] / vxodbc / misc.cc
blob44cb46489087a522b50da02cdab66723e201cf0b
1 /*
2 * Description: This module contains miscellaneous routines
3 * such as for debugging/logging and string functions.
4 */
5 #include "psqlodbc.h"
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include <time.h>
13 #ifndef WIN32
14 #include <pwd.h>
15 #include <sys/types.h>
16 #include <unistd.h>
17 #else
18 #include <process.h>
19 #endif
20 #include "connection.h"
21 #include "multibyte.h"
24 * returns STRCPY_FAIL, STRCPY_TRUNCATED, or #bytes copied
25 * (not including null term)
27 ssize_t
28 my_strcpy(char *dst, ssize_t dst_len, const char *src, ssize_t src_len)
30 if (dst_len <= 0)
31 return STRCPY_FAIL;
33 if (src_len == SQL_NULL_DATA)
35 dst[0] = '\0';
36 return STRCPY_NULL;
37 } else if (src_len == SQL_NTS)
38 src_len = strlen(src);
40 if (src_len <= 0)
41 return STRCPY_FAIL;
42 else
44 if (src_len < dst_len)
46 memcpy(dst, src, src_len);
47 dst[src_len] = '\0';
48 } else
50 memcpy(dst, src, dst_len - 1);
51 dst[dst_len - 1] = '\0'; /* truncated */
52 return STRCPY_TRUNCATED;
56 return strlen(dst);
61 * strncpy copies up to len characters, and doesn't terminate
62 * the destination string if src has len characters or more.
63 * instead, I want it to copy up to len-1 characters and always
64 * terminate the destination string.
66 char *strncpy_null(char *dst, const char *src, ssize_t len)
68 int i;
70 if (NULL != dst)
72 /* Just in case, check for special lengths */
73 if (len == SQL_NULL_DATA)
75 dst[0] = '\0';
76 return NULL;
77 } else if (len == SQL_NTS)
78 len = strlen(src) + 1;
80 for (i = 0; src[i] && i < len - 1; i++)
81 dst[i] = src[i];
83 if (len > 0)
84 dst[i] = '\0';
86 return dst;
90 /*------
91 * Create a null terminated string (handling the SQL_NTS thing):
92 * 1. If buf is supplied, place the string in there
93 * (assumes enough space) and return buf.
94 * 2. If buf is not supplied, malloc space and return this string
95 *------
97 char *make_string(const unsigned char *_s, ssize_t len, char *buf, size_t bufsize)
99 size_t length;
100 const char *s = (const char *)_s;
101 char *str;
103 if (!s || SQL_NULL_DATA == len)
104 return NULL;
105 if (len >= 0)
106 length = len;
107 else if (SQL_NTS == len)
108 length = strlen(s);
109 else
111 mylog("make_string invalid length=%d\n", len);
112 return NULL;
114 if (buf)
116 strncpy_null(buf, s, bufsize > length ? length + 1 : bufsize);
117 return buf;
120 inolog("malloc size=%d\n", length);
121 str = (char *)malloc(length + 1);
122 inolog("str=%p\n", str);
123 if (!str)
124 return NULL;
126 strncpy_null(str, s, length + 1);
127 return str;
130 /*------
131 * Create a null terminated lower-case string if the
132 * original string contains upper-case characters.
133 * The SQL_NTS length is considered.
134 *------
136 char *make_lstring_ifneeded(ConnectionClass * conn, const void *_s,
137 ssize_t len, BOOL ifallupper)
139 const char *s = (const char *)_s;
140 ssize_t length = len;
141 char *str = NULL;
143 if (s && (len > 0 || (len == SQL_NTS && (length = strlen(s)) > 0)))
145 int i;
146 const char *ptr;
147 encoded_str encstr;
149 make_encoded_str(&encstr, conn, s);
150 for (i = 0, ptr = s; i < length; i++, ptr++)
152 encoded_nextchar(&encstr);
153 if (ENCODE_STATUS(encstr) != 0)
154 continue;
155 if (ifallupper && islower(*ptr))
157 if (str)
159 free(str);
160 str = NULL;
162 break;
164 if (tolower(*ptr) != *ptr)
166 if (!str)
168 str = (char *)malloc(length + 1);
169 memcpy(str, s, length);
170 str[length] = '\0';
172 str[i] = tolower(*ptr);
177 return str;
182 * Concatenate a single formatted argument to a given buffer handling the SQL_NTS thing.
183 * "fmt" must contain somewhere in it the single form '%.*s'.
184 * This is heavily used in creating queries for info routines (SQLTables, SQLColumns).
185 * This routine could be modified to use vsprintf() to handle multiple arguments.
187 char *my_strcat(char *buf, const char *fmt, const char *s, ssize_t len)
189 if (s && (len > 0 || (len == SQL_NTS && strlen(s) > 0)))
191 size_t length = (len > 0) ? len : strlen(s);
193 size_t pos = strlen(buf);
195 sprintf(&buf[pos], fmt, length, s);
196 return buf;
198 return NULL;
201 char *schema_strcat(char *buf, const char *fmt, const char *s,
202 ssize_t len, const char *tbname, int tbnmlen,
203 ConnectionClass * conn)
205 if (!s || 0 == len)
208 * Note that this driver assumes the implicit schema is
209 * the CURRENT_SCHEMA() though it doesn't worth the
210 * naming.
212 if (conn->schema_support && tbname
213 && (tbnmlen > 0 || tbnmlen == SQL_NTS))
214 return my_strcat(buf, fmt, CC_get_current_schema(conn),
215 SQL_NTS);
216 return NULL;
218 return my_strcat(buf, fmt, s, len);
222 void remove_newlines(char *string)
224 size_t i, len = strlen(string);
226 for (i = 0; i < len; i++)
228 if ((PG_LINEFEED == string[i]) ||
229 (PG_CARRIAGE_RETURN == string[i]))
230 string[i] = ' ';
235 char *trim(char *s)
237 size_t i;
239 for (i = strlen(s) - 1; i >= 0; i--)
241 if (s[i] == ' ')
242 s[i] = '\0';
243 else
244 break;
247 return s;
251 * my_strcat1 is a extension of my_strcat.
252 * It can have 1 more parameter than my_strcat.
254 char *my_strcat1(char *buf, const char *fmt, const char *s1,
255 const char *s, ssize_t len)
257 ssize_t length = len;
259 if (s && (len > 0 || (len == SQL_NTS && (length = strlen(s)) > 0)))
261 size_t pos = strlen(buf);
263 if (s1)
264 sprintf(&buf[pos], fmt, s1, length, s);
265 else
266 sprintf(&buf[pos], fmt, length, s);
267 return buf;
269 return NULL;
272 char *schema_strcat1(char *buf, const char *fmt, const char *s1,
273 const char *s, ssize_t len, const char *tbname,
274 int tbnmlen, ConnectionClass * conn)
276 if (!s || 0 == len)
278 if (conn->schema_support && tbname
279 && (tbnmlen > 0 || tbnmlen == SQL_NTS))
280 return my_strcat1(buf, fmt, s1, CC_get_current_schema(conn),
281 SQL_NTS);
282 return NULL;
284 return my_strcat1(buf, fmt, s1, s, len);
288 * snprintf_add is a extension to snprintf
289 * It add format to buf at given pos
292 int snprintf_add(char *buf, size_t size, const char *format, ...)
294 int len;
295 size_t pos = strlen(buf);
296 va_list arglist;
298 va_start(arglist, format);
299 len = vsnprintf(buf + pos, size - pos, format, arglist);
300 va_end(arglist);
301 return len;
305 * snprintf_addlen is a extension to snprintf
306 * It returns strlen of buf every time (not -1 when truncated)
309 size_t snprintf_len(char *buf, size_t size, const char *format, ...)
311 ssize_t len;
312 va_list arglist;
314 va_start(arglist, format);
315 if ((len = vsnprintf(buf, size, format, arglist)) < 0)
316 len = size;
317 va_end(arglist);
318 return len;