def write_signed_vint(self, i): """ Helper method for writing 32-bit signed value, using "zig zag encoding" (see protocol buffers for explanation -- basically, sign bit is moved as LSB, rest of value shifted left by one) coupled with basic variable length encoding :param int i: Signed int """ self.write_positive_vint(util.zigzag_encode(i))
def write_number(self, i): """ Write Numner :param int|long|float|str i: number """ if isinstance(i, int): # First things first: let's zigzag encode number i = util.zigzag_encode(i) # tiny (single byte) or small (type + 6-bit value) number? if 0x3F >= i >= 0: if i <= 0x1F: self.write_byte(int((TOKEN_PREFIX_SMALL_INT + i))) return # nope, just small, 2 bytes (type, 1-byte zigzag value) for 6 bit value self.write_bytes(TOKEN_BYTE_INT_32, int((0x80 + i))) return # Ok: let's find minimal representation then b0 = int((0x80 + (i & 0x3F))) i >>= 6 if i <= 0x7F: # 13 bits is enough (== 3 byte total encoding) self.write_bytes(TOKEN_BYTE_INT_32, int(i), b0) return b1 = int((i & 0x7F)) i >>= 7 if i <= 0x7F: self.write_bytes(TOKEN_BYTE_INT_32, int(i), b1, b0) return b2 = int((i & 0x7F)) i >>= 7 if i <= 0x7F: self.write_bytes(TOKEN_BYTE_INT_32, int(i), b2, b1, b0) return # no, need all 5 bytes b3 = int((i & 0x7F)) self.write_bytes(TOKEN_BYTE_INT_32, int((i >> 7)), b3, b2, b1, b0) elif isinstance(i, long): # First: maybe 32 bits is enough? if MAX_INT_AS_LONG >= i >= MIN_INT_AS_LONG: return self.write_number(int(i)) # Then let's zigzag encode it l = util.zigzag_encode(i) # Ok, well, we do know that 5 lowest-significant bytes are needed i = int(l) # 4 can be extracted from lower int b0 = int((0x80 + (i & 0x3F))) # sign bit set in the last byte b1 = int(((i >> 6) & 0x7F)) b2 = int(((i >> 13) & 0x7F)) b3 = int(((i >> 20) & 0x7F)) # fifth one is split between ints: l = bsr(l, 27) b4 = int(((int(l)) & 0x7F)) # which may be enough? i = int((l >> 7)) if i == 0: self.write_bytes(TOKEN_BYTE_INT_64, b4, b3, b2, b1, b0) return if i <= 0x7F: self.write_bytes(TOKEN_BYTE_INT_64, int(i), b4, b3, b2, b1, b0) return b5 = int((i & 0x7F)) i >>= 7 if i <= 0x7F: self.write_bytes(TOKEN_BYTE_INT_64, int(i), b5, b4, b3, b2, b1, b0) return b6 = int((i & 0x7F)) i >>= 7 if i <= 0x7F: self.write_bytes(TOKEN_BYTE_INT_64, int(i), b6, b5, b4, b3, b2, b1, b0) return b7 = int((i & 0x7F)) i >>= 7 if i <= 0x7F: self.write_bytes(TOKEN_BYTE_INT_64, int(i), b7, b6, b5, b4, b3, b2, b1, b0) return b8 = int((i & 0x7F)) i >>= 7 # must be done, with 10 bytes! (9 * 7 + 6 == 69 bits; only need 63) self.write_bytes(TOKEN_BYTE_INT_64, int(i), b8, b7, b6, b5, b4, b3, b2, b1, b0) elif isinstance(i, basestring): if not i: self.write_null() return neg = i.startswith('-') i = i.strip('-') if i.isdigit(): self.write_integral_number(i, neg) else: self.write_decimal_number(i) elif isinstance(i, (float, decimal.Decimal)): if isinstance(i, decimal.Decimal) and isinstance(int(float(i)), long): self.write_byte(TOKEN_BYTE_BIG_DECIMAL) scale = i.as_tuple().exponent self.write_signed_vint(scale) self.write_7bit_binary(bytearray(str(i.to_integral_value()))) else: i = float(i) try: i = util.float_to_bits(i) self.write_byte(TOKEN_BYTE_FLOAT_32) self.write_byte(int(i & 0x7F)) for _ in xrange(4): i >>= 7 self.write_byte(int(i & 0x7F)) except struct.error: i = util.float_to_raw_long_bits(i) self.write_byte(TOKEN_BYTE_FLOAT_64) self.write_byte(int(i & 0x7F)) for _ in xrange(9): i >>= 7 self.write_byte(int(i & 0x7F))
def write_number(self, i): """ Write Numner :param int|long|float|str i: number """ if isinstance(i, int): # First things first: let's zigzag encode number i = util.zigzag_encode(i) # tiny (single byte) or small (type + 6-bit value) number? if 0x3F >= i >= 0: if i <= 0x1F: self.write_byte(int((TOKEN_PREFIX_SMALL_INT + i))) return # nope, just small, 2 bytes (type, 1-byte zigzag value) for 6 bit value self.write_bytes(TOKEN_BYTE_INT_32, int((0x80 + i))) return # Ok: let's find minimal representation then b0 = int((0x80 + (i & 0x3F))) i >>= 6 if i <= 0x7F: # 13 bits is enough (== 3 byte total encoding) self.write_bytes(TOKEN_BYTE_INT_32, int(i), b0) return b1 = int((i & 0x7F)) i >>= 7 if i <= 0x7F: self.write_bytes(TOKEN_BYTE_INT_32, int(i), b1, b0) return b2 = int((i & 0x7F)) i >>= 7 if i <= 0x7F: self.write_bytes(TOKEN_BYTE_INT_32, int(i), b2, b1, b0) return # no, need all 5 bytes b3 = int((i & 0x7F)) self.write_bytes(TOKEN_BYTE_INT_32, int((i >> 7)), b3, b2, b1, b0) elif isinstance(i, long): # First: maybe 32 bits is enough? if MAX_INT_AS_LONG >= i >= MIN_INT_AS_LONG: return self.write_number(int(i)) # Then let's zigzag encode it l = util.zigzag_encode(i) # Ok, well, we do know that 5 lowest-significant bytes are needed i = int(l) # 4 can be extracted from lower int b0 = int((0x80 + (i & 0x3F))) # sign bit set in the last byte b1 = int(((i >> 6) & 0x7F)) b2 = int(((i >> 13) & 0x7F)) b3 = int(((i >> 20) & 0x7F)) # fifth one is split between ints: l = bsr(l, 27) b4 = int(((int(l)) & 0x7F)) # which may be enough? i = int((l >> 7)) if i == 0: self.write_bytes(TOKEN_BYTE_INT_64, b4, b3, b2, b1, b0) return if i <= 0x7F: self.write_bytes(TOKEN_BYTE_INT_64, int(i), b4, b3, b2, b1, b0) return b5 = int((i & 0x7F)) i >>= 7 if i <= 0x7F: self.write_bytes(TOKEN_BYTE_INT_64, int(i), b5, b4, b3, b2, b1, b0) return b6 = int((i & 0x7F)) i >>= 7 if i <= 0x7F: self.write_bytes(TOKEN_BYTE_INT_64, int(i), b6, b5, b4, b3, b2, b1, b0) return b7 = int((i & 0x7F)) i >>= 7 if i <= 0x7F: self.write_bytes(TOKEN_BYTE_INT_64, int(i), b7, b6, b5, b4, b3, b2, b1, b0) return b8 = int((i & 0x7F)) i >>= 7 # must be done, with 10 bytes! (9 * 7 + 6 == 69 bits; only need 63) self.write_bytes(TOKEN_BYTE_INT_64, int(i), b8, b7, b6, b5, b4, b3, b2, b1, b0) elif isinstance(i, basestring): if not i: self.write_null() return neg = i.startswith('-') i = i.strip('-') if i.isdigit(): self.write_integral_number(i, neg) else: self.write_decimal_number(i) elif isinstance(i, (float, decimal.Decimal)): if isinstance(i, decimal.Decimal) and isinstance( int(float(i)), long): self.write_byte(TOKEN_BYTE_BIG_DECIMAL) scale = i.as_tuple().exponent self.write_signed_vint(scale) self.write_7bit_binary(bytearray(str(i.to_integral_value()))) else: i = float(i) try: i = util.float_to_bits(i) self.write_byte(TOKEN_BYTE_FLOAT_32) self.write_byte(int(i & 0x7F)) for _ in xrange(4): i >>= 7 self.write_byte(int(i & 0x7F)) except struct.error: i = util.float_to_raw_long_bits(i) self.write_byte(TOKEN_BYTE_FLOAT_64) self.write_byte(int(i & 0x7F)) for _ in xrange(9): i >>= 7 self.write_byte(int(i & 0x7F))