Esempio n. 1
0
    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))
Esempio n. 2
0
    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))
Esempio n. 3
0
    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))
Esempio n. 4
0
    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))