source: proto/parabix2/bitutil.py @ 312

Last change on this file since 312 was 312, checked in by ksherdy, 10 years ago

Since, Python 2.x's string type acts as an immutable byte array read file data as bytes independent of encoding.
Transpose bytes as before, independent of encoding, just as bytes.

File size: 4.2 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
10# August 19, 2009
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)
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 extract_bit(strm, pos):
47        bit = (strm >> pos) & 1
48        return bit
49
50def transpose_streams(s):
51        b = []
52        mask = 128
53        index = 0
54        while index < 8:
55                current = 0
56                cursor = 1
57                for byte in s:
58                        if  (ord(byte) & mask != 0):
59                                current += cursor
60                        cursor <<= 1
61                       
62                index+=1
63                mask>>=1
64                b.append(current)
65        return (b, cursor-1)  # basis streams and EOF mask
66
67def inverse_transpose(bitset, len):
68        bytestream=""
69        cursor = 1
70        for i in range(0, len):
71                byteval = 0
72                for j in range(0,8):
73                        if bitset[j] & cursor != 0:
74                                byteval += 128 >> j
75                bytestream += chr(byteval)
76                cursor += cursor
77        return bytestream
78                       
79def filter_bits(bitstream, delmask):
80        newstream = 0
81        cursor = 1
82        while delmask > 0:
83                if delmask & 1 == 0:
84                        if bitstream & 1 == 1:
85                                newstream += cursor
86                        cursor += cursor
87                delmask >>= 1
88                bitstream >>= 1
89        while bitstream > 0:
90                if bitstream & 1 == 1:
91                        newstream += cursor
92                cursor += cursor
93                bitstream >>= 1         
94        return newstream
95                       
96def filter_bytes(bytestream, delmask):
97        newstream=""
98        cursor = 1
99        for c in bytestream:
100                if delmask & cursor == 0:
101                        newstream += c
102                cursor += cursor
103        return newstream
104                       
105def merge_bytes(stream1, stream2):
106        s = ""
107        for i in range(len(stream1)):
108                s += stream1[i]
109                s += stream2[i]
110        return s
111
112def bitstream2string(stream, lgth):
113        str = ""
114        for i in range(lgth):
115                if stream & 1 == 1: str += '1'
116                else: str += '_'
117                stream >>= 1
118        return str
119
120def print_aligned_streams(stream_list):
121        """Print out a set of aligned streams."""
122        label_max = max([len(p[0]) for p in stream_list])
123        for p in stream_list:
124                print (p[0] + " "*(label_max - len(p[0]))) + ": " + p[1] 
125
126def print_aligned_u8_byte_streams(u8_byte_stream):
127        """Print out a set of 'encoding' aligned streams."""
128
129        # Set the system info to print utf-8
130        info = codecs.lookup('utf-8')
131        sys.stdout = info.streamwriter(sys.stdout) 
132
133        label_max = max([len(p[0]) for p in u8_byte_stream])
134        for p in u8_byte_stream:
135                sys.stdout.write(p[0] + " "*(label_max - len(p[0])) + ": ")
136               
137                for c in (p[1].decode('utf-8')):                        # for each unicode character
138                        u8_seq_len = len(c.encode('utf-8'))     # encode the unicode character as utf-8 and get the utf-8 sequence length
139                        if u8_seq_len == 1:
140                                sys.stdout.write(c)
141                        elif u8_seq_len == 2:
142                                sys.stdout.write('2_')                          # align 2 byte sequences with a trailing 2
143                        elif u8_seq_len == 3:
144                                sys.stdout.write('3__')                         # align 3 byte sequences with 2 trailing 3's
145                        elif u8_seq_len == 4:
146                                sys.stdout.write('4___')                        # align 2 byte sequences with 3 trailing 4's             
147                        else:
148                                sys.stdout.write('Error: Invalid UTF-8 character sequence of length: ' + str(u8_seq_len) + '.')                 
149                sys.stdout.write('\n')   
150
151def high_nybble_stream(bytes):
152        str=""
153        for b in bytes:
154                h = hex(ord(b))[-2]
155                if h == 'x': str += '0'
156                else: str += h
157        return str
158
159def low_nybble_stream(bytes):
160        str=""
161        for b in bytes:
162                str += hex(ord(b))[-1]
163        return str
164
165
166       
167#
168#  ScanThru is the core operation for parallel scanning.
169#  Given a bitstream Cursors marking current cursor positions,
170#  advance each cursor through occurrences of a character
171#  class identified by ScanStream.
172
173def ScanThru(Cursors, ScanStream):
174        return (Cursors + ScanStream) & ~ScanStream
175
176#
177# Advance all cursors by one position.
178def Advance(stream):
179        return stream + stream
180
Note: See TracBrowser for help on using the repository browser.