source: proto/Compiler/workspace/bitutil.py @ 668

Last change on this file since 668 was 668, checked in by ksherdy, 9 years ago

Fix print_aligned_streams.

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