| 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 |
|---|