@@ -59,7 +59,7 @@ void HistogramRegistry::setHash(uint32_t hash)
5959// create histogram from specification and insert it into the registry
6060HistPtr HistogramRegistry::insert (const HistogramSpec& histSpec)
6161{
62- validateHistName (histSpec.name . data () , histSpec.hash );
62+ validateHistName (histSpec.name , histSpec.hash );
6363 const uint32_t idx = imask (histSpec.hash );
6464 for (auto i = 0u ; i < MAX_REGISTRY_SIZE; ++i) {
6565 TObject* rawPtr = nullptr ;
@@ -77,7 +77,7 @@ HistPtr HistogramRegistry::insert(const HistogramSpec& histSpec)
7777}
7878
7979// helper function that checks if histogram name can be used in registry
80- void HistogramRegistry::validateHistName (const char * name, const uint32_t hash)
80+ void HistogramRegistry::validateHistName (const std::string& name, const uint32_t hash)
8181{
8282 // validate that hash is unique
8383 auto it = std::find (mRegistryKey .begin (), mRegistryKey .end (), hash);
@@ -87,13 +87,11 @@ void HistogramRegistry::validateHistName(const char* name, const uint32_t hash)
8787 std::visit ([&](const auto & hist) { collidingName = hist->GetName (); }, mRegistryValue [idx]);
8888 LOGF (FATAL, R"( Hash collision in HistogramRegistry "%s"! Please rename histogram "%s" or "%s".)" , mName , name, collidingName);
8989 }
90+
9091 // validate that name contains only allowed characters
91- /*
92- TODO: exactly determine constraints for valid histogram names
93- if (!std::regex_match(name, std::regex("[A-Za-z0-9\-_/]+"))) {
92+ if (!std::regex_match (name, std::regex (" ([a-zA-Z0-9])(([\\ /_])?[a-zA-Z0-9])*" ))) {
9493 LOGF (FATAL, R"( Histogram name "%s" contains invalid characters.)" , name);
9594 }
96- */
9795}
9896
9997HistPtr HistogramRegistry::add (const HistogramSpec& histSpec)
@@ -239,7 +237,6 @@ void HistogramRegistry::print(bool showAxisDetails)
239237 LOGF (INFO, " " );
240238 LOGF (INFO, " %s" , titleString);
241239 LOGF (INFO, " %s\" %s\" " , std::string ((int )(0.5 * titleString.size () - (1 + 0.5 * mName .size ())), ' ' ), mName );
242- std::sort (mRegisteredNames .begin (), mRegisteredNames .end ());
243240 for (auto & curHistName : mRegisteredNames ) {
244241 std::visit (printHistInfo, mRegistryValue [getHistIndex (HistName{curHistName.data ()})]);
245242 }
@@ -269,9 +266,17 @@ TList* HistogramRegistry::operator*()
269266 TList* list = new TList ();
270267 list->SetName (mName .data ());
271268
272- for (auto i = 0u ; i < MAX_REGISTRY_SIZE; ++i) {
269+ if (mSortHistos ) {
270+ auto caseInsensitiveCompare = [](const std::string& s1, const std::string& s2) {
271+ return std::lexicographical_compare (s1.begin (), s1.end (), s2.begin (), s2.end (),
272+ [](char c1, char c2) { return std::tolower (static_cast <unsigned char >(c1)) < std::tolower (static_cast <unsigned char >(c2)); });
273+ };
274+ std::sort (mRegisteredNames .begin (), mRegisteredNames .end (), caseInsensitiveCompare);
275+ }
276+
277+ for (auto & curHistName : mRegisteredNames ) {
273278 TNamed* rawPtr = nullptr ;
274- std::visit ([&](const auto & sharedPtr) { rawPtr = (TNamed*)sharedPtr.get (); }, mRegistryValue [i ]);
279+ std::visit ([&](const auto & sharedPtr) { rawPtr = (TNamed*)sharedPtr.get (); }, mRegistryValue [getHistIndex (HistName{curHistName. data ()}) ]);
275280 if (rawPtr) {
276281 std::deque<std::string> path = splitPath (rawPtr->GetName ());
277282 std::string name = path.back ();
@@ -286,29 +291,25 @@ TList* HistogramRegistry::operator*()
286291 }
287292 }
288293
289- // sort histograms in output file alphabetically
290- if (mSortHistos ) {
291- std::function<void (TList*)> sortList;
292- sortList = [&](TList* list) {
293- list->Sort ();
294- TIter next (list);
295- TNamed* subList = nullptr ;
296- std::vector<TObject*> subLists;
297- while ((subList = (TNamed*)next ())) {
298- if (subList->InheritsFrom (TList::Class ())) {
299- subLists.push_back (subList);
300- sortList ((TList*)subList);
301- }
302- }
303- // place lists always at the top
304- std::reverse (subLists.begin (), subLists.end ());
305- for (auto curList : subLists) {
306- list->Remove (curList);
307- list->AddFirst (curList);
294+ // place lists always at the top
295+ std::function<void (TList*)> moveListsToTop;
296+ moveListsToTop = [&](TList* list) {
297+ TIter next (list);
298+ TNamed* subList = nullptr ;
299+ std::vector<TObject*> subLists;
300+ while ((subList = (TNamed*)next ())) {
301+ if (subList->InheritsFrom (TList::Class ())) {
302+ subLists.push_back (subList);
303+ moveListsToTop ((TList*)subList);
308304 }
309- };
310- sortList (list);
311- }
305+ }
306+ std::reverse (subLists.begin (), subLists.end ());
307+ for (auto curList : subLists) {
308+ list->Remove (curList);
309+ list->AddFirst (curList);
310+ }
311+ };
312+ moveListsToTop (list);
312313
313314 // create dedicated directory containing all of the registrys histograms
314315 if (mCreateRegistryDir ) {
0 commit comments