1 #!/usr/bin/env python 2 3 """ 4 Variable-length integer functions. 5 6 Copyright (C) 2009, 2010 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 15 PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License along 18 with this program. If not, see <http://www.gnu.org/licenses/>. 19 """ 20 21 from array import array 22 23 vint_cache = {} 24 vint_bytes_cache = {} 25 26 def vint(number): 27 28 "Write 'number' as a variable-length integer." 29 30 try: 31 return vint_cache[number] 32 except KeyError: 33 if number >= 0: 34 bytes = array('B') 35 _vint_to_array(number, bytes) 36 return bytes.tostring() 37 38 # Negative numbers are not supported. 39 40 else: 41 raise ValueError, "Number %r is negative." % number 42 43 def vint_to_array(number, bytes): 44 45 "Write 'number' as a variable-length integer to 'bytes'." 46 47 try: 48 bytes += vint_bytes_cache[number] 49 except KeyError: 50 if number >= 0: 51 _vint_to_array(number, bytes) 52 53 # Negative numbers are not supported. 54 55 else: 56 raise ValueError, "Number %r is negative." % number 57 58 def _vint_to_array(number, bytes): 59 60 "Write the 'number' to 'bytes' from least to most significant digits." 61 62 while number > 127: 63 bytes.append(number & 127 | 128) 64 number = number >> 7 65 else: 66 bytes.append(number) 67 68 def string_to_array(s, bytes): 69 70 "Write the given string 's' to 'bytes'." 71 72 vint_to_array(len(s), bytes) 73 bytes.fromstring(s.encode("utf-8")) 74 75 for i in xrange(0, 65536): 76 bytes = array('B') 77 _vint_to_array(i, bytes) 78 vint_bytes_cache[i] = bytes 79 vint_cache[i] = bytes.tostring() 80 81 # vim: tabstop=4 expandtab shiftwidth=4