Line data Source code
1 : /* 2 : * Distributed under the OpenDDS License. 3 : * See: http://www.opendds.org/license.html 4 : */ 5 : 6 : #ifndef OPENDDS_DCPS_VALUE_HELPER_H 7 : #define OPENDDS_DCPS_VALUE_HELPER_H 8 : 9 : #include "RestoreOutputStreamState.h" 10 : #include "Definitions.h" 11 : 12 : #include <ostream> 13 : #include <iostream> 14 : #include <iomanip> 15 : 16 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL 17 : 18 : namespace OpenDDS { 19 : namespace DCPS { 20 : 21 : template <typename IntType> 22 : std::ostream& signed_int_helper(std::ostream& o, IntType value, IntType min) 23 : { 24 : /* 25 : * It seems that in C/C++ the minus sign and the bare number are parsed 26 : * separately for negative integer literals. This can cause compilers 27 : * to complain when using the minimum value of a signed integer because 28 : * the number without the minus sign is 1 past the max signed value. 29 : * 30 : * https://stackoverflow.com/questions/65007935 31 : * 32 : * Apparently the workaround is to write it as `VALUE_PLUS_ONE - 1`. 33 : */ 34 : const bool min_value = value == min; 35 : if (min_value) ++value; 36 : o << value; 37 : if (min_value) o << " - 1"; 38 : return o; 39 : } 40 : 41 : #if ACE_SIZEOF_LONG_DOUBLE != 16 42 : inline ostream& operator<<(ostream& os, const ACE_CDR::LongDouble& val) 43 : { 44 : os << ACE_CDR::LongDouble::NativeImpl(val); 45 : return os; 46 : } 47 : #endif 48 : 49 : inline 50 2 : std::ostream& hex_value(std::ostream& o, unsigned value, size_t bytes) 51 : { 52 2 : OpenDDS::DCPS::RestoreOutputStreamState ross(o); 53 2 : o << std::hex << std::setw(bytes * 2) << std::setfill('0') << value; 54 2 : return o; 55 2 : } 56 : 57 : template <typename CharType> 58 2 : unsigned char_value(CharType value) 59 : { 60 2 : return value; 61 : } 62 : 63 : #if CHAR_MIN < 0 64 : /* 65 : * If char is signed, then it needs to be reinterpreted as unsigned char or 66 : * else static casting '\xff' to a 32-bit unsigned int would result in 67 : * 0xffffffff because those are both the signed 2's complement forms of -1. 68 : */ 69 : template <> 70 10 : inline unsigned char_value<char>(char value) 71 : { 72 10 : return reinterpret_cast<unsigned char&>(value); 73 : } 74 : #endif 75 : 76 : template <typename CharType> 77 12 : std::ostream& char_helper(std::ostream& o, CharType value) 78 : { 79 12 : switch (value) { 80 0 : case '\'': 81 : case '\"': 82 : case '\\': 83 : case '\?': 84 0 : return o << '\\' << static_cast<char>(value); 85 0 : case '\n': 86 0 : return o << "\\n"; 87 0 : case '\t': 88 0 : return o << "\\t"; 89 0 : case '\v': 90 0 : return o << "\\v"; 91 0 : case '\b': 92 0 : return o << "\\b"; 93 0 : case '\r': 94 0 : return o << "\\r"; 95 0 : case '\f': 96 0 : return o << "\\f"; 97 0 : case '\a': 98 0 : return o << "\\a"; 99 : } 100 12 : const unsigned cvalue = char_value(value); 101 12 : if (cvalue <= UCHAR_MAX && isprint(cvalue)) { 102 10 : return o << static_cast<char>(value); 103 : } 104 2 : return hex_value(o << "\\x", cvalue, sizeof(CharType) == 1 ? 1 : 2); 105 : } 106 : 107 : template <typename CharType> 108 0 : std::ostream& string_helper(std::ostream& o, const CharType* value) 109 : { 110 0 : for (size_t i = 0; value[i] != 0; ++i) { 111 0 : char_helper<CharType>(o, value[i]); 112 : } 113 0 : return o; 114 : } 115 : 116 : template <typename CharType> 117 1 : std::ostream& string_helper(std::ostream& o, const CharType* value, size_t length) 118 : { 119 9 : for (size_t i = 0; i != length; ++i) { 120 8 : char_helper<CharType>(o, value[i]); 121 : } 122 1 : return o; 123 : } 124 : 125 : } // namespace DCPS 126 : } // namespace OpenDDS 127 : 128 : OPENDDS_END_VERSIONED_NAMESPACE_DECL 129 : 130 : #endif /* OPENDDS_DCPS_VALUE_HELPER_H */