protolib.py revision 10269:82773ace39fa
110779SCurtis.Dunham@arm.com#!/usr/bin/env python
210779SCurtis.Dunham@arm.com
310779SCurtis.Dunham@arm.com# Copyright (c) 2013 ARM Limited
410779SCurtis.Dunham@arm.com# All rights reserved
510779SCurtis.Dunham@arm.com#
610779SCurtis.Dunham@arm.com# The license below extends only to copyright in the software and shall
710779SCurtis.Dunham@arm.com# not be construed as granting a license to any other intellectual
810779SCurtis.Dunham@arm.com# property including but not limited to intellectual property relating
910779SCurtis.Dunham@arm.com# to a hardware implementation of the functionality of the software
1010779SCurtis.Dunham@arm.com# licensed hereunder.  You may use the software subject to the license
1110779SCurtis.Dunham@arm.com# terms below provided that you ensure that this notice is replicated
1210779SCurtis.Dunham@arm.com# unmodified and in its entirety in all distributions of the software,
1310779SCurtis.Dunham@arm.com# modified or unmodified, in source code or in binary form.
1410779SCurtis.Dunham@arm.com#
1510779SCurtis.Dunham@arm.com# Redistribution and use in source and binary forms, with or without
1610779SCurtis.Dunham@arm.com# modification, are permitted provided that the following conditions are
1710779SCurtis.Dunham@arm.com# met: redistributions of source code must retain the above copyright
1810779SCurtis.Dunham@arm.com# notice, this list of conditions and the following disclaimer;
1910779SCurtis.Dunham@arm.com# redistributions in binary form must reproduce the above copyright
2010779SCurtis.Dunham@arm.com# notice, this list of conditions and the following disclaimer in the
2110779SCurtis.Dunham@arm.com# documentation and/or other materials provided with the distribution;
2210779SCurtis.Dunham@arm.com# neither the name of the copyright holders nor the names of its
2310779SCurtis.Dunham@arm.com# contributors may be used to endorse or promote products derived from
2410779SCurtis.Dunham@arm.com# this software without specific prior written permission.
2510779SCurtis.Dunham@arm.com#
2610779SCurtis.Dunham@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2710779SCurtis.Dunham@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2810779SCurtis.Dunham@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2910779SCurtis.Dunham@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3010779SCurtis.Dunham@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3110779SCurtis.Dunham@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3210779SCurtis.Dunham@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3310779SCurtis.Dunham@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3410779SCurtis.Dunham@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3510779SCurtis.Dunham@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3610779SCurtis.Dunham@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3710779SCurtis.Dunham@arm.com#
3810779SCurtis.Dunham@arm.com# Copyright 2008 Google Inc.  All rights reserved.
3910779SCurtis.Dunham@arm.com# http://code.google.com/p/protobuf/
4010779SCurtis.Dunham@arm.com#
4110779SCurtis.Dunham@arm.com# Redistribution and use in source and binary forms, with or without
4210779SCurtis.Dunham@arm.com# modification, are permitted provided that the following conditions are
4310779SCurtis.Dunham@arm.com# met:
4410779SCurtis.Dunham@arm.com#
4510779SCurtis.Dunham@arm.com#     * Redistributions of source code must retain the above copyright
4610779SCurtis.Dunham@arm.com# notice, this list of conditions and the following disclaimer.
4710779SCurtis.Dunham@arm.com#     * Redistributions in binary form must reproduce the above
4810779SCurtis.Dunham@arm.com# copyright notice, this list of conditions and the following disclaimer
4910779SCurtis.Dunham@arm.com# in the documentation and/or other materials provided with the
5010779SCurtis.Dunham@arm.com# distribution.
5110779SCurtis.Dunham@arm.com#     * Neither the name of Google Inc. nor the names of its
5210779SCurtis.Dunham@arm.com# contributors may be used to endorse or promote products derived from
5310779SCurtis.Dunham@arm.com# this software without specific prior written permission.
5410779SCurtis.Dunham@arm.com#
5510779SCurtis.Dunham@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5610779SCurtis.Dunham@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5710779SCurtis.Dunham@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
5810779SCurtis.Dunham@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
5910779SCurtis.Dunham@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
6010779SCurtis.Dunham@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
6110779SCurtis.Dunham@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
6210779SCurtis.Dunham@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6310779SCurtis.Dunham@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6410779SCurtis.Dunham@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
6510779SCurtis.Dunham@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6610779SCurtis.Dunham@arm.com#
6710779SCurtis.Dunham@arm.com# Authors: Andreas Hansson
6810779SCurtis.Dunham@arm.com#          Radhika Jagtap
6910779SCurtis.Dunham@arm.com
7010779SCurtis.Dunham@arm.com# This file is a library of commonly used functions used when interfacing
7110779SCurtis.Dunham@arm.com# with protobuf python messages. For eg, the decode scripts for different
7210779SCurtis.Dunham@arm.com# types of proto objects can use the same function to decode a single message
7310779SCurtis.Dunham@arm.com
7410779SCurtis.Dunham@arm.comimport gzip
7510779SCurtis.Dunham@arm.comimport struct
7610779SCurtis.Dunham@arm.com
7710779SCurtis.Dunham@arm.comdef openFileRd(in_file):
7810779SCurtis.Dunham@arm.com    """
7910779SCurtis.Dunham@arm.com    This opens the file passed as argument for reading using an appropriate
8010779SCurtis.Dunham@arm.com    function depending on if it is gzipped or not. It returns the file
8110779SCurtis.Dunham@arm.com    handle.
8210779SCurtis.Dunham@arm.com    """
8310779SCurtis.Dunham@arm.com    try:
8410779SCurtis.Dunham@arm.com        # First see if this file is gzipped
8510779SCurtis.Dunham@arm.com        try:
8610779SCurtis.Dunham@arm.com            # Opening the file works even if it is not a gzip file
8710779SCurtis.Dunham@arm.com            proto_in = gzip.open(in_file, 'rb')
8810779SCurtis.Dunham@arm.com
8910779SCurtis.Dunham@arm.com            # Force a check of the magic number by seeking in the
9010779SCurtis.Dunham@arm.com            # file. If we do not do it here the error will occur when
9110779SCurtis.Dunham@arm.com            # reading the first message.
9210779SCurtis.Dunham@arm.com            proto_in.seek(1)
9310779SCurtis.Dunham@arm.com            proto_in.seek(0)
9410779SCurtis.Dunham@arm.com        except IOError:
9510779SCurtis.Dunham@arm.com            proto_in = open(in_file, 'rb')
9610779SCurtis.Dunham@arm.com    except IOError:
9710779SCurtis.Dunham@arm.com        print "Failed to open ", in_file, " for reading"
9810779SCurtis.Dunham@arm.com        exit(-1)
9910779SCurtis.Dunham@arm.com    return proto_in
10010779SCurtis.Dunham@arm.com
10110779SCurtis.Dunham@arm.comdef DecodeVarint(in_file):
10210779SCurtis.Dunham@arm.com    """
10310779SCurtis.Dunham@arm.com    The decoding of the Varint32 is copied from
10410779SCurtis.Dunham@arm.com    google.protobuf.internal.decoder and is only repeated here to
10510779SCurtis.Dunham@arm.com    avoid depending on the internal functions in the library. If the
10610779SCurtis.Dunham@arm.com    end of file is reached, return (0, 0).
10710779SCurtis.Dunham@arm.com    """
10810779SCurtis.Dunham@arm.com    result = 0
10910779SCurtis.Dunham@arm.com    shift = 0
11010779SCurtis.Dunham@arm.com    pos = 0
11110779SCurtis.Dunham@arm.com    # Use a 32-bit mask
11210779SCurtis.Dunham@arm.com    mask = 0xffffffff
11310779SCurtis.Dunham@arm.com    while 1:
11410779SCurtis.Dunham@arm.com        c = in_file.read(1)
11510779SCurtis.Dunham@arm.com        if len(c) == 0:
11610779SCurtis.Dunham@arm.com            return (0, 0)
11710779SCurtis.Dunham@arm.com        b = struct.unpack('<B', c)[0]
11810779SCurtis.Dunham@arm.com        result |= ((b & 0x7f) << shift)
11910779SCurtis.Dunham@arm.com        pos += 1
12010779SCurtis.Dunham@arm.com        if not (b & 0x80):
12110779SCurtis.Dunham@arm.com            if result > 0x7fffffffffffffff:
12210779SCurtis.Dunham@arm.com                result -= (1 << 64)
12310779SCurtis.Dunham@arm.com                result |= ~mask
12410779SCurtis.Dunham@arm.com            else:
12510779SCurtis.Dunham@arm.com                result &= mask
12610779SCurtis.Dunham@arm.com                return (result, pos)
12710779SCurtis.Dunham@arm.com            shift += 7
12810779SCurtis.Dunham@arm.com            if shift >= 64:
12910779SCurtis.Dunham@arm.com                raise IOError('Too many bytes when decoding varint.')
13010779SCurtis.Dunham@arm.com
13110779SCurtis.Dunham@arm.comdef decodeMessage(in_file, message):
13210779SCurtis.Dunham@arm.com    """
13310779SCurtis.Dunham@arm.com    Attempt to read a message from the file and decode it. Return
13410779SCurtis.Dunham@arm.com    False if no message could be read.
13510779SCurtis.Dunham@arm.com    """
13610779SCurtis.Dunham@arm.com    try:
13710779SCurtis.Dunham@arm.com        size, pos = DecodeVarint(in_file)
13810779SCurtis.Dunham@arm.com        if size == 0:
13910779SCurtis.Dunham@arm.com            return False
14010779SCurtis.Dunham@arm.com        buf = in_file.read(size)
14110779SCurtis.Dunham@arm.com        message.ParseFromString(buf)
14210779SCurtis.Dunham@arm.com        return True
14310779SCurtis.Dunham@arm.com    except IOError:
14410779SCurtis.Dunham@arm.com        return False
14510779SCurtis.Dunham@arm.com
14610779SCurtis.Dunham@arm.comdef EncodeVarint(out_file, value):
14710779SCurtis.Dunham@arm.com  """
14810779SCurtis.Dunham@arm.com  The encoding of the Varint32 is copied from
14910779SCurtis.Dunham@arm.com  google.protobuf.internal.encoder and is only repeated here to
15010779SCurtis.Dunham@arm.com  avoid depending on the internal functions in the library.
15110779SCurtis.Dunham@arm.com  """
15210779SCurtis.Dunham@arm.com  bits = value & 0x7f
15310779SCurtis.Dunham@arm.com  value >>= 7
15410779SCurtis.Dunham@arm.com  while value:
15510779SCurtis.Dunham@arm.com    out_file.write(struct.pack('<B', 0x80|bits))
15610779SCurtis.Dunham@arm.com    bits = value & 0x7f
15710779SCurtis.Dunham@arm.com    value >>= 7
15810779SCurtis.Dunham@arm.com  out_file.write(struct.pack('<B', bits))
15910779SCurtis.Dunham@arm.com
16010779SCurtis.Dunham@arm.comdef encodeMessage(out_file, message):
16110779SCurtis.Dunham@arm.com    """
16210779SCurtis.Dunham@arm.com    Encoded a message with the length prepended as a 32-bit varint.
16310779SCurtis.Dunham@arm.com    """
16410779SCurtis.Dunham@arm.com    out = message.SerializeToString()
16510779SCurtis.Dunham@arm.com    EncodeVarint(out_file, len(out))
16610779SCurtis.Dunham@arm.com    out_file.write(out)
16710779SCurtis.Dunham@arm.com