summaryrefslogtreecommitdiff
path: root/src/common/io.h
blob: 1932b121555397c7169e4fe5c2d97fce7d2116d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

/* Chrysalide - Outil d'analyse de fichiers binaires
 * io.h - prototypes pour des entrées sorties fiables et la manipulation des nombres
 *
 * Copyright (C) 2014-2019 Cyrille Bagard
 *
 *  This file is part of Chrysalide.
 *
 *  Chrysalide is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Chrysalide is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
 */


#ifndef _COMMON_IO_H
#define _COMMON_IO_H


#include <stdbool.h>
#include <sys/types.h>


#include "datatypes.h"



/* ------------------------ ENTREES/SORTIES BRUTES ENCADREES ------------------------ */


/* Lit des données depuis un flux local. */
bool safe_read(int, void *, size_t);

#define load_u8(f, v) \
    safe_read(f, v, sizeof(uint8_t));

#define load_u16(f, v, e)                               \
    ({                                                  \
        bool __ret;                                     \
        uint16_t __val;                                 \
        __ret = safe_read(f, &__val, sizeof(uint16_t)); \
        __val = swap_u16(&__val, e);                    \
        *(v) = __val;                                   \
        __ret;                                          \
    })

#define load_u32(f, v, e)                               \
    ({                                                  \
        bool __ret;                                     \
        uint32_t __val;                                 \
        __ret = safe_read(f, &__val, sizeof(uint32_t)); \
        __val = swap_u32(&__val, e);                    \
        *(v) = __val;                                   \
        __ret;                                          \
    })

#define load_u64(f, v, e)                               \
    ({                                                  \
        bool __ret;                                     \
        uint64_t __val;                                 \
        __ret = safe_read(f, &__val, sizeof(uint64_t)); \
        __val = swap_u64(&__val, e);                    \
        *(v) = __val;                                   \
        __ret;                                          \
    })

/* Lit des données depuis un flux local. */
ssize_t safe_read_partial(int, void *, size_t);

/* Ecrit des données dans un flux local. */
bool safe_write(int, const void *, size_t);

#define store_u8(f, v) \
    safe_write(f, (const uint8_t []){ v }, sizeof(uint8_t));

#define store_u16(f, v, e)                              \
    ({                                                  \
        uint16_t __val;                                 \
        __val = swap_u16((const uint16_t []){ v }, e);  \
        safe_write(f, &__val, sizeof(uint16_t));        \
    })

#define store_u32(f, v, e)                              \
    ({                                                  \
        uint32_t __val;                                 \
        __val = swap_u32((const uint32_t []){ v }, e);  \
        safe_write(f, &__val, sizeof(uint32_t));        \
    })

#define store_u64(f, v, e)                              \
    ({                                                  \
        uint64_t __val;                                 \
        __val = swap_u64((const uint64_t []){ v }, e);  \
        safe_write(f, &__val, sizeof(uint64_t));        \
    })

/* Réceptionne des données depuis un flux réseau. */
bool safe_recv(int, void *, size_t, int);

/* Envoie des données au travers un flux réseau. */
bool safe_send(int, const void *, size_t, int);



/* --------------------------- CONVERSION ENTRE BOUTISMES --------------------------- */


/* Adapte un nombre sur 16 bits à un boutisme donné. */
uint16_t swap_u16(const uint16_t *, SourceEndian);

/* Adapte un nombre sur 16 bits à un boutisme donné. */
uint32_t swap_u32(const uint32_t *, SourceEndian);

/* Adapte un nombre sur 16 bits à un boutisme donné. */
uint64_t swap_u64(const uint64_t *, SourceEndian);


#define from_u16(v, e) swap_u16(v, e)
#define from_u32(v, e) swap_u32(v, e)
#define from_u64(v, e) swap_u64(v, e)


#define to_u16(v, e) swap_u16(v, e)
#define to_u32(v, e) swap_u32(v, e)
#define to_u64(v, e) swap_u64(v, e)



/* ------------------------- BOUTISME DES ENTREES / SORTIES ------------------------- */


/* Lit un nombre non signé sur 4 bits. */
bool read_u4(uint8_t *, const bin_t *, phys_t *, phys_t, bool *);

/* Lit un nombre non signé sur un octet. */
bool read_u8(uint8_t *, const bin_t *, phys_t *, phys_t);

/* Lit un nombre non signé sur deux octets. */
bool read_u16(uint16_t *, const bin_t *, phys_t *, phys_t, SourceEndian);

/* Lit un nombre non signé sur quatre octets. */
bool read_u32(uint32_t *, const bin_t *, phys_t *, phys_t, SourceEndian);

/* Lit un nombre non signé sur huit octets. */
bool read_u64(uint64_t *, const bin_t *, phys_t *, phys_t, SourceEndian);


#define read_s4(target, data, pos, len, low) read_u4((uint8_t *)target, data, pos, len, low)
#define read_s8(target, data, pos, len) read_u8((uint8_t *)target, data, pos, len)
#define read_s16(target, data, pos, len, endian) read_u16((uint16_t *)target, data, pos, len, endian)
#define read_s32(target, data, pos, len, endian) read_u32((uint32_t *)target, data, pos, len, endian)
#define read_s64(target, data, pos, len, endian) read_u64((uint64_t *)target, data, pos, len, endian)


/* Ecrit un nombre non signé sur n octets. */
bool _write_un(const bin_t *, size_t, bin_t *, off_t *, off_t, SourceEndian);


#define write_un(value, data, pos, len, endian, type)                       \
    ({                                                                      \
        type __tmp;                                                         \
        (void)(value == &__tmp);                                            \
        _write_un((bin_t *)value, sizeof(type), data, pos, len, endian);    \
    })


#define write_u8(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint8_t)
#define write_u16(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint16_t)
#define write_u32(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint32_t)
#define write_u64(value, data, pos, len, endian) write_un(value, data, pos, len, endian, uint64_t)

#define write_s8(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint8_t)
#define write_s16(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint16_t)
#define write_s32(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint32_t)
#define write_s64(value, data, pos, len, endian) write_un(value, data, pos, len, endian, sint64_t)


/* Lit un nombre hexadécimal non signé sur deux octets. */
bool strtou8(uint8_t *, const char *, size_t *, size_t, SourceEndian);

/* Lit un nombre hexadécimal non signé sur n octets. */
bool _strtoun(uint8_t, const char *, size_t *, size_t, SourceEndian, ...);


#define strtou32(target, data, pos, len, endian) _strtoun(4, data, pos, len, endian, target)



#endif  /* _COMMON_IO_H */