blob: d9f862fa864175daa5515fbd3c6eb3867a9e1ab0 [file] [log] [blame]
Harry Terkelsen1fa4e392022-02-23 15:03:09 -08001#!/usr/bin/env python
2
3# Copyright 2022 Google LLC.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7'''
8Generate a source file containing the given binary data.
9
10Output type is C++.
11
12This is required for a WASM build because the Emscripten toolchain cannot
13load data files using file I/O, nor can it consume assembly files.
14
15This is in use by the Flutter web engine and Skia CanvasKit. See
16[this](https://github.com/google/skia/blob/main/modules/canvaskit/README.md)
17for an example of a build using this.
18'''
19
20from __future__ import print_function
21
22import os
23import struct
24import sys
25import mmap
26
27def get_version_number(path):
28 input_data = open(path, 'rb').read()
29 n = input_data.find(b'icudt')
30 if n == -1:
31 exit("Cannot find a version number in %s." % path)
32
33 return input_data[n + 5:n + 7].decode("ascii")
34
35def iterate_as_uint32(path):
36 with open(path, 'rb') as f:
37 s = struct.Struct('@I')
38 assert s.size == 4
39 mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
40 assert (len(mm) % s.size) == 0
41 for offset in range(0, len(mm), s.size):
42 yield s.unpack_from(mm, offset)[0]
43 mm.close()
44
45
46def convert(fmt, src_path, dst_path):
47 header, line_begin, line_end, footer = fmt
48 assert os.path.exists(src_path)
49 version_number = get_version_number(src_path)
50 name = 'icudt%s_dat' % version_number
51 src = iterate_as_uint32(src_path)
52 with open(dst_path, 'w') as o:
53 o.write(header.format(name))
54 while True:
55 line = ','.join('%d' % v for _, v in zip(range(8), src))
56 if not line:
57 break
58 o.write('%s%s%s\n' % (line_begin, line, line_end))
59 o.write(footer.format(name))
60
61
62cpp = ('#include <cstdint>\nextern "C" uint32_t {0}[] __attribute__((aligned(16))) = {{\n',
63 '', ',', '}};\n')
64
65if __name__ == '__main__':
66 convert(cpp, sys.argv[1], sys.argv[2])