source: proto/JSON/bitutil.py @ 3153

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

Add initial JSON protoype implementation files.

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