Line data Source code
1 : /* 2 : * SPDX-License-Identifier: MPL-2.0 3 : * 4 : * This Source Code Form is subject to the terms of the Mozilla Public 5 : * License, v. 2.0. If a copy of the MPL was not distributed with this 6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 : * 8 : * Copyright 2024 MonetDB Foundation; 9 : * Copyright August 2008 - 2023 MonetDB B.V.; 10 : * Copyright 1997 - July 2008 CWI. 11 : */ 12 : 13 : #ifndef COPYBINARY_SUPPORT_H 14 : #define COPYBINARY_SUPPORT_H 15 : 16 : #include "copybinary.h" 17 : 18 : // According to Godbolt, these code sequences are recognized by 19 : // GCC at least back to 6.2 and Clang at least back to 6.0.0. 20 : // I didn't check earlier ones. 21 : // They properly use byte swapping instructions. 22 : // MSVC doesn't recognize it but that's no problem because we will 23 : // not ever use it for big endian platforms. 24 : 25 : // First some macros that can be used a expressions: 26 : // uint16_t swapped = copy_binary_byteswap16(value); 27 : 28 : 29 : #ifdef _MSC_VER 30 : 31 : static inline uint16_t 32 : copy_binary_byteswap16(uint16_t value) { 33 : return _byteswap_ushort(value); 34 : } 35 : 36 : static inline uint32_t 37 : copy_binary_byteswap32(uint32_t value) { 38 : return _byteswap_ulong(value); 39 : } 40 : 41 : static inline uint64_t 42 : copy_binary_byteswap64(uint64_t value) { 43 : return _byteswap_uint64(value); 44 : } 45 : 46 : #else 47 : 48 : static inline uint16_t 49 5000022 : copy_binary_byteswap16(uint16_t value) { 50 5000022 : return 51 5000018 : ((value & 0xFF00u) >> 8u) | 52 : ((value & 0x00FFu) << 8u) 53 : ; 54 : } 55 : 56 : static inline uint32_t 57 14000047 : copy_binary_byteswap32(uint32_t value) { 58 14000047 : return 59 14000047 : ((value & 0xFF000000u) >> 24u) | 60 14000047 : ((value & 0x00FF0000u) >> 8u) | 61 14000047 : ((value & 0x0000FF00u) << 8u) | 62 14000045 : ((value & 0x000000FFu) << 24u) 63 : ; 64 : } 65 : 66 : static inline uint64_t 67 15000033 : copy_binary_byteswap64(uint64_t value) { 68 15000033 : return 69 15000033 : ((value & 0xFF00000000000000u) >> 56u) | 70 15000033 : ((value & 0x00FF000000000000u) >> 40u) | 71 15000033 : ((value & 0x0000FF0000000000u) >> 24u) | 72 15000033 : ((value & 0x000000FF00000000u) >> 8u) | 73 15000033 : ((value & 0x00000000FF000000u) << 8u) | 74 15000033 : ((value & 0x0000000000FF0000u) << 24u) | 75 15000033 : ((value & 0x000000000000FF00u) << 40u) | 76 15000033 : ((value & 0x00000000000000FFu) << 56u) 77 : ; 78 : } 79 : 80 : #endif 81 : 82 : #ifdef HAVE_HGE 83 : static inline 84 6 : uhge copy_binary_byteswap128(uhge value) { 85 6 : uint64_t lo = (uint64_t) value; 86 6 : uint64_t hi = (uint64_t) (value >> 64); 87 6 : uhge swapped_lo = (uhge)copy_binary_byteswap64(lo); 88 6 : uhge swapped_hi = (uhge)copy_binary_byteswap64(hi); 89 6 : return swapped_hi | (swapped_lo << 64); 90 : } 91 : #endif 92 : 93 : static inline copy_binary_date 94 4 : copy_binary_byteswap_date(copy_binary_date value) 95 : { 96 4 : return (copy_binary_date) { 97 : .day = value.day, 98 : .month = value.month, 99 2 : .year = copy_binary_byteswap16(value.year), 100 : }; 101 : } 102 : 103 : static inline copy_binary_time 104 2 : copy_binary_byteswap_time(copy_binary_time value) 105 : { 106 2 : return (copy_binary_time) { 107 2 : .ms = copy_binary_byteswap32(value.ms), 108 2 : .seconds = value.seconds, 109 2 : .minutes = value.minutes, 110 2 : .hours = value.hours, 111 2 : .padding = value.padding, 112 : }; 113 : } 114 : 115 : static inline copy_binary_timestamp 116 2 : copy_binary_byteswap_timestamp(copy_binary_timestamp value) 117 : { 118 2 : return (copy_binary_timestamp) { 119 2 : .time = copy_binary_byteswap_time(value.time), 120 2 : .date = copy_binary_byteswap_date(value.date), 121 : }; 122 : } 123 : 124 : 125 : 126 : 127 : // These macros are used to convert a value in-place. 128 : // This makes it possible to also convert timestamp structs. 129 : 130 : static inline void 131 1000012 : copy_binary_convert16(void *p) 132 : { 133 1000012 : uint16_t *pp = (uint16_t*)p; 134 1000012 : *pp = copy_binary_byteswap16(*pp); 135 1000012 : } 136 : 137 : static inline void 138 2000012 : copy_binary_convert32(void *p) 139 : { 140 2000012 : uint32_t *pp = (uint32_t*)p; 141 2000012 : *pp = copy_binary_byteswap32(*pp); 142 2000012 : } 143 : 144 : static inline void 145 7000012 : copy_binary_convert64(void *p) 146 : { 147 7000012 : uint64_t *pp = (uint64_t*)p; 148 7000012 : *pp = copy_binary_byteswap64(*pp); 149 7000012 : } 150 : 151 : #ifdef HAVE_HGE 152 : static inline void 153 0 : copy_binary_convert128(void *p) 154 : { 155 0 : uhge *pp = (uhge*)p; 156 0 : *pp = copy_binary_byteswap128(*pp); 157 0 : } 158 : #endif 159 : 160 : static inline void 161 0 : copy_binary_convert_date(void *p) 162 : { 163 0 : copy_binary_date *pp = (copy_binary_date*)p; 164 0 : copy_binary_convert16(&pp->year); 165 : } 166 : 167 : 168 : static inline void 169 0 : copy_binary_convert_time(void *p) 170 : { 171 0 : copy_binary_time *pp = (copy_binary_time*)p; 172 0 : copy_binary_convert32(&pp->ms); 173 : } 174 : 175 : static inline void 176 0 : copy_binary_convert_timestamp(void *p) 177 : { 178 0 : copy_binary_timestamp *pp = (copy_binary_timestamp*)p; 179 0 : copy_binary_convert_date(&pp->date); 180 0 : copy_binary_convert_time(&pp->time); 181 0 : } 182 : 183 : #endif