// all network traffic is in 32bit ints, which are then compressed using the following simple scheme (assumes that most values are small). /* * ii[jjkk][llmm] * * (ii == -128) => jjkk * (ii == -127) => jjkkllmm * (ii > -127) => ii */ void putint(uchar *&p, int n) { if(n<128 && n>-127) { *p++ = n; } else if(n<0x8000 && n>=-0x8000) { *p++ = 0x80; *p++ = n; *p++ = n>>8; } else { *p++ = 0x81; *p++ = n; *p++ = n>>8; *p++ = n>>16; *p++ = n>>24; }; }; int getint(uchar *&p) { int c = *((char *)p); p++; if(c==-128) { int n = *p++; n |= *((char *)p)<<8; p++; return n;} else if(c==-127) { int n = *p++; n |= *p++<<8; n |= *p++<<16; return n|(*p++<<24); } else return c; }; // much smaller encoding for unsigned integers up to 28 bits, but can handle signed /* * i[01234567] j[01234567] k[01234567] l[01234567] * * (!i[7]) => i[0..6] 25*0 * ( i[7] && !j[7]) => i[0..6] j[0..6] 18*0 * ( i[7] && j[7] && !k[7]) => i[0..6] j[0..6] k[0..6] 11*0 * ( i[7] && j[7] && k[7] && !l[7]) => i[0..6] j[0..6] k[0..6] l[0..6] 4*0 * ( i[7] && j[7] && k[7] && l[7]) => i[0..6] j[0..6] k[0..6] l[0..6] 4*F */ void putuint(uchar *&p, int n) { if(n < 0 || n >= (1<<21)) { // 4 bytes to put *p++ = 0x80 | (n & 0x7F); *p++ = 0x80 | ((n >> 7) & 0x7F); *p++ = 0x80 | ((n >> 14) & 0x7F); *p++ = ((n >> 21) & 0xFF); } else if(n < (1<<7)) *p++ = n; // 1 bytes to put else if(n < (1<<14)) { // 2 bytes to put *p++ = 0x80 | (n & 0x7F); *p++ = n >> 7; } else { // 3 bytes to put *p++ = 0x80 | (n & 0x7F); *p++ = 0x80 | ((n >> 7) & 0x7F); *p++ = n >> 14; }; }; int getuint(uchar *&p) { int n = *p++; if(n & 0x80) { n += (*p++ << 7) - 0x80; if(n & (1<<14)) n += (*p++ << 14) - (1<<14); if(n & (1<<21)) n += (*p++ << 21) - (1<<21); if(n & (1<<28)) n |= 0xF0000000; }; return n; };