Package ais :: Module aisstring
[hide private]
[frames] | no frames]

Source Code for Module ais.aisstring

  1  #!/usr/bin/env python 
  2   
  3  __version__ = '$Revision: 2068 $'.split()[1] 
  4  __date__ = '$Date: 2006-05-02 08:17:59 -0400 (Tue, 02 May 2006) $'.split()[1] 
  5  __author__ = 'Kurt Schwehr' 
  6   
  7  __doc__=''' 
  8  Handle encoding and decoding AIS strings. 
  9   
 10  @bug: need some more interesting doctests! 
 11  @bug: needs to throw an exception if the character is not in the LUT 
 12  @bug: what to do about string with trailing @@@ or "   " (white space) 
 13   
 14  @var characterLUT: lookup table for decode to fetch characters faster 
 15  @type characterLUT: list 
 16   
 17  @var characterBits: lookup table for going from a single character to a 6 bit BitVector 
 18  @type characterBits: dict 
 19   
 20   
 21  @author: '''+__author__+''' 
 22  @version: ''' + __version__ +''' 
 23  @copyright: 2006 
 24   
 25  @var __date__: Date of last svn commit 
 26  @undocumented: __version__ __author__ __doc__ myparser 
 27  @undocumented: buildDict 
 28  ''' 
 29   
 30   
 31   
 32  # python standard library 
 33  import sys 
 34   
 35  # External libs 
 36  from BitVector import BitVector 
 37   
 38  # Local 
 39  import binary 
 40  #import verbosity 
 41  #from verbosity import BOMBASTIC,VERBOSE,TRACE,TERSE,ALWAYS 
 42   
 43  characterLUT=[ '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 
 44                 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 
 45                 'Z', '[', '\\', ']', '^', '-', ' ', 
 46                 '!', '"', '#', '$', '%', '&', '`', '(', ')', '*', '+', ',', '-', '.', '/', 
 47                 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
 48                 ':', ';', '<', '=', '>', '?' 
 49  ] 
 50   
 51  characterDict={ 
 52      '@': 0, 'A': 1, 'B': 2, 'C': 3, 'D': 4, 'E': 5, 'F': 6, 
 53      'G': 7, 'H': 8, 'I': 9, 'J': 10, 'K': 11, 'L': 12, 'M': 13, 
 54      'N': 14, 'O': 15, 'P': 16, 'Q': 17, 'R': 18, 'S': 19, 'T': 20, 
 55      'U': 21, 'V': 22, 'W': 23, 'X': 24, 'Y': 25, 'Z': 26, '[': 27, 
 56      '\\': 28, ']': 29, '^': 30, '-': 31, ' ': 32, '!': 33, '"': 34, 
 57      '#': 35, '$': 36, '%': 37, '&': 38, '`': 39, '(': 40, ')': 41, 
 58      '*': 42, '+': 43, ',': 44, '-': 45, '.': 46, '/': 47, '0': 48, 
 59      '1': 49, '2': 50, '3': 51, '4': 52, '5': 53, '6': 54, '7': 55, 
 60      '8': 56, '9': 57, ':': 58, ';': 59, '<': 60, '=': 61, '>': 62, 
 61      '?': 63 
 62  } 
 63  '''Fast lookup for the AIS int code for a character ''' 
 64  # The above illustrates the inline ways of documenting module variables 
 65   
 66   
 67  characterBits={} 
 68  characterBits['@']=binary.setBitVectorSize(BitVector(intVal=0),6) 
 69  characterBits['A']=binary.setBitVectorSize(BitVector(intVal=1),6) 
 70  characterBits['B']=binary.setBitVectorSize(BitVector(intVal=2),6) 
 71  characterBits['C']=binary.setBitVectorSize(BitVector(intVal=3),6) 
 72  characterBits['D']=binary.setBitVectorSize(BitVector(intVal=4),6) 
 73  characterBits['E']=binary.setBitVectorSize(BitVector(intVal=5),6) 
 74  characterBits['F']=binary.setBitVectorSize(BitVector(intVal=6),6) 
 75  characterBits['G']=binary.setBitVectorSize(BitVector(intVal=7),6) 
 76  characterBits['H']=binary.setBitVectorSize(BitVector(intVal=8),6) 
 77  characterBits['I']=binary.setBitVectorSize(BitVector(intVal=9),6) 
 78  characterBits['J']=binary.setBitVectorSize(BitVector(intVal=10),6) 
 79  characterBits['K']=binary.setBitVectorSize(BitVector(intVal=11),6) 
 80  characterBits['L']=binary.setBitVectorSize(BitVector(intVal=12),6) 
 81  characterBits['M']=binary.setBitVectorSize(BitVector(intVal=13),6) 
 82  characterBits['N']=binary.setBitVectorSize(BitVector(intVal=14),6) 
 83  characterBits['O']=binary.setBitVectorSize(BitVector(intVal=15),6) 
 84  characterBits['P']=binary.setBitVectorSize(BitVector(intVal=16),6) 
 85  characterBits['Q']=binary.setBitVectorSize(BitVector(intVal=17),6) 
 86  characterBits['R']=binary.setBitVectorSize(BitVector(intVal=18),6) 
 87  characterBits['S']=binary.setBitVectorSize(BitVector(intVal=19),6) 
 88  characterBits['T']=binary.setBitVectorSize(BitVector(intVal=20),6) 
 89  characterBits['U']=binary.setBitVectorSize(BitVector(intVal=21),6) 
 90  characterBits['V']=binary.setBitVectorSize(BitVector(intVal=22),6) 
 91  characterBits['W']=binary.setBitVectorSize(BitVector(intVal=23),6) 
 92  characterBits['X']=binary.setBitVectorSize(BitVector(intVal=24),6) 
 93  characterBits['Y']=binary.setBitVectorSize(BitVector(intVal=25),6) 
 94  characterBits['Z']=binary.setBitVectorSize(BitVector(intVal=26),6) 
 95  characterBits['[']=binary.setBitVectorSize(BitVector(intVal=27),6) 
 96  characterBits['\\']=binary.setBitVectorSize(BitVector(intVal=28),6) 
 97  characterBits[']']=binary.setBitVectorSize(BitVector(intVal=29),6) 
 98  characterBits['^']=binary.setBitVectorSize(BitVector(intVal=30),6) 
 99  characterBits['-']=binary.setBitVectorSize(BitVector(intVal=31),6) 
100  characterBits[' ']=binary.setBitVectorSize(BitVector(intVal=32),6) 
101  characterBits['!']=binary.setBitVectorSize(BitVector(intVal=33),6) 
102  characterBits['"']=binary.setBitVectorSize(BitVector(intVal=34),6) 
103  characterBits['#']=binary.setBitVectorSize(BitVector(intVal=35),6) 
104  characterBits['$']=binary.setBitVectorSize(BitVector(intVal=36),6) 
105  characterBits['%']=binary.setBitVectorSize(BitVector(intVal=37),6) 
106  characterBits['&']=binary.setBitVectorSize(BitVector(intVal=38),6) 
107  characterBits['`']=binary.setBitVectorSize(BitVector(intVal=39),6) 
108  characterBits['(']=binary.setBitVectorSize(BitVector(intVal=40),6) 
109  characterBits[')']=binary.setBitVectorSize(BitVector(intVal=41),6) 
110  characterBits['*']=binary.setBitVectorSize(BitVector(intVal=42),6) 
111  characterBits['+']=binary.setBitVectorSize(BitVector(intVal=43),6) 
112  characterBits[',']=binary.setBitVectorSize(BitVector(intVal=44),6) 
113  characterBits['-']=binary.setBitVectorSize(BitVector(intVal=45),6) 
114  characterBits['.']=binary.setBitVectorSize(BitVector(intVal=46),6) 
115  characterBits['/']=binary.setBitVectorSize(BitVector(intVal=47),6) 
116  characterBits['0']=binary.setBitVectorSize(BitVector(intVal=48),6) 
117  characterBits['1']=binary.setBitVectorSize(BitVector(intVal=49),6) 
118  characterBits['2']=binary.setBitVectorSize(BitVector(intVal=50),6) 
119  characterBits['3']=binary.setBitVectorSize(BitVector(intVal=51),6) 
120  characterBits['4']=binary.setBitVectorSize(BitVector(intVal=52),6) 
121  characterBits['5']=binary.setBitVectorSize(BitVector(intVal=53),6) 
122  characterBits['6']=binary.setBitVectorSize(BitVector(intVal=54),6) 
123  characterBits['7']=binary.setBitVectorSize(BitVector(intVal=55),6) 
124  characterBits['8']=binary.setBitVectorSize(BitVector(intVal=56),6) 
125  characterBits['9']=binary.setBitVectorSize(BitVector(intVal=57),6) 
126  characterBits[':']=binary.setBitVectorSize(BitVector(intVal=58),6) 
127  characterBits[';']=binary.setBitVectorSize(BitVector(intVal=59),6) 
128  characterBits['<']=binary.setBitVectorSize(BitVector(intVal=60),6) 
129  characterBits['=']=binary.setBitVectorSize(BitVector(intVal=61),6) 
130  characterBits['>']=binary.setBitVectorSize(BitVector(intVal=62),6) 
131  characterBits['?']=binary.setBitVectorSize(BitVector(intVal=63),6) 
132   
133   
134 -def buildDict():
135 ''' 136 Helper to build the build the carachterBits and Dict tables 137 138 @rtype: test to stdout 139 ''' 140 count=0 141 print 'characterDict={' 142 for i in range(len(characterLUT)): 143 count += 1 144 c = characterLUT[i] 145 if c=='\\': c='\\\\' 146 print "'"+c+"': "+str(i)+",", 147 if count%6==0: 148 print 149 print '}' 150 151 print 'characterBits={}' 152 for i in range(len(characterLUT)): 153 c = characterLUT[i] 154 if c=='\\': c='\\\\' 155 print "characterBits['"+c+"']"+'=binary.setBitVectorSize(BitVector(intVal='+str(i)+'),6)'
156 157
158 -def decode(bits,dropAfterFirstAt=False):
159 ''' 160 Decode bits as a string. Does not remove the end space or @@@@. Must be an multiple of 6 bits. 161 162 @param bits: n*6 bits that represent a string. 163 @type bits: BitVector 164 @return: string with pad spaces or @@@@ 165 @rtype: str 166 ''' 167 #assert(len(bits) % 6 == 0) 168 numchar=len(bits)/6 169 s = [] 170 for i in range(numchar): # FIX: off by one? 171 start = 6 * i 172 end = start+6 #6 * (i+1) 173 charbits=bits[start:end] 174 val = int(charbits) 175 if dropAfterFirstAt and val==0: 176 break # 0 is the @ character which is used to pad strings. 177 s.append(characterLUT[val]) 178 179 return ''.join(s)
180 181
182 -def encode(string,bitSize=None):
183 ''' 184 @param string: python ascii string to encode. 185 @type string: str 186 @param bitSize: how many bits should this take. must be a multiple of 6 187 @type bitSize: int 188 @return: enocded bits for the string 189 @rtype: BitVector 190 @bug: force to upper case 191 @bug: building this in reverse may be faster 192 @bug: check that bitSize is a multple of 6 193 @bug: pad with "@" to reach requested bitSize 194 ''' 195 if bitSize: 196 assert(bitSize%6==0) 197 bv = BitVector(size=0) 198 for i in range(len(string)): 199 bv = bv+characterBits[string[i]] 200 if bitSize: 201 if bitSize < len(bv): 202 print 'ERROR: string longer than specified bit count: "'+string+'"', bitSize, len(bv) 203 assert False 204 extra = bitSize - len(bv) 205 bv = bv+BitVector(size=extra) 206 return bv
207
208 -def unpad(string,removeBlanks=True):
209 """ 210 Remove AIS string padding 211 212 >>> unpad('@') 213 '' 214 >>> unpad('A@') 215 'A' 216 >>> unpad('ABCDEF1234@@@@@') 217 'ABCDEF1234' 218 219 FIX: is this the correct response? 220 221 >>> unpad('A@B') 222 'A@B' 223 224 This is non standard behavior, but some AIS systems space pad the right 225 226 >>> unpad(' ') 227 '' 228 >>> unpad('MY SHIP NAME ') 229 'MY SHIP NAME' 230 231 The standard implies this behavior with is less fun 232 233 >>> unpad('MY SHIP NAME ',removeBlanks=False) 234 'MY SHIP NAME ' 235 236 @bug: use a faster algorithm for truncating the string 237 @param string: string to cleanup 238 @type string: str 239 @param removeBlanks: set to true to strip spaces on the right 240 @type removeBlanks: bool 241 @return: cleaned up string 242 @rtype: str 243 """ 244 while len(string)>0 and string[-1]=='@': 245 string=string[:-1] 246 if removeBlanks: 247 while len(string)>0 and string[-1]==' ': 248 string=string[:-1] 249 return string
250
251 -def pad(string,length):
252 ''' 253 pad a string out to the proper length with the @ character as required by the ais spec 254 255 >>> pad('',0) 256 '' 257 >>> pad('',1) 258 '@' 259 >>> pad('A',1) 260 'A' 261 >>> pad('A',2) 262 'A@' 263 >>> pad('MY SHIP NAME',20) 264 'MY SHIP NAME@@@@@@@@' 265 266 @param string: string to pad out 267 @type string: str 268 @param length: number of characters that the string must be 269 @type length: int 270 @return: str of len length 271 @rtype: str 272 273 @bug: Use a list and join to make the string building faster 274 ''' 275 while len(string)<length: string += '@' 276 return string
277 278 279 if __name__ == '__main__': 280 from optparse import OptionParser 281 myparser = OptionParser(usage="%prog [options]",version="%prog "+__version__) 282 myparser.add_option('--test','--doc-test',dest='doctest',default=False,action='store_true', 283 help='run the documentation tests') 284 # verbosity.addVerbosityOptions(myparser) 285 (options,args) = myparser.parse_args() 286 287 success=True 288 289 if options.doctest: 290 import os; print os.path.basename(sys.argv[0]), 'doctests ...', 291 sys.argv= [sys.argv[0]] 292 # if options.verbosity>=VERBOSE: sys.argv.append('-v') 293 import doctest 294 numfail,numtests=doctest.testmod() 295 if numfail==0: print 'ok' 296 else: 297 print 'FAILED' 298 success=False 299 300 if not success: 301 sys.exit('Something Failed') 302