1#!/bin/env python3 2 3# Copyright (C) 2024 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import argparse 18 19 20def fetch_arguments(): 21 parser = argparse.ArgumentParser( 22 prog="ditto2cpp", 23 description="Translate .ditto file to C++ source files to embed in the benchmark." 24 ) 25 parser.add_argument("-o", "--output", required=True, help="Output file", 26 type=str) 27 parser.add_argument("-s", "--sources", required=True, nargs='+', 28 help="Source .ditto files", type=str) 29 parser.add_argument("-v", "--verbose", help="Verbose output", 30 action='store_true') 31 args = parser.parse_args() 32 33 if args.verbose: 34 print('From: "{}"'.format(args.sources)) 35 print('Output: "{}"'.format(args.output)) 36 37 return args 38 39 40def compute_common_prefix(arr): 41 result = arr[0] 42 length = len(result) 43 44 # Iterate for the rest of the elements in the array 45 for i in range(1, len(arr)): 46 # Find the index of result in the current string 47 while arr[i].find(result) != 0: 48 # Update the matched substring prefix 49 result = result[:length - 1] 50 length -= 1 51 52 # Check for an empty case and return if true 53 if not result: 54 raise Exception("No results") 55 return result 56 57 58def generate_benchmark_source(output, sources): 59 common_prefix = compute_common_prefix(sources) 60 last_slash_in_prefix = 0 61 try: 62 last_slash_in_prefix = len(common_prefix) - common_prefix[::-1].index('/') 63 except ValueError: 64 # This happens when '/' cannot be found in `common_prefix` 65 pass 66 prefix_length = min(len(common_prefix), last_slash_in_prefix) 67 suffix_length = len(".ditto") 68 69 file_header = ''' 70 #include <ditto/embedded_benchmarks.h> 71 const std::map<std::string, std::string> ditto_static_config = { 72 ''' 73 file_footer = ''' 74 }; 75 ''' 76 with open(output, 'w') as fo: 77 fo.write(file_header) 78 for fi_path in sources: 79 fi_name = fi_path[prefix_length:-suffix_length] 80 with open(fi_path, 'r') as fi: 81 fo.write('\t') 82 fo.write('{{"{}", "{}"}},'.format( 83 fi_name, 84 fi.read().replace('\n', '').replace('"', '\\"') 85 )) 86 fo.write('\n') 87 fo.write(file_footer) 88 89 90if __name__ == '__main__': 91 args = fetch_arguments() 92 93 generate_benchmark_source(args.output, args.sources) 94 95 if args.verbose: 96 print("Output file content:") 97 print('-' * 32) 98 with open(args.output, 'r') as fo: 99 print(fo.read()) 100 print('-' * 32) 101