source: proto/u16u8/bitutil.py @ 5322

Last change on this file since 5322 was 358, checked in by cameron, 10 years ago

u16u8 prototype

File size: 4.9 KB
Line 
1#
2# bitutil.py
3#
4# Bitstream Utilities
5#
6# These are quick-and-dirty Python implementations of utilities
7# for demo purposes only.
8#
9# Robert D. Cameron and Dan Lin
10# Feb. 7, 2010  (additional utilities for u16u8)
11#
12#----------------------------------------------------------------------------
13#
14# We use python's unlimited precision integers for unbounded bit streams.
15# This permits simple logical operations on the entire stream.
16# Assumption: bitstreams are little-endian (e.g., as on x86).
17#
18#----------------------------------------------------------------------------
19#
20import sys
21import codecs
22# Utility functions for demo purposes.
23#
24
25def writefile(filename, s, charcode='utf-8',):
26        f = codecs.open(filename, 'w', encoding=charcode)
27        f.write(s) # writes encoded bytes to file
28        f.close()
29
30def readfile(filename):
31        f = open(filename, 'rb')
32        contents = f.read() 
33        f.close()
34        return contents
35
36def count_leading_zeroes(strm):
37        zeroes = 0
38        while (strm & 0xFFFFFFFF) == 0: 
39                zeroes += 32
40                strm >>= 32
41        while (strm & 1) == 0:
42                zeroes += 1
43                strm >>= 1
44        return zeroes
45
46def EOF_mask(strm_lgth):
47        mask = 1
48        mask <<= (strm_lgth + 1)
49        mask -= 1
50        return mask
51
52def extract_bit(strm, pos):
53        bit = (strm >> pos) & 1
54        return bit
55
56def transpose_streams(s):
57        b = []
58        mask = 128
59        index = 0
60        while index < 8:
61                current = 0
62                cursor = 1
63                for byte in s:
64                        if  (ord(byte) & mask != 0):
65                                current += cursor
66                        cursor <<= 1
67                       
68                index+=1
69                mask>>=1
70                b.append(current)
71        return (b, cursor-1)  # basis streams and EOF mask
72
73def inverse_transpose(bitset, len):
74        bytestream=""
75        cursor = 1
76        for i in range(0, len):
77                byteval = 0
78                for j in range(0,8):
79                        if bitset[j] & cursor != 0:
80                                byteval += 128 >> j
81                bytestream += chr(byteval)
82                cursor += cursor
83        return bytestream
84                       
85def filter_bits(bitstream, delmask):
86        newstream = 0
87        cursor = 1
88        while delmask > 0:
89                if delmask & 1 == 0:
90                        if bitstream & 1 == 1:
91                                newstream += cursor
92                        cursor += cursor
93                delmask >>= 1
94                bitstream >>= 1
95        while bitstream > 0:
96                if bitstream & 1 == 1:
97                        newstream += cursor
98                cursor += cursor
99                bitstream >>= 1         
100        return newstream
101                       
102def filter_bytes(bytestream, delmask):
103        newstream=""
104        cursor = 1
105        for c in bytestream:
106                if delmask & cursor == 0:
107                        newstream += c
108                cursor += cursor
109        return newstream
110                       
111def merge_bytes(stream1, stream2):
112        s = ""
113        for i in range(len(stream1)):
114                s += stream1[i]
115                s += stream2[i]
116        return s
117
118def merge_doublebytes(stream1, stream2):
119        s = ""
120        for i in range(0, len(stream1), 2):
121                s += stream1[i]+stream1[i+1]
122                s += stream2[i]+stream2[i+1]
123        return s
124       
125def merge_1(r1,r2):
126        r = 0
127        i = 0
128       
129        while (r1|r2):
130                r |= (r1&1 | ((r2&1)<<1))<<i
131                r1 >>= 1
132                r2 >>= 1
133                i = i+2
134        return r
135       
136def merge_2(r1,r2):
137        r = 0
138        i = 0
139       
140        while (r1|r2):
141                r |= (r1&3 | ((r2&3)<<2))<<i
142                r1 >>= 2
143                r2 >>= 2
144                i = i+4
145        return r
146       
147def pack_U16h(stream):
148        s = ""
149        for i in range (len(stream)/2):
150                s += stream[i*2]
151        return s
152
153def pack_U16i(stream):
154        s = ""
155        for i in range (len(stream)/2):
156                s += stream[i*2+1]
157        return s
158       
159def bitstream2string(stream, lgth):
160        str = ""
161        for i in range(lgth):
162                if stream & 1 == 1: str += '1'
163                else: str += '_'
164                stream >>= 1
165        return str
166
167def print_aligned_streams(stream_list):
168        """Print out a set of aligned streams."""
169        label_max = max([len(p[0]) for p in stream_list])
170        for p in stream_list:
171                print (p[0] + " "*(label_max - len(p[0]))) + ": " + p[1] 
172
173def print_aligned_u8_byte_streams(u8_byte_stream):
174        """Print out a set of 'encoding' aligned streams."""
175
176        # Set the system info to print utf-8
177        info = codecs.lookup('utf-8')
178        sys.stdout = info.streamwriter(sys.stdout) 
179
180        label_max = max([len(p[0]) for p in u8_byte_stream])
181        for p in u8_byte_stream:
182                sys.stdout.write(p[0] + " "*(label_max - len(p[0])) + ": ")
183               
184                for c in (p[1].decode('utf-8')):                        # for each unicode character
185                        u8_seq_len = len(c.encode('utf-8'))     # encode the unicode character as utf-8 and get the utf-8 sequence length
186                        if u8_seq_len == 1:
187                                sys.stdout.write(c)
188                        elif u8_seq_len == 2:
189                                sys.stdout.write('2_')                          # align 2 byte sequences with a trailing 2
190                        elif u8_seq_len == 3:
191                                sys.stdout.write('3__')                         # align 3 byte sequences with 2 trailing 3's
192                        elif u8_seq_len == 4:
193                                sys.stdout.write('4___')                        # align 2 byte sequences with 3 trailing 4's             
194                        else:
195                                sys.stdout.write('Error: Invalid UTF-8 character sequence of length: ' + str(u8_seq_len) + '.')                 
196                sys.stdout.write('\n')   
197
198def high_nybble_stream(bytes):
199        str=""
200        for b in bytes:
201                h = hex(ord(b))[-2]
202                if h == 'x': str += '0'
203                else: str += h
204        return str
205
206def low_nybble_stream(bytes):
207        str=""
208        for b in bytes:
209                str += hex(ord(b))[-1]
210        return str
211
212
213       
214#
215#  ScanThru is the core operation for parallel scanning.
216#  Given a bitstream Cursors marking current cursor positions,
217#  advance each cursor through occurrences of a character
218#  class identified by ScanStream.
219
220def ScanThru(Cursors, ScanStream):
221        return (Cursors + ScanStream) & ~ScanStream
222
223#
224# Advance all cursors by one position.
225def Advance(stream):
226        return stream + stream
227
Note: See TracBrowser for help on using the repository browser.