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