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