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