1 /*
2    Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
16 
17 /* There may be prolems include all of theese. Try to test in
18    configure with ones are needed? */
19 
20 /*  This is needed for the definitions of strchr... on solaris */
21 
22 #ifndef _m_string_h
23 #define _m_string_h
24 
25 #include "my_global.h"                          /* HAVE_* */
26 
27 #ifndef __USE_GNU
28 #define __USE_GNU				/* We want to use stpcpy */
29 #endif
30 #if defined(HAVE_STRINGS_H)
31 #include <strings.h>
32 #endif
33 #if defined(HAVE_STRING_H)
34 #include <string.h>
35 #endif
36 
37 /* need by my_vsnprintf */
38 #include <stdarg.h>
39 
40 /*  This is needed for the definitions of bzero... on solaris */
41 #if defined(HAVE_STRINGS_H)
42 #include <strings.h>
43 #endif
44 
45 /*  This is needed for the definitions of memcpy... on solaris */
46 #if defined(HAVE_MEMORY_H) && !defined(__cplusplus)
47 #include <memory.h>
48 #endif
49 
50 #if !defined(HAVE_MEMCPY) && !defined(HAVE_MEMMOVE)
51 # define memcpy(d, s, n)	bcopy ((s), (d), (n))
52 # define memset(A,C,B)		bfill((A),(B),(C))
53 # define memmove(d, s, n)	bmove ((d), (s), (n))
54 #elif defined(HAVE_MEMMOVE)
55 # define bmove(d, s, n)		memmove((d), (s), (n))
56 #endif
57 
58 /* Unixware 7 */
59 #if !defined(HAVE_BFILL)
60 # define bfill(A,B,C)           memset((A),(C),(B))
61 #endif
62 
63 #if !defined(bzero) && (!defined(HAVE_BZERO) || !HAVE_DECL_BZERO || defined(_AIX))
64 /* See autoconf doku: "HAVE_DECL_symbol" will be defined after configure, to 0 or 1 */
65 /* AIX has bzero() as a function, but the declaration prototype is strangely hidden */
66 # define bzero(A,B)             memset((A),0,(B))
67 #endif
68 
69 #if defined(__cplusplus)
70 extern "C" {
71 #endif
72 
73 /*
74   my_str_malloc() and my_str_free() are assigned to implementations in
75   strings/alloc.c, but can be overridden in the calling program.
76  */
77 extern void *(*my_str_malloc)(size_t);
78 extern void (*my_str_free)(void *);
79 
80 #if defined(HAVE_STPCPY) && MY_GNUC_PREREQ(3, 4) && !defined(__INTEL_COMPILER)
81 #define strmov(A,B) __builtin_stpcpy((A),(B))
82 #elif defined(HAVE_STPCPY)
83 #define strmov(A,B) stpcpy((A),(B))
84 #ifndef stpcpy
85 extern char *stpcpy(char *, const char *);	/* For AIX with gcc 2.95.3 */
86 #endif
87 #endif
88 
89 /* Declared in int2str() */
90 extern char _dig_vec_upper[];
91 extern char _dig_vec_lower[];
92 
93 #ifndef strmov
94 #define strmov_overlapp(A,B) strmov(A,B)
95 #define strmake_overlapp(A,B,C) strmake(A,B,C)
96 #endif
97 
98 	/* Prototypes for string functions */
99 
100 extern	void bmove_upp(uchar *dst,const uchar *src,size_t len);
101 extern	void bchange(uchar *dst,size_t old_len,const uchar *src,
102 		     size_t new_len,size_t tot_len);
103 extern	void strappend(char *s,size_t len,pchar fill);
104 extern	char *strend(const char *s);
105 extern  char *strcend(const char *, pchar);
106 extern	char *strfill(char * s,size_t len,pchar fill);
107 extern	char *strmake(char *dst,const char *src,size_t length);
108 
109 #ifndef strmov
110 extern	char *strmov(char *dst,const char *src);
111 #else
112 extern	char *strmov_overlapp(char *dst,const char *src);
113 #endif
114 extern	char *strnmov(char *dst, const char *src, size_t n);
115 extern	char *strcont(const char *src, const char *set);
116 extern	char *strxmov(char *dst, const char *src, ...);
117 extern	char *strxnmov(char *dst, size_t len, const char *src, ...);
118 
119 /* Prototypes of normal stringfunctions (with may ours) */
120 #ifndef HAVE_STRNLEN
121 extern size_t strnlen(const char *s, size_t n);
122 #endif
123 
124 extern int is_prefix(const char *, const char *);
125 
126 /* Conversion routines */
127 typedef enum {
128   MY_GCVT_ARG_FLOAT,
129   MY_GCVT_ARG_DOUBLE
130 } my_gcvt_arg_type;
131 
132 double my_strtod(const char *str, char **end, int *error);
133 double my_atof(const char *nptr);
134 size_t my_fcvt(double x, int precision, char *to, my_bool *error);
135 size_t my_gcvt(double x, my_gcvt_arg_type type, int width, char *to,
136                my_bool *error);
137 
138 #define NOT_FIXED_DEC 31
139 
140 /*
141   The longest string my_fcvt can return is 311 + "precision" bytes.
142   Here we assume that we never cal my_fcvt() with precision >= NOT_FIXED_DEC
143   (+ 1 byte for the terminating '\0').
144 */
145 #define FLOATING_POINT_BUFFER (311 + NOT_FIXED_DEC)
146 
147 /*
148   We want to use the 'e' format in some cases even if we have enough space
149   for the 'f' one just to mimic sprintf("%.15g") behavior for large integers,
150   and to improve it for numbers < 10^(-4).
151   That is, for |x| < 1 we require |x| >= 10^(-15), and for |x| > 1 we require
152   it to be integer and be <= 10^DBL_DIG for the 'f' format to be used.
153   We don't lose precision, but make cases like "1e200" or "0.00001" look nicer.
154 */
155 #define MAX_DECPT_FOR_F_FORMAT DBL_DIG
156 
157 /*
158   The maximum possible field width for my_gcvt() conversion.
159   (DBL_DIG + 2) significant digits + sign + "." + ("e-NNN" or
160   MAX_DECPT_FOR_F_FORMAT zeros for cases when |x|<1 and the 'f' format is used).
161 */
162 #define MY_GCVT_MAX_FIELD_WIDTH (DBL_DIG + 4 + max(5, MAX_DECPT_FOR_F_FORMAT)) \
163 
164 extern char *llstr(longlong value,char *buff);
165 extern char *ullstr(longlong value,char *buff);
166 #ifndef HAVE_STRTOUL
167 extern long strtol(const char *str, char **ptr, int base);
168 extern ulong strtoul(const char *str, char **ptr, int base);
169 #endif
170 
171 extern char *int2str(long val, char *dst, int radix, int upcase);
172 extern char *int10_to_str(long val,char *dst,int radix);
173 extern char *str2int(const char *src,int radix,long lower,long upper,
174 			 long *val);
175 longlong my_strtoll10(const char *nptr, char **endptr, int *error);
176 #if SIZEOF_LONG == SIZEOF_LONG_LONG
177 #define ll2str(A,B,C,D) int2str((A),(B),(C),(D))
178 #define longlong10_to_str(A,B,C) int10_to_str((A),(B),(C))
179 #undef strtoll
180 #define strtoll(A,B,C) strtol((A),(B),(C))
181 #define strtoull(A,B,C) strtoul((A),(B),(C))
182 #ifndef HAVE_STRTOULL
183 #define HAVE_STRTOULL
184 #endif
185 #ifndef HAVE_STRTOLL
186 #define HAVE_STRTOLL
187 #endif
188 #else
189 #ifdef HAVE_LONG_LONG
190 extern char *ll2str(longlong val,char *dst,int radix, int upcase);
191 extern char *longlong10_to_str(longlong val,char *dst,int radix);
192 #if (!defined(HAVE_STRTOULL) || defined(NO_STRTOLL_PROTO))
193 extern longlong strtoll(const char *str, char **ptr, int base);
194 extern ulonglong strtoull(const char *str, char **ptr, int base);
195 #endif
196 #endif
197 #endif
198 #define longlong2str(A,B,C) ll2str((A),(B),(C),1)
199 
200 #if defined(__cplusplus)
201 }
202 #endif
203 
204 /*
205   LEX_STRING -- a pair of a C-string and its length.
206   (it's part of the plugin API as a MYSQL_LEX_STRING)
207 */
208 
209 #include <mysql/plugin.h>
210 typedef struct st_mysql_lex_string LEX_STRING;
211 
212 #define STRING_WITH_LEN(X) (X), ((size_t) (sizeof(X) - 1))
213 #define USTRING_WITH_LEN(X) ((uchar*) X), ((size_t) (sizeof(X) - 1))
214 #define C_STRING_WITH_LEN(X) ((char *) (X)), ((size_t) (sizeof(X) - 1))
215 
216 struct st_mysql_const_lex_string
217 {
218   const char *str;
219   size_t length;
220 };
221 typedef struct st_mysql_const_lex_string LEX_CSTRING;
222 
223 /* SPACE_INT is a word that contains only spaces */
224 #if SIZEOF_INT == 4
225 #define SPACE_INT 0x20202020
226 #elif SIZEOF_INT == 8
227 #define SPACE_INT 0x2020202020202020
228 #else
229 #error define the appropriate constant for a word full of spaces
230 #endif
231 
232 /**
233   Skip trailing space.
234 
235   On most systems reading memory in larger chunks (ideally equal to the size of
236   the chinks that the machine physically reads from memory) causes fewer memory
237   access loops and hence increased performance.
238   This is why the 'int' type is used : it's closest to that (according to how
239   it's defined in C).
240   So when we determine the amount of whitespace at the end of a string we do
241   the following :
242     1. We divide the string into 3 zones :
243       a) from the start of the string (__start) to the first multiple
244         of sizeof(int)  (__start_words)
245       b) from the end of the string (__end) to the last multiple of sizeof(int)
246         (__end_words)
247       c) a zone that is aligned to sizeof(int) and can be safely accessed
248         through an int *
249     2. We start comparing backwards from (c) char-by-char. If all we find is
250        space then we continue
251     3. If there are elements in zone (b) we compare them as unsigned ints to a
252        int mask (SPACE_INT) consisting of all spaces
253     4. Finally we compare the remaining part (a) of the string char by char.
254        This covers for the last non-space unsigned int from 3. (if any)
255 
256    This algorithm works well for relatively larger strings, but it will slow
257    the things down for smaller strings (because of the additional calculations
258    and checks compared to the naive method). Thus the barrier of length 20
259    is added.
260 
261    @param     ptr   pointer to the input string
262    @param     len   the length of the string
263    @return          the last non-space character
264 */
265 
skip_trailing_space(const uchar * ptr,size_t len)266 static inline const uchar *skip_trailing_space(const uchar *ptr,size_t len)
267 {
268   const uchar *end= ptr + len;
269 
270   if (len > 20)
271   {
272     const uchar *end_words= (const uchar *)(intptr)
273       (((ulonglong)(intptr)end) / SIZEOF_INT * SIZEOF_INT);
274     const uchar *start_words= (const uchar *)(intptr)
275        ((((ulonglong)(intptr)ptr) + SIZEOF_INT - 1) / SIZEOF_INT * SIZEOF_INT);
276 
277     DBUG_ASSERT(((ulonglong)(intptr)ptr) >= SIZEOF_INT);
278     if (end_words > ptr)
279     {
280       while (end > end_words && end[-1] == 0x20)
281         end--;
282       if (end[-1] == 0x20 && start_words < end_words)
283         while (end > start_words && ((unsigned *)end)[-1] == SPACE_INT)
284           end -= SIZEOF_INT;
285     }
286   }
287   while (end > ptr && end[-1] == 0x20)
288     end--;
289   return (end);
290 }
291 
lex_string_set(LEX_STRING * lex_str,const char * c_str)292 static inline void lex_string_set(LEX_STRING *lex_str, const char *c_str)
293 {
294   lex_str->str= (char *) c_str;
295   lex_str->length= strlen(c_str);
296 }
297 
298 #endif
299