comparison mercurial/util.py @ 35755:2384523cee4d

util: implement varint functions This will be useful in an incoming version-2 of the stream format.
author Gregory Szorc <gregory.szorc@gmail.com>
date Fri, 19 Jan 2018 22:52:35 +0100
parents fb0be099063f
children 72de5c504833 48783333f45c
comparison
equal deleted inserted replaced
35754:fb0be099063f 35755:2384523cee4d
3872 if len(s) < n: 3872 if len(s) < n:
3873 raise error.Abort(_("stream ended unexpectedly" 3873 raise error.Abort(_("stream ended unexpectedly"
3874 " (got %d bytes, expected %d)") 3874 " (got %d bytes, expected %d)")
3875 % (len(s), n)) 3875 % (len(s), n))
3876 return s 3876 return s
3877
3878 def uvarintencode(value):
3879 """Encode an unsigned integer value to a varint.
3880
3881 A varint is a variable length integer of 1 or more bytes. Each byte
3882 except the last has the most significant bit set. The lower 7 bits of
3883 each byte store the 2's complement representation, least significant group
3884 first.
3885
3886 >>> uvarintencode(0)
3887 '\\x00'
3888 >>> uvarintencode(1)
3889 '\\x01'
3890 >>> uvarintencode(127)
3891 '\\x7f'
3892 >>> uvarintencode(1337)
3893 '\\xb9\\n'
3894 >>> uvarintencode(65536)
3895 '\\x80\\x80\\x04'
3896 >>> uvarintencode(-1)
3897 Traceback (most recent call last):
3898 ...
3899 ProgrammingError: negative value for uvarint: -1
3900 """
3901 if value < 0:
3902 raise error.ProgrammingError('negative value for uvarint: %d'
3903 % value)
3904 bits = value & 0x7f
3905 value >>= 7
3906 bytes = []
3907 while value:
3908 bytes.append(pycompat.bytechr(0x80 | bits))
3909 bits = value & 0x7f
3910 value >>= 7
3911 bytes.append(pycompat.bytechr(bits))
3912
3913 return ''.join(bytes)
3914
3915 def uvarintdecodestream(fh):
3916 """Decode an unsigned variable length integer from a stream.
3917
3918 The passed argument is anything that has a ``.read(N)`` method.
3919
3920 >>> try:
3921 ... from StringIO import StringIO as BytesIO
3922 ... except ImportError:
3923 ... from io import BytesIO
3924 >>> uvarintdecodestream(BytesIO(b'\\x00'))
3925 0
3926 >>> uvarintdecodestream(BytesIO(b'\\x01'))
3927 1
3928 >>> uvarintdecodestream(BytesIO(b'\\x7f'))
3929 127
3930 >>> uvarintdecodestream(BytesIO(b'\\xb9\\n'))
3931 1337
3932 >>> uvarintdecodestream(BytesIO(b'\\x80\\x80\\x04'))
3933 65536
3934 >>> uvarintdecodestream(BytesIO(b'\\x80'))
3935 Traceback (most recent call last):
3936 ...
3937 Abort: stream ended unexpectedly (got 0 bytes, expected 1)
3938 """
3939 result = 0
3940 shift = 0
3941 while True:
3942 byte = ord(readexactly(fh, 1))
3943 result |= ((byte & 0x7f) << shift)
3944 if not (byte & 0x80):
3945 return result
3946 shift += 7