2
Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
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.
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.
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
18
#ifndef NDB_TYPES_UTIL_HPP
19
#define NDB_TYPES_UTIL_HPP
24
#include "my_global.h"
26
#include "ndb_constants.h"
27
#include "ndb_types.h"
30
* Traits and Helper classes for NDB data types.
33
// ---------------------------------------------------------------------------
34
// Traits classes providing information on NDB (column) data types
35
// ---------------------------------------------------------------------------
38
* These Traits classes support code genericity by parametrizing over
39
* NDB (column) data types. They provide compile-time information on
40
* - array types: [long][var](binary|char)
41
* - numeric types: [U]Int8..[U]Int64|float|double
43
* For instance, Traits functions
44
* - isFixedSized() for array types
45
* - lowest(), highest() for numeric types
46
* allow for the generic handling of arrays or numeric limits.
48
* Notes: the Traits classes
49
* - provide uniform access to type meta-data
50
* - are used as a type argument to a class or function template
51
* - have pure compile-time scope, lack instantiation at runtime
52
* - have _no_ link or library dependencies upon C++ stdlib code
53
* (compare to the bounds definitions in std::numeric_limits)
54
* - are defined below as inline template specializations.
58
* Common Traits of NDB array types.
60
template< int TID > // the NDB type id as defined in ndb_constants.h
61
struct ArrayTypeTraits {
62
// whether this array type is a binary or character type
63
static bool isBinary();
65
// whether this array type is fixed-or variable-sized
66
static bool isFixedSized();
68
// the size of the length prefix in bytes, or zero if a fixed-sized array
69
static Uint32 lengthPrefixSize();
72
// aliases for array type traits
73
typedef ArrayTypeTraits< NDB_TYPE_CHAR > Tchar;
74
typedef ArrayTypeTraits< NDB_TYPE_BINARY > Tbinary;
75
typedef ArrayTypeTraits< NDB_TYPE_VARCHAR > Tvarchar;
76
typedef ArrayTypeTraits< NDB_TYPE_VARBINARY > Tvarbinary;
77
typedef ArrayTypeTraits< NDB_TYPE_LONGVARCHAR > Tlongvarchar;
78
typedef ArrayTypeTraits< NDB_TYPE_LONGVARBINARY > Tlongvarbinary;
80
// internal helper class
81
template< typename T >
85
* Common Traits of NDB numeric types.
87
* Notes: the C++ stdlib offers limits as part of std::numeric_limits;
88
* its bounds definitions result in a non-uniform usage over different
89
* data types, with min() referring to the smallest positive value for
90
* float and double, but lowest negative value for integral types.
91
* In contrast, this Traits class's functions lowest() and smallest()
92
* support a uniform usage.
94
template< typename T >
95
struct NumTypeTraits {
97
typedef typename NumTypeMap< T >::DomainT DomainT;
99
// if T is integral, the signed type of same width; otherwise T
100
typedef typename NumTypeMap< T >::SignedT SignedT;
102
// if T is integral, the unsigned type of same width; otherwise T
103
typedef typename NumTypeMap< T >::UnsignedT UnsignedT;
105
// whether the domain type is an integer type
106
static bool isIntegral() { return NumTypeMap< T >::isIntegral(); };
108
// whether the domain type is signed or unsigned
109
static bool isSigned() { return NumTypeMap< T >::isSigned(); };
111
// the width of the type in bytes
112
static Uint32 size();
114
// the minimum finite value
117
// the maximum finite value
120
// the minimum positive normalized value, or 0 for integral types
124
// aliases for standard numeric type traits
125
typedef NumTypeTraits< Int8 > Tint8;
126
typedef NumTypeTraits< Int16 > Tint16;
127
typedef NumTypeTraits< Int32 > Tint32;
128
typedef NumTypeTraits< Int64 > Tint64;
129
typedef NumTypeTraits< Uint8 > Tuint8;
130
typedef NumTypeTraits< Uint16 > Tuint16;
131
typedef NumTypeTraits< Uint32 > Tuint32;
132
typedef NumTypeTraits< Uint64 > Tuint64;
133
// not implemented yet: float, double
134
// ansi C type 'long double' is not a supported numeric NDB type
137
* Common Traits of non-standard NDB numeric types.
139
* Unless distinct [U]Int24 value types are defined to represent these
140
* proper subsets of [U]Int32 numbers, the correspoding Traits classes
141
* need to be defined as separate types (not just mere specializations).
142
* Using a derived class does that and allows to partially override.
144
template< typename T >
145
struct NonStdNumTypeTraits : NumTypeTraits< T > {
146
// the minimum finite value
149
// the maximum finite value
153
// aliases for standard numeric type traits
154
typedef NonStdNumTypeTraits< Int32 > Tint24;
155
typedef NonStdNumTypeTraits< Uint32 > Tuint24;
157
// ---------------------------------------------------------------------------
158
// Helper classes providing common functions on NDB (column) data
159
// ---------------------------------------------------------------------------
162
* These Helper classes provide basic utility functions on NDB types.
164
* For example, Helper functions
165
* - read/writeLengthPrefix() for array types
166
* - load(), store() for numeric types
167
* allow to abstract from the details of writing an array's length prefix
168
* or from reading/writing a numeric value from/to an unaligned buffer.
170
* Notes: the Helper classes
171
* - extend Traits classes for convenience
172
* - only add basic utility functions that
173
* - have _no_ link or library dependencies upon MySQL code
174
* (in contrast to other SQL utility code like ./NdbSqlUtil)
175
* - are defined below as inline template specializations.
179
* Basic Helper functions for NDB array types.
182
struct ArrayTypeHelper : ArrayTypeTraits< ID > {
183
// read the length prefix (not available if a fixed-sized array)
184
static Uint32 readLengthPrefix(const void * a);
186
// write the length prefix (not available if a fixed-sized array)
187
// the non-length-prefix bytes of 'l' must be zero
188
static void writeLengthPrefix(void * a, Uint32 l);
191
// aliases for array type helpers
192
typedef ArrayTypeHelper< NDB_TYPE_CHAR > Hchar;
193
typedef ArrayTypeHelper< NDB_TYPE_BINARY > Hbinary;
194
typedef ArrayTypeHelper< NDB_TYPE_VARCHAR > Hvarchar;
195
typedef ArrayTypeHelper< NDB_TYPE_VARBINARY > Hvarbinary;
196
typedef ArrayTypeHelper< NDB_TYPE_LONGVARCHAR > Hlongvarchar;
197
typedef ArrayTypeHelper< NDB_TYPE_LONGVARBINARY > Hlongvarbinary;
200
* Basic Helper functions for numeric NDB types.
202
* As another design option, these helper functions could be defined as
203
* individual function templates, which'd allow for implicit function
204
* resolution based on the parameter type but, on the other hand, required
205
* distinct value types for all data (i.e., an Int24 value type).
207
template< typename T >
208
struct NumTypeHelper : NumTypeTraits< T > {
209
// convenience aliases
210
typedef typename NumTypeTraits< T >::SignedT SignedT;
211
typedef typename NumTypeTraits< T >::UnsignedT UnsignedT;
213
// casts a value to the signed numerical type of same width
214
static SignedT asSigned(T t) { return static_cast< SignedT >(t); }
216
// casts a value to the unsigned numerical type of same width
217
static UnsignedT asUnsigned(T t) { return static_cast< UnsignedT >(t); }
219
// read a single value from an unaligned buffer; s, t must not overlap
220
static void load(T * t, const char * s);
222
// write a single value to an unaligned buffer; s, t must not overlap
223
static void store(char * t, const T * s);
226
// aliases for numeric type helpers
227
typedef NumTypeHelper< Int8 > Hint8;
228
typedef NumTypeHelper< Int16 > Hint16;
229
typedef NumTypeHelper< Int32 > Hint32;
230
typedef NumTypeHelper< Int64 > Hint64;
231
typedef NumTypeHelper< Uint8 > Huint8;
232
typedef NumTypeHelper< Uint16 > Huint16;
233
typedef NumTypeHelper< Uint32 > Huint32;
234
typedef NumTypeHelper< Uint64 > Huint64;
235
// not implemented yet: float, double
236
// ansi C type 'long double' is not a supported numeric NDB type
239
* Basic Helper functions of non-standard NDB numeric types.
241
* Unless distinct [U]Int24 value types are defined to represent these
242
* proper subsets of [U]Int32 numbers, the correspoding Helper classes
243
* need to be defined as separate types (not just mere specializations).
244
* This class only derives from the Traits class to avoid member access
245
* ambiguities resulting from multiple inheritance.
247
template< typename T >
248
struct NonStdNumTypeHelper : NonStdNumTypeTraits< T > {
250
typedef typename NonStdNumTypeTraits< T >::SignedT SignedT;
251
typedef typename NonStdNumTypeTraits< T >::UnsignedT UnsignedT;
253
// casts a value to the signed numerical type of same width
254
static SignedT asSigned(T t) { return static_cast< SignedT >(t); }
256
// casts a value to the unsigned numerical type of same width
257
static UnsignedT asUnsigned(T t) { return static_cast< UnsignedT >(t); }
259
// read a single value from an unaligned buffer; s, t must not overlap
260
static void load(T * t, const char * s);
262
// write a single value to an unaligned buffer; s, t must not overlap
263
static void store(char * t, const T * s);
266
// aliases for non-standard numeric type helpers
267
typedef NonStdNumTypeHelper< Int32 > Hint24;
268
typedef NonStdNumTypeHelper< Uint32 > Huint24;
270
// ---------------------------------------------------------------------------
271
// Definitions/Specializations of Traits classes
272
// ---------------------------------------------------------------------------
274
// specialize the Traits template members for array types
275
#define NDB_SPECIALIZE_ARRAY_TYPE_TRAITS( TR, B, FS, LPS ) \
276
template<> inline bool TR::isBinary() { return B; } \
277
template<> inline bool TR::isFixedSized() { return FS; } \
278
template<> inline Uint32 TR::lengthPrefixSize() { return LPS; }
280
// coincidentally, we could use ndb constants
281
// NDB_ARRAYTYPE_FIXED, NDB_ARRAYTYPE_SHORT_VAR, NDB_ARRAYTYPE_MEDIUM_VAR
282
// instead of literals, but let's not confuse ordinal/cardinal numbers
283
NDB_SPECIALIZE_ARRAY_TYPE_TRAITS(Tchar, false, true, 0)
284
NDB_SPECIALIZE_ARRAY_TYPE_TRAITS(Tbinary, true, true, 0)
285
NDB_SPECIALIZE_ARRAY_TYPE_TRAITS(Tvarchar, false, false, 1)
286
NDB_SPECIALIZE_ARRAY_TYPE_TRAITS(Tvarbinary, true, false, 1)
287
NDB_SPECIALIZE_ARRAY_TYPE_TRAITS(Tlongvarchar, false, false, 2)
288
NDB_SPECIALIZE_ARRAY_TYPE_TRAITS(Tlongvarbinary, true, false, 2)
289
#undef NDB_SPECIALIZE_ARRAY_TYPE_TRAITS
291
// specialize the TypeMap template for numeric types
292
#define NDB_SPECIALIZE_NUM_TYPE_MAP( DT, ST, UT, I, S ) \
293
template<> struct NumTypeMap< DT > { \
294
typedef DT DomainT; \
295
typedef ST SignedT; \
296
typedef UT UnsignedT; \
297
static bool isIntegral() { return S; }; \
298
static bool isSigned() { return S; }; \
301
NDB_SPECIALIZE_NUM_TYPE_MAP(Int8, Int8, Uint8, true, true)
302
NDB_SPECIALIZE_NUM_TYPE_MAP(Uint8, Int8, Uint8, true, false)
303
NDB_SPECIALIZE_NUM_TYPE_MAP(Int16, Int16, Uint16, true, true)
304
NDB_SPECIALIZE_NUM_TYPE_MAP(Uint16, Int16, Uint16, true, false)
305
NDB_SPECIALIZE_NUM_TYPE_MAP(Int32, Int32, Uint32, true, true)
306
NDB_SPECIALIZE_NUM_TYPE_MAP(Uint32, Int32, Uint32, true, false)
307
NDB_SPECIALIZE_NUM_TYPE_MAP(Int64, Int64, Uint64, true, true)
308
NDB_SPECIALIZE_NUM_TYPE_MAP(Uint64, Int64, Uint64, true, false)
310
NDB_SPECIALIZE_NUM_TYPE_MAP(float, float, float, false, true)
311
NDB_SPECIALIZE_NUM_TYPE_MAP(double, double, double, false, true)
312
#undef NDB_SPECIALIZE_NUM_TYPE_MAP
314
// specialize the Traits template members for numeric types
315
#define NDB_SPECIALIZE_NUM_TYPE_TRAITS( TR, T, SZ, LO, HI, SM ) \
316
template<> inline Uint32 TR::size() { return SZ; } \
317
template<> inline T TR::lowest() { return LO; } \
318
template<> inline T TR::highest() { return HI; } \
319
template<> inline T TR::smallest() { return SM; }
321
NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tint8, Int8, 1, INT_MIN8, INT_MAX8, 0)
322
NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tint16, Int16, 2, INT_MIN16, INT_MAX16, 0)
323
NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tint32, Int32, 4, INT_MIN32, INT_MAX32, 0)
324
NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tint64, Int64, 8, INT_MIN64, INT_MAX64, 0)
326
NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tuint8, Uint8, 1, 0, UINT_MAX8, 0)
327
NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tuint16, Uint16, 2, 0, UINT_MAX16, 0)
328
NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tuint32, Uint32, 4, 0, UINT_MAX32, 0)
329
NDB_SPECIALIZE_NUM_TYPE_TRAITS(Tuint64, Uint64, 8, 0, UINT_MAX64, 0)
330
// not implemented yet: float, double
331
#undef NDB_SPECIALIZE_NUM_TYPE_TRAITS
333
// specialize the Traits template members for non-standard numeric types
334
#define NDB_SPECIALIZE_NON_STD_NUM_TYPE_TRAITS( TR, T, LO, HI ) \
335
template<> inline T TR::lowest() { return LO; } \
336
template<> inline T TR::highest() { return HI; }
338
NDB_SPECIALIZE_NON_STD_NUM_TYPE_TRAITS(Tint24, Int32, INT_MIN24, INT_MAX24)
339
NDB_SPECIALIZE_NON_STD_NUM_TYPE_TRAITS(Tuint24, Uint32, 0, UINT_MAX24)
340
#undef NDB_SPECIALIZE_NON_STD_NUM_TYPE_TRAITS
342
// ---------------------------------------------------------------------------
343
// Definitions/Specializations of Helper classes
344
// ---------------------------------------------------------------------------
346
// specialize the Helper template members for fixed-sized arrays
347
#define NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS0( H ) \
348
template<> inline Uint32 H::readLengthPrefix(const void * a) { \
353
template<> inline void H::writeLengthPrefix(void * a, Uint32 l) { \
358
NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS0(Hchar)
359
NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS0(Hbinary)
360
#undef NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS0
362
// specialize the Helper template members for short-var arrays
363
#define NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS1( H ) \
364
template<> inline Uint32 H::readLengthPrefix(const void * a) { \
366
const Uint8 * s = static_cast<const Uint8 *>(a); \
369
template<> inline void H::writeLengthPrefix(void * a, Uint32 l) { \
371
assert(l >> (lengthPrefixSize() * 8) == 0); \
372
Uint8 * t = static_cast<Uint8 *>(a); \
373
t[0] = l & 0x000000FF; \
376
NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS1(Hvarchar)
377
NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS1(Hvarbinary)
378
#undef NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS1
380
// specialize the Helper template members for medium-var arrays
381
#define NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS2( H ) \
382
template<> inline Uint32 H::readLengthPrefix(const void * a) { \
384
const Uint8 * s = static_cast<const Uint8 *>(a); \
385
return static_cast<Uint32>(s[0] + (s[1] << 8)); \
387
template<> inline void H::writeLengthPrefix(void * a, Uint32 l) { \
389
assert(l >> (lengthPrefixSize() * 8) == 0); \
390
Uint8 * t = static_cast<Uint8 *>(a); \
391
t[0] = static_cast<Uint8>(l & 0x000000FF); \
392
t[1] = static_cast<Uint8>((l & 0x0000FF00) >> 8); \
395
NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS2(Hlongvarchar)
396
NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS2(Hlongvarbinary)
397
#undef NDB_SPECIALIZE_ARRAY_TYPE_HELPER_LPS2
399
// specialize the Helper template members for single-byte types
400
#define NDB_SPECIALIZE_NUM_TYPE_HELPER_BYTE( H, T ) \
401
template<> inline void H::load(T * t, const char * s) { \
402
assert(t); assert(s); assert(t != (const T *)s); \
403
*t = static_cast<T>(*s); \
405
template<> inline void H::store(char * t, const T * s) { \
406
H::load(reinterpret_cast<T *>(t), \
407
reinterpret_cast<const char *>(s)); \
410
NDB_SPECIALIZE_NUM_TYPE_HELPER_BYTE(Hint8, Int8);
411
NDB_SPECIALIZE_NUM_TYPE_HELPER_BYTE(Huint8, Uint8);
412
#undef NDB_SPECIALIZE_NUM_TYPE_HELPER_BYTE
414
// specialize the Helper template members for numeric types
415
#define NDB_SPECIALIZE_NUM_TYPE_HELPER( H, T ) \
416
template<> inline void H::load(T * t, const char * s) { \
417
assert(t); assert(s); assert(t != (const T *)s); \
418
memcpy(t, s, H::size()); \
420
template<> inline void H::store(char * t, const T * s) { \
421
H::load(reinterpret_cast<T *>(t), \
422
reinterpret_cast<const char *>(s)); \
425
NDB_SPECIALIZE_NUM_TYPE_HELPER(Hint16, Int16);
426
NDB_SPECIALIZE_NUM_TYPE_HELPER(Hint32, Int32);
427
NDB_SPECIALIZE_NUM_TYPE_HELPER(Hint64, Int64);
429
NDB_SPECIALIZE_NUM_TYPE_HELPER(Huint16, Uint16);
430
NDB_SPECIALIZE_NUM_TYPE_HELPER(Huint32, Uint32);
431
NDB_SPECIALIZE_NUM_TYPE_HELPER(Huint64, Uint64);
432
// not implemented yet: float, double
433
#undef NDB_SPECIALIZE_NUM_TYPE_HELPER
435
// specialize the Helper template members for non-standard numeric types
436
#define NDB_SPECIALIZE_NON_STD_NUM_TYPE_HELPER( H, T, INT3KORR ) \
437
template<> inline void H::load(T * t, const char * s) { \
438
assert(t); assert(s); assert(t != (const T *)s); \
439
*t = (INT3KORR(s)); \
441
template<> inline void H::store(char * t, const T * s) { \
442
assert(t); assert(s); assert((const T *)t != s); \
443
int3store(t, (*s)); \
446
NDB_SPECIALIZE_NON_STD_NUM_TYPE_HELPER(Hint24, Int32, sint3korr)
447
NDB_SPECIALIZE_NON_STD_NUM_TYPE_HELPER(Huint24, Uint32, uint3korr)
448
#undef NDB_SPECIALIZE_NON_STD_NUM_TYPE_HELPER
450
#endif /* !NDB_TYPES_UTIL_HPP */