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