1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
#!/usr/bin/python
# Look for all static member functions marked LLFIO_MAKE_FREE_FUNCTION and make them free
# (C) 2017 Niall Douglas
from __future__ import print_function
import glob, re
for header in glob.glob("../include/afio/*/*.hpp"):
with open(header, "rt") as ih:
lines = ih.readlines()
current_class = None
functions_to_be_freed = []
functions_to_be_freed_begin = -1
functions_to_be_freed_end = -1
for lineidx in range(0, len(lines)):
if lines[lineidx].startswith('class'):
current_class = lines[lineidx][6:lines[lineidx].find(':')]
current_class = current_class.replace('LLFIO_DECL', '').lstrip().rstrip()
if 'LLFIO_MAKE_FREE_FUNCTION' in lines[lineidx] and re.match('\s*LLFIO_MAKE_FREE_FUNCTION', lines[lineidx]):
function = ''
for n in range(1, 100):
if 'LLFIO_REQUIRES' in lines[lineidx+n]:
continue
function += lines[lineidx+n]
if lineidx+n+1 >= len(lines):
print(lines[lineidx:])
raise Exception()
if '{' in lines[lineidx+n+1] or ';' in lines[lineidx+n]:
break
function = function.replace('//\n', '')
function = function.replace('\n', '')
function = function.replace(';', '')
docs = ''
if '*/' in lines[lineidx-1] or '//!' in lines[lineidx-1]:
for n in range(1, 100):
if '//!' in lines[lineidx-n] or '/*!' in lines[lineidx-n]:
docs = ''.join(lines[lineidx-n:lineidx])
# Remove any indent
docs = docs.replace('\n ', '\n')[2:]
break
functions_to_be_freed.append((current_class, function, docs))
elif '// BEGIN make_free_functions.py' in lines[lineidx]:
functions_to_be_freed_begin = lineidx
elif '// END make_free_functions.py' in lines[lineidx]:
functions_to_be_freed_end = lineidx
if functions_to_be_freed:
if functions_to_be_freed_begin != -1:
del lines[functions_to_be_freed_begin+1:functions_to_be_freed_end]
else:
# Place just before the last LLFIO_V2_NAMESPACE_END
functions_to_be_freed_begin = len(lines)-1
while not lines[functions_to_be_freed_begin].startswith('LLFIO_V2_NAMESPACE_END'):
functions_to_be_freed_begin = functions_to_be_freed_begin - 1
lines.insert(functions_to_be_freed_begin, '// END make_free_functions.py\n\n')
lines.insert(functions_to_be_freed_begin, '// BEGIN make_free_functions.py\n')
idx = functions_to_be_freed_begin + 1
for classname, function, docs in functions_to_be_freed:
print((classname, function))
function = function.replace('virtual ', '')
function = function.replace('override', '')
function = function.replace('LLFIO_HEADERS_ONLY_MEMFUNC_SPEC ', '')
function = function.replace('LLFIO_HEADERS_ONLY_VIRTUAL_SPEC ', '')
completion_template = 'template <class CompletionRoutine>' in function
function = function.replace('template <class CompletionRoutine> ', '')
is_static = 'static ' in function
function = function.replace('static ', '')
function = function.lstrip()
if not function.startswith('inline'):
function = 'inline ' + function
if completion_template:
function = 'template <class CompletionRoutine> ' + function
def replace(function, item):
function = function.replace(' '+item+' ', ' '+classname+'::'+item+' ')
function = function.replace('('+item+' ', '('+classname+'::'+item+' ')
function = function.replace('<'+item+',', '<'+classname+'::'+item+',')
function = function.replace('<'+item+'>', '<'+classname+'::'+item+'>')
function = function.replace(' '+item+'>', ' '+classname+'::'+item+'>')
return function
function = replace(function, 'path_view_type')
function = replace(function, 'extent_type')
function = replace(function, 'size_type')
function = replace(function, 'buffer_type')
function = replace(function, 'const_buffer_type')
function = replace(function, 'enumerate_info')
function = replace(function, 'buffers_type')
function = replace(function, 'const_buffers_type')
function = replace(function, 'io_state_ptr')
function = function.replace('path_view_type()', classname+'::path_view_type()')
function = function.replace(' io_result<', ' '+classname+'::io_result<')
function = function.replace(' io_request<', ' '+classname+'::io_request<')
function = function.replace('(io_request<', '('+classname+'::io_request<')
function = function.replace('<io_state_ptr<', '<'+classname+'::io_state_ptr<')
function = function.replace('<awaitable<', '<'+classname+'::awaitable<')
function = function.replace(' mode ', ' '+classname+'::mode ')
function = function.replace(' mode::', ' '+classname+'::mode::')
function = function.replace(' creation ', ' '+classname+'::creation ')
function = function.replace(' creation::', ' '+classname+'::creation::')
function = function.replace(' caching ', ' '+classname+'::caching ')
function = function.replace(' caching::', ' '+classname+'::caching::')
function = function.replace(' flag ', ' '+classname+'::flag ')
function = function.replace(' flag::', ' '+classname+'::flag::')
function = function.replace(' filter ', ' '+classname+'::filter ')
function = function.replace(' filter::', ' '+classname+'::filter::')
if function[-2] == ';':
function=function[:-2]
elif '}' in function:
function = function[:function.rfind('{')] + function[function.rfind('}')+1:]
function = function.rstrip()
idx1 = function.rfind('const')
idx2 = function.rfind(')')
is_const = False
if idx1 > idx2:
function = function[:idx1] + function[idx1+6:]
function = function.rstrip()
is_const = True
idx1 = function.rfind('= 0')
if idx1 > idx2:
function = function[:idx1] + function[idx1+3:]
function = function.rstrip()
if is_static:
call = function
impl = "\n{\n return "+classname+"::"
else:
call = function
idx1 = function.find('(')
idx2 = function.rfind(')')
function = function[:idx1+1] + (('const ' + classname) if is_const else classname) + (' &self, ' if idx1+1 != idx2 else ' &self') + function[idx1+1:]
impl = "\n{\n return self."
idx1 = docs.find('\\param')
if idx1 != -1:
docs = docs[:idx1] + '\param self The object whose member function to call.\n' + docs[idx1:]
#print(call)
call = re.sub(r'^.+?(?= [^ ]+\()', '', call) # remove anything before the function call
#print(call)
call = re.sub(r'(?<=\) ).*', '', call) # remove anything after the function call
#print(call)
call = re.sub(r'".*?"', '', call) # remove any string literals
#print(call)
call = re.sub(r'\s?=.+?(?:\(.*?\))?(?=[,)])', '', call) # remove all default initialisers
#print(call)
impl += re.match(r'.+\(', call).group(0).lstrip()
first = True
for par in re.finditer(r'\w*[,)]', call):
if not first:
impl += ' '
else:
first = False
p = par.group(0)
if p == ')':
impl += ')'
else:
impl += 'std::forward<decltype('+p[:-1]+')>('+p[:-1]+')'+p[-1]
impl += ";\n}\n"
lines.insert(idx, function+impl)
lines.insert(idx, docs)
idx = idx + 2
with open(header, "wt") as oh:
oh.writelines(lines)
|