1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2006, 2011 Free Software Foundation, Inc.
3
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, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifndef LIBPSPP_INTEGER_FORMAT_H
18 #define LIBPSPP_INTEGER_FORMAT_H 1
19
20 #include <byteswap.h>
21 #include <stdint.h>
22 #include <string.h>
23
24 #include "libpspp/str.h"
25
26 /* An integer format. */
27 enum integer_format
28 {
29 INTEGER_MSB_FIRST, /* Big-endian: MSB at lowest address. */
30 INTEGER_LSB_FIRST, /* Little-endian: LSB at lowest address. */
31 INTEGER_VAX, /* VAX-endian: little-endian 16-bit words
32 in big-endian order. */
33
34 /* Native endianness. */
35 #ifdef WORDS_BIGENDIAN
36 INTEGER_NATIVE = INTEGER_MSB_FIRST
37 #else
38 INTEGER_NATIVE = INTEGER_LSB_FIRST
39 #endif
40 };
41
42 void integer_convert (enum integer_format, const void *,
43 enum integer_format, void *,
44 size_t);
45 uint64_t integer_get (enum integer_format, const void *, size_t);
46 void integer_put (uint64_t, enum integer_format, void *, size_t);
47
48 bool integer_identify (uint64_t expected_value, const void *, size_t,
49 enum integer_format *);
50
51 /* Returns the 16-bit unsigned integer at P, which need not be aligned. */
52 static inline uint16_t
get_uint16(const void * p)53 get_uint16 (const void *p)
54 {
55 uint16_t x;
56 memcpy (&x, p, sizeof x);
57 return x;
58 }
59
60 /* Returns the 32-bit unsigned integer at P, which need not be aligned. */
61 static inline uint32_t
get_uint32(const void * p)62 get_uint32 (const void *p)
63 {
64 uint32_t x;
65 memcpy (&x, p, sizeof x);
66 return x;
67 }
68
69 /* Returns the 64-bit unsigned integer at P, which need not be aligned. */
70 static inline uint64_t
get_uint64(const void * p)71 get_uint64 (const void *p)
72 {
73 uint64_t x;
74 memcpy (&x, p, sizeof x);
75 return x;
76 }
77
78 /* Stores 16-bit unsigned integer X at P, which need not be aligned. */
79 static inline void
put_uint16(uint16_t x,void * p)80 put_uint16 (uint16_t x, void *p)
81 {
82 memcpy (p, &x, sizeof x);
83 }
84
85 /* Stores 32-bit unsigned integer X at P, which need not be aligned. */
86 static inline void
put_uint32(uint32_t x,void * p)87 put_uint32 (uint32_t x, void *p)
88 {
89 memcpy (p, &x, sizeof x);
90 }
91
92 /* Stores 64-bit unsigned integer X at P, which need not be aligned. */
93 static inline void
put_uint64(uint64_t x,void * p)94 put_uint64 (uint64_t x, void *p)
95 {
96 memcpy (p, &x, sizeof x);
97 }
98
99 /* Returns NATIVE converted to a form that, when stored in
100 memory, will be in little-endian byte order. */
101 static inline uint16_t
native_to_le16(uint16_t native)102 native_to_le16 (uint16_t native)
103 {
104 return INTEGER_NATIVE == INTEGER_LSB_FIRST ? native : bswap_16 (native);
105 }
106
107 /* Returns NATIVE converted to a form that, when stored in
108 memory, will be in big-endian byte order. */
109 static inline uint16_t
native_to_be16(uint16_t native)110 native_to_be16 (uint16_t native)
111 {
112 return INTEGER_NATIVE == INTEGER_MSB_FIRST ? native : bswap_16 (native);
113 }
114
115 /* Returns NATIVE converted to a form that, when stored in
116 memory, will be in little-endian byte order. */
117 static inline uint32_t
native_to_le32(uint32_t native)118 native_to_le32 (uint32_t native)
119 {
120 return INTEGER_NATIVE == INTEGER_LSB_FIRST ? native : bswap_32 (native);
121 }
122
123 /* Returns NATIVE converted to a form that, when stored in
124 memory, will be in big-endian byte order. */
125 static inline uint32_t
native_to_be32(uint32_t native)126 native_to_be32 (uint32_t native)
127 {
128 return INTEGER_NATIVE == INTEGER_MSB_FIRST ? native : bswap_32 (native);
129 }
130
131 /* Returns NATIVE converted to a form that, when stored in
132 memory, will be in little-endian byte order. */
133 static inline uint64_t
native_to_le64(uint64_t native)134 native_to_le64 (uint64_t native)
135 {
136 return INTEGER_NATIVE == INTEGER_LSB_FIRST ? native : bswap_64 (native);
137 }
138
139 /* Returns NATIVE converted to a form that, when stored in
140 memory, will be in big-endian byte order. */
141 static inline uint64_t
native_to_be64(uint64_t native)142 native_to_be64 (uint64_t native)
143 {
144 return INTEGER_NATIVE == INTEGER_MSB_FIRST ? native : bswap_64 (native);
145 }
146
147 /* Given LE, obtained from memory in little-endian format,
148 returns its value. */
149 static inline uint16_t
le_to_native16(uint16_t le)150 le_to_native16 (uint16_t le)
151 {
152 return INTEGER_NATIVE == INTEGER_LSB_FIRST ? le : bswap_16 (le);
153 }
154
155 /* Given BE, obtained from memory in big-endian format, returns
156 its value. */
157 static inline uint16_t
be_to_native16(uint16_t be)158 be_to_native16 (uint16_t be)
159 {
160 return INTEGER_NATIVE == INTEGER_MSB_FIRST ? be : bswap_16 (be);
161 }
162
163 /* Given LE, obtained from memory in little-endian format,
164 returns its value. */
165 static inline uint32_t
le_to_native32(uint32_t le)166 le_to_native32 (uint32_t le)
167 {
168 return INTEGER_NATIVE == INTEGER_LSB_FIRST ? le : bswap_32 (le);
169 }
170
171 /* Given BE, obtained from memory in big-endian format, returns
172 its value. */
173 static inline uint32_t
be_to_native32(uint32_t be)174 be_to_native32 (uint32_t be)
175 {
176 return INTEGER_NATIVE == INTEGER_MSB_FIRST ? be : bswap_32 (be);
177 }
178
179 /* Given LE, obtained from memory in little-endian format,
180 returns its value. */
181 static inline uint64_t
le_to_native64(uint64_t le)182 le_to_native64 (uint64_t le)
183 {
184 return INTEGER_NATIVE == INTEGER_LSB_FIRST ? le : bswap_64 (le);
185 }
186
187 /* Given BE, obtained from memory in big-endian format, returns
188 its value. */
189 static inline uint64_t
be_to_native64(uint64_t be)190 be_to_native64 (uint64_t be)
191 {
192 return INTEGER_NATIVE == INTEGER_MSB_FIRST ? be : bswap_64 (be);
193 }
194
195
196 #endif /* libpspp/integer-format.h */
197