Skip to content

Commit 94b98c7

Browse files
authored
Merge pull request #808 from elbeno/reserve-string-ids
✨ Allow string ID ranges to be reserved on the command line
2 parents c429859 + d7ad695 commit 94b98c7

File tree

4 files changed

+70
-6
lines changed

4 files changed

+70
-6
lines changed

cmake/string_catalog.cmake

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ function(gen_str_catalog)
1111
GUID_ID
1212
GUID_MASK
1313
MODULE_ID_MAX
14+
RESERVED_IDS
1415
OUTPUTS_TARGET)
1516
set(multiValueArgs INPUT_JSON INPUT_LIBS INPUT_HEADERS STABLE_JSON)
1617
cmake_parse_arguments(SC "${options}" "${oneValueArgs}" "${multiValueArgs}"
@@ -68,6 +69,9 @@ function(gen_str_catalog)
6869
if(SC_MODULE_ID_MAX)
6970
set(MODULE_ID_MAX_ARG --module_id_max ${SC_MODULE_ID_MAX})
7071
endif()
72+
if(SC_RESERVED_IDS)
73+
set(RESERVED_IDS_ARG --reserved_ids ${SC_RESERVED_IDS})
74+
endif()
7175
if(NOT SC_GEN_STR_CATALOG)
7276
set(SC_GEN_STR_CATALOG ${GEN_STR_CATALOG})
7377
endif()
@@ -80,7 +84,7 @@ function(gen_str_catalog)
8084
--cpp_output ${SC_OUTPUT_CPP} --json_output ${SC_OUTPUT_JSON}
8185
--xml_output ${SC_OUTPUT_XML} --stable_json ${STABLE_JSON}
8286
${FORGET_ARG} ${CLIENT_NAME_ARG} ${VERSION_ARG} ${GUID_ID_ARG}
83-
${GUID_MASK_ARG} ${MODULE_ID_MAX_ARG}
87+
${GUID_MASK_ARG} ${MODULE_ID_MAX_ARG} ${RESERVED_IDS_ARG}
8488
DEPENDS ${UNDEFS} ${INPUT_JSON} ${SC_GEN_STR_CATALOG} ${STABLE_JSON}
8589
COMMAND_EXPAND_LISTS)
8690

test/log/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ gen_str_catalog(
4040
"01234567-89ab-cdef-0123-456789abcdef"
4141
GUID_MASK
4242
"ffffffff-ffff-ffff-ffff-ffffffffffff"
43+
RESERVED_IDS
44+
"1,1000-1005,1010"
4345
OUTPUTS_TARGET
4446
test_catalog_json)
4547

tools/gen_str_catalog.py

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,31 @@ def split_args(s: str) -> list[str]:
3131
return args
3232

3333

34+
class Intervals:
35+
def __init__(self, text: str):
36+
self.intervals = []
37+
for i in text.split(","):
38+
rng = i.split("-")
39+
if rng != [""]:
40+
start = int(rng[0], 0)
41+
self.intervals.append(
42+
(start, int(rng[1], 0) if len(rng) == 2 else start)
43+
)
44+
45+
def contains(self, v: int) -> bool:
46+
return any(map(lambda x: v >= x[0] and v <= x[1], self.intervals))
47+
48+
def __str__(self):
49+
rngs = map(
50+
lambda x: f"{x[0]}-{x[1]}" if x[0] != x[1] else f"{x[0]}",
51+
self.intervals,
52+
)
53+
return ",".join(rngs)
54+
55+
def __repr__(self):
56+
return f'Intervals("{self}")'
57+
58+
3459
class Message:
3560
cpp_prefix: str = "sc::message<sc::undefined"
3661

@@ -152,7 +177,7 @@ def assign_ids_with(items, id_fn):
152177
return list(sorted_items)
153178

154179

155-
def assign_ids(messages, modules, stable_data):
180+
def assign_ids(messages, modules, stable_data, reserved_ids):
156181
def get_id(stables, gen, obj):
157182
key = obj.key()
158183
if key in stables:
@@ -167,7 +192,10 @@ def get_id(stables, gen, obj):
167192
stable_modules[module.key()] = module
168193

169194
old_msg_ids = set(m.id for m in stable_msgs.values())
170-
msg_id_gen = itertools.filterfalse(old_msg_ids.__contains__, itertools.count(0))
195+
msg_id_gen = itertools.filterfalse(
196+
lambda x: old_msg_ids.__contains__(x) or reserved_ids.contains(x),
197+
itertools.count(0),
198+
)
171199
get_msg_id = partial(get_id, stable_msgs, msg_id_gen)
172200

173201
old_module_ids = set(m.id for m in stable_modules.values())
@@ -182,7 +210,7 @@ def get_id(stables, gen, obj):
182210
)
183211

184212

185-
def read_input(filenames: list[str], stable_data):
213+
def read_input(filenames: list[str], stable_data, reserved_ids):
186214
line_re = re.compile(r"^.*unsigned (?:int|long) (catalog|module)<(.+?)>\(\)$")
187215

188216
def read_file(filename):
@@ -199,7 +227,7 @@ def read_file(filename):
199227
modules = filter(lambda x: isinstance(x, Module), items)
200228
unique_modules = {m.key(): m for m in modules}.values()
201229

202-
return assign_ids(unique_messages, unique_modules, stable_data)
230+
return assign_ids(unique_messages, unique_modules, stable_data, reserved_ids)
203231

204232

205233
def make_cpp_scoped_enum_decl(e: str, ut: str) -> str:
@@ -542,6 +570,12 @@ def parse_cmdline():
542570
default=127,
543571
help="The maximum value of a module ID.",
544572
)
573+
parser.add_argument(
574+
"--reserved_ids",
575+
type=lambda x: Intervals(x),
576+
default="",
577+
help="A list of (inclusive) ranges of string IDs that should be reserved and not used. e.g. '1-5,10-15,20'",
578+
)
545579
return parser.parse_args()
546580

547581

@@ -565,7 +599,7 @@ def main():
565599

566600
stable_data = read_stable(args.stable_json)
567601
try:
568-
messages, modules = read_input(args.input, stable_data)
602+
messages, modules = read_input(args.input, stable_data, args.reserved_ids)
569603
except Exception as e:
570604
raise Exception(f"{str(e)} from file {args.input}")
571605

tools/gen_str_catalog_test.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,27 @@ def test_module_cpp_type():
7070
def test_module_json():
7171
m = gen.Module("abc", 42)
7272
assert m.to_json() == {"string": "abc", "id": 42}
73+
74+
75+
test_ints = "1-5,8-10,15"
76+
77+
78+
def test_intervals():
79+
m = gen.Intervals(test_ints)
80+
assert m.contains(1)
81+
assert m.contains(5)
82+
assert not m.contains(6)
83+
assert m.contains(8)
84+
assert m.contains(10)
85+
assert m.contains(15)
86+
87+
88+
def test_empty_intervals():
89+
m = gen.Intervals("")
90+
assert not m.contains(1)
91+
92+
93+
def test_intervals_repr():
94+
m = gen.Intervals(test_ints)
95+
assert f"{m}" == "1-5,8-10,15"
96+
assert repr(m) == 'Intervals("1-5,8-10,15")'

0 commit comments

Comments
 (0)