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