ARB
PT_tools.h
Go to the documentation of this file.
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 
24 typedef void * PT_PNTR;
25 
26 typedef unsigned char uint_8; // @@@ use uint8_t, uint16_t, uint32_t, uint64_t here
27 typedef unsigned short uint_16;
28 typedef unsigned int uint_32;
29 typedef unsigned long uint_64;
30 
31 #if defined(ARB_64)
32 typedef uint_64 uint_big;
33 #else
34 typedef uint_32 uint_big;
35 #endif
36 
37 // ----------------------
38 // bswap for OSX
39 
40 #if defined(DARWIN)
41 
42 static inline unsigned short bswap_16(unsigned short x) {
43  return (x>>8) | (x<<8);
44 }
45 
46 static inline unsigned int bswap_32(unsigned int x) {
47  return (bswap_16(x&0xffff)<<16) | bswap_16(x>>16);
48 }
49 
50 static 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 
71 inline uint_8 PT_read_char (const void *fromMem) { return *(uint_8*)fromMem; }
72 inline uint_16 PT_read_short(const void *fromMem) { return bswap_16(*(uint_16*)fromMem); }
73 inline uint_32 PT_read_int (const void *fromMem) { return bswap_32(*(uint_32*)fromMem); }
74 #if defined(ARB_64)
75 inline uint_64 PT_read_long (const void *fromMem) { return bswap_64(*(uint_64*)fromMem); }
76 inline uint_big PT_read_big (const void *fromMem) { return PT_read_long(fromMem); }
77 #else
78 inline uint_big PT_read_big (const void *fromMem) { return PT_read_int(fromMem); }
79 #endif
80 
81 inline void PT_write_char (void *toMem, uint_8 i) { *(uint_8*) toMem = i; }
82 inline void PT_write_short(void *toMem, uint_16 i) { *(uint_16*)toMem = bswap_16(i); }
83 inline void PT_write_int (void *toMem, uint_32 i) { *(uint_32*)toMem = bswap_32(i); }
84 #if defined(ARB_64)
85 inline void PT_write_long (void *toMem, uint_64 i) { *(uint_64*)toMem = bswap_64(i); }
86 inline void PT_write_big (void *toMem, uint_big i) { PT_write_long(toMem, i); }
87 #else
88 inline 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]
97 template <int B> struct BitMask { enum { value = (1<<B) }; };
98 
99 // compile-time generation of mask-values for all bits below bit B = [0..32]
100 template <int B> struct BitsBelowBit { enum { value = (BitMask<B>::value-1) }; };
101 template <> struct BitsBelowBit<32> { enum { value = 0xffffffff }; }; // avoid shift overflow
102 template <> 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 //
106 template <int HB, int LB> struct BitRange { enum { value = (BitsBelowBit<HB+1>::value-BitsBelowBit<LB>::value) }; };
107 
108 
109 template <int R> // R is number of reserved bits
110 inline 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 
146 template <int R> // R is number of reserved bits
147 inline 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 
183 template <int R>
184 inline 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 }
187 template <int R>
188 inline 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)
196 inline uint_32 PT_read_compact_nat(const char*& fromMem) { uint_8 nothing; return read_nat_with_reserved_bits<0>(fromMem, nothing); }
197 inline 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 
203 STATIC_ASSERT(sizeof(void*) == sizeof(uint_big));
204 
205 inline void *PT_read_void_pointer(const void *fromMem) { return (void*)PT_read_big(fromMem); }
206 inline void PT_write_pointer(void *toMem, const void *thePtr) { PT_write_big(toMem, (uint_big)thePtr); }
207 
208 template<typename POINTED>
209 inline POINTED* PT_read_pointer(const void *fromMem) { return (POINTED*)PT_read_void_pointer(fromMem); }
210 
211 inline 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
unsigned long uint_64
Definition: PT_tools.h:29
void * PT_PNTR
Definition: PT_tools.h:24
uint_big PT_read_big(const void *fromMem)
Definition: PT_tools.h:78
void fflush_all()
Definition: PT_tools.h:211
void PT_write_short(void *toMem, uint_16 i)
Definition: PT_tools.h:82
void write_int_with_reserved_bits(char *&toMem, int32_t i, uint_8 reserved_bits)
Definition: PT_tools.h:184
unsigned short uint_16
Definition: PT_tools.h:27
unsigned int uint_32
Definition: PT_tools.h:28
uint_32 PT_read_compact_nat(const char *&fromMem)
Definition: PT_tools.h:196
void PT_write_char(void *toMem, uint_8 i)
Definition: PT_tools.h:81
void PT_write_pointer(void *toMem, const void *thePtr)
Definition: PT_tools.h:206
fflush(stdout)
unsigned int nat
Definition: gb_aci_impl.h:61
void PT_write_compact_nat(char *&toMem, uint_32 nat)
Definition: PT_tools.h:197
STATIC_ASSERT(sizeof(void *)==sizeof(uint_big))
POINTED * PT_read_pointer(const void *fromMem)
Definition: PT_tools.h:209
#define pt_assert(bed)
Definition: PT_tools.h:22
void write_nat_with_reserved_bits(char *&toMem, uint_32 nat, uint_8 reserved_bits)
Definition: PT_tools.h:110
uint_8 PT_read_char(const void *fromMem)
Definition: PT_tools.h:71
uint_32 uint_big
Definition: PT_tools.h:34
uint_32 PT_read_int(const void *fromMem)
Definition: PT_tools.h:73
unsigned char uint_8
Definition: PT_tools.h:26
uint_16 PT_read_short(const void *fromMem)
Definition: PT_tools.h:72
void PT_write_big(void *toMem, uint_big i)
Definition: PT_tools.h:88
int32_t read_int_with_reserved_bits(const char *&fromMem, uint_8 &reserved_bits)
Definition: PT_tools.h:188
uint_32 read_nat_with_reserved_bits(const char *&fromMem, uint_8 &reserved_bits)
Definition: PT_tools.h:147
void * PT_read_void_pointer(const void *fromMem)
Definition: PT_tools.h:205
void PT_write_int(void *toMem, uint_32 i)
Definition: PT_tools.h:83