1 /* 2 Copyright (c) 2011, 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, version 2.0, 6 as published by the Free Software Foundation. 7 8 This program is also distributed with certain software (including 9 but not limited to OpenSSL) that is licensed under separate terms, 10 as designated in a particular file or component or in included license 11 documentation. The authors of MySQL hereby grant you an additional 12 permission to link the program and your derivative works with the 13 separately licensed software that they have included with MySQL. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License, version 2.0, for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 */ 24 25 #ifndef NDB_TYPES_UTIL_HPP 26 #define NDB_TYPES_UTIL_HPP 27 28 #include <assert.h> 29 #include <string.h> 30 31 #include "my_global.h" 32 33 #include "ndb_constants.h" 34 #include "ndb_types.h" 35 36 /* 37 * Traits and Helper classes for NDB data types. 38 */ 39 40 // --------------------------------------------------------------------------- 41 // Traits classes providing information on NDB (column) data types 42 // --------------------------------------------------------------------------- 43 44 /* 45 * These Traits classes support code genericity by parametrizing over 46 * NDB (column) data types. They provide compile-time information on 47 * - array types: [long][var](binary|char) 48 * - numeric types: [U]Int8..[U]Int64|float|double 49 * 50 * For instance, Traits functions 51 * - isFixedSized() for array types 52 * - lowest(), highest() for numeric types 53 * allow for the generic handling of arrays or numeric limits. 54 * 55 * Notes: the Traits classes 56 * - provide uniform access to type meta-data 57 * - are used as a type argument to a class or function template 58 * - have pure compile-time scope, lack instantiation at runtime 59 * - have _no_ link or library dependencies upon C++ stdlib code 60 * (compare to the bounds definitions in std::numeric_limits) 61 * - are defined below as inline template specializations. 62 */ 63 64 /** 65 * Common Traits of NDB array types. 66 */ 67 template< int TID > // the NDB type id as defined in ndb_constants.h 68 struct ArrayTypeTraits { 69 // whether this array type is a binary or character type 70 static bool isBinary(); 71 72 // whether this array type is fixed-or variable-sized 73 static bool isFixedSized(); 74 75 // the size of the length prefix in bytes, or zero if a fixed-sized array 76 static Uint32 lengthPrefixSize(); 77 }; 78 79 // aliases for array type traits 80 typedef ArrayTypeTraits< NDB_TYPE_CHAR > Tchar; 81 typedef ArrayTypeTraits< NDB_TYPE_BINARY > Tbinary; 82 typedef ArrayTypeTraits< NDB_TYPE_VARCHAR > Tvarchar; 83 typedef ArrayTypeTraits< NDB_TYPE_VARBINARY > Tvarbinary; 84 typedef ArrayTypeTraits< NDB_TYPE_LONGVARCHAR > Tlongvarchar; 85 typedef ArrayTypeTraits< NDB_TYPE_LONGVARBINARY > Tlongvarbinary; 86 87 // internal helper class 88 template< typename T > 89 struct NumTypeMap {}; 90 91 /** 92 * Common Traits of NDB numeric types. 93 * 94 * Notes: the C++ stdlib offers limits as part of std::numeric_limits; 95 * its bounds definitions result in a non-uniform usage over different 96 * data types, with min() referring to the smallest positive value for 97 * float and double, but lowest negative value for integral types. 98 * In contrast, this Traits class's functions lowest() and smallest() 99 * support a uniform usage. 100 */ 101 template< typename T > 102 struct NumTypeTraits { 103 // the domain type T 104 typedef typename NumTypeMap< T >::DomainT DomainT; 105 106 // if T is integral, the signed type of same width; otherwise T 107 typedef typename NumTypeMap< T >::SignedT SignedT; 108 109 // if T is integral, the unsigned type of same width; otherwise T 110 typedef typename NumTypeMap< T >::UnsignedT UnsignedT; 111 112 // whether the domain type is an integer type isIntegralNumTypeTraits113 static bool isIntegral() { return NumTypeMap< T >::isIntegral(); }; 114 115 // whether the domain type is signed or unsigned isSignedNumTypeTraits116 static bool isSigned() { return NumTypeMap< T >::isSigned(); }; 117 118 // the width of the type in bytes 119 static Uint32 size(); 120 121 // the minimum finite value 122 static T lowest(); 123 124 // the maximum finite value 125 static T highest(); 126 127 // the minimum positive normalized value, or 0 for integral types 128 static T smallest(); 129 }; 130 131 // aliases for standard numeric type traits 132 typedef NumTypeTraits< Int8 > Tint8; 133 typedef NumTypeTraits< Int16 > Tint16; 134 typedef NumTypeTraits< Int32 > Tint32; 135 typedef NumTypeTraits< Int64 > Tint64; 136 typedef NumTypeTraits< Uint8 > Tuint8; 137 typedef NumTypeTraits< Uint16 > Tuint16; 138 typedef NumTypeTraits< Uint32 > Tuint32; 139 typedef NumTypeTraits< Uint64 > Tuint64; 140 // not implemented yet: float, double 141 // ansi C type 'long double' is not a supported numeric NDB type 142 143 /** 144 * Common Traits of non-standard NDB numeric types. 145 * 146 * Unless distinct [U]Int24 value types are defined to represent these 147 * proper subsets of [U]Int32 numbers, the correspoding Traits classes 148 * need to be defined as separate types (not just mere specializations). 149 * Using a derived class does that and allows to partially override. 150 */ 151 template< typename T > 152 struct NonStdNumTypeTraits : NumTypeTraits< T > { 153 // the minimum finite value 154 static T lowest(); 155 156 // the maximum finite value 157 static T highest(); 158 }; 159 160 // aliases for standard numeric type traits 161 typedef NonStdNumTypeTraits< Int32 > Tint24; 162 typedef NonStdNumTypeTraits< Uint32 > Tuint24; 163 164 // --------------------------------------------------------------------------- 165 // Helper classes providing common functions on NDB (column) data 166 // --------------------------------------------------------------------------- 167 168 /* 169 * These Helper classes provide basic utility functions on NDB types. 170 * 171 * For example, Helper functions 172 * - read/writeLengthPrefix() for array types 173 * - load(), store() for numeric types 174 * allow to abstract from the details of writing an array's length prefix 175 * or from reading/writing a numeric value from/to an unaligned buffer. 176 * 177 * Notes: the Helper classes 178 * - extend Traits classes for convenience 179 * - only add basic utility functions that 180 * - have _no_ link or library dependencies upon MySQL code 181 * (in contrast to other SQL utility code like ./NdbSqlUtil) 182 * - are defined below as inline template specializations. 183 */ 184 185 /** 186 * Basic Helper functions for NDB array types. 187 */ 188 template< int ID > 189 struct ArrayTypeHelper : ArrayTypeTraits< ID > { 190 // read the length prefix (not available if a fixed-sized array) 191 static Uint32 readLengthPrefix(const void * a); 192 193 // write the length prefix (not available if a fixed-sized array) 194 // the non-length-prefix bytes of 'l' must be zero 195 static void writeLengthPrefix(void * a, Uint32 l); 196 }; 197 198 // aliases for array type helpers 199 typedef ArrayTypeHelper< NDB_TYPE_CHAR > Hchar; 200 typedef ArrayTypeHelper< NDB_TYPE_BINARY > Hbinary; 201 typedef ArrayTypeHelper< NDB_TYPE_VARCHAR > Hvarchar; 202 typedef ArrayTypeHelper< NDB_TYPE_VARBINARY > Hvarbinary; 203 typedef ArrayTypeHelper< NDB_TYPE_LONGVARCHAR > Hlongvarchar; 204 typedef ArrayTypeHelper< NDB_TYPE_LONGVARBINARY > Hlongvarbinary; 205 206 /** 207 * Basic Helper functions for numeric NDB types. 208 * 209 * As another design option, these helper functions could be defined as 210 * individual function templates, which'd allow for implicit function 211 * resolution based on the parameter type but, on the other hand, required 212 * distinct value types for all data (i.e., an Int24 value type). 213 */ 214 template< typename T > 215 struct NumTypeHelper : NumTypeTraits< T > { 216 // convenience aliases 217 typedef typename NumTypeTraits< T >::SignedT SignedT; 218 typedef typename NumTypeTraits< T >::UnsignedT UnsignedT; 219 220 // casts a value to the signed numerical type of same width asSignedNumTypeHelper221 static SignedT asSigned(T t) { return static_cast< SignedT >(t); } 222 223 // casts a value to the unsigned numerical type of same width asUnsignedNumTypeHelper224 static UnsignedT asUnsigned(T t) { return static_cast< UnsignedT >(t); } 225 226 // read a single value from an unaligned buffer; s, t must not overlap 227 static void load(T * t, const char * s); 228 229 // write a single value to an unaligned buffer; s, t must not overlap 230 static void store(char * t, const T * s); 231 }; 232 233 // aliases for numeric type helpers 234 typedef NumTypeHelper< Int8 > Hint8; 235 typedef NumTypeHelper< Int16 > Hint16; 236 typedef NumTypeHelper< Int32 > Hint32; 237 typedef NumTypeHelper< Int64 > Hint64; 238 typedef NumTypeHelper< Uint8 > Huint8; 239 typedef NumTypeHelper< Uint16 > Huint16; 240 typedef NumTypeHelper< Uint32 > Huint32; 241 typedef NumTypeHelper< Uint64 > Huint64; 242 // not implemented yet: float, double 243 // ansi C type 'long double' is not a supported numeric NDB type 244 245 /** 246 * Basic Helper functions of non-standard NDB numeric types. 247 * 248 * Unless distinct [U]Int24 value types are defined to represent these 249 * proper subsets of [U]Int32 numbers, the correspoding Helper classes 250 * need to be defined as separate types (not just mere specializations). 251 * This class only derives from the Traits class to avoid member access 252 * ambiguities resulting from multiple inheritance. 253 */ 254 template< typename T > 255 struct NonStdNumTypeHelper : NonStdNumTypeTraits< T > { 256 // convenience alias 257 typedef typename NonStdNumTypeTraits< T >::SignedT SignedT; 258 typedef typename NonStdNumTypeTraits< T >::UnsignedT UnsignedT; 259 260 // casts a value to the signed numerical type of same width asSignedNonStdNumTypeHelper261 static SignedT asSigned(T t) { return static_cast< SignedT >(t); } 262 263 // casts a value to the unsigned numerical type of same width asUnsignedNonStdNumTypeHelper264 static UnsignedT asUnsigned(T t) { return static_cast< UnsignedT >(t); } 265 266 // read a single value from an unaligned buffer; s, t must not overlap 267 static void load(T * t, const char * s); 268 269 // write a single value to an unaligned buffer; s, t must not overlap 270 static void store(char * t, const T * s); 271 }; 272 273 // aliases for non-standard numeric type helpers 274 typedef NonStdNumTypeHelper< Int32 > Hint24; 275 typedef NonStdNumTypeHelper< Uint32 > Huint24; 276 277 // --------------------------------------------------------------------------- 278 // Definitions/Specializations of Traits classes 279 // --------------------------------------------------------------------------- 280 281 // specialize the Traits template members for array types 282 #define NDB_SPECIALIZE_ARRAY_TYPE_TRAITS( TR, B, FS, LPS ) \ 283 template<> inline bool TR::isBinary() { return B; } \ 284 template<> inline bool TR::isFixedSized() { return FS; } \ 285 template<> inline Uint32 TR::lengthPrefixSize() { return LPS; } 286 287 // coincidentally, we could use ndb constants 288 // NDB_ARRAYTYPE_FIXED, NDB_ARRAYTYPE_SHORT_VAR, NDB_ARRAYTYPE_MEDIUM_VAR 289 // instead of literals, but let's not confuse ordinal/cardinal numbers 290 NDB_SPECIALIZE_ARRAY_TYPE_TRAITS(Tchar, false, true, 0) 291 NDB_SPECIALIZE_ARRAY_TYPE_TRAITS(Tbinary, true, true, 0) 292 NDB_SPECIALIZE_ARRAY_TYPE_TRAITS(Tvarchar, false, false, 1) 293 NDB_SPECIALIZE_ARRAY_TYPE_TRAITS(Tvarbinary, true, false, 1) 294 NDB_SPECIALIZE_ARRAY_TYPE_TRAITS(Tlongvarchar, false, false, 2) 295 NDB_SPECIALIZE_ARRAY_TYPE_TRAITS(Tlongvarbinary, true, false, 2) 296 #undef NDB_SPECIALIZE_ARRAY_TYPE_TRAITS 297 298 // specialize the TypeMap template for numeric types 299 #define NDB_SPECIALIZE_NUM_TYPE_MAP( DT, ST, UT, I, S ) \ 300 template<> struct NumTypeMap< DT > { \ 301 typedef DT DomainT; \ 302 typedef ST SignedT; \ 303 typedef UT UnsignedT; \ 304 static bool isIntegral() { return S; }; \ 305 static bool isSigned() { return S; }; \ 306 }; 307 308 NDB_SPECIALIZE_NUM_TYPE_MAP(Int8, Int8, Uint8, true, true) 309 NDB_SPECIALIZE_NUM_TYPE_MAP(Uint8, Int8, Uint8, true, false) 310 NDB_SPECIALIZE_NUM_TYPE_MAP(Int16, Int16, Uint16, true, true) 311 NDB_SPECIALIZE_NUM_TYPE_MAP(Uint16, Int16, Uint16, true, false) 312 NDB_SPECIALIZE_NUM_TYPE_MAP(Int32, Int32, Uint32, true, true) 313 NDB_SPECIALIZE_NUM_TYPE_MAP(Uint32, Int32, Uint32, true, false) 314 NDB_SPECIALIZE_NUM_TYPE_MAP(Int64, Int64, Uint64, true, true) 315 NDB_SPECIALIZE_NUM_TYPE_MAP(Uint64, Int64, Uint64, true, false) 316 317 NDB_SPECIALIZE_NUM_TYPE_MAP(float, float, float, false, true) 318 NDB_SPECIALIZE_NUM_TYPE_MAP(double, double, double, false, true) 319 #undef NDB_SPECIALIZE_NUM_TYPE_MAP 320 321 // specialize the Traits template members for numeric types 322 #define NDB_SPECIALIZE_NUM_TYPE_TRAITS( TR, T, SZ, LO, HI, SM ) \ 323 template<> inline Uint32 TR::size() { return SZ; } \ 324 template<> inline T TR::lowest() { return LO; } \ 325 template<> inline T TR::highest() { return HI; } \ 326 template<> inline T TR::smallest() { return SM; } 327 328 NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tint8, Int8, 1, INT_MIN8, INT_MAX8, 0) 329 NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tint16, Int16, 2, INT_MIN16, INT_MAX16, 0) 330 NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tint32, Int32, 4, INT_MIN32, INT_MAX32, 0) 331 NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tint64, Int64, 8, INT_MIN64, INT_MAX64, 0) 332 333 NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tuint8, Uint8, 1, 0, UINT_MAX8, 0) 334 NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tuint16, Uint16, 2, 0, UINT_MAX16, 0) 335 NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tuint32, Uint32, 4, 0, UINT_MAX32, 0) 336 NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tuint64, Uint64, 8, 0, UINT_MAX64, 0) 337 // not implemented yet: float, double 338 #undef NDB_SPECIALIZE_NUM_TYPE_TRAITS 339 340 // specialize the Traits template members for non-standard numeric types 341 #define NDB_SPECIALIZE_NON_STD_NUM_TYPE_TRAITS( TR, T, LO, HI ) \ 342 template<> inline T TR::lowest() { return LO; } \ 343 template<> inline T TR::highest() { return HI; } 344 345 NDB_SPECIALIZE_NON_STD_NUM_TYPE_TRAITS(Tint24, Int32, INT_MIN24, INT_MAX24) 346 NDB_SPECIALIZE_NON_STD_NUM_TYPE_TRAITS(Tuint24, Uint32, 0, UINT_MAX24) 347 #undef NDB_SPECIALIZE_NON_STD_NUM_TYPE_TRAITS 348 349 // --------------------------------------------------------------------------- 350 // Definitions/Specializations of Helper classes 351 // --------------------------------------------------------------------------- 352 353 // specialize the Helper template members for fixed-sized arrays 354 #define NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS0( H ) \ 355 template<> inline Uint32 H::readLengthPrefix(const void * a) { \ 356 assert(false); \ 357 (void)a; \ 358 return 0; \ 359 }; \ 360 template<> inline void H::writeLengthPrefix(void * a, Uint32 l) { \ 361 assert(false); \ 362 (void)a; (void)l; \ 363 } 364 365 NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS0(Hchar) 366 NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS0(Hbinary) 367 #undef NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS0 368 369 // specialize the Helper template members for short-var arrays 370 #define NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS1( H ) \ 371 template<> inline Uint32 H::readLengthPrefix(const void * a) { \ 372 assert(a); \ 373 const Uint8 * s = static_cast<const Uint8 *>(a); \ 374 return s[0]; \ 375 }; \ 376 template<> inline void H::writeLengthPrefix(void * a, Uint32 l) { \ 377 assert(a); \ 378 assert(l >> (lengthPrefixSize() * 8) == 0); \ 379 Uint8 * t = static_cast<Uint8 *>(a); \ 380 t[0] = l & 0x000000FF; \ 381 } 382 383 NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS1(Hvarchar) 384 NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS1(Hvarbinary) 385 #undef NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS1 386 387 // specialize the Helper template members for medium-var arrays 388 #define NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS2( H ) \ 389 template<> inline Uint32 H::readLengthPrefix(const void * a) { \ 390 assert(a); \ 391 const Uint8 * s = static_cast<const Uint8 *>(a); \ 392 return static_cast<Uint32>(s[0] + (s[1] << 8)); \ 393 }; \ 394 template<> inline void H::writeLengthPrefix(void * a, Uint32 l) { \ 395 assert(a); \ 396 assert(l >> (lengthPrefixSize() * 8) == 0); \ 397 Uint8 * t = static_cast<Uint8 *>(a); \ 398 t[0] = static_cast<Uint8>(l & 0x000000FF); \ 399 t[1] = static_cast<Uint8>((l & 0x0000FF00) >> 8); \ 400 } 401 402 NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS2(Hlongvarchar) 403 NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS2(Hlongvarbinary) 404 #undef NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS2 405 406 // specialize the Helper template members for single-byte types 407 #define NDB_SPECIALIZE_NUM_TYPE_HELPER_BYTE( H, T ) \ 408 template<> inline void H::load(T * t, const char * s) { \ 409 assert(t); assert(s); assert(t != (const T *)s); \ 410 *t = static_cast<T>(*s); \ 411 } \ 412 template<> inline void H::store(char * t, const T * s) { \ 413 H::load(reinterpret_cast<T *>(t), \ 414 reinterpret_cast<const char *>(s)); \ 415 } 416 417 NDB_SPECIALIZE_NUM_TYPE_HELPER_BYTE(Hint8, Int8); 418 NDB_SPECIALIZE_NUM_TYPE_HELPER_BYTE(Huint8, Uint8); 419 #undef NDB_SPECIALIZE_NUM_TYPE_HELPER_BYTE 420 421 // specialize the Helper template members for numeric types 422 #define NDB_SPECIALIZE_NUM_TYPE_HELPER( H, T ) \ 423 template<> inline void H::load(T * t, const char * s) { \ 424 assert(t); assert(s); assert(t != (const T *)s); \ 425 memcpy(t, s, H::size()); \ 426 } \ 427 template<> inline void H::store(char * t, const T * s) { \ 428 H::load(reinterpret_cast<T *>(t), \ 429 reinterpret_cast<const char *>(s)); \ 430 } 431 432 NDB_SPECIALIZE_NUM_TYPE_HELPER(Hint16, Int16); 433 NDB_SPECIALIZE_NUM_TYPE_HELPER(Hint32, Int32); 434 NDB_SPECIALIZE_NUM_TYPE_HELPER(Hint64, Int64); 435 436 NDB_SPECIALIZE_NUM_TYPE_HELPER(Huint16, Uint16); 437 NDB_SPECIALIZE_NUM_TYPE_HELPER(Huint32, Uint32); 438 NDB_SPECIALIZE_NUM_TYPE_HELPER(Huint64, Uint64); 439 // not implemented yet: float, double 440 #undef NDB_SPECIALIZE_NUM_TYPE_HELPER 441 442 // specialize the Helper template members for non-standard numeric types 443 #define NDB_SPECIALIZE_NON_STD_NUM_TYPE_HELPER( H, T, INT3KORR ) \ 444 template<> inline void H::load(T * t, const char * s) { \ 445 assert(t); assert(s); assert(t != (const T *)s); \ 446 *t = (INT3KORR(s)); \ 447 } \ 448 template<> inline void H::store(char * t, const T * s) { \ 449 assert(t); assert(s); assert((const T *)t != s); \ 450 int3store(t, (*s)); \ 451 } 452 453 NDB_SPECIALIZE_NON_STD_NUM_TYPE_HELPER(Hint24, Int32, sint3korr) 454 NDB_SPECIALIZE_NON_STD_NUM_TYPE_HELPER(Huint24, Uint32, uint3korr) 455 #undef NDB_SPECIALIZE_NON_STD_NUM_TYPE_HELPER 456 457 #endif /* !NDB_TYPES_UTIL_HPP */ 458