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