configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/hcr_reader.py
changeset 0 2e8eeb919028
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/hcr_reader.py	Thu Mar 11 17:04:37 2010 +0200
@@ -0,0 +1,151 @@
+#
+# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description: 
+#
+
+import logging
+import __init__
+from hcrplugin.hcrrepository import HcrRecord, HcrRepository
+from struct import pack, unpack
+from hcrplugin.hcr_writer import VALUE_TYPE_MAP,VALUE_TYPES_WITH_LSD,VALUE_TYPES_UNSIGNED_INT
+from hcrplugin.hcr_header import HcrHeader
+from hcrplugin.hcr_exceptions import *
+
+
+class HcrReader(object):
+    
+    def parse_repository_from_bindata(self, data):
+        """
+        @return: HcrRepository object constructed from the given binary data.
+        """
+        header_data = data[:32]
+        header = HcrHeader()
+        header.loads(header_data)
+        
+        expected_len = 32 + header.nrecords * 20 + header.lsd_size
+        if len(data) < expected_len:
+            raise InvalidHcrDataSizeError("File size is %d, expected at least %d based on header" \
+                                          % (len(data), expected_len))
+        
+        expected_lsd_offset = 32 + header.nrecords * 20
+        if header.lsd_offset != expected_lsd_offset: 
+            raise InvalidLsdSectionOffsetError("LSD offset is %d, expected %d" \
+                                               % (header.lsd_offset, expected_lsd_offset))
+        
+        records = []
+        for i in xrange(header.nrecords):
+            record_offset =  32 + i * 20
+            record_data = data[record_offset:record_offset+20]
+            record,lsd_pos = self.parse_record_from_bindata(record_data)
+            if lsd_pos != None:
+                if lsd_pos[0] > header.lsd_size or (lsd_pos[0] + lsd_pos[1]) > header.lsd_size:
+                    raise InvalidRecordLsdPositionError(
+                        "LSD offset of record %d (category=%d, element=%d) is %r, but LSD section size is %d" \
+                        % (i, record.category_id, record.element_id, lsd_pos, header.lsd_size))
+                lsd_offset = lsd_pos[0] + header.lsd_offset
+                lsd_data = data[lsd_offset:lsd_offset+lsd_pos[1]]
+                record.value = self.parse_record_value_from_lsd_bindata(record.type,lsd_data)
+            records.append(record)
+                
+        return HcrRepository(records,header.version,header.flags)
+
+    def parse_record_from_bindata(self, data):
+        """
+        @return: Tuple: (record, lsd_pos) where
+            record  = HcrRecord object constructed from the given binary data.
+            lsd_pos = The position of the record's data in the LSD section in the
+                      form of a tuple (offset, size), or None if the record does
+                      not have any data in the LSD section.
+        """
+        
+        if len(data) != 20:
+            raise HcrReaderError("Invalid record length: %d, expected 20" % len(data))
+        
+        result = unpack("<IIIHH",data[:16])
+        
+        category_id = result[0]
+        element_id = result[1]
+        value_type = result[2]
+        flag = result[3]
+        lsd_len = result[4]
+        
+        
+        
+        for key,val in VALUE_TYPE_MAP.iteritems():
+            if val == value_type:
+                value_type = key
+                break
+        if value_type not in VALUE_TYPE_MAP:
+            raise InvalidRecordValueTypeError("Invalid value type:%X" % value_type)
+        
+        value = None
+        lsd_pos = None
+        if value_type in VALUE_TYPES_WITH_LSD:
+            lsd_offset = unpack("<I",data[16:])[0]
+            lsd_pos = (lsd_offset,lsd_len)
+        else:
+            if value_type in VALUE_TYPES_UNSIGNED_INT:
+                format = "<I"
+            elif value_type == HcrRecord.VALTYPE_INT8:
+                format = "<bxxx"
+            elif value_type == HcrRecord.VALTYPE_INT16:
+                format = "<hxx"
+            else:
+                format = "<i"
+            
+            value = unpack(format, data[16:])[0]
+                
+            if value_type == HcrRecord.VALTYPE_BOOL:
+                value = bool(value)
+                
+            
+        
+        record = HcrRecord(value_type,value,category_id,element_id,flag)
+
+        return record,lsd_pos
+        
+    
+    def parse_record_value_from_lsd_bindata(self, record_type, data):
+        """
+        @return: The record value parsed from the given binary data in the LSD section.
+        @param type: The HCRML type of the record whose LSD data is to be parsed.
+        """
+        if record_type == HcrRecord.VALTYPE_TEXT8:
+            return data.decode("utf-8")
+        
+        elif record_type == HcrRecord.VALTYPE_BIN_DATA:
+            return data 
+
+        elif record_type == HcrRecord.VALTYPE_ARRAY_INT32:
+            if len(data) % 4 != 0:
+                raise InvalidRecordLsdPositionError("Int32 array requires an amount of LSD data that is divisible by 4 (data with size %d was given)" % len(data))
+            return list(unpack("<%di"%(len(data)/4), data))
+
+        elif record_type == HcrRecord.VALTYPE_ARRAY_UINT32:
+            if len(data) % 4 != 0:
+                raise InvalidRecordLsdPositionError("Uint32 array requires an amount of LSD data that is divisible by 4 (data with size %d was given)" % len(data))
+            return list(unpack("<%dI"%(len(data)/4), data))
+
+        elif record_type == HcrRecord.VALTYPE_INT64:
+            if len(data) != 8:
+                raise InvalidRecordLsdPositionError("Int64 requires LSD data size to be 8 bytes (%d given)" % len(data))
+            return unpack("<q",data)[0]
+
+        elif record_type == HcrRecord.VALTYPE_UINT64:
+            if len(data) != 8:
+                raise InvalidRecordLsdPositionError("Uint64 requires LSD data size to be 8 bytes (%d given)" % len(data))
+            return unpack("<Q",data)[0]
+        
+        else:
+            return None