1 // Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
2 //
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License, version 2.0, as
5 // published by the Free Software Foundation.
6 //
7 // This program is also distributed with certain software (including
8 // but not limited to OpenSSL) that is licensed under separate terms,
9 // as designated in a particular file or component or in included license
10 // documentation. The authors of MySQL hereby grant you an
11 // additional permission to link the program and your derivative works
12 // with the separately licensed software that they have included with
13 // MySQL.
14 //
15 // Without limiting anything contained in the foregoing, this file,
16 // which is part of MySQL Server, is also subject to the
17 // Universal FOSS Exception, version 1.0, a copy of which can be found at
18 // http://oss.oracle.com/licenses/universal-foss-exception.
19 //
20 // This program is distributed in the hope that it will be useful, but
21 // WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 // See the GNU General Public License, version 2.0, for more details.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with this program; if not, write to the Free Software Foundation, Inc.,
27 // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28
29 #ifndef _m_string_h
30 #define _m_string_h
31
32 /**
33 @file include/m_string.h
34 */
35
36 #include <float.h>
37 #include <stdbool.h> // IWYU pragma: keep
38 #include <stdint.h>
39 #include <stdlib.h>
40 #include <string.h>
41
42 #include "lex_string.h"
43 #include "my_config.h"
44 #include "my_inttypes.h"
45 #include "my_macros.h"
46
47 /**
48 Definition of the null string (a null pointer of type char *),
49 used in some of our string handling code. New code should use
50 nullptr instead.
51 */
52 #define NullS (char *)0
53
54 /*
55 my_str_malloc(), my_str_realloc() and my_str_free() are assigned to
56 implementations in strings/alloc.c, but can be overridden in
57 the calling program.
58 */
59 extern void *(*my_str_malloc)(size_t);
60 extern void *(*my_str_realloc)(void *, size_t);
61 extern void (*my_str_free)(void *);
62
63 /* Declared in int2str() */
64 extern char _dig_vec_upper[];
65 extern char _dig_vec_lower[];
66
67 /* Prototypes for string functions */
68
69 extern char *strmake(char *dst, const char *src, size_t length);
70 extern char *strcont(const char *src, const char *set);
71 extern char *strxmov(char *dst, const char *src, ...);
72 extern char *strxnmov(char *dst, size_t len, const char *src, ...);
73
74 /*
75 bchange(dst, old_length, src, new_length, tot_length)
76 replaces old_length characters at dst to new_length characters from
77 src in a buffer with tot_length bytes.
78 */
bchange(uchar * dst,size_t old_length,const uchar * src,size_t new_length,size_t tot_length)79 static inline void bchange(uchar *dst, size_t old_length, const uchar *src,
80 size_t new_length, size_t tot_length) {
81 memmove(dst + new_length, dst + old_length, tot_length - old_length);
82 memcpy(dst, src, new_length);
83 }
84
85 /*
86 strend(s) returns a character pointer to the NUL which ends s. That
87 is, strend(s)-s == strlen(s). This is useful for adding things at
88 the end of strings. It is redundant, because strchr(s,'\0') could
89 be used instead, but this is clearer and faster.
90 */
strend(const char * s)91 static inline char *strend(const char *s) {
92 while (*s++)
93 ;
94 return (char *)(s - 1);
95 }
96
97 /*
98 strcend(s, c) returns a pointer to the first place in s where c
99 occurs, or a pointer to the end-null of s if c does not occur in s.
100 */
strcend(const char * s,char c)101 static inline char *strcend(const char *s, char c) {
102 for (;;) {
103 if (*s == (char)c) return (char *)s;
104 if (!*s++) return (char *)s - 1;
105 }
106 }
107
108 /*
109 strfill(dest, len, fill) makes a string of fill-characters. The result
110 string is of length == len. The des+len character is allways set to NULL.
111 strfill() returns pointer to dest+len;
112 */
strfill(char * s,size_t len,char fill)113 static inline char *strfill(char *s, size_t len, char fill) {
114 while (len--) *s++ = fill;
115 *(s) = '\0';
116 return (s);
117 }
118
119 /*
120 my_stpmov(dst, src) moves all the characters of src (including the
121 closing NUL) to dst, and returns a pointer to the new closing NUL in
122 dst. The similar UNIX routine strcpy returns the old value of dst,
123 which I have never found useful. my_stpmov(my_stpmov(dst,a),b) moves a//b
124 into dst, which seems useful.
125 */
my_stpmov(char * dst,const char * src)126 static inline char *my_stpmov(char *dst, const char *src) {
127 while ((*dst++ = *src++))
128 ;
129 return dst - 1;
130 }
131
132 /*
133 my_stpnmov(dst,src,length) moves length characters, or until end, of src to
134 dst and appends a closing NUL to dst if src is shorter than length.
135 The result is a pointer to the first NUL in dst, or is dst+n if dst was
136 truncated.
137 */
my_stpnmov(char * dst,const char * src,size_t n)138 static inline char *my_stpnmov(char *dst, const char *src, size_t n) {
139 while (n-- != 0) {
140 if (!(*dst++ = *src++)) return (char *)dst - 1;
141 }
142 return dst;
143 }
144
145 /**
146 Copy a string from src to dst until (and including) terminating null byte.
147
148 @param dst Destination
149 @param src Source
150
151 @note src and dst cannot overlap.
152 Use my_stpmov() if src and dst overlaps.
153
154 @note Unsafe, consider using my_stpnpy() instead.
155
156 @return pointer to terminating null byte.
157 */
my_stpcpy(char * dst,const char * src)158 static inline char *my_stpcpy(char *dst, const char *src) {
159 #if defined(HAVE_BUILTIN_STPCPY)
160 return __builtin_stpcpy(dst, src);
161 #elif defined(HAVE_STPCPY)
162 return stpcpy(dst, src);
163 #else
164 /* Fallback to implementation supporting overlap. */
165 return my_stpmov(dst, src);
166 #endif
167 }
168
169 /**
170 Copy fixed-size string from src to dst.
171
172 @param dst Destination
173 @param src Source
174 @param n Maximum number of characters to copy.
175
176 @note src and dst cannot overlap
177 Use my_stpnmov() if src and dst overlaps.
178
179 @return pointer to terminating null byte.
180 */
my_stpncpy(char * dst,const char * src,size_t n)181 static inline char *my_stpncpy(char *dst, const char *src, size_t n) {
182 #if defined(HAVE_STPNCPY)
183 return stpncpy(dst, src, n);
184 #else
185 /* Fallback to implementation supporting overlap. */
186 return my_stpnmov(dst, src, n);
187 #endif
188 }
189
my_strtoll(const char * nptr,char ** endptr,int base)190 static inline longlong my_strtoll(const char *nptr, char **endptr, int base) {
191 #if defined _WIN32
192 return _strtoi64(nptr, endptr, base);
193 #else
194 return strtoll(nptr, endptr, base);
195 #endif
196 }
197
my_strtoull(const char * nptr,char ** endptr,int base)198 static inline ulonglong my_strtoull(const char *nptr, char **endptr, int base) {
199 #if defined _WIN32
200 return _strtoui64(nptr, endptr, base);
201 #else
202 return strtoull(nptr, endptr, base);
203 #endif
204 }
205
my_strtok_r(char * str,const char * delim,char ** saveptr)206 static inline char *my_strtok_r(char *str, const char *delim, char **saveptr) {
207 #if defined _WIN32
208 return strtok_s(str, delim, saveptr);
209 #else
210 return strtok_r(str, delim, saveptr);
211 #endif
212 }
213
214 /* native_ rather than my_ since my_strcasecmp already exists */
native_strcasecmp(const char * s1,const char * s2)215 static inline int native_strcasecmp(const char *s1, const char *s2) {
216 #if defined _WIN32
217 return _stricmp(s1, s2);
218 #else
219 return strcasecmp(s1, s2);
220 #endif
221 }
222
223 /* native_ rather than my_ for consistency with native_strcasecmp */
native_strncasecmp(const char * s1,const char * s2,size_t n)224 static inline int native_strncasecmp(const char *s1, const char *s2, size_t n) {
225 #if defined _WIN32
226 return _strnicmp(s1, s2, n);
227 #else
228 return strncasecmp(s1, s2, n);
229 #endif
230 }
231
232 /*
233 is_prefix(s, t) returns 1 if s starts with t.
234 A empty t is always a prefix.
235 */
is_prefix(const char * s,const char * t)236 static inline int is_prefix(const char *s, const char *t) {
237 while (*t)
238 if (*s++ != *t++) return 0;
239 return 1; /* WRONG */
240 }
241
242 /* Conversion routines */
243 typedef enum { MY_GCVT_ARG_FLOAT, MY_GCVT_ARG_DOUBLE } my_gcvt_arg_type;
244
245 double my_strtod(const char *str, char **end, int *error);
246 double my_atof(const char *nptr);
247 size_t my_fcvt(double x, int precision, char *to, bool *error);
248 size_t my_gcvt(double x, my_gcvt_arg_type type, int width, char *to,
249 bool *error);
250
251 #define NOT_FIXED_DEC 31
252
253 /*
254 The longest string my_fcvt can return is 311 + "precision" bytes.
255 Here we assume that we never cal my_fcvt() with precision >= NOT_FIXED_DEC
256 (+ 1 byte for the terminating '\0').
257 */
258 #define FLOATING_POINT_BUFFER (311 + NOT_FIXED_DEC)
259
260 /*
261 We want to use the 'e' format in some cases even if we have enough space
262 for the 'f' one just to mimic sprintf("%.15g") behavior for large integers,
263 and to improve it for numbers < 10^(-4).
264 That is, for |x| < 1 we require |x| >= 10^(-15), and for |x| > 1 we require
265 it to be integer and be <= 10^DBL_DIG for the 'f' format to be used.
266 We don't lose precision, but make cases like "1e200" or "0.00001" look nicer.
267 */
268 #define MAX_DECPT_FOR_F_FORMAT DBL_DIG
269
270 /*
271 The maximum possible field width for my_gcvt() conversion.
272 (DBL_DIG + 2) significant digits + sign + "." + ("e-NNN" or
273 MAX_DECPT_FOR_F_FORMAT zeros for cases when |x|<1 and the 'f' format is used).
274 */
275 #define MY_GCVT_MAX_FIELD_WIDTH \
276 (DBL_DIG + 4 + MY_MAX(5, MAX_DECPT_FOR_F_FORMAT))
277
278 extern char *int2str(long val, char *dst, int radix, int upcase);
279 C_MODE_START
280 extern char *int10_to_str(long val, char *dst, int radix);
281 C_MODE_END
282 extern char *str2int(const char *src, int radix, long lower, long upper,
283 long *val);
284 longlong my_strtoll10(const char *nptr, char **endptr, int *error);
285 #if SIZEOF_LONG == SIZEOF_LONG_LONG
286 #define ll2str(A, B, C, D) int2str((A), (B), (C), (D))
287 #define longlong10_to_str(A, B, C) int10_to_str((A), (B), (C))
288 #undef strtoll
289 #define strtoll(A, B, C) strtol((A), (B), (C))
290 #define strtoull(A, B, C) strtoul((A), (B), (C))
291 #else
292 extern char *ll2str(longlong val, char *dst, int radix, int upcase);
293 extern char *longlong10_to_str(longlong val, char *dst, int radix);
294 #endif
295 #define longlong2str(A, B, C) ll2str((A), (B), (C), 1)
296
297 /*
298 This function saves a longlong value in a buffer and returns the pointer to
299 the buffer.
300 */
llstr(longlong value,char * buff)301 static inline char *llstr(longlong value, char *buff) {
302 longlong10_to_str(value, buff, -10);
303 return buff;
304 }
305
ullstr(longlong value,char * buff)306 static inline char *ullstr(longlong value, char *buff) {
307 longlong10_to_str(value, buff, 10);
308 return buff;
309 }
310
311 #define STRING_WITH_LEN(X) (X), ((sizeof(X) - 1))
312 #define USTRING_WITH_LEN(X) ((uchar *)X), ((sizeof(X) - 1))
313 #define C_STRING_WITH_LEN(X) ((char *)(X)), ((sizeof(X) - 1))
314
315 /**
316 Skip trailing space (ASCII spaces only).
317
318 @return New end of the string.
319 */
skip_trailing_space(const uchar * ptr,size_t len)320 static inline const uchar *skip_trailing_space(const uchar *ptr, size_t len) {
321 const uchar *end = ptr + len;
322 while (end - ptr >= 8) {
323 uint64_t chunk;
324 memcpy(&chunk, end - 8, sizeof(chunk));
325 if (chunk != 0x2020202020202020ULL) break;
326 end -= 8;
327 }
328 while (end > ptr && end[-1] == 0x20) end--;
329 return (end);
330 }
331
lex_string_set(LEX_STRING * lex_str,const char * c_str)332 static inline void lex_string_set(LEX_STRING *lex_str, const char *c_str) {
333 lex_str->str = (char *)c_str;
334 lex_str->length = strlen(c_str);
335 }
336
lex_cstring_set(LEX_CSTRING * lex_str,const char * c_str)337 static inline void lex_cstring_set(LEX_CSTRING *lex_str, const char *c_str) {
338 lex_str->str = c_str;
339 lex_str->length = strlen(c_str);
340 }
341
342 #endif
343