]> mj.ucw.cz Git - libucw.git/blob - ucw/ff-binary.h
bgets_mp(): Added a non-intuitive warning to documentation.
[libucw.git] / ucw / ff-binary.h
1 /*
2  *      UCW Library -- Fast Buffered I/O on Binary Values
3  *
4  *      (c) 1997--2007 Martin Mares <mj@ucw.cz>
5  *      (c) 2004 Robert Spalek <robert@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #ifndef _UCW_FF_BINARY_H
12 #define _UCW_FF_BINARY_H
13
14 #include <ucw/fastbuf.h>
15 #include <ucw/unaligned.h>
16
17 #ifdef CONFIG_UCW_CLEAN_ABI
18 #define bget5_be_slow ucw_bget5_be_slow
19 #define bget5_le_slow ucw_bget5_le_slow
20 #define bget5_slow ucw_bget5_slow
21 #define bgetl_be_slow ucw_bgetl_be_slow
22 #define bgetl_le_slow ucw_bgetl_le_slow
23 #define bgetl_slow ucw_bgetl_slow
24 #define bgetq_be_slow ucw_bgetq_be_slow
25 #define bgetq_le_slow ucw_bgetq_le_slow
26 #define bgetq_slow ucw_bgetq_slow
27 #define bgetw_be_slow ucw_bgetw_be_slow
28 #define bgetw_le_slow ucw_bgetw_le_slow
29 #define bgetw_slow ucw_bgetw_slow
30 #define bput5_be_slow ucw_bput5_be_slow
31 #define bput5_le_slow ucw_bput5_le_slow
32 #define bput5_slow ucw_bput5_slow
33 #define bputl_be_slow ucw_bputl_be_slow
34 #define bputl_le_slow ucw_bputl_le_slow
35 #define bputl_slow ucw_bputl_slow
36 #define bputq_be_slow ucw_bputq_be_slow
37 #define bputq_le_slow ucw_bputq_le_slow
38 #define bputq_slow ucw_bputq_slow
39 #define bputw_be_slow ucw_bputw_be_slow
40 #define bputw_le_slow ucw_bputw_le_slow
41 #define bputw_slow ucw_bputw_slow
42 #endif
43
44 #ifdef CPU_BIG_ENDIAN
45 #define FF_ENDIAN be
46 #else
47 #define FF_ENDIAN le
48 #endif
49
50 /***
51  *
52  * We define several functions to read or write binary integer values.
53  *
54  * The name patterns for such routines are:
55  *
56  * - `TYPE bget \#\# NAME \#\# ENDIAN(struct fastbuf *f);`
57  * - `void bput \#\# NAME \#\# ENDIAN(struct fastbuf *f, TYPE value);`
58  *
59  * where `NAME` together with `TYPE` can be:
60  *
61  * - `w` for 16-bit unsigned integers stored in sequences of 2 bytes, the `TYPE` is int
62  * - `l` for 32-bit unsigned integers stored in sequences of 4 bytes, the `TYPE` is uint
63  * - `5` for 40-bit unsigned integers stored in sequences of 5 bytes, the `TYPE` is u64
64  * - `q` for 64-bit unsigned integers stored in sequences of 8 bytes, the `TYPE` is u64
65  *
66  * and supported `ENDIAN` suffixes are:
67  *
68  * - empty for the default order of bytes (defined by CPU)
69  * - `_le` for little-endian
70  * - `_be` for big-endian
71  *
72  * If we fail to read enough bytes because of EOF, the reading function returns `(TYPE)-1`.
73  *
74  ***/
75
76 #define GET_FUNC(type, name, bits, endian)                      \
77   type bget##name##_##endian##_slow(struct fastbuf *f);         \
78   static inline type bget##name##_##endian(struct fastbuf *f)   \
79   {                                                             \
80     if (bavailr(f) >= bits/8)                                   \
81       {                                                         \
82         type w = get_u##bits##_##endian(f->bptr);               \
83         f->bptr += bits/8;                                      \
84         return w;                                               \
85       }                                                         \
86     else                                                        \
87       return bget##name##_##endian##_slow(f);                   \
88   }
89
90 #define PUT_FUNC(type, name, bits, endian)                      \
91   void bput##name##_##endian##_slow(struct fastbuf *f, type x); \
92   static inline void bput##name##_##endian(struct fastbuf *f, type x)   \
93   {                                                             \
94     if (bavailw(f) >= bits/8)                                   \
95       {                                                         \
96         put_u##bits##_##endian(f->bptr, x);                     \
97         f->bptr += bits/8;                                      \
98       }                                                         \
99     else                                                        \
100       return bput##name##_##endian##_slow(f, x);                \
101   }
102
103 #define FF_ALL_X(type, name, bits, defendian)                   \
104   GET_FUNC(type, name, bits, be)                                \
105   GET_FUNC(type, name, bits, le)                                \
106   PUT_FUNC(type, name, bits, be)                                \
107   PUT_FUNC(type, name, bits, le)                                \
108   static inline type bget##name(struct fastbuf *f) { return bget##name##_##defendian(f); }              \
109   static inline void bput##name(struct fastbuf *f, type x) { bput##name##_##defendian(f, x); }
110
111 #define FF_ALL(type, name, bits, defendian) FF_ALL_X(type, name, bits, defendian)
112
113 FF_ALL(int, w, 16, FF_ENDIAN)
114 FF_ALL(uint, l, 32, FF_ENDIAN)
115 FF_ALL(u64, q, 64, FF_ENDIAN)
116 FF_ALL(u64, 5, 40, FF_ENDIAN)
117
118 #undef GET_FUNC
119 #undef PUT_FUNC
120 #undef FF_ENDIAN
121 #undef FF_ALL_X
122 #undef FF_ALL
123
124 /* I/O on uintptr_t (only native endianity) */
125
126 #ifdef CPU_64BIT_POINTERS
127 #define bputa(x,p) bputq(x,p)
128 #define bgeta(x) bgetq(x)
129 #else
130 #define bputa(x,p) bputl(x,p)
131 #define bgeta(x) bgetl(x)
132 #endif
133
134 #endif