integer-format: Add some useful helper functions.
[pspp] / src / libpspp / integer-format.h
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 \f
51 /* Returns the 16-bit unsigned integer at P, which need not be aligned. */
52 static inline uint16_t
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 */