scripts/python/sis2rom/sis/sisreader.py
changeset 28 ab800b3e45ab
equal deleted inserted replaced
27:8a82bd4d7b19 28:ab800b3e45ab
       
     1 """
       
     2 Copyright (c) 2006, Jari Sukanen
       
     3 All rights reserved.
       
     4 
       
     5 Redistribution and use in source and binary forms, with or 
       
     6 without modification, are permitted provided that the following 
       
     7 conditions are met:
       
     8 	* Redistributions of source code must retain the above copyright 
       
     9 	  notice, this list of conditions and the following disclaimer.
       
    10     * Redistributions in binary form must reproduce the above copyright 
       
    11 	  notice, this list of conditions and the following disclaimer in 
       
    12 	  the documentation and/or other materials provided with the 
       
    13 	  distribution.
       
    14     * Names of the contributors may not be used to endorse or promote 
       
    15 	  products derived from this software without specific prior written 
       
    16 	  permission.
       
    17 
       
    18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
       
    19 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
       
    20 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
       
    21 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
       
    22 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
       
    23 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
       
    24 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
       
    25 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
       
    26 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
       
    27 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
       
    28 THE POSSIBILITY OF SUCH DAMAGE.
       
    29 """
       
    30 
       
    31 
       
    32 import struct
       
    33 import sisfields
       
    34 
       
    35 class SISReader :
       
    36 	def __init__(self) :
       
    37 		pass
       
    38 		
       
    39 	def readUnsignedBytes(self, numBytes) :
       
    40 		buf = self.readPlainBytes(numBytes)
       
    41 		if len(buf) < numBytes :
       
    42 			return []
       
    43 			
       
    44 		format = ""
       
    45 		for i in range(numBytes) :
       
    46 			format += "B"
       
    47 		return struct.unpack(format, buf)
       
    48 	
       
    49 	def readSignedBytes(self, numBytes) :
       
    50 		buf = self.readPlainBytes(numBytes)
       
    51 		if len(buf) < numBytes :
       
    52 			return []
       
    53 			
       
    54 		format = ""
       
    55 		for i in range(numBytes) :
       
    56 			format += "b"
       
    57 		return struct.unpack(format, buf)
       
    58 		
       
    59 	def readBytesAsUint(self, numBytes) :
       
    60 		result = 0
       
    61 		bytes = self.readUnsignedBytes(numBytes)
       
    62 		if len(bytes) == numBytes :
       
    63 			for i in range(numBytes) :
       
    64 				result |= bytes[i] << (i*8)
       
    65 		
       
    66 		return result
       
    67 		
       
    68 	def readBytesAsInt(self, numBytes) :
       
    69 		result = 0
       
    70 		bytes = self.readSignedBytes(numBytes)
       
    71 		if len(bytes) == numBytes :
       
    72 			for i in range(numBytes) :
       
    73 				result |= bytes[i] << (i*8)
       
    74 		
       
    75 		return result
       
    76 		
       
    77 	def skipPadding(self) :
       
    78 		result = 0
       
    79 		if self.bytesRead % 4 != 0 :
       
    80 			paddingLength = 4 - self.bytesRead % 4
       
    81 			self.readPlainBytes(paddingLength)
       
    82 			result = paddingLength
       
    83 			
       
    84 		return result
       
    85 	
       
    86 
       
    87 class SISFileReader(SISReader) : 
       
    88 	def __init__(self, inStream) :
       
    89 		self.inStream = inStream
       
    90 		self.eof = False
       
    91 		self.bytesRead = 0
       
    92 
       
    93 	def readPlainBytes(self, numBytes) :
       
    94 		if self.eof :
       
    95 			return ""
       
    96 			
       
    97 		if numBytes == 0 :
       
    98 			return ""
       
    99 			
       
   100 		buf = ""
       
   101 		buf = self.inStream.read(numBytes)
       
   102 		if len(buf) < numBytes :
       
   103 			self.eof = True
       
   104 			return ""
       
   105 			
       
   106 		self.bytesRead += numBytes
       
   107 		
       
   108 		return buf
       
   109 
       
   110 	def isEof(self) :
       
   111 		return self.eof
       
   112 		
       
   113 class SISBufferReader(SISReader) :
       
   114 	def __init__(self, buffer) :
       
   115 		self.buffer = buffer
       
   116 		self.bytesRead = 0
       
   117 		
       
   118 	def readPlainBytes(self, numBytes) :
       
   119 		if self.isEof() :
       
   120 			return ""
       
   121 			
       
   122 		if numBytes == 0 :
       
   123 			return ""
       
   124 			
       
   125 		result = self.buffer[self.bytesRead:self.bytesRead+numBytes]
       
   126 			
       
   127 		self.bytesRead += numBytes
       
   128 		
       
   129 		return result
       
   130 			
       
   131 	def isEof(self) :
       
   132 		return self.bytesRead >= len(self.buffer)
       
   133 		
       
   134 class SISFieldParser :
       
   135 	def __init__(self) :
       
   136 		self.lastReadBytes = 0
       
   137 		
       
   138 	def parseField(self, fileReader) :
       
   139 		"""Reads the next field from the fileReader stream and returns it"""
       
   140 		field = None
       
   141 		self.lastReadBytes = 0
       
   142 		type = fileReader.readBytesAsUint(4)
       
   143 		self.lastReadBytes += 4
       
   144 		if type != 0 :
       
   145 			field = sisfields.SISFieldTypes[type]()
       
   146 			field.type = type
       
   147 			field.initFromFile(fileReader)
       
   148 			self.lastReadBytes += field.length + 4 # Field length + length field
       
   149 			self.lastReadBytes += fileReader.skipPadding()
       
   150 		return field