Skip to content

Commit 5808635

Browse files
committed
py/makeqstrdata.py: Refactor qstr class.
Use Qstr class instead of tuple, where properties are calculated only when accessed. This is needed as preparation to using hash as the sort key instead the qstr string. It also makes the code more readable when referring to a qstr in py/makeqstrdata.py and tools/mpy-tool.py (for example, refer to q.order instead of q[0], or q.qstr instead of q[2]) Signed-off-by: Amir Gonnen <amirgonnen@gmail.com>
1 parent 5312b34 commit 5808635

File tree

2 files changed

+65
-44
lines changed

2 files changed

+65
-44
lines changed

py/makeqstrdata.py

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@
223223
]
224224

225225
# this must match the equivalent function in qstr.c
226+
227+
226228
def compute_hash(qstr, bytes_hash):
227229
hash = 5381
228230
for b in qstr:
@@ -257,7 +259,7 @@ def parse_input_headers(infiles):
257259

258260
# add the qstr to the list, with order number to retain original order in file
259261
order = len(qstrs) - 300000
260-
qstrs[ident] = (order, ident, qstr)
262+
qstrs[ident] = Qstr(order, ident, qstr)
261263

262264
# read the qstrs in from the input files
263265
for infile in infiles:
@@ -308,7 +310,7 @@ def parse_input_headers(infiles):
308310
order = -190000
309311
elif ident.startswith("__"):
310312
order -= 100000
311-
qstrs[ident] = (order, ident, qstr)
313+
qstrs[ident] = Qstr(order, ident, qstr)
312314

313315
if not qcfgs:
314316
sys.stderr.write("ERROR: Empty preprocessor output - check for errors above\n")
@@ -317,31 +319,44 @@ def parse_input_headers(infiles):
317319
return qcfgs, qstrs
318320

319321

320-
def escape_bytes(qstr, qbytes):
321-
if all(32 <= ord(c) <= 126 and c != "\\" and c != '"' for c in qstr):
322-
# qstr is all printable ASCII so render it as-is (for easier debugging)
323-
return qstr
324-
else:
325-
# qstr contains non-printable codes so render entire thing as hex pairs
326-
return "".join(("\\x%02x" % b) for b in qbytes)
322+
class Qstr:
323+
cfg_bytes_len = 0
324+
cfg_bytes_hash = 0
327325

326+
def __init__(self, order, ident, qstr):
327+
self.order = order
328+
self.ident = ident
329+
self.qstr = qstr
328330

329-
def make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr):
330-
qbytes = bytes_cons(qstr, "utf8")
331-
qlen = len(qbytes)
332-
qhash = compute_hash(qbytes, cfg_bytes_hash)
333-
if qlen >= (1 << (8 * cfg_bytes_len)):
334-
print("qstr is too long:", qstr)
335-
assert False
336-
qdata = escape_bytes(qstr, qbytes)
337-
return '%d, %d, "%s"' % (qhash, qlen, qdata)
331+
@property
332+
def qbytes(self):
333+
return bytes_cons(self.qstr, "utf8")
338334

335+
@property
336+
def qlen(self):
337+
if len(self.qbytes) >= (1 << (8 * Qstr.cfg_bytes_len)):
338+
print("qstr is too long:", self.qstr)
339+
assert False
340+
return len(self.qbytes)
339341

340-
def print_qstr_data(qcfgs, qstrs):
341-
# get config variables
342-
cfg_bytes_len = int(qcfgs["BYTES_IN_LEN"])
343-
cfg_bytes_hash = int(qcfgs["BYTES_IN_HASH"])
342+
@property
343+
def qhash(self):
344+
return compute_hash(self.qbytes, Qstr.cfg_bytes_hash)
345+
346+
def _escape_bytes(self):
347+
if all(32 <= ord(c) <= 126 and c != "\\" and c != '"' for c in self.qstr):
348+
# qstr is all printable ASCII so render it as-is (for easier debugging)
349+
return self.qstr
350+
else:
351+
# qstr contains non-printable codes so render entire thing as hex pairs
352+
return "".join(("\\x%02x" % b) for b in self.qbytes)
353+
354+
@property
355+
def qdata(self):
356+
return self._escape_bytes()
344357

358+
359+
def print_qstr_data(qstrs):
345360
# print out the starter of the generated C header file
346361
print("// This file was automatically generated by makeqstrdata.py")
347362
print("")
@@ -350,23 +365,26 @@ def print_qstr_data(qcfgs, qstrs):
350365
print('QDEF0(MP_QSTRnull, 0, 0, "")')
351366

352367
# split qstr values into two pools. static consts first.
353-
q0_values = [q for q in qstrs.values() if q[0] < 0]
354-
q1_values = [q for q in qstrs.values() if q[0] >= 0]
368+
q0_values = [q for q in qstrs.values() if q.order < 0]
369+
q1_values = [q for q in qstrs.values() if q.order >= 0]
355370

356371
# go through each qstr in pool 0 and print it out. pool0 has special sort.
357-
for order, ident, qstr in sorted(q0_values, key=lambda x: x[0]):
358-
qbytes = make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr)
359-
print("QDEF0(MP_QSTR_%s, %s)" % (ident, qbytes))
372+
for q in sorted(q0_values, key=lambda x: x.order):
373+
print('QDEF0(MP_QSTR_%s, %d, %d, "%s")' % (q.ident, q.qhash, q.qlen, q.qdata))
360374

361375
# go through each qstr in pool 1 and print it out. pool1 is regularly sorted.
362-
for order, ident, qstr in sorted(q1_values, key=lambda x: x[2]):
363-
qbytes = make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr)
364-
print("QDEF1(MP_QSTR_%s, %s)" % (ident, qbytes))
376+
for q in sorted(q1_values, key=lambda x: x.qstr):
377+
print('QDEF1(MP_QSTR_%s, %d, %d, "%s")' % (q.ident, q.qhash, q.qlen, q.qdata))
365378

366379

367380
def do_work(infiles):
368381
qcfgs, qstrs = parse_input_headers(infiles)
369-
print_qstr_data(qcfgs, qstrs)
382+
383+
# get config variables
384+
Qstr.cfg_bytes_len = int(qcfgs["BYTES_IN_LEN"])
385+
Qstr.cfg_bytes_hash = int(qcfgs["BYTES_IN_HASH"])
386+
387+
print_qstr_data(qstrs)
370388

371389

372390
if __name__ == "__main__":

tools/mpy-tool.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,8 +1272,8 @@ def freeze_mpy(base_qstrs, compiled_modules):
12721272
# don't add duplicates
12731273
if q is None or q.qstr_esc in base_qstrs or q.qstr_esc in new:
12741274
continue
1275-
new[q.qstr_esc] = (len(new), q.qstr_esc, q.str, bytes_cons(q.str, "utf8"))
1276-
new = sorted(new.values(), key=lambda x: x[2])
1275+
new[q.qstr_esc] = qstrutil.Qstr(len(new), q.qstr_esc, q.str)
1276+
new = sorted(new.values(), key=lambda x: x.qstr)
12771277

12781278
print('#include "py/mpconfig.h"')
12791279
print('#include "py/objint.h"')
@@ -1314,9 +1314,9 @@ def freeze_mpy(base_qstrs, compiled_modules):
13141314
print("enum {")
13151315
for i in range(len(new)):
13161316
if i == 0:
1317-
print(" MP_QSTR_%s = MP_QSTRnumber_of," % new[i][1])
1317+
print(" MP_QSTR_%s = MP_QSTRnumber_of," % new[i].ident)
13181318
else:
1319-
print(" MP_QSTR_%s," % new[i][1])
1319+
print(" MP_QSTR_%s," % new[i].ident)
13201320
print("};")
13211321

13221322
# As in qstr.c, set so that the first dynamically allocated pool is twice this size; must be <= the len
@@ -1336,18 +1336,17 @@ def freeze_mpy(base_qstrs, compiled_modules):
13361336
print()
13371337
print("const qstr_hash_t mp_qstr_frozen_const_hashes[] = {")
13381338
qstr_size = {"metadata": 0, "data": 0}
1339-
for _, _, _, qbytes in new:
1340-
qhash = qstrutil.compute_hash(qbytes, config.MICROPY_QSTR_BYTES_IN_HASH)
1341-
print(" %d," % qhash)
1339+
for q in new:
1340+
print(" %d," % q.qhash)
13421341
print("};")
13431342
print()
13441343
print("const qstr_len_t mp_qstr_frozen_const_lengths[] = {")
1345-
for _, _, _, qbytes in new:
1346-
print(" %d," % len(qbytes))
1344+
for q in new:
1345+
print(" %d," % len(q.qbytes))
13471346
qstr_size["metadata"] += (
13481347
config.MICROPY_QSTR_BYTES_IN_LEN + config.MICROPY_QSTR_BYTES_IN_HASH
13491348
)
1350-
qstr_size["data"] += len(qbytes)
1349+
qstr_size["data"] += len(q.qbytes)
13511350
print("};")
13521351
print()
13531352
print("extern const qstr_pool_t mp_qstr_const_pool;")
@@ -1360,10 +1359,10 @@ def freeze_mpy(base_qstrs, compiled_modules):
13601359
print(" (qstr_len_t *)mp_qstr_frozen_const_lengths,")
13611360
print(" true, // entries are sorted")
13621361
print(" {")
1363-
for _, _, qstr, qbytes in new:
1364-
print(' "%s",' % qstrutil.escape_bytes(qstr, qbytes))
1362+
for q in new:
1363+
print(' "%s",' % q.qdata)
13651364
qstr_content += (
1366-
config.MICROPY_QSTR_BYTES_IN_LEN + config.MICROPY_QSTR_BYTES_IN_HASH + len(qbytes) + 1
1365+
config.MICROPY_QSTR_BYTES_IN_LEN + config.MICROPY_QSTR_BYTES_IN_HASH + len(q.qbytes) + 1
13671366
)
13681367
print(" },")
13691368
print("};")
@@ -1560,13 +1559,17 @@ def main():
15601559
config.MICROPY_QSTR_BYTES_IN_LEN = 1
15611560
config.MICROPY_QSTR_BYTES_IN_HASH = 1
15621561
base_qstrs = list(qstrutil.static_qstr_list)
1562+
1563+
qstrutil.Qstr.cfg_bytes_len = config.MICROPY_QSTR_BYTES_IN_LEN
1564+
qstrutil.Qstr.cfg_bytes_hash = config.MICROPY_QSTR_BYTES_IN_HASH
15631565

15641566
# Load all .mpy files.
15651567
try:
15661568
compiled_modules = [read_mpy(file) for file in args.files]
15671569
except MPYReadError as er:
15681570
print(er, file=sys.stderr)
15691571
sys.exit(1)
1572+
base_qstrs = {}
15701573

15711574
if args.hexdump:
15721575
hexdump_mpy(compiled_modules)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy