1/*****************************************************************************
2
3Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License, version 2.0,
7as published by the Free Software Foundation.
8
9This program is also distributed with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation.  The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have included with MySQL.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License, version 2.0, for more details.
20
21You should have received a copy of the GNU General Public License along with
22this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24
25*****************************************************************************/
26
27/*******************************************************************//**
28@file include/ut0mem.ic
29Memory primitives
30
31Created 5/30/1994 Heikki Tuuri
32************************************************************************/
33
34#include "ut0byte.h"
35#include "mach0data.h"
36
37/** Wrapper for memcpy(3).  Copy memory area when the source and
38target are not overlapping.
39* @param dest	in: copy to
40* @param sour	in: copy from
41* @param n	in: number of bytes to copy
42* @return	dest */
43UNIV_INLINE
44void*
45ut_memcpy(void* dest, const void* sour, ulint n)
46{
47	return(memcpy(dest, sour, n));
48}
49
50/** Wrapper for memmove(3).  Copy memory area when the source and
51target are overlapping.
52* @param dest	in: copy to
53* @param sour	in: copy from
54* @param n	in: number of bytes to copy
55* @return	dest */
56UNIV_INLINE
57void*
58ut_memmove(void* dest, const void* sour, ulint n)
59{
60	return(memmove(dest, sour, n));
61}
62
63/** Wrapper for memcmp(3).  Compare memory areas.
64* @param str1	in: first memory block to compare
65* @param str2	in: second memory block to compare
66* @param n	in: number of bytes to compare
67* @return	negative, 0, or positive if str1 is smaller, equal,
68		or greater than str2, respectively. */
69UNIV_INLINE
70int
71ut_memcmp(const void* str1, const void* str2, ulint n)
72{
73	return(memcmp(str1, str2, n));
74}
75
76/** Wrapper for strcpy(3).  Copy a NUL-terminated string.
77* @param dest	in: copy to
78* @param sour	in: copy from
79* @return	dest */
80UNIV_INLINE
81char*
82ut_strcpy(char* dest, const char* sour)
83{
84	return(strcpy(dest, sour));
85}
86
87/** Wrapper for strlen(3).  Determine the length of a NUL-terminated string.
88* @param str	in: string
89* @return	length of the string in bytes, excluding the terminating NUL */
90UNIV_INLINE
91ulint
92ut_strlen(const char* str)
93{
94	return(strlen(str));
95}
96
97/** Wrapper for strcmp(3).  Compare NUL-terminated strings.
98* @param str1	in: first string to compare
99* @param str2	in: second string to compare
100* @return	negative, 0, or positive if str1 is smaller, equal,
101		or greater than str2, respectively. */
102UNIV_INLINE
103int
104ut_strcmp(const char* str1, const char* str2)
105{
106	return(strcmp(str1, str2));
107}
108
109/**********************************************************************//**
110Converts a raw binary data to a NUL-terminated hex string. The output is
111truncated if there is not enough space in "hex", make sure "hex_size" is at
112least (2 * raw_size + 1) if you do not want this to happen. Returns the
113actual number of characters written to "hex" (including the NUL).
114@return	number of chars written */
115UNIV_INLINE
116ulint
117ut_raw_to_hex(
118/*==========*/
119	const void*	raw,		/*!< in: raw data */
120	ulint		raw_size,	/*!< in: "raw" length in bytes */
121	char*		hex,		/*!< out: hex string */
122	ulint		hex_size)	/*!< in: "hex" size in bytes */
123{
124
125#ifdef WORDS_BIGENDIAN
126
127#define MK_UINT16(a, b) (((uint16) (a)) << 8 | (uint16) (b))
128
129#define UINT16_GET_A(u)	((unsigned char) ((u) >> 8))
130#define UINT16_GET_B(u)	((unsigned char) ((u) & 0xFF))
131
132#else /* WORDS_BIGENDIAN */
133
134#define MK_UINT16(a, b) (((uint16) (b)) << 8 | (uint16) (a))
135
136#define UINT16_GET_A(u)	((unsigned char) ((u) & 0xFF))
137#define UINT16_GET_B(u)	((unsigned char) ((u) >> 8))
138
139#endif /* WORDS_BIGENDIAN */
140
141#define MK_ALL_UINT16_WITH_A(a)	\
142	MK_UINT16(a, '0'),	\
143	MK_UINT16(a, '1'),	\
144	MK_UINT16(a, '2'),	\
145	MK_UINT16(a, '3'),	\
146	MK_UINT16(a, '4'),	\
147	MK_UINT16(a, '5'),	\
148	MK_UINT16(a, '6'),	\
149	MK_UINT16(a, '7'),	\
150	MK_UINT16(a, '8'),	\
151	MK_UINT16(a, '9'),	\
152	MK_UINT16(a, 'A'),	\
153	MK_UINT16(a, 'B'),	\
154	MK_UINT16(a, 'C'),	\
155	MK_UINT16(a, 'D'),	\
156	MK_UINT16(a, 'E'),	\
157	MK_UINT16(a, 'F')
158
159	static const uint16	hex_map[256] = {
160		MK_ALL_UINT16_WITH_A('0'),
161		MK_ALL_UINT16_WITH_A('1'),
162		MK_ALL_UINT16_WITH_A('2'),
163		MK_ALL_UINT16_WITH_A('3'),
164		MK_ALL_UINT16_WITH_A('4'),
165		MK_ALL_UINT16_WITH_A('5'),
166		MK_ALL_UINT16_WITH_A('6'),
167		MK_ALL_UINT16_WITH_A('7'),
168		MK_ALL_UINT16_WITH_A('8'),
169		MK_ALL_UINT16_WITH_A('9'),
170		MK_ALL_UINT16_WITH_A('A'),
171		MK_ALL_UINT16_WITH_A('B'),
172		MK_ALL_UINT16_WITH_A('C'),
173		MK_ALL_UINT16_WITH_A('D'),
174		MK_ALL_UINT16_WITH_A('E'),
175		MK_ALL_UINT16_WITH_A('F')
176	};
177	const unsigned char*	rawc;
178	ulint			read_bytes;
179	ulint			write_bytes;
180	ulint			i;
181
182	rawc = (const unsigned char*) raw;
183
184	if (hex_size == 0) {
185
186		return(0);
187	}
188
189	if (hex_size <= 2 * raw_size) {
190
191		read_bytes = hex_size / 2;
192		write_bytes = hex_size;
193	} else {
194
195		read_bytes = raw_size;
196		write_bytes = 2 * raw_size + 1;
197	}
198
199#define LOOP_READ_BYTES(ASSIGN)			\
200	for (i = 0; i < read_bytes; i++) {	\
201		ASSIGN;				\
202		hex += 2;			\
203		rawc++;				\
204	}
205
206	if (ut_align_offset(hex, 2) == 0) {
207
208		LOOP_READ_BYTES(
209			*(uint16*) hex = hex_map[*rawc]
210		);
211	} else {
212
213		LOOP_READ_BYTES(
214			*hex       = UINT16_GET_A(hex_map[*rawc]);
215			*(hex + 1) = UINT16_GET_B(hex_map[*rawc])
216		);
217	}
218
219	if (hex_size <= 2 * raw_size && hex_size % 2 == 0) {
220
221		hex--;
222	}
223
224	*hex = '\0';
225
226	return(write_bytes);
227}
228
229/*******************************************************************//**
230Adds single quotes to the start and end of string and escapes any quotes
231by doubling them. Returns the number of bytes that were written to "buf"
232(including the terminating NUL). If buf_size is too small then the
233trailing bytes from "str" are discarded.
234@return	number of bytes that were written */
235UNIV_INLINE
236ulint
237ut_str_sql_format(
238/*==============*/
239	const char*	str,		/*!< in: string */
240	ulint		str_len,	/*!< in: string length in bytes */
241	char*		buf,		/*!< out: output buffer */
242	ulint		buf_size)	/*!< in: output buffer size
243					in bytes */
244{
245	ulint	str_i;
246	ulint	buf_i;
247
248	buf_i = 0;
249
250	switch (buf_size) {
251	case 3:
252
253		if (str_len == 0) {
254
255			buf[buf_i] = '\'';
256			buf_i++;
257			buf[buf_i] = '\'';
258			buf_i++;
259		}
260		/* FALLTHROUGH */
261	case 2:
262	case 1:
263
264		buf[buf_i] = '\0';
265		buf_i++;
266		/* FALLTHROUGH */
267	case 0:
268
269		return(buf_i);
270	}
271
272	/* buf_size >= 4 */
273
274	buf[0] = '\'';
275	buf_i = 1;
276
277	for (str_i = 0; str_i < str_len; str_i++) {
278
279		char	ch;
280
281		if (buf_size - buf_i == 2) {
282
283			break;
284		}
285
286		ch = str[str_i];
287
288		switch (ch) {
289		case '\0':
290
291			if (buf_size - buf_i < 4) {
292
293				goto func_exit;
294			}
295			buf[buf_i] = '\\';
296			buf_i++;
297			buf[buf_i] = '0';
298			buf_i++;
299			break;
300		case '\'':
301		case '\\':
302
303			if (buf_size - buf_i < 4) {
304
305				goto func_exit;
306			}
307			buf[buf_i] = ch;
308			buf_i++;
309			/* FALLTHROUGH */
310		default:
311
312			buf[buf_i] = ch;
313			buf_i++;
314		}
315	}
316
317func_exit:
318
319	buf[buf_i] = '\'';
320	buf_i++;
321	buf[buf_i] = '\0';
322	buf_i++;
323
324	return(buf_i);
325}
326