xref: /PHP-7.4/ext/mysqlnd/mysqlnd_portability.h (revision 412b476b)
1 /* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
2 This file is public domain and comes with NO WARRANTY of any kind */
3 
4 /*
5   Parts of the original, which are not applicable to mysqlnd have been removed.
6 
7   With small modifications, mostly casting but adding few more macros by
8   Andrey Hristov <andrey@php.net> . The additions are in the public domain and
9   were added to improve the header file, to get it more consistent.
10 */
11 
12 #ifndef MYSQLND_PORTABILITY_H
13 #define MYSQLND_PORTABILITY_H
14 
15 
16 
17 /* Comes from global.h as OFFSET, renamed to STRUCT_OFFSET */
18 #define STRUCT_OFFSET(t, f)   XtOffsetOf(t, f)
19 
20 #ifndef __attribute
21 #if !defined(__GNUC__)
22 #define __attribute(A)
23 #endif
24 #endif
25 
26 #ifdef __CYGWIN__
27 /* We use a Unix API, so pretend it's not Windows */
28 #undef WIN
29 #undef WIN32
30 #undef _WIN
31 #undef _WIN32
32 #undef _WIN64
33 #undef __WIN__
34 #undef __WIN32__
35 #endif /* __CYGWIN__ */
36 
37 #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
38 #  include "ext/mysqlnd/config-win.h"
39 #endif /* _WIN32... */
40 
41 #if __STDC_VERSION__ < 199901L && !defined(atoll)
42   /* "inline" is a keyword */
43   #define atoll atol
44 #endif
45 
46 #include "php_stdint.h"
47 
48 #if SIZEOF_LONG_LONG > 4 && !defined(_LONG_LONG)
49 #define _LONG_LONG 1        /* For AIX string library */
50 #endif
51 
52 /* Go around some bugs in different OS and compilers */
53 
54 #if SIZEOF_LONG_LONG > 4
55 #define HAVE_LONG_LONG 1
56 #endif
57 
58 #ifdef PHP_WIN32
59 #define MYSQLND_SZ_T_SPEC "%Id"
60 #ifndef L64
61 #define L64(x) x##i64
62 #endif
63 #else
64 
65 #define MYSQLND_SZ_T_SPEC "%zd"
66 #ifndef L64
67 #define L64(x) x##LL
68 #endif
69 #endif
70 
71 
72 #define int1store(T,A)	do { *((int8_t*) (T)) = (A); } while(0)
73 #define uint1korr(A)	(*(((uint8_t*)(A))))
74 
75 /* Bit values are sent in reverted order of bytes, compared to normal !!! */
76 #define bit_uint2korr(A) ((uint16_t) (((uint16_t) (((unsigned char*) (A))[1])) +\
77                                    ((uint16_t) (((unsigned char*) (A))[0]) << 8)))
78 #define bit_uint3korr(A) ((uint32_t) (((uint32_t) (((unsigned char*) (A))[2])) +\
79                                    (((uint32_t) (((unsigned char*) (A))[1])) << 8) +\
80                                    (((uint32_t) (((unsigned char*) (A))[0])) << 16)))
81 #define bit_uint4korr(A) ((uint32_t) (((uint32_t) (((unsigned char*) (A))[3])) +\
82                                    (((uint32_t) (((unsigned char*) (A))[2])) << 8) +\
83                                    (((uint32_t) (((unsigned char*) (A))[1])) << 16) +\
84                                    (((uint32_t) (((unsigned char*) (A))[0])) << 24)))
85 #define bit_uint5korr(A) ((uint64_t)(((uint32_t) (((unsigned char*) (A))[4])) +\
86                                     (((uint32_t) (((unsigned char*) (A))[3])) << 8) +\
87                                     (((uint32_t) (((unsigned char*) (A))[2])) << 16) +\
88                                    (((uint32_t) (((unsigned char*) (A))[1])) << 24)) +\
89                                     (((uint64_t) (((unsigned char*) (A))[0])) << 32))
90 #define bit_uint6korr(A) ((uint64_t)(((uint32_t) (((unsigned char*) (A))[5])) +\
91                                     (((uint32_t) (((unsigned char*) (A))[4])) << 8) +\
92                                     (((uint32_t) (((unsigned char*) (A))[3])) << 16) +\
93                                     (((uint32_t) (((unsigned char*) (A))[2])) << 24)) +\
94                         (((uint64_t) (((uint32_t) (((unsigned char*) (A))[1])) +\
95                                     (((uint32_t) (((unsigned char*) (A))[0]) << 8)))) <<\
96                                      32))
97 #define bit_uint7korr(A) ((uint64_t)(((uint32_t) (((unsigned char*) (A))[6])) +\
98                                     (((uint32_t) (((unsigned char*) (A))[5])) << 8) +\
99                                     (((uint32_t) (((unsigned char*) (A))[4])) << 16) +\
100                                    (((uint32_t) (((unsigned char*) (A))[3])) << 24)) +\
101                         (((uint64_t) (((uint32_t) (((unsigned char*) (A))[2])) +\
102                                     (((uint32_t) (((unsigned char*) (A))[1])) << 8) +\
103                                     (((uint32_t) (((unsigned char*) (A))[0])) << 16))) <<\
104                                      32))
105 #define bit_uint8korr(A) ((uint64_t)(((uint32_t) (((unsigned char*) (A))[7])) +\
106                                     (((uint32_t) (((unsigned char*) (A))[6])) << 8) +\
107                                     (((uint32_t) (((unsigned char*) (A))[5])) << 16) +\
108                                     (((uint32_t) (((unsigned char*) (A))[4])) << 24)) +\
109                         (((uint64_t) (((uint32_t) (((unsigned char*) (A))[3])) +\
110                                     (((uint32_t) (((unsigned char*) (A))[2])) << 8) +\
111                                     (((uint32_t) (((unsigned char*) (A))[1])) << 16) +\
112                                     (((uint32_t) (((unsigned char*) (A))[0])) << 24))) <<\
113                                     32))
114 
115 
116 /*
117 ** Define-funktions for reading and storing in machine independent format
118 **  (low byte first)
119 */
120 
121 /* Optimized store functions for Intel x86, non-valid for WIN64. __i386__ is GCC */
122 #if defined(__i386__) && !defined(_WIN64)
123 #define sint2korr(A)    (*((int16_t *) (A)))
124 #define sint3korr(A)    ((int32_t) ((((zend_uchar) (A)[2]) & 128) ? \
125                    (((uint32_t) 255L << 24) | \
126                    (((uint32_t) (zend_uchar) (A)[2]) << 16) |\
127                    (((uint32_t) (zend_uchar) (A)[1]) << 8) | \
128                     ((uint32_t) (zend_uchar) (A)[0])) : \
129                    (((uint32_t) (zend_uchar) (A)[2]) << 16) |\
130                    (((uint32_t) (zend_uchar) (A)[1]) << 8) | \
131                     ((uint32_t) (zend_uchar) (A)[0])))
132 #define sint4korr(A)  (*((zend_long *) (A)))
133 
134 #define uint2korr(A)  (*((uint16_t *) (A)))
135 #define uint3korr(A)  (uint32_t) (((uint32_t) ((zend_uchar) (A)[0])) +\
136                                (((uint32_t) ((zend_uchar) (A)[1])) << 8) +\
137                                (((uint32_t) ((zend_uchar) (A)[2])) << 16))
138 #define uint4korr(A)  (*((zend_ulong *) (A)))
139 
140 
141 
142 #define uint8korr(A)    (*((uint64_t *) (A)))
143 #define sint8korr(A)    (*((int64_t *) (A)))
144 #define int2store(T,A)    *((uint16_t*) (T))= (uint16_t) (A)
145 #define int3store(T,A)   { \
146                   *(T)=  (zend_uchar) ((A));\
147                   *(T+1)=(zend_uchar) (((uint32_t) (A) >> 8));\
148                   *(T+2)=(zend_uchar) (((A) >> 16)); }
149 #define int4store(T,A)    *((zend_long *) (T))= (zend_long) (A)
150 #define int5store(T,A)    { \
151               *((zend_uchar *)(T))= (zend_uchar)((A));\
152               *(((zend_uchar *)(T))+1)=(zend_uchar) (((A) >> 8));\
153               *(((zend_uchar *)(T))+2)=(zend_uchar) (((A) >> 16));\
154               *(((zend_uchar *)(T))+3)=(zend_uchar) (((A) >> 24)); \
155               *(((zend_uchar *)(T))+4)=(zend_uchar) (((A) >> 32)); }
156 
157 /* From Andrey Hristov, based on int5store() */
158 #define int6store(T,A)    { \
159               *(((zend_uchar *)(T)))= (zend_uchar)((A));\
160               *(((zend_uchar *)(T))+1))=(zend_uchar) (((A) >> 8));\
161               *(((zend_uchar *)(T))+2))=(zend_uchar) (((A) >> 16));\
162               *(((zend_uchar *)(T))+3))=(zend_uchar) (((A) >> 24)); \
163               *(((zend_uchar *)(T))+4))=(zend_uchar) (((A) >> 32)); \
164               *(((zend_uchar *)(T))+5))=(zend_uchar) (((A) >> 40)); }
165 
166 #define int8store(T,A)    *((uint64_t *) (T))= (uint64_t) (A)
167 
168 typedef union {
169   double v;
170   zend_long m[2];
171 } float8get_union;
172 #define float8get(V,M)    { ((float8get_union *)&(V))->m[0] = *((zend_long*) (M)); \
173                             ((float8get_union *)&(V))->m[1] = *(((zend_long*) (M))+1); }
174 #define float8store(T,V) { *((zend_long *) (T))     = ((float8get_union *)&(V))->m[0]; \
175                            *(((zend_long *) (T))+1) = ((float8get_union *)&(V))->m[1]; }
176 #define float4get(V,M)	{ *((float *) &(V)) = *((float*) (M)); }
177 /* From Andrey Hristov based on float8get */
178 #define floatget(V,M)    memcpy((char*) &(V),(char*) (M),sizeof(float))
179 #endif /* __i386__ */
180 
181 
182 /* If we haven't defined sint2korr, which is because the platform is not x86 or it's WIN64 */
183 #ifndef sint2korr
184 #define sint2korr(A)    (int16_t) (((int16_t) ((zend_uchar) (A)[0])) +\
185                                  ((int16_t) ((int16_t) (A)[1]) << 8))
186 #define sint3korr(A)    ((int32_t) ((((zend_uchar) (A)[2]) & 128) ? \
187                   (((uint32_t) 255L << 24) | \
188                   (((uint32_t) (zend_uchar) (A)[2]) << 16) |\
189                   (((uint32_t) (zend_uchar) (A)[1]) << 8) | \
190                    ((uint32_t) (zend_uchar) (A)[0])) : \
191                   (((uint32_t) (zend_uchar) (A)[2]) << 16) |\
192                   (((uint32_t) (zend_uchar) (A)[1]) << 8) | \
193                   ((uint32_t) (zend_uchar) (A)[0])))
194 #define sint4korr(A)  (int32_t) (((uint32_t) ((A)[0])) +\
195                               (((uint32_t) ((A)[1]) << 8)) +\
196                               (((uint32_t) ((A)[2]) << 16)) +\
197                               (((uint32_t) ((A)[3]) << 24)))
198 
199 #define sint8korr(A)  (int64_t) uint8korr(A)
200 #define uint2korr(A)  (uint16_t) (((uint16_t) ((zend_uchar) (A)[0])) +\
201                                ((uint16_t) ((zend_uchar) (A)[1]) << 8))
202 #define uint3korr(A)  (uint32_t) (((uint32_t) ((zend_uchar) (A)[0])) +\
203                                (((uint32_t) ((zend_uchar) (A)[1])) << 8) +\
204                                (((uint32_t) ((zend_uchar) (A)[2])) << 16))
205 #define uint4korr(A)  (uint32_t) (((uint32_t) ((zend_uchar) (A)[0])) +\
206                                (((uint32_t) ((zend_uchar) (A)[1])) << 8) +\
207                                (((uint32_t) ((zend_uchar) (A)[2])) << 16) +\
208                                (((uint32_t) ((zend_uchar) (A)[3])) << 24))
209 
210 #define uint8korr(A)	((uint64_t)(((uint32_t) ((zend_uchar) (A)[0])) +\
211 									(((uint32_t) ((zend_uchar) (A)[1])) << 8) +\
212 									(((uint32_t) ((zend_uchar) (A)[2])) << 16) +\
213 									(((uint32_t) ((zend_uchar) (A)[3])) << 24)) +\
214 									(((uint64_t) (((uint32_t) ((zend_uchar) (A)[4])) +\
215 									(((uint32_t) ((zend_uchar) (A)[5])) << 8) +\
216 									(((uint32_t) ((zend_uchar) (A)[6])) << 16) +\
217 									(((uint32_t) ((zend_uchar) (A)[7])) << 24))) << 32))
218 
219 
220 #define int2store(T,A)  do { uint32_t def_temp= (uint32_t) (A) ;\
221                   *((zend_uchar*) (T))  =  (zend_uchar)(def_temp); \
222                   *((zend_uchar*) (T+1)) = (zend_uchar)((def_temp >> 8)); } while (0)
223 #define int3store(T,A)  do { /*lint -save -e734 */\
224                   *(((char *)(T)))   = (char) ((A));\
225                   *(((char *)(T))+1) = (char) (((A) >> 8));\
226                   *(((char *)(T))+2) = (char) (((A) >> 16)); \
227                   /*lint -restore */} while (0)
228 #define int4store(T,A)  do { \
229                   *(((char *)(T)))   = (char) ((A));\
230                   *(((char *)(T))+1) = (char) (((A) >> 8));\
231                   *(((char *)(T))+2) = (char) (((A) >> 16));\
232                   *(((char *)(T))+3) = (char) (((A) >> 24)); } while (0)
233 #define int5store(T,A)  do { \
234                   *(((char *)(T)))   = (char)((A));\
235                   *(((char *)(T))+1) = (char)(((A) >> 8));\
236                   *(((char *)(T))+2) = (char)(((A) >> 16));\
237                   *(((char *)(T))+3) = (char)(((A) >> 24)); \
238                   *(((char *)(T))+4) = (char)(((A) >> 32)); } while (0)
239 /* Based on int5store() from Andrey Hristov */
240 #define int6store(T,A)  do { \
241                   *(((char *)(T)))   = (char)((A));\
242                   *(((char *)(T))+1) = (char)(((A) >> 8));\
243                   *(((char *)(T))+2) = (char)(((A) >> 16));\
244                   *(((char *)(T))+3) = (char)(((A) >> 24)); \
245                   *(((char *)(T))+4) = (char)(((A) >> 32)); \
246                   *(((char *)(T))+5) = (char)(((A) >> 40)); } while (0)
247 #define int8store(T,A)        { uint32_t def_temp= (uint32_t) (A), def_temp2= (uint32_t) ((A) >> 32); \
248                   int4store((T),def_temp); \
249                   int4store((T+4),def_temp2); \
250                 }
251 #ifdef WORDS_BIGENDIAN
252 #define float4get(V,M)   do { float def_temp;\
253                           ((char*) &def_temp)[0] = (M)[3];\
254                           ((char*) &def_temp)[1] = (M)[2];\
255                           ((char*) &def_temp)[2] = (M)[1];\
256                           ((char*) &def_temp)[3] = (M)[0];\
257                           (V)=def_temp; } while (0)
258 #define float8store(T,V)  do { \
259                            *(((char *)(T)))   = (char) ((char *) &(V))[7];\
260                            *(((char *)(T))+1) = (char) ((char *) &(V))[6];\
261                            *(((char *)(T))+2) = (char) ((char *) &(V))[5];\
262                            *(((char *)(T))+3) = (char) ((char *) &(V))[4];\
263                            *(((char *)(T))+4) = (char) ((char *) &(V))[3];\
264                            *(((char *)(T))+5) = (char) ((char *) &(V))[2];\
265                            *(((char *)(T))+6) = (char) ((char *) &(V))[1];\
266                            *(((char *)(T))+7) = (char) ((char *) &(V))[0]; } while (0)
267 
268 #define float8get(V,M)   do { double def_temp;\
269                           ((char*) &def_temp)[0] = (M)[7];\
270                           ((char*) &def_temp)[1] = (M)[6];\
271                           ((char*) &def_temp)[2] = (M)[5];\
272                           ((char*) &def_temp)[3] = (M)[4];\
273                           ((char*) &def_temp)[4] = (M)[3];\
274                           ((char*) &def_temp)[5] = (M)[2];\
275                           ((char*) &def_temp)[6] = (M)[1];\
276                           ((char*) &def_temp)[7] = (M)[0];\
277                           (V) = def_temp; \
278                          } while (0)
279 #else
280 #define float4get(V,M)   memcpy((char*) &(V),(char*) (M),sizeof(float))
281 
282 #if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
283 #define float8store(T,V)  do { \
284                          *(((char *)(T)))= ((char *) &(V))[4];\
285                          *(((char *)(T))+1)=(char) ((char *) &(V))[5];\
286                          *(((char *)(T))+2)=(char) ((char *) &(V))[6];\
287                          *(((char *)(T))+3)=(char) ((char *) &(V))[7];\
288                          *(((char *)(T))+4)=(char) ((char *) &(V))[0];\
289                          *(((char *)(T))+5)=(char) ((char *) &(V))[1];\
290                          *(((char *)(T))+6)=(char) ((char *) &(V))[2];\
291                          *(((char *)(T))+7)=(char) ((char *) &(V))[3];} while (0)
292 #define float8get(V,M) do { double def_temp;\
293                          ((char*) &def_temp)[0]=(M)[4];\
294                          ((char*) &def_temp)[1]=(M)[5];\
295                          ((char*) &def_temp)[2]=(M)[6];\
296                          ((char*) &def_temp)[3]=(M)[7];\
297                          ((char*) &def_temp)[4]=(M)[0];\
298                          ((char*) &def_temp)[5]=(M)[1];\
299                          ((char*) &def_temp)[6]=(M)[2];\
300                          ((char*) &def_temp)[7]=(M)[3];\
301                          (V) = def_temp; } while (0)
302 #endif /* __FLOAT_WORD_ORDER */
303 
304 #endif /* WORDS_BIGENDIAN */
305 
306 #endif /* sint2korr */
307 /* To here if the platform is not x86 or it's WIN64 */
308 
309 
310 /* Define-funktions for reading and storing in machine format from/to
311    short/long to/from some place in memory V should be a (not
312    register) variable, M is a pointer to byte */
313 
314 #ifndef float8get
315 
316 #ifdef WORDS_BIGENDIAN
317 #define float8get(V,M)		memcpy((char*) &(V),(char*)  (M), sizeof(double))
318 #define float8store(T,V)	memcpy((char*)  (T),(char*) &(V), sizeof(double))
319 #else
320 #define float8get(V,M)    memcpy((char*) &(V),(char*) (M),sizeof(double))
321 #define float8store(T,V)  memcpy((char*) (T),(char*) &(V),sizeof(double))
322 #endif /* WORDS_BIGENDIAN */
323 
324 #endif /* float8get */
325 
326 #endif /* MYSQLND_PORTABILITY_H */
327