source: trunk/PROBE/PT_tools.h

Last change on this file was 18730, checked in by westram, 3 years ago
  • remove trailing whitespace from c source.
File size: 7.9 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : PT_tools.h                                        //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Coded by Ralf Westram (coder@reallysoft.de) in October 2012   //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#ifndef PT_TOOLS_H
13#define PT_TOOLS_H
14
15#ifndef STATIC_ASSERT_H
16#include <static_assert.h>
17#endif
18#ifndef ARB_ASSERT_H
19#include <arb_assert.h>
20#endif
21
22#define pt_assert(bed) arb_assert(bed)
23
24typedef void * PT_PNTR;
25
26typedef unsigned char  uint_8;  // @@@ use uint8_t, uint16_t, uint32_t, uint64_t here
27typedef unsigned short uint_16;
28typedef unsigned int   uint_32;
29typedef unsigned long  uint_64;
30
31#if defined(ARB_64)
32typedef uint_64 uint_big;
33#else
34typedef uint_32 uint_big;
35#endif
36
37// ----------------------
38//      bswap for OSX
39
40#if defined(DARWIN)
41
42static inline unsigned short bswap_16(unsigned short x) {
43    return (x>>8) | (x<<8);
44}
45
46static inline unsigned int bswap_32(unsigned int x) {
47    return (bswap_16(x&0xffff)<<16) | bswap_16(x>>16);
48}
49
50static inline unsigned long long bswap_64(unsigned long long x) {
51    return (((unsigned long long)bswap_32(x&0xffffffffull))<<32) | bswap_32(x>>32);
52}
53
54#else
55#include <byteswap.h>
56#endif // DARWIN
57
58// ------------------------------------------------------------
59// Note about bswap as used here:
60//
61// * MSB has to be at start of written byte-chain, cause the most significant bit is used to separate
62//   between INT and SHORT
63//
64// * To use PT-server on a big-endian system it has to be skipped
65// ------------------------------------------------------------
66
67
68// ----------------------------
69//      read/write numbers
70
71inline uint_8   PT_read_char (const void *fromMem)  { return *(uint_8*)fromMem; }
72inline uint_16  PT_read_short(const void *fromMem)  { return bswap_16(*(uint_16*)fromMem); }
73inline uint_32  PT_read_int  (const void *fromMem)  { return bswap_32(*(uint_32*)fromMem); }
74#if defined(ARB_64)
75inline uint_64  PT_read_long (const void *fromMem)  { return bswap_64(*(uint_64*)fromMem); }
76inline uint_big PT_read_big  (const void *fromMem)  { return PT_read_long(fromMem); }
77#else
78inline uint_big PT_read_big  (const void *fromMem)  { return PT_read_int(fromMem); }
79#endif
80
81inline void PT_write_char (void *toMem, uint_8  i)  { *(uint_8*) toMem = i; }
82inline void PT_write_short(void *toMem, uint_16 i)  { *(uint_16*)toMem = bswap_16(i); }
83inline void PT_write_int  (void *toMem, uint_32 i)  { *(uint_32*)toMem = bswap_32(i); }
84#if defined(ARB_64)
85inline void PT_write_long (void *toMem, uint_64 i)  { *(uint_64*)toMem = bswap_64(i); }
86inline void PT_write_big  (void *toMem, uint_big i) { PT_write_long(toMem, i); }
87#else
88inline void PT_write_big  (void *toMem, uint_big i) { PT_write_int(toMem, i); }
89#endif
90
91// ------------------------------------------------
92//      compressed read/write positive numbers
93
94// Note: number of least significant bit is 0 (in template parameters)
95
96// compile-time generation of mask-values for bit B = [0..31]
97template <int B> struct BitMask { enum { value = (1<<B) }; };
98
99// compile-time generation of mask-values for all bits below bit B = [0..32]
100template <int B> struct BitsBelowBit { enum { value = (BitMask<B>::value-1) }; };
101template <> struct BitsBelowBit<32> { enum { value = 0xffffffff }; }; // avoid shift overflow
102template <> struct BitsBelowBit<31> { enum { value = 0x7fffffff }; }; // avoid int overflow
103
104// compile-time generation of mask-values for all bits in range [LB..HB]
105//
106template <int HB, int LB> struct BitRange { enum { value = (BitsBelowBit<HB+1>::value-BitsBelowBit<LB>::value) }; };
107
108
109template <int R> // R is number of reserved bits
110inline void write_nat_with_reserved_bits(char*& toMem, uint_32 nat, uint_8 reserved_bits) {
111    pt_assert((reserved_bits&BitsBelowBit<R>::value) == reserved_bits); // reserved_bits exceed allowed value-range
112    reserved_bits = reserved_bits << (8-R);
113    if (nat < BitMask<7-R>::value) {
114        PT_write_char(toMem, nat|reserved_bits);
115        toMem += 1;
116    }
117    else {
118        nat -= BitMask<7-R>::value;
119        if (nat < BitMask<6-R+8>::value) {
120            PT_write_short(toMem, nat|BitMask<7-R+8>::value|(reserved_bits<<8));
121            toMem += 2;
122        }
123        else {
124            nat -= BitMask<6-R+8>::value;
125            if (nat < BitMask<5-R+16>::value) {
126                PT_write_char(toMem, (nat>>16)|BitRange<7-R,6-R>::value|reserved_bits);
127                PT_write_short(toMem+1, nat&0xffff);
128                toMem += 3;
129            }
130            else {
131                nat -= BitMask<5-R+16>::value;
132                if (nat < BitMask<4-R+24>::value) {
133                    PT_write_int(toMem, nat|BitRange<7-R+24,5-R+24>::value|(reserved_bits<<24));
134                    toMem += 4;
135                }
136                else {
137                    PT_write_char(toMem, BitRange<7-R,4-R>::value|reserved_bits);
138                    PT_write_int(toMem+1, nat);
139                    toMem += 5;
140                }
141            }
142        }
143    }
144}
145
146template <int R> // R is number of reserved bits
147inline uint_32 read_nat_with_reserved_bits(const char*& fromMem, uint_8& reserved_bits) {
148    uint_32 nat   = PT_read_char(fromMem);
149    reserved_bits = nat >> (8-R);
150    nat           = nat & BitsBelowBit<8-R>::value;
151
152    if (nat & BitMask<7-R>::value) {
153        if (nat & BitMask<6-R>::value) {
154            if (nat & BitMask<5-R>::value) {
155                if (nat & BitMask<4-R>::value) { // 5 bytes
156                    nat      = PT_read_int(fromMem+1);
157                    fromMem += 5;
158                }
159                else { // 4 bytes
160                    nat      = PT_read_int(fromMem) & (BitMask<4-R+24>::value-1);
161                    fromMem += 4;
162                }
163                nat += BitMask<5-R+16>::value;
164            }
165            else { // 3 bytes
166                nat      = ((nat&(BitMask<6-R>::value-1))<<16)|PT_read_short(fromMem+1);
167                fromMem += 3;
168            }
169            nat += BitMask<6-R+8>::value;
170        }
171        else { // 2 bytes
172            nat      = PT_read_short(fromMem) & (BitMask<7-R+8>::value-1);
173            fromMem += 2;
174        }
175        nat += BitMask<7-R>::value;
176    }
177    else { // 1 byte
178        ++fromMem;
179    }
180    return nat;
181}
182
183template <int R>
184inline void write_int_with_reserved_bits(char*& toMem, int32_t i, uint_8 reserved_bits) {
185    write_nat_with_reserved_bits<R+1>(toMem, i<0 ? -i-1 : i, (reserved_bits<<1)|(i<0));
186}
187template <int R>
188inline int32_t read_int_with_reserved_bits(const char*& fromMem, uint_8& reserved_bits) {
189    uint_32 nat   = read_nat_with_reserved_bits<R+1>(fromMem, reserved_bits);
190    bool    isNeg = reserved_bits&1;
191    reserved_bits = reserved_bits>>1;
192    return isNeg ? -nat-1 : nat;
193}
194
195// read/write uint_32 using variable amount of mem (small numbers use less space than big numbers)
196inline uint_32 PT_read_compact_nat(const char*& fromMem) { uint_8 nothing; return read_nat_with_reserved_bits<0>(fromMem, nothing); }
197inline void PT_write_compact_nat(char*& toMem, uint_32 nat) { write_nat_with_reserved_bits<0>(toMem, nat, 0); }
198
199// -----------------------------
200//      read/write pointers
201
202
203STATIC_ASSERT(sizeof(void*) == sizeof(uint_big));
204
205inline void *PT_read_void_pointer(const void *fromMem) { return (void*)PT_read_big(fromMem); }
206inline void PT_write_pointer(void *toMem, const void *thePtr) { PT_write_big(toMem, (uint_big)thePtr); }
207
208template<typename POINTED>
209inline POINTED* PT_read_pointer(const void *fromMem) { return (POINTED*)PT_read_void_pointer(fromMem); }
210
211inline void fflush_all() {
212    fflush(stderr);
213    fflush(stdout);
214}
215
216#else
217#error PT_tools.h included twice
218#endif // PT_TOOLS_H
Note: See TracBrowser for help on using the repository browser.