xref: /aosp_15_r20/external/XNNPACK/scripts/sort-filenames.py (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1#!/usr/bin/python3
2import re
3import argparse
4
5parser = argparse.ArgumentParser()
6parser.add_argument('inputs', nargs='+', help='Input filename')
7parser.add_argument('--min_lines', type=int, default=1, help='Specify the min number of lines to rearrange')
8args = parser.parse_args()
9
10min_num_lines = args.min_lines
11
12filename_regex = '(src|source|unit_test|include)/.*$'
13
14# caveat: Does fully not handle numbers with different number of digits.
15def compare_strs(str1, str2, num_sort=True):
16    winner = 0 # which one's bigger
17    num_sort_mode = False
18    for i in range(min(len(str1),len(str2))):
19        if winner == 0:
20            if num_sort:
21                if str1[i].isdigit() and str2[i].isdigit():
22                    if num_sort_mode:
23                        str1_num += str1[i]
24                        str2_num += str2[i]
25                    else:
26                        num_sort_mode = True
27                        str1_num = str1[i]
28                        str2_num = str2[i]
29                elif num_sort_mode:
30                    if str1[i].isdigit(): str1_num += str1[i]
31                    if str2[i].isdigit(): str2_num += str2[i]
32                    winner = int(str1_num) - int(str2_num)
33                    num_sort_mode = False
34                    if winner != 0: break
35            if str1[i] != str2[i] and not num_sort_mode:
36                if str2[i].isdigit():
37                    winner = -1
38                elif str1[i].isdigit() or str1[i] > str2[i]:
39                    winner = 1
40                else:
41                    winner = -1
42    if num_sort_mode: # if it's still in num_sort_mode then find the results
43        if len(str1)-1 > i:
44            i += 1
45            if str1[i].isdigit(): str1_num += str1[i]
46        elif len(str2)-1 > i:
47            i += 1
48            if str2[i].isdigit(): str2_num += str2[i]
49        if int(str1_num) > int(str2_num):
50            winner = 1
51        elif int(str1_num) < int(str2_num):
52            winner = -1
53        num_sort_mode = False
54
55    if winner == 0:
56        if str2[i].isdigit():
57            winner = -1
58        elif str1[i].isdigit() or str1[i] > str2[i]:
59            winner = 1
60        else:
61            winner = -1
62    return winner
63
64
65def cmp_to_key(mycmp):
66    'Convert a cmp= function into a key= function'
67    class K:
68        def __init__(self, obj, *args):
69            self.obj = obj
70        def __lt__(self, other):
71            return mycmp(self.obj, other.obj) < 0
72        def __gt__(self, other):
73            return mycmp(self.obj, other.obj) > 0
74        def __eq__(self, other):
75            return mycmp(self.obj, other.obj) == 0
76        def __le__(self, other):
77            return mycmp(self.obj, other.obj) <= 0
78        def __ge__(self, other):
79            return mycmp(self.obj, other.obj) >= 0
80        def __ne__(self, other):
81            return mycmp(self.obj, other.obj) != 0
82    return K
83
84def custom_sort(listy):
85    for _ in range(len(listy)-1+1):
86        for i in range(len(listy)-1):
87            bigger = compare_strs(listy[i], listy[i+1])
88            if bigger > 0:
89                tmp_str = listy[i]
90                listy[i] = listy[i+1]
91                listy[i+1] = tmp_str
92    return listy
93
94# file_lines = [l.strip(stripchars) for l in file_lines]
95# currently sorting by first number in filename. smallest numbers first
96# this thing may need the ability to recognize filenames
97# file_lines = sorted(file_lines, key=lambda line: int(re.search('\d+', line.split('/')[-1] + ' 0').group(0)))
98input_filenames=args.inputs
99for input_filename in input_filenames:
100    with open(input_filename,'r') as file:
101        file_lines = file.read().split('\n')
102    output_filename=input_filename
103    files_range = [] # is a tuple
104    filenames_ranges = []
105    for i, line in enumerate(file_lines):
106        if re.search(filename_regex, line):
107            if files_range == []:
108                files_range.append(i)
109        else:
110            if files_range != []:
111                files_range.append(i-1)
112                # manages min num lines
113                if files_range[1] - files_range[0] + 1 >= min_num_lines:filenames_ranges.append(files_range)
114                files_range = []
115    if files_range != []:
116        files_range.append(i-1)
117        # manages min num lines
118        if files_range[1] - files_range[0] + 1 >= min_num_lines:filenames_ranges.append(files_range)
119        files_range = []
120
121
122    for x in filenames_ranges:
123        # accommodate for a close bracket at the end of the last filename
124        if file_lines[x[1]][-1] == ')':
125            append_chars = ')'
126            file_lines[x[1]] = file_lines[x[1]][:-1]
127        else:
128            append_chars = ''
129
130        new_lines = sorted(file_lines[x[0]:x[1]+1], key=cmp_to_key(compare_strs))
131        for i, l in enumerate(range(x[0], x[1]+1)):
132            file_lines[l] = new_lines[i]
133            if l == x[1]:
134                file_lines[l] += append_chars
135
136    with open(output_filename, 'w') as file:
137        file.write('\n'.join(file_lines))
138