configurationengine/source/plugins/symbian/ConeHCRPlugin/hcrplugin/hcr_reader.py
changeset 0 2e8eeb919028
equal deleted inserted replaced
-1:000000000000 0:2e8eeb919028
       
     1 #
       
     2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: 
       
    15 #
       
    16 
       
    17 import logging
       
    18 import __init__
       
    19 from hcrplugin.hcrrepository import HcrRecord, HcrRepository
       
    20 from struct import pack, unpack
       
    21 from hcrplugin.hcr_writer import VALUE_TYPE_MAP,VALUE_TYPES_WITH_LSD,VALUE_TYPES_UNSIGNED_INT
       
    22 from hcrplugin.hcr_header import HcrHeader
       
    23 from hcrplugin.hcr_exceptions import *
       
    24 
       
    25 
       
    26 class HcrReader(object):
       
    27     
       
    28     def parse_repository_from_bindata(self, data):
       
    29         """
       
    30         @return: HcrRepository object constructed from the given binary data.
       
    31         """
       
    32         header_data = data[:32]
       
    33         header = HcrHeader()
       
    34         header.loads(header_data)
       
    35         
       
    36         expected_len = 32 + header.nrecords * 20 + header.lsd_size
       
    37         if len(data) < expected_len:
       
    38             raise InvalidHcrDataSizeError("File size is %d, expected at least %d based on header" \
       
    39                                           % (len(data), expected_len))
       
    40         
       
    41         expected_lsd_offset = 32 + header.nrecords * 20
       
    42         if header.lsd_offset != expected_lsd_offset: 
       
    43             raise InvalidLsdSectionOffsetError("LSD offset is %d, expected %d" \
       
    44                                                % (header.lsd_offset, expected_lsd_offset))
       
    45         
       
    46         records = []
       
    47         for i in xrange(header.nrecords):
       
    48             record_offset =  32 + i * 20
       
    49             record_data = data[record_offset:record_offset+20]
       
    50             record,lsd_pos = self.parse_record_from_bindata(record_data)
       
    51             if lsd_pos != None:
       
    52                 if lsd_pos[0] > header.lsd_size or (lsd_pos[0] + lsd_pos[1]) > header.lsd_size:
       
    53                     raise InvalidRecordLsdPositionError(
       
    54                         "LSD offset of record %d (category=%d, element=%d) is %r, but LSD section size is %d" \
       
    55                         % (i, record.category_id, record.element_id, lsd_pos, header.lsd_size))
       
    56                 lsd_offset = lsd_pos[0] + header.lsd_offset
       
    57                 lsd_data = data[lsd_offset:lsd_offset+lsd_pos[1]]
       
    58                 record.value = self.parse_record_value_from_lsd_bindata(record.type,lsd_data)
       
    59             records.append(record)
       
    60                 
       
    61         return HcrRepository(records,header.version,header.flags)
       
    62 
       
    63     def parse_record_from_bindata(self, data):
       
    64         """
       
    65         @return: Tuple: (record, lsd_pos) where
       
    66             record  = HcrRecord object constructed from the given binary data.
       
    67             lsd_pos = The position of the record's data in the LSD section in the
       
    68                       form of a tuple (offset, size), or None if the record does
       
    69                       not have any data in the LSD section.
       
    70         """
       
    71         
       
    72         if len(data) != 20:
       
    73             raise HcrReaderError("Invalid record length: %d, expected 20" % len(data))
       
    74         
       
    75         result = unpack("<IIIHH",data[:16])
       
    76         
       
    77         category_id = result[0]
       
    78         element_id = result[1]
       
    79         value_type = result[2]
       
    80         flag = result[3]
       
    81         lsd_len = result[4]
       
    82         
       
    83         
       
    84         
       
    85         for key,val in VALUE_TYPE_MAP.iteritems():
       
    86             if val == value_type:
       
    87                 value_type = key
       
    88                 break
       
    89         if value_type not in VALUE_TYPE_MAP:
       
    90             raise InvalidRecordValueTypeError("Invalid value type:%X" % value_type)
       
    91         
       
    92         value = None
       
    93         lsd_pos = None
       
    94         if value_type in VALUE_TYPES_WITH_LSD:
       
    95             lsd_offset = unpack("<I",data[16:])[0]
       
    96             lsd_pos = (lsd_offset,lsd_len)
       
    97         else:
       
    98             if value_type in VALUE_TYPES_UNSIGNED_INT:
       
    99                 format = "<I"
       
   100             elif value_type == HcrRecord.VALTYPE_INT8:
       
   101                 format = "<bxxx"
       
   102             elif value_type == HcrRecord.VALTYPE_INT16:
       
   103                 format = "<hxx"
       
   104             else:
       
   105                 format = "<i"
       
   106             
       
   107             value = unpack(format, data[16:])[0]
       
   108                 
       
   109             if value_type == HcrRecord.VALTYPE_BOOL:
       
   110                 value = bool(value)
       
   111                 
       
   112             
       
   113         
       
   114         record = HcrRecord(value_type,value,category_id,element_id,flag)
       
   115 
       
   116         return record,lsd_pos
       
   117         
       
   118     
       
   119     def parse_record_value_from_lsd_bindata(self, record_type, data):
       
   120         """
       
   121         @return: The record value parsed from the given binary data in the LSD section.
       
   122         @param type: The HCRML type of the record whose LSD data is to be parsed.
       
   123         """
       
   124         if record_type == HcrRecord.VALTYPE_TEXT8:
       
   125             return data.decode("utf-8")
       
   126         
       
   127         elif record_type == HcrRecord.VALTYPE_BIN_DATA:
       
   128             return data 
       
   129 
       
   130         elif record_type == HcrRecord.VALTYPE_ARRAY_INT32:
       
   131             if len(data) % 4 != 0:
       
   132                 raise InvalidRecordLsdPositionError("Int32 array requires an amount of LSD data that is divisible by 4 (data with size %d was given)" % len(data))
       
   133             return list(unpack("<%di"%(len(data)/4), data))
       
   134 
       
   135         elif record_type == HcrRecord.VALTYPE_ARRAY_UINT32:
       
   136             if len(data) % 4 != 0:
       
   137                 raise InvalidRecordLsdPositionError("Uint32 array requires an amount of LSD data that is divisible by 4 (data with size %d was given)" % len(data))
       
   138             return list(unpack("<%dI"%(len(data)/4), data))
       
   139 
       
   140         elif record_type == HcrRecord.VALTYPE_INT64:
       
   141             if len(data) != 8:
       
   142                 raise InvalidRecordLsdPositionError("Int64 requires LSD data size to be 8 bytes (%d given)" % len(data))
       
   143             return unpack("<q",data)[0]
       
   144 
       
   145         elif record_type == HcrRecord.VALTYPE_UINT64:
       
   146             if len(data) != 8:
       
   147                 raise InvalidRecordLsdPositionError("Uint64 requires LSD data size to be 8 bytes (%d given)" % len(data))
       
   148             return unpack("<Q",data)[0]
       
   149         
       
   150         else:
       
   151             return None