1# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2#
3# This Source Code Form is subject to the terms of the Mozilla Public
4# License, v. 2.0. If a copy of the MPL was not distributed with this
5# file, You can obtain one at http://mozilla.org/MPL/2.0/.
6#
7
8import sys
9import struct
10
11column_block_type = {
12        0 : "empty block",
13        1 : "numeric block",
14        2 : "string block"
15        }
16
17
18def parse_block(data, index):
19    start_row = struct.unpack('Q', data[index:index+8])[0]
20    index += 8
21    data_size = struct.unpack('Q', data[index:index+8])[0]
22    index += 8
23    block_type = struct.unpack('B', data[index:index+1])[0]
24    index += 1
25    vals = {}
26    if block_type == 1:
27        # numeric block
28        for i in range(data_size):
29            vals[start_row + i] = struct.unpack('d', data[index:index+8])[0]
30            index += 8
31    elif block_type == 2:
32        # string block
33        for i in range(data_size):
34            str_length = struct.unpack('i', data[index:index+4])[0]
35            index += 4
36            vals[start_row + i] = data[index:index+str_length].decode("utf-8")
37            index += str_length
38    elif block_type == 3:
39        # formula block
40        read_rows = 0
41        while read_rows < data_size:
42            formula_group_size = struct.unpack('Q', data[index:index+8])[0]
43            index += 8
44            str_length = struct.unpack('i', data[index:index+4])[0]
45            index += 4
46            vals[start_row + read_rows] = (data[index:index+str_length].decode("utf-8"), "formula group length %i"% formula_group_size)
47            read_rows += formula_group_size
48            index += str_length
49
50    return index, data_size, vals
51
52
53def parse_column(data, index):
54    column_index = struct.unpack('Q', data[index:index+8])[0]
55    index += 8
56    column_entries = struct.unpack('Q', data[index:index+8])[0]
57    index += 8
58    imported_columns = 0
59    column_values = {}
60    while imported_columns < column_entries:
61        index, block_size, vals = parse_block(data, index)
62        imported_columns += block_size
63        column_values.update(vals)
64    return index, column_values
65
66def parse_columns(data, index):
67    column_count = struct.unpack('Q', data[index:index+8])[0]
68    index += 8
69    columns = {}
70    for i in range(column_count):
71        index, column_values = parse_column(data, index)
72        columns[i] = column_values
73
74    return columns
75
76def main():
77    filename = sys.argv[1]
78    with open(filename, "rb") as f:
79        content = f.read()
80        index = 0
81        columns = parse_columns(content, index)
82        print(columns)
83
84if __name__ == "__main__":
85    main()
86
87# vim:set shiftwidth=4 softtabstop=4 expandtab: */
88