1 //-***************************************************************************** 2 // 3 // Copyright (c) 2009-2012, 4 // Sony Pictures Imageworks Inc. and 5 // Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd. 6 // 7 // All rights reserved. 8 // 9 // Redistribution and use in source and binary forms, with or without 10 // modification, are permitted provided that the following conditions are 11 // met: 12 // * Redistributions of source code must retain the above copyright 13 // notice, this list of conditions and the following disclaimer. 14 // * Redistributions in binary form must reproduce the above 15 // copyright notice, this list of conditions and the following disclaimer 16 // in the documentation and/or other materials provided with the 17 // distribution. 18 // * Neither the name of Sony Pictures Imageworks, nor 19 // Industrial Light & Magic, nor the names of their contributors may be used 20 // to endorse or promote products derived from this software without specific 21 // prior written permission. 22 // 23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 // 35 //-***************************************************************************** 36 37 #ifndef Alembic_Util_PlainOldDataType_h 38 #define Alembic_Util_PlainOldDataType_h 39 40 #include <Alembic/Util/Foundation.h> 41 #include <Alembic/Util/Exception.h> 42 43 // stdint.h is not in anything prior to Visual Studio 2010 44 #if !defined(_MSC_VER) || _MSC_VER >= 1600 45 #include <stdint.h> 46 #endif 47 48 namespace Alembic { 49 namespace Util { 50 namespace ALEMBIC_VERSION_NS { 51 52 //-***************************************************************************** 53 //! Bytes are unsigned chars, by definition. 54 //! We use bytes in Alembic as the name of anonymous storage memory, since 55 //! it is not possible to create arrays of voids. 56 typedef unsigned char byte_t; 57 58 //-***************************************************************************** 59 //-***************************************************************************** 60 //! BOOLEAN BASE TYPE - since C++ doesn't explicitly demand that bool 61 //! be a given bit depth, but we need it to be here, we make our own 62 //! bool type, which is a bit silly. This is purely for storage reasons. 63 //-***************************************************************************** 64 class bool_t 65 { 66 public: bool_t()67 bool_t() : m_byte( 0 ) {} 68 bool_t(bool tf)69 bool_t( bool tf ) : m_byte( static_cast<byte_t>( tf ) ) {} bool_t(byte_t b)70 bool_t( byte_t b ) : m_byte( b ) {} 71 72 73 //! Using default copy constructor 74 //! ... 75 76 //! Using default assignment operator 77 //! ... 78 79 bool_t& operator=( bool tf ) 80 { 81 m_byte = static_cast<byte_t>( tf ); 82 return *this; 83 } 84 85 bool_t& operator=( byte_t b ) 86 { 87 m_byte = b; 88 return *this; 89 } 90 91 bool_t operator!( void ) 92 { 93 return bool_t( m_byte == 0 ); 94 } 95 asBool()96 bool asBool() const { return ( m_byte != 0 ); } 97 operator bool() const { return ( m_byte != 0 ); } 98 99 private: 100 byte_t m_byte; 101 }; 102 103 //-***************************************************************************** 104 inline bool operator==( const bool_t &a, const bool_t &b ) 105 { 106 return a.asBool() == b.asBool(); 107 } 108 109 //-***************************************************************************** 110 inline bool operator==( const bool_t &a, bool b ) 111 { 112 return a.asBool() == b; 113 } 114 115 //-***************************************************************************** 116 inline bool operator==( bool a, const bool_t &b ) 117 { 118 return a == b.asBool(); 119 } 120 121 //-***************************************************************************** 122 inline bool operator!=( const bool_t &a, const bool_t &b ) 123 { 124 return a.asBool() != b.asBool(); 125 } 126 127 //-***************************************************************************** 128 inline bool operator!=( const bool_t &a, bool b ) 129 { 130 return a.asBool() != b; 131 } 132 133 //-***************************************************************************** 134 inline bool operator!=( bool a, const bool_t &b ) 135 { 136 return a != b.asBool(); 137 } 138 139 #if !defined(_MSC_VER) || _MSC_VER >= 1600 140 using ::uint8_t; 141 using ::int8_t; 142 using ::uint16_t; 143 using ::int16_t; 144 using ::uint32_t; 145 using ::int32_t; 146 using ::uint64_t; 147 using ::int64_t; 148 #else 149 typedef unsigned char uint8_t; 150 typedef signed char int8_t; 151 typedef unsigned short uint16_t; 152 typedef signed short int16_t; 153 typedef unsigned int uint32_t; 154 typedef int int32_t; 155 typedef unsigned long long uint64_t; 156 typedef long long int64_t; 157 #endif 158 159 typedef half float16_t; 160 typedef float float32_t; 161 typedef double float64_t; 162 163 //! Last, but not least, standard strings. 164 //! These are CLEARLY not "Plain Old Data Types", however, "strings" are 165 //! such ubiquitous components of programming, and without an enclosing 166 //! structure like std::string, they're so difficult to use from an API 167 //! point of view (call first time to find out length! allocate your own array! 168 //! call second time to get string value!), that I'm going to put my foot down 169 //! and say - from Alembic's point of view, std::string and std::wstring are 170 //! "Kinda Sorta POD types". Please pardon the abuse of the idiom. 171 using std::string; 172 using std::wstring; 173 174 //-***************************************************************************** 175 //! I'm using explicit names here because the terms 'int', 'short', 'long', etc, 176 //! have different bit-depths on different machine architectures. To avoid 177 //! any ambiguity whatsoever, I'm just making these explicit. End users will 178 //! rarely see these anyway, so it's okay to be a bit pedantic. 179 //! 180 //! These are always represented in the endian-ness of the host machine when 181 //! resident in working memory, but need to have an explicit endian-ness when 182 //! being written out. That's hidden from the user by HDF5. 183 enum PlainOldDataType 184 { 185 //! Booleans are difficult to store in arrays in a 'one bit per bool' 186 //! kind of way, so we actually file them as bytes (uint8). But again 187 //! this is entirely hidden from the end user. Implemented via the 188 //! "bool_t" type defined above. 189 kBooleanPOD, 190 191 //! Char/UChar 192 kUint8POD, 193 kInt8POD, 194 195 //! Short/UShort 196 kUint16POD, 197 kInt16POD, 198 199 //! Int/UInt 200 kUint32POD, 201 kInt32POD, 202 203 //! Long/ULong 204 kUint64POD, 205 kInt64POD, 206 207 //! Half/Float/Double 208 kFloat16POD, 209 kFloat32POD, 210 kFloat64POD, 211 212 //! String Pointer 213 kStringPOD, 214 215 //! Wide String Pointer 216 kWstringPOD, 217 218 //! Number of POD 219 kNumPlainOldDataTypes, 220 221 //! Unknown 222 kUnknownPOD = 127 223 }; 224 225 //-***************************************************************************** 226 //-***************************************************************************** 227 //-***************************************************************************** 228 // A little traits class that binds these things together. 229 //-***************************************************************************** 230 //-***************************************************************************** 231 //-***************************************************************************** 232 template <PlainOldDataType PODT, class T > struct PODTraits {}; 233 234 //-***************************************************************************** 235 //! Unfortunately, C++ only allows for static const declaration of constants 236 //! with integral types, not floating. Therefore, we have the whole 237 //! inlined static function for default values. 238 #define DECLARE_TRAITS( PENUM, PTYPE, PNAME, DFLT, PTDEF ) \ 239 template <> \ 240 struct PODTraits< PENUM , PTYPE > \ 241 { \ 242 static const PlainOldDataType pod_enum = PENUM ; \ 243 typedef PTYPE value_type ; \ 244 static const char * name() { return PNAME ; } \ 245 static PTYPE default_value() \ 246 { return ( DFLT ) ; } \ 247 static size_t numBytes() \ 248 { return sizeof( PTYPE ) ; } \ 249 }; \ 250 typedef PODTraits< PENUM , PTYPE > PTDEF 251 252 //-***************************************************************************** 253 // Actual specialized traits 254 DECLARE_TRAITS( kBooleanPOD, bool_t, "bool_t", false, BooleanPODTraits ); 255 DECLARE_TRAITS( kUint8POD, uint8_t, "uint8_t", 0, Uint8PODTraits ); 256 DECLARE_TRAITS( kInt8POD, int8_t, "int8_t", 0, Int8PODTraits ); 257 DECLARE_TRAITS( kUint16POD, uint16_t, "uint16_t", 0, Uint16PODTraits ); 258 DECLARE_TRAITS( kInt16POD, int16_t, "int16_t", 0, Int16PODTraits ); 259 DECLARE_TRAITS( kUint32POD, uint32_t, "uint32_t", 0, Uint32PODTraits ); 260 DECLARE_TRAITS( kInt32POD, int32_t, "int32_t", 0, Int32PODTraits ); 261 DECLARE_TRAITS( kUint64POD, uint64_t, "uint64_t", 0, Uint64PODTraits ); 262 DECLARE_TRAITS( kInt64POD, int64_t, "int64_t", 0, Int64PODTraits ); 263 DECLARE_TRAITS( kFloat16POD, float16_t, "float16_t", 0, Float16PODTraits ); 264 DECLARE_TRAITS( kFloat32POD, float32_t, "float32_t", 0, Float32PODTraits ); 265 DECLARE_TRAITS( kFloat64POD, float64_t, "float64_t", 0, Float64PODTraits ); 266 DECLARE_TRAITS( kStringPOD, string, "string", "", StringPODTraits ); 267 DECLARE_TRAITS( kWstringPOD, wstring, "wstring", L"", WstringPODTraits ); 268 269 #undef DECLARE_TRAITS 270 271 //-***************************************************************************** 272 //-***************************************************************************** 273 // Okay, now tools for extracting POD Traits from enums and from types. 274 // No easy way to do it from a name. 275 //-***************************************************************************** 276 277 //-***************************************************************************** 278 //-***************************************************************************** 279 // FROM ENUMS 280 //-***************************************************************************** 281 //-***************************************************************************** 282 template <PlainOldDataType PENUM> 283 struct PODTraitsFromEnum {}; 284 285 //-***************************************************************************** 286 // Actual specializations 287 template <> struct PODTraitsFromEnum<kBooleanPOD> : public BooleanPODTraits {}; 288 template <> struct PODTraitsFromEnum<kUint8POD> : public Uint8PODTraits {}; 289 template <> struct PODTraitsFromEnum<kInt8POD> : public Int8PODTraits {}; 290 template <> struct PODTraitsFromEnum<kUint16POD> : public Uint16PODTraits {}; 291 template <> struct PODTraitsFromEnum<kInt16POD> : public Int16PODTraits {}; 292 template <> struct PODTraitsFromEnum<kUint32POD> : public Uint32PODTraits {}; 293 template <> struct PODTraitsFromEnum<kInt32POD> : public Int32PODTraits {}; 294 template <> struct PODTraitsFromEnum<kUint64POD> : public Uint64PODTraits {}; 295 template <> struct PODTraitsFromEnum<kInt64POD> : public Int64PODTraits {}; 296 template <> struct PODTraitsFromEnum<kFloat16POD> : public Float16PODTraits {}; 297 template <> struct PODTraitsFromEnum<kFloat32POD> : public Float32PODTraits {}; 298 template <> struct PODTraitsFromEnum<kFloat64POD> : public Float64PODTraits {}; 299 template <> struct PODTraitsFromEnum<kStringPOD> : public StringPODTraits {}; 300 template <> struct PODTraitsFromEnum<kWstringPOD> : public WstringPODTraits {}; 301 302 //-***************************************************************************** 303 //-***************************************************************************** 304 // FROM TYPES 305 //-***************************************************************************** 306 //-***************************************************************************** 307 template <class PTYPE> 308 struct PODTraitsFromType {}; 309 310 //-***************************************************************************** 311 // Actual specializations 312 template <> struct PODTraitsFromType<bool_t> : public BooleanPODTraits {}; 313 template <> struct PODTraitsFromType<uint8_t> : public Uint8PODTraits {}; 314 template <> struct PODTraitsFromType<int8_t> : public Int8PODTraits {}; 315 template <> struct PODTraitsFromType<uint16_t> : public Uint16PODTraits {}; 316 template <> struct PODTraitsFromType<int16_t> : public Int16PODTraits {}; 317 template <> struct PODTraitsFromType<uint32_t> : public Uint32PODTraits {}; 318 template <> struct PODTraitsFromType<int32_t> : public Int32PODTraits {}; 319 template <> struct PODTraitsFromType<uint64_t> : public Uint64PODTraits {}; 320 template <> struct PODTraitsFromType<int64_t> : public Int64PODTraits {}; 321 template <> struct PODTraitsFromType<float16_t> : public Float16PODTraits {}; 322 template <> struct PODTraitsFromType<float32_t> : public Float32PODTraits {}; 323 template <> struct PODTraitsFromType<float64_t> : public Float64PODTraits {}; 324 template <> struct PODTraitsFromType<string> : public StringPODTraits {}; 325 template <> struct PODTraitsFromType<wstring> : public WstringPODTraits {}; 326 327 //-***************************************************************************** 328 //-***************************************************************************** 329 // Some runtime stuff, for when templates won't help. 330 //-***************************************************************************** 331 //-***************************************************************************** 332 inline size_t PODNumBytes( PlainOldDataType pod ) 333 { 334 switch ( pod ) 335 { 336 case kBooleanPOD: return BooleanPODTraits::numBytes(); 337 case kUint8POD: return Uint8PODTraits::numBytes(); 338 case kInt8POD: return Int8PODTraits::numBytes(); 339 case kUint16POD: return Uint16PODTraits::numBytes(); 340 case kInt16POD: return Int16PODTraits::numBytes(); 341 case kUint32POD: return Uint32PODTraits::numBytes(); 342 case kInt32POD: return Int32PODTraits::numBytes(); 343 case kUint64POD: return Uint64PODTraits::numBytes(); 344 case kInt64POD: return Int64PODTraits::numBytes(); 345 case kFloat16POD: return Float16PODTraits::numBytes(); 346 case kFloat32POD: return Float32PODTraits::numBytes(); 347 case kFloat64POD: return Float64PODTraits::numBytes(); 348 case kStringPOD: return StringPODTraits::numBytes(); 349 case kWstringPOD: return WstringPODTraits::numBytes(); 350 default: 351 // Badness! 352 assert( false ); 353 return 0; 354 }; 355 } 356 357 //-***************************************************************************** 358 inline const char *PODName( PlainOldDataType pod ) 359 { 360 switch ( pod ) 361 { 362 case kBooleanPOD: return BooleanPODTraits::name(); 363 case kUint8POD: return Uint8PODTraits::name(); 364 case kInt8POD: return Int8PODTraits::name(); 365 case kUint16POD: return Uint16PODTraits::name(); 366 case kInt16POD: return Int16PODTraits::name(); 367 case kUint32POD: return Uint32PODTraits::name(); 368 case kInt32POD: return Int32PODTraits::name(); 369 case kUint64POD: return Uint64PODTraits::name(); 370 case kInt64POD: return Int64PODTraits::name(); 371 case kFloat16POD: return Float16PODTraits::name(); 372 case kFloat32POD: return Float32PODTraits::name(); 373 case kFloat64POD: return Float64PODTraits::name(); 374 case kStringPOD: return StringPODTraits::name(); 375 case kWstringPOD: return WstringPODTraits::name(); 376 default: 377 // Can't throw from here, so just return 0. 378 // assert( false ); 379 return "UNKNOWN"; 380 // return 0; 381 }; 382 } 383 384 //-***************************************************************************** 385 inline PlainOldDataType PODFromName( const std::string &n ) 386 { 387 if ( n == BooleanPODTraits::name() ) return BooleanPODTraits::pod_enum; 388 else if ( n == Uint8PODTraits::name() ) return Uint8PODTraits::pod_enum; 389 else if ( n == Int8PODTraits::name() ) return Int8PODTraits::pod_enum; 390 else if ( n == Uint16PODTraits::name() ) return Uint16PODTraits::pod_enum; 391 else if ( n == Int16PODTraits::name() ) return Int16PODTraits::pod_enum; 392 else if ( n == Uint32PODTraits::name() ) return Uint32PODTraits::pod_enum; 393 else if ( n == Int32PODTraits::name() ) return Int32PODTraits::pod_enum; 394 else if ( n == Uint64PODTraits::name() ) return Uint64PODTraits::pod_enum; 395 else if ( n == Int64PODTraits::name() ) return Int64PODTraits::pod_enum; 396 else if ( n == Float16PODTraits::name() ) return Float16PODTraits::pod_enum; 397 else if ( n == Float32PODTraits::name() ) return Float32PODTraits::pod_enum; 398 else if ( n == Float64PODTraits::name() ) return Float64PODTraits::pod_enum; 399 else if ( n == StringPODTraits::name() ) return StringPODTraits::pod_enum; 400 else if ( n == WstringPODTraits::name() ) return WstringPODTraits::pod_enum; 401 else return kUnknownPOD; 402 } 403 404 //-***************************************************************************** 405 //! This actually does work with strings! 406 template <PlainOldDataType POD> 407 inline void PODSetDefaultPOD( void *addr ) 408 { 409 typedef typename PODTraitsFromEnum<POD>::value_type value_type; 410 value_type *valPtr = reinterpret_cast<value_type*>( addr ); 411 if ( valPtr ) { *valPtr = PODTraitsFromEnum<POD>::default_value(); } 412 } 413 414 //-***************************************************************************** 415 inline void PODSetDefault( PlainOldDataType pod, void *bytes ) 416 { 417 switch ( pod ) 418 { 419 case kBooleanPOD: PODSetDefaultPOD<kBooleanPOD>( bytes ); return; 420 case kUint8POD: PODSetDefaultPOD<kUint8POD>( bytes ); return; 421 case kInt8POD: PODSetDefaultPOD<kInt8POD>( bytes ); return; 422 case kUint16POD: PODSetDefaultPOD<kUint16POD>( bytes ); return; 423 case kInt16POD: PODSetDefaultPOD<kInt16POD>( bytes ); return; 424 case kUint32POD: PODSetDefaultPOD<kUint32POD>( bytes ); return; 425 case kInt32POD: PODSetDefaultPOD<kInt32POD>( bytes ); return; 426 case kUint64POD: PODSetDefaultPOD<kUint64POD>( bytes ); return; 427 case kInt64POD: PODSetDefaultPOD<kInt64POD>( bytes ); return; 428 case kFloat16POD: PODSetDefaultPOD<kFloat16POD>( bytes ); return; 429 case kFloat32POD: PODSetDefaultPOD<kFloat32POD>( bytes ); return; 430 case kFloat64POD: PODSetDefaultPOD<kFloat64POD>( bytes ); return; 431 432 // This isn't tremendously valid for the string types. Eeek. 433 case kStringPOD: PODSetDefaultPOD<kStringPOD>( bytes ); return; 434 case kWstringPOD: PODSetDefaultPOD<kWstringPOD>( bytes ); return; 435 default: 436 // Can't throw, but in debug... 437 assert( false ); 438 }; 439 } 440 441 } // End namespace ALEMBIC_VERSION_NS 442 443 using namespace ALEMBIC_VERSION_NS; 444 445 } // End namespace Util 446 } // End namespace Alembic 447 448 #endif 449 450