1#!/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]) 67