diff --git a/Changelog.md b/Changelog.md index e30c7f297..ad610972b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -30,6 +30,9 @@ 1. Evict large function definitions from the Helpers.hh header file. * [Pull request 288](https://github.com/ignitionrobotics/ign-math/pull/288) +1. Defer regex construction to avoid static initialization. + * [Pull request 289](https://github.com/ignitionrobotics/ign-math/pull/289) + 1. Remove virtual from destructors of copyable classes. * [Pull request 293](https://github.com/ignitionrobotics/ign-math/pull/293) diff --git a/src/Helpers.cc b/src/Helpers.cc index 56ed58302..ab9f760b5 100644 --- a/src/Helpers.cc +++ b/src/Helpers.cc @@ -76,32 +76,6 @@ namespace ignition return outputString.str(); } - // The following regex takes a time string in the general format of - // "dd hh:mm:ss.nnn" where n is milliseconds, if just one number is - // provided, it is assumed to be seconds - static const std::regex time_regex( - "^([0-9]+ ){0,1}" // day: - // Any positive integer - - "(?:([1-9]:|[0-1][0-9]:|2[0-3]:){0,1}" // hour: - // 1 - 9: - // 01 - 19: - // 20 - 23: - - "([0-9]:|[0-5][0-9]:)){0,1}" // minute: - // 0 - 9: - // 00 - 59: - - "(?:([0-9]|[0-5][0-9]){0,1}" // second: - // 0 - 9 - // 00 - 59 - - "(\\.[0-9]{1,3}){0,1})$"); // millisecond: - // .0 - .9 - // .00 - .99 - // .000 - 0.999 - - ///////////////////////////////////////////// bool splitTimeBasedOnTimeRegex( const std::string &_timeString, @@ -109,6 +83,33 @@ namespace ignition uint64_t & numberMinutes, uint64_t & numberSeconds, uint64_t & numberMilliseconds) { + // The following regex takes a time string in the general format of + // "dd hh:mm:ss.nnn" where n is milliseconds, if just one number is + // provided, it is assumed to be seconds. We construct upon first use + // and never destroy it, in order to avoid the [Static Initialization + // Order Fiasco](https://en.cppreference.com/w/cpp/language/siof). + static const std::regex * const kTimeRegex = new std::regex( + "^([0-9]+ ){0,1}" // day: + // Any positive integer + + "(?:([1-9]:|[0-1][0-9]:|2[0-3]:){0,1}" // hour: + // 1 - 9: + // 01 - 19: + // 20 - 23: + + "([0-9]:|[0-5][0-9]:)){0,1}" // minute: + // 0 - 9: + // 00 - 59: + + "(?:([0-9]|[0-5][0-9]){0,1}" // second: + // 0 - 9 + // 00 - 59 + + "(\\.[0-9]{1,3}){0,1})$"); // millisecond: + // .0 - .9 + // .00 - .99 + // .000 - 0.999 + std::smatch matches; // `matches` should always be a size of 6 as there are 6 matching @@ -123,7 +124,7 @@ namespace ignition // Note that the space will remain in the day match, the colon // will remain in the hour and minute matches, and the period will // remain in the millisecond match - if (!std::regex_search(_timeString, matches, time_regex) || + if (!std::regex_search(_timeString, matches, *kTimeRegex) || matches.size() != 6) return false;