forked from mavlink/mavlink
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmavtemplate.py
127 lines (116 loc) · 5.33 KB
/
mavtemplate.py
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
#!/usr/bin/env python
'''
simple templating system for mavlink generator
Copyright Andrew Tridgell 2011
Released under GNU GPL version 3 or later
'''
from mavparse import MAVParseError
class MAVTemplate(object):
'''simple templating system'''
def __init__(self,
start_var_token="${",
end_var_token="}",
start_rep_token="${{",
end_rep_token="}}",
trim_leading_lf=True,
checkmissing=True):
self.start_var_token = start_var_token
self.end_var_token = end_var_token
self.start_rep_token = start_rep_token
self.end_rep_token = end_rep_token
self.trim_leading_lf = trim_leading_lf
self.checkmissing = checkmissing
def find_end(self, text, start_token, end_token, ignore_end_token=None):
'''find the of a token.
Returns the offset in the string immediately after the matching end_token'''
if not text.startswith(start_token):
raise MAVParseError("invalid token start")
offset = len(start_token)
nesting = 1
while nesting > 0:
idx1 = text[offset:].find(start_token)
idx2 = text[offset:].find(end_token)
# Check for false positives due to another similar token
# For example, make sure idx2 points to the second '}' in ${{field: ${name}}}
if ignore_end_token:
combined_token = ignore_end_token + end_token
if text[offset+idx2:offset+idx2+len(combined_token)] == combined_token:
idx2 += len(ignore_end_token)
if idx1 == -1 and idx2 == -1:
raise MAVParseError("token nesting error")
if idx1 == -1 or idx1 > idx2:
offset += idx2 + len(end_token)
nesting -= 1
else:
offset += idx1 + len(start_token)
nesting += 1
return offset
def find_var_end(self, text):
'''find the of a variable'''
return self.find_end(text, self.start_var_token, self.end_var_token)
def find_rep_end(self, text):
'''find the of a repitition'''
return self.find_end(text, self.start_rep_token, self.end_rep_token, ignore_end_token=self.end_var_token)
def substitute(self, text, subvars={},
trim_leading_lf=None, checkmissing=None):
'''substitute variables in a string'''
if trim_leading_lf is None:
trim_leading_lf = self.trim_leading_lf
if checkmissing is None:
checkmissing = self.checkmissing
# handle repititions
while True:
subidx = text.find(self.start_rep_token)
if subidx == -1:
break
endidx = self.find_rep_end(text[subidx:])
if endidx == -1:
raise MAVParseError("missing end macro in %s" % text[subidx:])
part1 = text[0:subidx]
part2 = text[subidx+len(self.start_rep_token):subidx+(endidx-len(self.end_rep_token))]
part3 = text[subidx+endidx:]
a = part2.split(':')
field_name = a[0]
rest = ':'.join(a[1:])
v = getattr(subvars, field_name, None)
if v is None:
raise MAVParseError('unable to find field %s' % field_name)
t1 = part1
for f in v:
t1 += self.substitute(rest, f, trim_leading_lf=False, checkmissing=False)
if len(v) != 0 and t1[-1] in ["\n", ","]:
t1 = t1[:-1]
t1 += part3
text = t1
if trim_leading_lf:
if text[0] == '\n':
text = text[1:]
while True:
idx = text.find(self.start_var_token)
if idx == -1:
return text
endidx = text[idx:].find(self.end_var_token)
if endidx == -1:
raise MAVParseError('missing end of variable: %s' % text[idx:idx+10])
varname = text[idx+2:idx+endidx]
if isinstance(subvars, dict):
if not varname in subvars:
if checkmissing:
raise MAVParseError("unknown variable in '%s%s%s'" % (
self.start_var_token, varname, self.end_var_token))
return text[0:idx+endidx] + self.substitute(text[idx+endidx:], subvars,
trim_leading_lf=False, checkmissing=False)
value = subvars[varname]
else:
value = getattr(subvars, varname, None)
if value is None:
if checkmissing:
raise MAVParseError("unknown variable in '%s%s%s'" % (
self.start_var_token, varname, self.end_var_token))
return text[0:idx+endidx] + self.substitute(text[idx+endidx:], subvars,
trim_leading_lf=False, checkmissing=False)
text = text.replace("%s%s%s" % (self.start_var_token, varname, self.end_var_token), str(value))
return text
def write(self, file, text, subvars={}, trim_leading_lf=True):
'''write to a file with variable substitution'''
file.write(self.substitute(text, subvars=subvars, trim_leading_lf=trim_leading_lf))