1 | // ============================================================= // |
---|
2 | // // |
---|
3 | // File : ad_io_inline.h // |
---|
4 | // Purpose : // |
---|
5 | // // |
---|
6 | // Coded by Ralf Westram (coder@reallysoft.de) in April 2012 // |
---|
7 | // Institute of Microbiology (Technical University Munich) // |
---|
8 | // http://www.arb-home.de/ // |
---|
9 | // // |
---|
10 | // ============================================================= // |
---|
11 | |
---|
12 | #ifndef AD_IO_INLINE_H |
---|
13 | #define AD_IO_INLINE_H |
---|
14 | |
---|
15 | #ifndef STATIC_ASSERT_H |
---|
16 | #include <static_assert.h> |
---|
17 | #endif |
---|
18 | |
---|
19 | CONSTEXPR_INLINE_Cxx14 void swap(unsigned char& c1, unsigned char& c2) { unsigned char c = c1; c1 = c2; c2 = c; } |
---|
20 | |
---|
21 | inline uint32_t reverse_byteorder(uint32_t val) { |
---|
22 | union { |
---|
23 | uint32_t as_uint32; |
---|
24 | unsigned char as_char[4]; |
---|
25 | } data; |
---|
26 | STATIC_ASSERT(sizeof(data) == 4); |
---|
27 | STATIC_ASSERT(sizeof(data.as_uint32) == 4); |
---|
28 | |
---|
29 | data.as_uint32 = val; |
---|
30 | |
---|
31 | swap(data.as_char[0], data.as_char[3]); |
---|
32 | swap(data.as_char[1], data.as_char[2]); |
---|
33 | |
---|
34 | return data.as_uint32; |
---|
35 | } |
---|
36 | |
---|
37 | inline void gb_write_out_uint32(uint32_t data, FILE *out) { |
---|
38 | // opposite of gb_read_in_uint32 |
---|
39 | ASSERT_RESULT(size_t, 1, fwrite(&data, sizeof(data), 1, out)); |
---|
40 | } |
---|
41 | |
---|
42 | inline uint32_t gb_read_in_uint32(FILE *in, bool reversed) { |
---|
43 | // opposite of gb_write_out_uint32 |
---|
44 | uint32_t val; |
---|
45 | ASSERT_RESULT(size_t, 1, fread(&val, sizeof(val), 1, in)); |
---|
46 | return reversed ? reverse_byteorder(val) : val; |
---|
47 | } |
---|
48 | |
---|
49 | inline void gb_put_number(long b0, FILE *out) { |
---|
50 | // opposite of gb_get_number |
---|
51 | |
---|
52 | if (b0 < 0) { |
---|
53 | // if this happens, we are in 32/64bit-hell |
---|
54 | // if it never fails, gb_put_number/gb_get_number should better work with uint32_t |
---|
55 | // see also ad_load.cxx@bit-hell |
---|
56 | GBK_terminate("32/64bit incompatibility detected in DB-engine, please inform devel@arb-home.de"); |
---|
57 | } |
---|
58 | |
---|
59 | typedef unsigned char uc; |
---|
60 | if (b0 >= 0x80) { |
---|
61 | long b1 = b0>>8; |
---|
62 | if (b1 >= 0x40) { |
---|
63 | long b2 = b1>>8; |
---|
64 | if (b2 >= 0x20) { |
---|
65 | long b3 = b2>>8; |
---|
66 | if (b3 >= 0x10) putc(0xf0, out); |
---|
67 | else b3 |= 0xE0; |
---|
68 | putc(uc(b3), out); |
---|
69 | } |
---|
70 | else b2 |= 0xC0; |
---|
71 | putc(uc(b2), out); |
---|
72 | } |
---|
73 | else b1 |= 0x80; |
---|
74 | putc(uc(b1), out); |
---|
75 | } |
---|
76 | putc(uc(b0), out); |
---|
77 | } |
---|
78 | |
---|
79 | inline long gb_get_number(FILE *in) { |
---|
80 | // opposite of gb_put_number |
---|
81 | unsigned int b0 = getc(in); |
---|
82 | unsigned int RES = b0; |
---|
83 | if (b0 & 0x80) { |
---|
84 | RES = getc(in); |
---|
85 | if (b0 & 0x40) { |
---|
86 | RES = (RES << 8) | getc(in); |
---|
87 | if (b0 & 0x20) { |
---|
88 | RES = (RES << 8) | getc(in); |
---|
89 | if (b0 & 0x10) RES = (RES << 8) | getc(in); |
---|
90 | else RES |= (b0 & 0x0f) << 24; |
---|
91 | } |
---|
92 | else RES |= (b0 & 0x1f) << 16; |
---|
93 | } |
---|
94 | else RES |= (b0 & 0x3f) << 8; |
---|
95 | } |
---|
96 | return RES; |
---|
97 | } |
---|
98 | |
---|
99 | |
---|
100 | #else |
---|
101 | #error ad_io_inline.h included twice |
---|
102 | #endif // AD_IO_INLINE_H |
---|