[tmf] simplify URI paths array using X-Macro (#12674)

This commit simplfies `thread/uri_paths.cpp` by introducing the
`UriEntryMapList` X-Macro. This macro centralizes the mapping
between the URI path string, its `kUri*` enum value and its string
name representation used in `UriToString()`.

By using this macro, we avoid redundant lists and manual template
specializations. The `kEntries[]` array, the compile-time assertions
validating the sorting of the array, and the `UriToString<>()`
template specializations are now all automatically generated from
this single list, improving maintainability and reducing the chance
of mismatches.
This commit is contained in:
Abtin Keshavarzian
2026-03-11 17:37:11 -07:00
committed by GitHub
parent 7696e38945
commit a03011cf73
+74 -148
View File
@@ -51,109 +51,79 @@ struct Entry
int Compare(const char *aPath) const { return strcmp(aPath, mPath); }
};
// The list of URI paths (MUST be sorted alphabetically)
static constexpr Entry kEntries[] = {
{"a/ae"}, // kUriAddressError
{"a/an"}, // kUriAddressNotify
{"a/aq"}, // kUriAddressQuery
{"a/ar"}, // kUriAddressRelease
{"a/as"}, // kUriAddressSolicit
{"a/sd"}, // kUriServerData
{"a/yl"}, // kUriAnycastLocate
{"b/ba"}, // kUriBackboneAnswer
{"b/bmr"}, // kUriBackboneMlr
{"b/bq"}, // kUriBackboneQuery
{"c/ab"}, // kUriAnnounceBegin
{"c/ag"}, // kUriActiveGet
{"c/ar"}, // kUriActiveReplace
{"c/as"}, // kUriActiveSet
{"c/ca"}, // kUriCommissionerKeepAlive
{"c/cg"}, // kUriCommissionerGet
{"c/cp"}, // kUriCommissionerPetition
{"c/cs"}, // kUriCommissionerSet
{"c/dc"}, // kUriDatasetChanged
{"c/er"}, // kUriEnergyReport
{"c/es"}, // kUriEnergyScan
{"c/je"}, // kUriJoinerEntrust
{"c/jf"}, // kUriJoinerFinalize
{"c/la"}, // kUriLeaderKeepAlive
{"c/lp"}, // kUriLeaderPetition
{"c/nj"}, // kUriEnrollerJoinerAccept
{"c/nk"}, // kUriEnrollerKeepAlive
{"c/nl"}, // kUriEnrollerJoinerRelease
{"c/nr"}, // kUriEnrollerRegister
{"c/ns"}, // kUriEnrollerReportState
{"c/pc"}, // kUriPanIdConflict
{"c/pg"}, // kUriPendingGet
{"c/pq"}, // kUriPanIdQuery
{"c/ps"}, // kUriPendingSet
{"c/rx"}, // kUriRelayRx
{"c/te"}, // kUriTcatEnable
{"c/tx"}, // kUriRelayTx
{"c/ur"}, // kUriProxyRx
{"c/ut"}, // kUriProxyTx
{"d/da"}, // kUriDiagnosticGetAnswer
{"d/dg"}, // kUriDiagnosticGetRequest
{"d/dq"}, // kUriDiagnosticGetQuery
{"d/dr"}, // kUriDiagnosticReset
{"h/an"}, // kUriHistoryAnswer
{"h/qy"}, // kUriHistoryQuery
{"n/dn"}, // kUriDuaRegistrationNotify
{"n/dr"}, // kUriDuaRegistrationRequest
{"n/mr"}, // kUriMlr
};
#define UriEntryMapList(_) \
_("a/ae", kUriAddressError, "AddrError") \
_("a/an", kUriAddressNotify, "AddrNotify") \
_("a/aq", kUriAddressQuery, "AddrQuery") \
_("a/ar", kUriAddressRelease, "AddrRelease") \
_("a/as", kUriAddressSolicit, "AddrSolicit") \
_("a/sd", kUriServerData, "ServerData") \
_("a/yl", kUriAnycastLocate, "AnycastLocate") \
_("b/ba", kUriBackboneAnswer, "BbAnswer") \
_("b/bmr", kUriBackboneMlr, "BbMlr") \
_("b/bq", kUriBackboneQuery, "BbQuery") \
_("c/ab", kUriAnnounceBegin, "AnnounceBegin") \
_("c/ag", kUriActiveGet, "ActiveGet") \
_("c/ar", kUriActiveReplace, "ActiveReplace") \
_("c/as", kUriActiveSet, "ActiveSet") \
_("c/ca", kUriCommissionerKeepAlive, "CommrKeepAlive") \
_("c/cg", kUriCommissionerGet, "CommrGet") \
_("c/cp", kUriCommissionerPetition, "CommrPetition") \
_("c/cs", kUriCommissionerSet, "CommrSet") \
_("c/dc", kUriDatasetChanged, "DatasetChanged") \
_("c/er", kUriEnergyReport, "EnergyReport") \
_("c/es", kUriEnergyScan, "EnergyScan") \
_("c/je", kUriJoinerEntrust, "JoinerEntrust") \
_("c/jf", kUriJoinerFinalize, "JoinerFinalize") \
_("c/la", kUriLeaderKeepAlive, "LeaderKeepAlive") \
_("c/lp", kUriLeaderPetition, "LeaderPetition") \
_("c/nj", kUriEnrollerJoinerAccept, "EnrollerJoinerAccept") \
_("c/nk", kUriEnrollerKeepAlive, "EnrollerKeepAlive") \
_("c/nl", kUriEnrollerJoinerRelease, "EnrollerJoinerRelease") \
_("c/nr", kUriEnrollerRegister, "EnrollerRegister") \
_("c/ns", kUriEnrollerReportState, "EnrollerReportState") \
_("c/pc", kUriPanIdConflict, "PanIdConflict") \
_("c/pg", kUriPendingGet, "PendingGet") \
_("c/pq", kUriPanIdQuery, "PanIdQuery") \
_("c/ps", kUriPendingSet, "PendingSet") \
_("c/rx", kUriRelayRx, "RelayRx") \
_("c/te", kUriTcatEnable, "TcatEnable") \
_("c/tx", kUriRelayTx, "RelayTx") \
_("c/ur", kUriProxyRx, "ProxyRx") \
_("c/ut", kUriProxyTx, "ProxyTx") \
_("d/da", kUriDiagnosticGetAnswer, "DiagGetAnswer") \
_("d/dg", kUriDiagnosticGetRequest, "DiagGetRequest") \
_("d/dq", kUriDiagnosticGetQuery, "DiagGetQuery") \
_("d/dr", kUriDiagnosticReset, "DiagReset") \
_("h/an", kUriHistoryAnswer, "HistAnswer") \
_("h/qy", kUriHistoryQuery, "HistQuery") \
_("n/dn", kUriDuaRegistrationNotify, "DuaRegNotify") \
_("n/dr", kUriDuaRegistrationRequest, "DuaRegRequest") \
_("n/mr", kUriMlr, "Mlr")
// We use the X-Macro pattern here. The `UriEntryMapList` macro defines the
// mapping between URI path string, its `kUri*` enum and its name string (for
// `UriToString`).
//
// The `UriEntryMapList` macro accepts a single parameter, which is a "visitor"
// macro (`_`). The visitor macro is called for each entry in the list. We define
// different visitor macros: one to define the `kEntries[]` array, another to
// validate the entries in the array (ensuring the URI paths match the enum
// values and are sorted properly), and a third to define the `UriToString()`
// template specializations.
#define _EntryArrayElement(kPathString, kUri, kName) {kPathString},
static constexpr const Entry kEntries[] = {UriEntryMapList(_EntryArrayElement)};
// The URI entries MUST be sorted based on their path string (e.g. `c/ut`)
static_assert(BinarySearch::IsSorted(kEntries), "kEntries is not sorted");
// Validate that the `kEntries[]` order match the `kUri*` enum constants
static_assert(AreConstStringsEqual(kEntries[kUriAddressError].mPath, "a/ae"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriAddressNotify].mPath, "a/an"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriAddressQuery].mPath, "a/aq"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriAddressRelease].mPath, "a/ar"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriAddressSolicit].mPath, "a/as"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriServerData].mPath, "a/sd"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriAnycastLocate].mPath, "a/yl"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriBackboneAnswer].mPath, "b/ba"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriBackboneMlr].mPath, "b/bmr"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriBackboneQuery].mPath, "b/bq"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriAnnounceBegin].mPath, "c/ab"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriActiveGet].mPath, "c/ag"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriActiveReplace].mPath, "c/ar"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriActiveSet].mPath, "c/as"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriCommissionerKeepAlive].mPath, "c/ca"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriCommissionerGet].mPath, "c/cg"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriCommissionerPetition].mPath, "c/cp"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriCommissionerSet].mPath, "c/cs"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriDatasetChanged].mPath, "c/dc"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriEnergyReport].mPath, "c/er"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriEnergyScan].mPath, "c/es"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriJoinerEntrust].mPath, "c/je"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriJoinerFinalize].mPath, "c/jf"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriLeaderKeepAlive].mPath, "c/la"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriLeaderPetition].mPath, "c/lp"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriEnrollerJoinerAccept].mPath, "c/nj"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriEnrollerKeepAlive].mPath, "c/nk"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriEnrollerJoinerRelease].mPath, "c/nl"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriEnrollerRegister].mPath, "c/nr"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriEnrollerReportState].mPath, "c/ns"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriPanIdConflict].mPath, "c/pc"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriPendingGet].mPath, "c/pg"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriPanIdQuery].mPath, "c/pq"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriPendingSet].mPath, "c/ps"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriRelayRx].mPath, "c/rx"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriTcatEnable].mPath, "c/te"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriRelayTx].mPath, "c/tx"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriProxyRx].mPath, "c/ur"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriProxyTx].mPath, "c/ut"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriDiagnosticGetAnswer].mPath, "d/da"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriDiagnosticGetRequest].mPath, "d/dg"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriDiagnosticGetQuery].mPath, "d/dq"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriDiagnosticReset].mPath, "d/dr"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriHistoryAnswer].mPath, "h/an"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriHistoryQuery].mPath, "h/qy"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriDuaRegistrationNotify].mPath, "n/dn"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriDuaRegistrationRequest].mPath, "n/dr"), "kEntries is invalid");
static_assert(AreConstStringsEqual(kEntries[kUriMlr].mPath, "n/mr"), "kEntries is invalid");
#define _ValidateEntryElement(kPathString, kUri, kName) \
static_assert(AreConstStringsEqual(kEntries[kUri].mPath, kPathString), \
#kUri " value is incorrect. list is not sorted");
UriEntryMapList(_ValidateEntryElement)
} // namespace UriList
@@ -176,53 +146,9 @@ exit:
return uri;
}
template <> const char *UriToString<kUriAddressError>(void) { return "AddressError"; }
template <> const char *UriToString<kUriAddressNotify>(void) { return "AddressNotify"; }
template <> const char *UriToString<kUriAddressQuery>(void) { return "AddressQuery"; }
template <> const char *UriToString<kUriAddressRelease>(void) { return "AddressRelease"; }
template <> const char *UriToString<kUriAddressSolicit>(void) { return "AddressSolicit"; }
template <> const char *UriToString<kUriServerData>(void) { return "ServerData"; }
template <> const char *UriToString<kUriAnycastLocate>(void) { return "AnycastLocate"; }
template <> const char *UriToString<kUriBackboneAnswer>(void) { return "BackboneAnswer"; }
template <> const char *UriToString<kUriBackboneMlr>(void) { return "BackboneMlr"; }
template <> const char *UriToString<kUriBackboneQuery>(void) { return "BackboneQuery"; }
template <> const char *UriToString<kUriAnnounceBegin>(void) { return "AnnounceBegin"; }
template <> const char *UriToString<kUriActiveGet>(void) { return "ActiveGet"; }
template <> const char *UriToString<kUriActiveReplace>(void) { return "ActiveReplace"; }
template <> const char *UriToString<kUriActiveSet>(void) { return "ActiveSet"; }
template <> const char *UriToString<kUriCommissionerKeepAlive>(void) { return "CommissionerKeepAlive"; }
template <> const char *UriToString<kUriCommissionerGet>(void) { return "CommissionerGet"; }
template <> const char *UriToString<kUriCommissionerPetition>(void) { return "CommissionerPetition"; }
template <> const char *UriToString<kUriCommissionerSet>(void) { return "CommissionerSet"; }
template <> const char *UriToString<kUriDatasetChanged>(void) { return "DatasetChanged"; }
template <> const char *UriToString<kUriEnergyReport>(void) { return "EnergyReport"; }
template <> const char *UriToString<kUriEnergyScan>(void) { return "EnergyScan"; }
template <> const char *UriToString<kUriJoinerEntrust>(void) { return "JoinerEntrust"; }
template <> const char *UriToString<kUriJoinerFinalize>(void) { return "JoinerFinalize"; }
template <> const char *UriToString<kUriLeaderKeepAlive>(void) { return "LeaderKeepAlive"; }
template <> const char *UriToString<kUriLeaderPetition>(void) { return "LeaderPetition"; }
template <> const char *UriToString<kUriEnrollerJoinerAccept>(void) { return "EnrollerJoinerAccept"; }
template <> const char *UriToString<kUriEnrollerKeepAlive>(void) { return "EnrollerKeepAlive"; }
template <> const char *UriToString<kUriEnrollerJoinerRelease>(void) { return "EnrollerJoinerRelease"; }
template <> const char *UriToString<kUriEnrollerRegister>(void) { return "EnrollerRegister"; }
template <> const char *UriToString<kUriEnrollerReportState>(void) { return "EnrollerReportState"; }
template <> const char *UriToString<kUriPanIdConflict>(void) { return "PanIdConflict"; }
template <> const char *UriToString<kUriPendingGet>(void) { return "PendingGet"; }
template <> const char *UriToString<kUriPanIdQuery>(void) { return "PanIdQuery"; }
template <> const char *UriToString<kUriPendingSet>(void) { return "PendingSet"; }
template <> const char *UriToString<kUriRelayRx>(void) { return "RelayRx"; }
template <> const char *UriToString<kUriTcatEnable>(void) { return "TcatEnable"; }
template <> const char *UriToString<kUriRelayTx>(void) { return "RelayTx"; }
template <> const char *UriToString<kUriProxyRx>(void) { return "ProxyRx"; }
template <> const char *UriToString<kUriProxyTx>(void) { return "ProxyTx"; }
template <> const char *UriToString<kUriDiagnosticGetAnswer>(void) { return "DiagGetAnswer"; }
template <> const char *UriToString<kUriDiagnosticGetRequest>(void) { return "DiagGetRequest"; }
template <> const char *UriToString<kUriDiagnosticGetQuery>(void) { return "DiagGetQuery"; }
template <> const char *UriToString<kUriDiagnosticReset>(void) { return "DiagReset"; }
template <> const char *UriToString<kUriHistoryAnswer>(void) { return "HistAnswer"; }
template <> const char *UriToString<kUriHistoryQuery>(void) { return "HistQuery"; }
template <> const char *UriToString<kUriDuaRegistrationNotify>(void) { return "DuaRegNotify"; }
template <> const char *UriToString<kUriDuaRegistrationRequest>(void) { return "DuaRegRequest"; }
template <> const char *UriToString<kUriMlr>(void) { return "Mlr"; }
#define _DefineUriToString(kPathString, kUri, kName) \
template <> const char *UriToString<kUri>(void) { return kName; }
UriEntryMapList(_DefineUriToString)
} // namespace ot