Vault
4.1
|
00001 /* 00002 Copyright c1997-2014 Trygve Isaacson. All rights reserved. 00003 This file is part of the Code Vault version 4.1 00004 http://www.bombaydigital.com/ 00005 License: MIT. See LICENSE.md in the Vault top level directory. 00006 */ 00007 00008 #ifndef vtypes_h 00009 #define vtypes_h 00010 00013 // This block comment is read by Doxygen to generate the index page: 00200 /* 00201 Next we include the few platform-specific definitions we've defined. 00202 Which actual file this refers to will depend on the include path 00203 set up for this platform build. 00204 */ 00205 #include "vtypes_platform.h" 00206 00207 #include <memory> // C++11 shared_ptr 00208 #include <vector> 00209 #include <stdarg.h> 00210 #include <vector> 00211 #include <iostream> 00212 #include <deque> 00213 #include <map> 00214 #include <limits> 00215 00216 /* 00217 We choose to define just the basic specific-sized data types. Most 00218 code should just use 'int' wherever a 32-bit signed value is sufficient. 00219 But if you need a specific size (such as when doing stream i/o or 00220 talking to an external API that uses a specific sized type, these 00221 are our official definitions. 00222 */ 00223 typedef int8_t Vs8; 00224 typedef uint8_t Vu8; 00225 00226 typedef int16_t Vs16; 00227 typedef uint16_t Vu16; 00228 00229 typedef int32_t Vs32; 00230 typedef uint32_t Vu32; 00231 00232 #ifndef VCOMPILER_MSVC_6_CRIPPLED /* MSVC++ 6 hacks for this are defined in the _win platform header */ 00233 typedef int64_t Vs64; 00234 typedef uint64_t Vu64; 00235 #endif 00236 00237 typedef float VFloat; 00238 typedef double VDouble; 00239 typedef Vs64 VFSize; 00240 typedef size_t VSizeType; 00241 00242 /* 00243 These three defines are to future-proof against compile errors when overloading functions 00244 that take various integer types. Which overloads are actually identical (and thus duplicates) 00245 depends on the compile flags. Specifically, and in most 32- and 64-bit environments, 00246 Vs32 = int32_t = int, so you can't have an overloaded function with both int and Vs32 versions. 00247 But if you use an ILP64 model, then Vs64 = int64_t = int, in which case the error would be if 00248 you overload a function with both int and Vs64 versions. I don't yet have an example to know 00249 how to detect ILP64, and all others (e.g., 32-bit and LP64) have int32_t = int, so for now we 00250 just define the first one all the time (Vs32 / Vu32 are int / unsigned int), and therefore 00251 where we have int overloads (VString assignment and increment, VAssert variants) we don't define 00252 the 32-bit overloads. If you use ILP64, make this define conditional on something appropriate, 00253 and we'll avoid defining the 64-bit overloads. The definition of size_t can also conflict with 00254 unsigned int if, as Microsoft does, the headers declare it as such a typedef. 00255 An enhancement would be to auto-detect or more conditionally define these; for now all supported 00256 environments use the Vx32_IS_xINT model, and V_SIZE_T_IS_UNSIGNED_INT is handled in the platform 00257 header for Windows, so that's not necessary. 00258 @see http://en.wikipedia.org/wiki/LP64#64-bit_data_models 00259 */ 00260 #define Vx32_IS_xINT /* Vs32 is int32_t is typedef of int. Correct for 32-bit, as well as 64-bit when using LLP64/IL32P64 (e.g. Microsoft X64/IA-64) or LP64/I32LP64 (e.g. Unix; everyone but Microsoft). The norm. */ 00261 //#define Vx64_IS_xINT /* Vs64 is int64_t is typedef of int. Correct for 64-bit when using ILP64 or SILP64. The oddball case. */ 00262 //#define V_SIZE_T_IS_UNSIGNED_INT /* size_t is typedef of unsigned int. This is defined in _win/vtypes_platform.h because in MS defines size_t this way, so overloading a function signature both ways won't work. */ 00263 00264 #ifndef NULL 00265 #define NULL 0 ///< Definition of NULL in compiler environments that don't already define it. 00266 #endif 00267 00268 /* 00269 Because MSVC++ 6 uses nonstandard notation, we use a macro whenever we need 00270 to define a 64-bit constant value. 00271 00272 For signed, instead of: 00273 12345678901234567890LL or 0x0123456789ABCDEFLL 00274 we must use: 00275 CONST_S64(12345678901234567890) or CONST_S64(0x0123456789ABCDEF) 00276 00277 For unsigned, instead of: 00278 12345678901234567890ULL or 0x0123456789ABCDEFULL 00279 we must use: 00280 CONST_U64(12345678901234567890) or CONST_U64(0x0123456789ABCDEF) 00281 */ 00282 #ifndef VCOMPILER_MSVC_6_CRIPPLED /* MSVC++ 6 hacks for this are defined in Win32 platform header */ 00283 #define CONST_S64(s) /*lint -save -e961*/ s##LL /*lint -restore*/ ///< Macro to declare a Vs64 constant in a way that works even in VC++ 6. 00284 #define CONST_U64(s) s##ULL ///< Macro to declare a Vu64 constant in a way that works even in VC++ 6. 00285 #endif 00286 00287 // Limit constants. 00288 static const Vs64 V_MIN_S8 = CONST_S64(0xFFFFFFFFFFFFFF80); 00289 static const Vs64 V_MAX_S8 = CONST_S64(0x000000000000007F); 00290 static const Vs64 V_MAX_U8 = CONST_S64(0x00000000000000FF); 00291 static const Vs64 V_MIN_S16 = CONST_S64(0xFFFFFFFFFFFF8000); 00292 static const Vs64 V_MAX_S16 = CONST_S64(0x0000000000007FFF); 00293 static const Vs64 V_MAX_U16 = CONST_S64(0x000000000000FFFF); 00294 static const Vs64 V_MIN_S32 = CONST_S64(0xFFFFFFFF80000000); 00295 static const Vs64 V_MAX_S32 = CONST_S64(0x000000007FFFFFFF); 00296 static const Vs64 V_MAX_U32 = CONST_S64(0x00000000FFFFFFFF); 00297 static const Vs64 V_MIN_S64 = CONST_S64(0x8000000000000000); 00298 static const Vs64 V_MAX_S64 = CONST_S64(0x7FFFFFFFFFFFFFFF); 00299 static const Vs64 V_MAX_U64 = CONST_S64(0xFFFFFFFFFFFFFFFF); 00300 static const size_t V_MAX_SIZE = std::numeric_limits<size_t>::max(); 00301 00302 namespace vault { 00303 00315 extern Vu16 VbyteSwap16(Vu16 a16BitValue); 00316 00328 extern Vu32 VbyteSwap32(Vu32 a32BitValue); 00329 00341 extern Vu64 VbyteSwap64(Vu64 a64BitValue); 00342 00354 extern VFloat VbyteSwapFloat(VFloat a32BitValue); 00355 00367 extern VDouble VbyteSwapDouble(VDouble a64BitValue); 00368 00380 extern Vs64 VgetMemoryUsage(); 00381 00386 inline void Vmemcpy(Vu8* to, Vu8* from, int length) { 00387 ::memcpy(to, (char*) from, (VSizeType) length); 00388 } 00389 00399 extern const Vu8* VgetNativeLineEnding(int& numBytes); 00400 00407 template <class T> 00408 void vectorDeleteAll(std::vector<T*>& v) { 00409 for (typename std::vector<T*>::iterator i = v.begin(); i != v.end(); ++i) { 00410 delete(*i); 00411 } 00412 00413 v.clear(); 00414 } 00415 00428 template <class KEY_TYPE, class VALUE_TYPE> 00429 void mapDeleteAllValues(std::map<KEY_TYPE, VALUE_TYPE*>& m) { 00430 for (typename std::map<KEY_TYPE, VALUE_TYPE*>::const_iterator i = m.begin(); i != m.end(); ++i) { 00431 delete(*i).second; 00432 } 00433 00434 m.clear(); 00435 } 00436 00451 template <class KEY_TYPE, class VALUE_TYPE> 00452 void mapDeleteOneValue(std::map<KEY_TYPE, VALUE_TYPE*>& m, KEY_TYPE key) { 00453 typename std::map<KEY_TYPE, VALUE_TYPE*>::iterator position = m.find(key); 00454 if (position != m.end()) { 00455 delete position->second; // Delete heap object pointed to by the value. 00456 (void) m.erase(position); // Remove the dead entry from the map. 00457 } 00458 } 00459 00460 } // namespace vault 00461 00462 // The vtypes_platform.h header decided whether VBYTESWAP_NEEDED is defined. 00463 #ifdef VBYTESWAP_NEEDED 00464 00465 // Signed 16-bit actual swapping: 00466 #define V_BYTESWAP_HTON_S16_GET(x) vault::VbyteSwap16((Vu16) x) 00467 #define V_BYTESWAP_NTOH_S16_GET(x) vault::VbyteSwap16((Vu16) x) 00468 #define V_BYTESWAP_HTON_S16_IN_PLACE(x) ((x) = (vault::VbyteSwap16((Vu16) x))) 00469 #define V_BYTESWAP_NTOH_S16_IN_PLACE(x) ((x) = (vault::VbyteSwap16((Vu16) x))) 00470 // Unsigned 16-bit actual swapping: 00471 #define V_BYTESWAP_HTON_U16_GET(x) vault::VbyteSwap16(x) 00472 #define V_BYTESWAP_NTOH_U16_GET(x) vault::VbyteSwap16(x) 00473 #define V_BYTESWAP_HTON_U16_IN_PLACE(x) ((x) = (vault::VbyteSwap16(x))) 00474 #define V_BYTESWAP_NTOH_U16_IN_PLACE(x) ((x) = (vault::VbyteSwap16(x))) 00475 00476 // Signed 32-bit actual swapping: 00477 #define V_BYTESWAP_HTON_S32_GET(x) vault::VbyteSwap32((Vu32) x) 00478 #define V_BYTESWAP_NTOH_S32_GET(x) vault::VbyteSwap32((Vu32) x) 00479 #define V_BYTESWAP_HTON_S32_IN_PLACE(x) ((x) = (Vs32)(vault::VbyteSwap32((Vu32) x))) 00480 #define V_BYTESWAP_NTOH_S32_IN_PLACE(x) ((x) = (Vs32)(vault::VbyteSwap32((Vu32) x))) 00481 // Unsigned 32-bit actual swapping: 00482 #define V_BYTESWAP_HTON_U32_GET(x) vault::VbyteSwap32(x) 00483 #define V_BYTESWAP_NTOH_U32_GET(x) vault::VbyteSwap32(x) 00484 #define V_BYTESWAP_HTON_U32_IN_PLACE(x) ((x) = (vault::VbyteSwap32(x))) 00485 #define V_BYTESWAP_NTOH_U32_IN_PLACE(x) ((x) = (vault::VbyteSwap32(x))) 00486 00487 // Signed 64-bit actual swapping: 00488 #define V_BYTESWAP_HTON_S64_GET(x) vault::VbyteSwap64((Vu64) x) 00489 #define V_BYTESWAP_NTOH_S64_GET(x) vault::VbyteSwap64((Vu64) x) 00490 #define V_BYTESWAP_HTON_S64_IN_PLACE(x) ((x) = (vault::VbyteSwap64((Vu64) x))) 00491 #define V_BYTESWAP_NTOH_S64_IN_PLACE(x) ((x) = (vault::VbyteSwap64((Vu64) x))) 00492 // Unsigned 64-bit actual swapping: 00493 #define V_BYTESWAP_HTON_U64_GET(x) vault::VbyteSwap64(x) 00494 #define V_BYTESWAP_NTOH_U64_GET(x) vault::VbyteSwap64(x) 00495 #define V_BYTESWAP_HTON_U64_IN_PLACE(x) ((x) = (vault::VbyteSwap64(x))) 00496 #define V_BYTESWAP_NTOH_U64_IN_PLACE(x) ((x) = (vault::VbyteSwap64(x))) 00497 00498 // VFloat (float) actual swapping: 00499 #define V_BYTESWAP_HTON_F_GET(x) vault::VbyteSwapFloat(x) 00500 #define V_BYTESWAP_NTOH_F_GET(x) vault::VbyteSwapFloat(x) 00501 #define V_BYTESWAP_HTON_F_IN_PLACE(x) ((x) = (vault::VbyteSwapFloat(x))) 00502 #define V_BYTESWAP_NTOH_F_IN_PLACE(x) ((x) = (vault::VbyteSwapFloat(x))) 00503 00504 // VDouble (double) actual swapping: 00505 #define V_BYTESWAP_HTON_D_GET(x) vault::VbyteSwapDouble(x) 00506 #define V_BYTESWAP_NTOH_D_GET(x) vault::VbyteSwapDouble(x) 00507 #define V_BYTESWAP_HTON_D_IN_PLACE(x) ((x) = (vault::VbyteSwapDouble(x))) 00508 #define V_BYTESWAP_NTOH_D_IN_PLACE(x) ((x) = (vault::VbyteSwapDouble(x))) 00509 00510 #else 00511 00512 // Signed 16-bit no-op non-swapping: 00513 #define V_BYTESWAP_HTON_S16_GET(x) (x) 00514 #define V_BYTESWAP_NTOH_S16_GET(x) (x) 00515 #define V_BYTESWAP_HTON_S16_IN_PLACE(x) ((void)0) 00516 #define V_BYTESWAP_NTOH_S16_IN_PLACE(x) ((void)0) 00517 // Unsigned 16-bit no-op non-swapping: 00518 #define V_BYTESWAP_HTON_U16_GET(x) (x) 00519 #define V_BYTESWAP_NTOH_U16_GET(x) (x) 00520 #define V_BYTESWAP_HTON_U16_IN_PLACE(x) ((void)0) 00521 #define V_BYTESWAP_NTOH_U16_IN_PLACE(x) ((void)0) 00522 00523 // Signed 32-bit no-op non-swapping: 00524 #define V_BYTESWAP_HTON_S32_GET(x) (x) 00525 #define V_BYTESWAP_NTOH_S32_GET(x) (x) 00526 #define V_BYTESWAP_HTON_S32_IN_PLACE(x) ((void)0) 00527 #define V_BYTESWAP_NTOH_S32_IN_PLACE(x) ((void)0) 00528 // Unsigned 32-bit no-op non-swapping: 00529 #define V_BYTESWAP_HTON_U32_GET(x) (x) 00530 #define V_BYTESWAP_NTOH_U32_GET(x) (x) 00531 #define V_BYTESWAP_HTON_U32_IN_PLACE(x) ((void)0) 00532 #define V_BYTESWAP_NTOH_U32_IN_PLACE(x) ((void)0) 00533 00534 // Signed 64-bit no-op non-swapping: 00535 #define V_BYTESWAP_HTON_S64_GET(x) (x) 00536 #define V_BYTESWAP_NTOH_S64_GET(x) (x) 00537 #define V_BYTESWAP_HTON_S64_IN_PLACE(x) ((void)0) 00538 #define V_BYTESWAP_NTOH_S64_IN_PLACE(x) ((void)0) 00539 // Unsigned 64-bit no-op non-swapping: 00540 #define V_BYTESWAP_HTON_U64_GET(x) (x) 00541 #define V_BYTESWAP_NTOH_U64_GET(x) (x) 00542 #define V_BYTESWAP_HTON_U64_IN_PLACE(x) ((void)0) 00543 #define V_BYTESWAP_NTOH_U64_IN_PLACE(x) ((void)0) 00544 00545 // VFloat (float) no-op non-swapping: 00546 #define V_BYTESWAP_HTON_F_GET(x) (x) 00547 #define V_BYTESWAP_NTOH_F_GET(x) (x) 00548 #define V_BYTESWAP_HTON_F_IN_PLACE(x) ((void)0) 00549 #define V_BYTESWAP_NTOH_F_IN_PLACE(x) ((void)0) 00550 00551 // VDouble (double) no-op non-swapping: 00552 #define V_BYTESWAP_HTON_D_GET(x) (x) 00553 #define V_BYTESWAP_NTOH_D_GET(x) (x) 00554 #define V_BYTESWAP_HTON_D_IN_PLACE(x) ((void)0) 00555 #define V_BYTESWAP_NTOH_D_IN_PLACE(x) ((void)0) 00556 00557 #endif 00558 00559 /* 00560 Because MSVC++ 6 does not support the C++ standard we must define a macro 00561 for defining static class constants such as "const static int kFoo = 1;" 00562 and doing something different in that compiler. 00563 */ 00564 #ifndef VCOMPILER_MSVC_6_CRIPPLED /* MSVC++ 6 hacks for this are defined in Win32 platform header */ 00565 #define CLASS_CONST(type, name, init) static const type name = (init) ///< Macro to declare a class static constant in a way that works even in VC++ 6. 00566 #endif 00567 00570 /* 00571 Here is where we use a hierarchy of preprocessor symbols to control assertion behavior. 00572 The hierarchy of user-definable symbols is: 00573 VAULT_ASSERTIONS_ENABLED 00574 V_ASSERT_INVARIANT_ENABLED 00575 V_ASSERT_INVARIANT_classname_ENABLED (for a given classname) 00576 00577 In vconfigure.h, you may define any or all of these symbols to 0 or 1 to force them off or on; 00578 by default, V_ASSERT_ENABLED is on unless VAULT_ASSERTIONS_NOOP is defined; and the others inherit their state from 00579 the level above. 00580 00581 Internally, we use the above symbols to define or leave undefined the following symbols: 00582 V_ASSERT_ACTIVE 00583 V_ASSERT_INVARIANT_ACTIVE 00584 V_ASSERT_INVARIANT_classname_ACTIVE (for a given classname) 00585 00586 This allows to the Vault code to simply #ifdef the existence of those symbols. 00587 00588 The following values for classname are implemented: 00589 VEXCEPTION 00590 VSTRING 00591 VDATE_AND_TIME 00592 VMESSAGE 00593 VMEMORYSTREAM 00594 VTEXTIOSTREAM 00595 */ 00596 00597 // Do the VASSERT macros do anything if called? 00598 #ifndef VAULT_ASSERTIONS_ENABLED 00599 #define V_ASSERT_ACTIVE 00600 #else 00601 #if VAULT_ASSERTIONS_ENABLED == 0 00602 // don't define V_ASSERT_ACTIVE, thereby disabling the VASSERT macros 00603 #else 00604 #define V_ASSERT_ACTIVE 00605 #endif 00606 #endif 00607 00608 // Does a "failed assertion" (e.g., VASSERT(false)) throws a VStackTraceException in addition to logging an error? 00609 // Turned on by default here; define to 0 in vconfigure.h to turn it off. 00610 #ifndef VAULT_ASSERTIONS_THROW 00611 #define V_ASSERT_THROWS_EXCEPTION 00612 #else 00613 #if VAULT_ASSERTIONS_THROW == 0 00614 // don't define V_ASSERT_THROWS_EXCEPTION, thereby disabling throwing upon assertion failure 00615 #else 00616 #define V_ASSERT_THROWS_EXCEPTION 00617 #endif 00618 #endif 00619 00620 // Does ASSERT_INVARIANT actually call this->_assertInvariant? 00621 #ifdef V_ASSERT_INVARIANT_ENABLED 00622 #if V_ASSERT_INVARIANT_ENABLED == 1 00623 #define V_ASSERT_INVARIANT_ACTIVE 00624 #endif 00625 #else 00626 #ifdef V_ASSERT_ACTIVE 00627 #define V_ASSERT_INVARIANT_ACTIVE 00628 #endif 00629 #endif 00630 00631 /* 00632 Now we can actually decide on the definition of ASSERT_INVARIANT(). 00633 It either calls this->_assertInvariant() or does nothing. 00634 */ 00635 #ifdef V_ASSERT_INVARIANT_ACTIVE 00636 #define ASSERT_INVARIANT() this->_assertInvariant() ///< Macro to call this->_assertInvariant(). 00637 #else 00638 #define ASSERT_INVARIANT() ((void) 0) ///< No-op. 00639 #endif 00640 00641 // This is useful in some _assertInvariant() methods, to detect when there is a 00642 // pointer that was already deallocated. In debug mode, VC++ generally sets pointers to 00643 // this value upon deleting the pointer. 00644 extern const void* const VCPP_DEBUG_BAD_POINTER_VALUE; 00645 00646 // Uncomment this define, or define it in your vconfigure.h to get a trace of static 00647 // initialization through the macro below: 00648 //#define V_DEBUG_STATIC_INITIALIZATION_TRACE 1 00649 00650 extern int Vtrace(const char* fileName, int lineNumber); 00651 #ifdef V_DEBUG_STATIC_INITIALIZATION_TRACE 00652 #define V_STATIC_INIT_TRACE static int staticVtrace = Vtrace(__FILE__, __LINE__); 00653 #else 00654 #define V_STATIC_INIT_TRACE 00655 #endif 00656 00657 #define V_CONSTRAIN_MINMAX(n, minValue, maxValue) V_MAX(minValue, V_MIN(maxValue, n)) 00658 00667 class VAutoreleasePool { 00668 public: 00669 VAutoreleasePool(); 00670 ~VAutoreleasePool(); 00671 void drain(); 00672 private: 00673 void* mPool; // "void*" so as not to add a type dependency on includers. 00674 }; 00675 00676 // In vconfigure.h this symbol's presence or lack thereof tells us whether we are 00677 // using the C++11 or Boost implementations of various smart pointer templates. 00678 // Any necessary boost includes and related compatibility stuff was done above in 00679 // vtypes_platform.h, so here we finally define the library-neutral names for 00680 // these things. The C++11 types are already made available by including <memory>. 00681 #ifdef VAULT_BOOST_SHARED_PTR_INCLUDE 00682 #define VUniquePtr boost::scoped_ptr 00683 #define VSharedPtr boost::shared_ptr 00684 #define VWeakPtr boost::weak_ptr 00685 #define VEnableSharedFromThis boost::enable_shared_from_this 00686 #define VStaticPtrCast boost::static_pointer_cast 00687 #define VDynamicPtrCast boost::dynamic_pointer_cast 00688 #define VConstPtrCast boost::const_pointer_cast 00689 #else 00690 #define VUniquePtr std::unique_ptr 00691 #define VSharedPtr std::shared_ptr 00692 #define VWeakPtr std::weak_ptr 00693 #define VEnableSharedFromThis std::enable_shared_from_this 00694 #define VStaticPtrCast std::static_pointer_cast 00695 #define VDynamicPtrCast std::dynamic_pointer_cast 00696 #define VConstPtrCast std::const_pointer_cast 00697 #endif 00698 00699 /* 00700 Memory leak tracking facility. See implementation in vmemorytracker.cpp. 00701 The feature is compiled in, or not, based on this defined preprocessor symbol. 00702 */ 00703 #ifndef __OBJC__ /* Redefining new is not compatible with NSObject use of new keyword. So OC code will not see this feature. */ 00704 #ifdef VAULT_MEMORY_ALLOCATION_TRACKING_SUPPORT 00705 00706 void* operator new(size_t size, const char* file, int line); 00707 void operator delete(void* p, const char* file, int line); 00708 void operator delete(void* p) throw(); 00709 void* operator new[](size_t size, const char* file, int line); 00710 void operator delete[](void* p, const char* file, int line); 00711 void operator delete[](void* p) throw(); 00712 #define V_NEW new(__FILE__, __LINE__) 00713 #define new V_NEW 00714 00715 class VTextIOStream; 00716 class VString; 00717 class VDuration; 00718 00719 class VMemoryTracker { 00720 public: 00721 00728 VMemoryTracker(bool enableAtStart = false); 00729 ~VMemoryTracker(); 00730 00731 static void enable(); 00732 static void disable(); 00733 static void reset(); 00734 static bool isEnabled(); 00735 static void setOver(size_t newOver); 00736 static size_t getOver(); 00737 static void setUnder(size_t newOver); 00738 static size_t getUnder(); 00739 static void setLimit(int maxNumAllocations); 00740 static int getLimit(); 00741 static void setExpiration(const VDuration& d); 00742 static Vs64 getExpirationTime(); 00743 static Vs64 getExpirationMilliseconds(); 00744 static void omitPointer(const void* p); 00745 static void enableCodeLocationCrawl(const VString& file, int line); 00746 static void disableCodeLocationCrawl(const VString& file, int line); 00747 static Vs64 getAllocationNumber(); 00759 static void reportMemoryTracking(const VString& label, bool toLogger, bool toConsole, VTextIOStream* toStream, Vs64 bufferLengthLimit, bool showDetails, bool performAnalysis); 00760 }; 00761 00762 #endif /* VAULT_MEMORY_ALLOCATION_TRACKING_SUPPORT */ 00763 #endif /* __OBJC__ */ 00764 00765 // Give app a chance to configure after us as well as before. 00766 #define VCONFIGURE_AFTER_VTYPES 00767 #include "vconfigure.h" 00768 #undef VCONFIGURE_AFTER_VTYPES 00769 00770 #endif /* vtypes_h */