Codebase list facter / f28729a
(CFACT-65) Replace RE2 with boost::regex Removes dependency on RE2. Uses an adapter class and function to abstract regular expression calls so it's easier to modify or switch packages if necessary (for speed or Unicode support), and simplify the call interface. Michael Smith 9 years ago
16 changed file(s) with 132 addition(s) and 113 deletion(s). Raw diff Collapse all Expand all
2020 - wget https://github.com/doxygen/doxygen/archive/Release_1_8_7.tar.gz -O $HOME/doxygen-1.8.7.tgz
2121 - pushd $HOME && tar xzf doxygen-1.8.7.tgz && cd $HOME/doxygen-Release_1_8_7 && ./configure > /dev/null && make > /dev/null && sudo make install > /dev/null && popd
2222 # Install dependencies of cfacter
23 - sudo apt-get -y install libboost-filesystem1.48-dev libboost-program-options1.48-dev liblog4cxx10-dev
24 - wget https://re2.googlecode.com/files/re2-20140304.tgz -O $HOME/re2-20140304.tgz
25 - pushd $HOME && tar xzf re2-20140304.tgz && cd $HOME/re2 && make > /dev/null && sudo make install > /dev/null && popd
23 - sudo apt-get -y install libboost-filesystem1.48-dev libboost-program-options1.48-dev libboost-regex1.48-dev liblog4cxx10-dev
2624 - wget https://yaml-cpp.googlecode.com/files/yaml-cpp-0.5.1.tar.gz -O $HOME/yaml-cpp-0.5.1.tgz
2725 - pushd $HOME && tar xzf yaml-cpp-0.5.1.tgz && cd $HOME/yaml-cpp-0.5.1 && cmake -DBUILD_SHARED_LIBS=ON . && make > /dev/null && sudo make install > /dev/null && popd
2826
1717 endif()
1818
1919 # Find our dependency packages
20 find_package(Boost 1.48 REQUIRED COMPONENTS program_options system filesystem)
20 find_package(Boost 1.48 REQUIRED COMPONENTS program_options system filesystem regex)
2121 find_package(LOG4CXX REQUIRED)
22 find_package(RE2 REQUIRED)
2322 find_package(OPENSSL REQUIRED)
2423 find_package(YAMLCPP REQUIRED)
2524
6564 "-readability/todo" # Seriously? todo comments need to identify an owner? pffft
6665 "-whitespace/empty_loop_body" # Can't handle do { ... } while(expr);
6766 "-runtime/int" # Some C types are needed for library interop
67 "-runtime/explicit" # Using implicit conversion from string to regex for regex calls.
6868 )
6969
7070 file(GLOB_RECURSE ALL_SOURCES lib/*.cc lib/*.h lib/*.hpp exe/*.cc exe/*.h exe/*.hpp)
1414 * Apache log4cxx >= 10.0
1515 * OpenSSL >= 1.0.1.g
1616 * yaml-cpp >= 0.5.1
17 * Google's RE2 library
1817
1918 ### Setup on Fedora 20
2019
2120 The following will install all required tools and libraries:
2221
23 yum install cmake boost-devel log4cxx-devel openssl-devel yaml-cpp-devel re2-devel
22 yum install cmake boost-devel log4cxx-devel openssl-devel yaml-cpp-devel
2423
2524 ### Setup on Mac OSX Mavericks (homebrew)
2625
2827
2928 The following will install all required libraries:
3029
31 brew install cmake boost log4cxx yaml-cpp re2
30 brew install cmake boost log4cxx yaml-cpp
3231
3332 ### Setup on Ubuntu 14.04 (Trusty)
3433
3635
3736 apt-get install build-essential cmake libboost-all-dev liblog4cxx10-dev libssl-dev libyaml-cpp-dev
3837
39 Google's RE2 library will need to be installed from source.
4038
4139 Pre-Build
4240 ---------
+0
-55
cmake/FindRE2.cmake less more
0 ################################################################################
1 #
2 # CMake script for finding RE2.
3 # The default CMake search process is used to locate files.
4 #
5 # This script creates the following variables:
6 # RE2_FOUND: Boolean that indicates if the package was found
7 # RE2_INCLUDE_DIRS: Paths to the necessary header files
8 # RE2_LIBRARIES: Package libraries
9 # RE2_LIBRARY_DIRS: Path to package libraries
10 #
11 ################################################################################
12
13 include(FindPackageHandleStandardArgs)
14
15 # See if RE2_ROOT is not already set in CMake
16 if (NOT RE2_ROOT)
17 # See if RE2_ROOT is set in process environment
18 if (NOT $ENV{RE2_ROOT} STREQUAL "")
19 set(RE2_ROOT "$ENV{RE2_ROOT}")
20 message(STATUS "Detected RE2_ROOT set to '${RE2_ROOT}'")
21 endif()
22 endif()
23
24 # If RE2_ROOT is available, set up our hints
25 if (RE2_ROOT)
26 set(RE2_INCLUDE_HINTS HINTS "${RE2_ROOT}/include" "${RE2_ROOT}")
27 set(RE2_LIBRARY_HINTS HINTS "${RE2_ROOT}/lib")
28 endif()
29
30 # Find headers and libraries
31 find_path(RE2_INCLUDE_DIR NAMES re2/re2.h ${RE2_INCLUDE_HINTS})
32 find_library(RE2_LIBRARY NAMES re2 ${RE2_LIBRARY_HINTS})
33
34 # Set RE2_FOUND honoring the QUIET and REQUIRED arguments
35 find_package_handle_standard_args(RE2 DEFAULT_MSG RE2_LIBRARY RE2_INCLUDE_DIR)
36
37 # Output variables
38 if (RE2_FOUND)
39 # Include dirs
40 set(RE2_INCLUDE_DIRS ${RE2_INCLUDE_DIR})
41
42 # Libraries
43 if(RE2_LIBRARY)
44 set(RE2_LIBRARIES ${RE2_LIBRARY})
45 else()
46 set(RE2_LIBRARIES "")
47 endif()
48
49 # Link dirs
50 get_filename_component(RE2_LIBRARY_DIRS ${RE2_LIBRARY} PATH)
51 endif()
52
53 # Advanced options for not cluttering the cmake UIs
54 mark_as_advanced(RE2_INCLUDE_DIR RE2_LIBRARY)
2020 depends_on "log4cxx"
2121 depends_on "openssl"
2222 depends_on "yaml-cpp"
23 depends_on "re2"
2423
2524 def install
2625 system "cmake", ".", *std_cmake_args
9797 # Set include directories
9898 include_directories(
9999 inc
100 ${RE2_INCLUDE_DIRS}
101100 ${RAPIDJSON_INCLUDE_DIRS}
102101 ${LOG4CXX_INCLUDE_DIRS}
103102 ${Boost_INCLUDE_DIRS}
119118 # Link in additional libraries
120119 target_link_libraries(libfacter
121120 ${THREAD_LIBS}
122 ${RE2_LIBRARIES}
123121 ${LOG4CXX_LIBRARIES}
124122 ${Boost_LIBRARIES}
125123 ${OPENSSL_LIBRARIES}
88 #include <memory>
99 #include <stdexcept>
1010 #include <string>
11
12 // Forward declare RE2 so users of this header don't have to include re2
13 namespace re2 {
14 class RE2;
15 }
11 #include <facter/util/regex.hpp>
1612
1713 namespace facter { namespace facts {
1814
129125 private:
130126 std::string _name;
131127 std::vector<std::string> _names;
132 std::vector<std::unique_ptr<re2::RE2>> _regexes;
128 std::vector<std::unique_ptr<facter::util::re_adapter>> _regexes;
133129 bool _resolving;
134130 };
135131
0 /**
1 * @file
2 * Defines an abstraction for using regular expression calls.
3 * It should be extended when new match methods are needed, and allows easily
4 * switching between regex libraries.
5 */
6 #ifndef FACTER_UTIL_REGEX_HPP_
7 #define FACTER_UTIL_REGEX_HPP_
8
9 #ifdef USE_RE2
10 #include <re2/re2.h>
11 #else
12 #include <boost/regex.hpp>
13 #include <boost/lexical_cast.hpp>
14 #endif
15
16 namespace facter { namespace util {
17 #ifdef USE_RE2
18 using re_adapter = re2::RE2;
19
20 template <typename... Args>
21 inline bool re_search(const re2::StringPiece &txt, const re2::RE2 &r, Args&&... args)
22 {
23 return re2::RE2::PartialMatch(txt, r, std::forward<Args>(args)...);
24 }
25 #else
26 class re_adapter : public boost::regex {
27 std::string _err;
28 public:
29 re_adapter(const char* pattern) try : boost::regex(pattern)
30 {
31 } catch (const boost::regex_error &e) {
32 _err = e.what();
33 }
34
35 re_adapter(const std::string &pattern) try : boost::regex(pattern)
36 {
37 } catch (const boost::regex_error &e) {
38 _err = e.what();
39 }
40
41 const std::string& error() const { return _err; }
42 bool ok() const { return error().empty(); }
43 };
44
45 template <typename Text>
46 inline bool re_search_helper(Text &txt, const boost::smatch &what, size_t depth)
47 {
48 return true;
49 }
50
51 template <typename Text, typename Arg, typename... Args>
52 inline bool re_search_helper(Text &txt, const boost::smatch &what, size_t depth, Arg arg, Args&&... args)
53 {
54 if (depth >= what.size()) {
55 return false;
56 }
57
58 try {
59 using ArgType = typename std::pointer_traits<Arg>::element_type;
60 auto val = boost::lexical_cast<ArgType>(what[depth]);
61 *arg = val;
62 } catch (const boost::bad_lexical_cast &e) {
63 return false;
64 }
65
66 return re_search_helper(txt, what, depth+1, std::forward<Args>(args)...);
67 }
68
69 template <typename Text, typename... Args>
70 inline bool re_search(Text &txt, const re_adapter &r, Args&&... args)
71 {
72 if (!r.ok()) {
73 return false;
74 }
75
76 boost::smatch what;
77 if (!boost::regex_search(txt, what, r)) {
78 return false;
79 }
80
81 return re_search_helper(txt, what, 1, std::forward<Args>(args)...);
82 }
83 #endif
84
85 }} // namespace facter::util
86
87 #endif // FACTER_UTIL_REGEX_HPP_
88
33 #include <facter/facts/scalar_value.hpp>
44 #include <facter/execution/execution.hpp>
55 #include <facter/util/string.hpp>
6 #include <re2/re2.h>
6 #include <facter/util/regex.hpp>
77
88 using namespace std;
99 using namespace facter::util;
8383 }
8484 string major;
8585 string minor;
86 if (!RE2::PartialMatch(dist_release->value(), "(\\d+)\\.(\\d*)", &major, &minor)) {
86 if (!re_search(dist_release->value(), "(\\d+)\\.(\\d*)", &major, &minor)) {
8787 major = dist_release->value();
8888 }
8989 facts.add(fact::lsb_dist_major_release, make_value<string_value>(move(major)));
77 #include <facter/execution/execution.hpp>
88 #include <facter/util/string.hpp>
99 #include <facter/util/file.hpp>
10 #include <re2/re2.h>
10 #include <facter/util/regex.hpp>
1111 #include <boost/filesystem.hpp>
1212 #include <map>
1313 #include <vector>
9797 if (ends_with(contents, "(Rawhide)")) {
9898 value = "Rawhide";
9999 } else {
100 RE2::PartialMatch(contents, "release (\\d[\\d.]*)", &value);
100 re_search(contents, "release (\\d[\\d.]*)", &value);
101101 }
102102 }
103103
120120 string contents = file::read(release_file::suse);
121121 string major;
122122 string minor;
123 if (RE2::PartialMatch(contents, "(?m)^VERSION\\s*=\\s*(\\d+)\\.?(\\d+)?", &major, &minor)) {
123 if (re_search(contents, "(?m)^VERSION\\s*=\\s*(\\d+)\\.?(\\d+)?", &major, &minor)) {
124124 // Check that we have a minor version; if not, use the patch level
125125 if (minor.empty()) {
126 if (!RE2::PartialMatch(contents, "(?m)^PATCHLEVEL\\s*=\\s*(\\d+)", &minor)) {
126 if (!re_search(contents, "(?m)^PATCHLEVEL\\s*=\\s*(\\d+)", &minor)) {
127127 minor = "0";
128128 }
129129 }
164164 }
165165 if (file) {
166166 string contents = file::read(file);
167 RE2::PartialMatch(contents, regex, &value);
167 re_search(contents, regex, &value);
168168 }
169169 }
170170
172172 if (value.empty() && operating_system->value() == os::vmware_esx) {
173173 auto result = execute("vmware", { "-v" });
174174 if (result.first) {
175 RE2::PartialMatch(result.second, "VMware ESX .*?(\\d.*)", &value);
175 re_search(result.second, "VMware ESX .*?(\\d.*)", &value);
176176 }
177177 }
178178
232232 if (is_regular_file(release_file::os, ec)) {
233233 string contents = trim(file::read(release_file::os));
234234 string release;
235 if (RE2::PartialMatch(contents, "(?m)^NAME=[\"']?(.+?)[\"']?$", &release)) {
235 if (re_search(contents, "(?m)^NAME=[\"']?(.+?)[\"']?$", &release)) {
236236 if (release == "Cumulus Linux") {
237237 return os::cumulus;
238238 }
286286
287287 string contents = trim(file::read(release_file::redhat));
288288 for (auto const& regex : regexs) {
289 if (RE2::PartialMatch(contents, get<0>(regex))) {
289 if (re_search(contents, get<0>(regex))) {
290290 return get<1>(regex);
291291 }
292292 }
307307
308308 string contents = trim(file::read(release_file::suse));
309309 for (auto const& regex : regexs) {
310 if (RE2::PartialMatch(contents, get<0>(regex))) {
310 if (re_search(contents, get<0>(regex))) {
311311 return get<1>(regex);
312312 }
313313 }
77 #include <facter/util/file.hpp>
88 #include <facter/util/directory.hpp>
99 #include <boost/filesystem.hpp>
10 #include <re2/re2.h>
10 #include <facter/util/regex.hpp>
1111 #include <unordered_set>
1212
1313 using namespace std;
14 using namespace re2;
1514 using namespace facter::facts;
1615 using namespace facter::facts::posix;
1716 using namespace facter::util;
4746 value = "amd64";
4847 }
4948 // For 32-bit, use "x86" for Gentoo and "i386" for everyone else
50 } else if (RE2::PartialMatch(model->value(), "i[3456]86|pentium")) {
49 } else if (re_search(model->value(), "i[3456]86|pentium")) {
5150 if (os->value() == os::gentoo) {
5251 value = "x86";
5352 } else {
22 #include <facter/facts/fact.hpp>
33 #include <facter/facts/scalar_value.hpp>
44 #include <facter/util/file.hpp>
5 #include <re2/re2.h>
5 #include <facter/util/regex.hpp>
66
77 using namespace std;
88 using namespace facter::util;
8181 }
8282
8383 string mode;
84 if (RE2::PartialMatch(buffer, "(?m)^SELINUX=(\\w+)$" , &mode)) {
84 if (re_search(buffer, "(?m)^SELINUX=(\\w+)$", &mode)) {
8585 facts.add(fact::selinux_config_mode, make_value<string_value>(move(mode)));
8686 }
8787
8888 string type;
89 if (RE2::PartialMatch(buffer, "(?m)^SELINUXTYPE=(\\w+)$" , &type)) {
89 if (re_search(buffer, "(?m)^SELINUXTYPE=(\\w+)$", &type)) {
9090 facts.add(fact::selinux_config_policy, make_value<string_value>(move(type)));
9191 }
9292 }
9393
9494 bool selinux_resolver::get_selinux_mountpoint(string& selinux_mount)
9595 {
96 RE2 regexp("\\S+ (\\S+) selinuxfs");
96 re_adapter regexp("\\S+ (\\S+) selinuxfs");
9797 bool is_mounted = false;
9898 file::each_line("/proc/self/mounts", [&](string& line) {
9999 string mountpoint;
100 if (RE2::PartialMatch(line, regexp, &mountpoint)) {
100 if (re_search(line, regexp, &mountpoint)) {
101101 selinux_mount = mountpoint;
102102 is_mounted = true;
103103 return false;
66 #include <facter/facts/posix/uptime_resolver.hpp>
77 #include <facter/util/file.hpp>
88 #include <facter/util/string.hpp>
9 #include <re2/re2.h>
9 #include <facter/util/regex.hpp>
1010
1111 using namespace std;
1212 using namespace facter::util;
119119
120120 int days, hours, minutes;
121121
122 if (RE2::PartialMatch(output, "(\\d+) day(?:s|\\(s\\))?,\\s+(\\d+):(\\d+)", &days, &hours, &minutes)) {
122 if (re_search(output, "(\\d+) day(?:s|\\(s\\))?,\\s+(\\d+):(\\d+)", &days, &hours, &minutes)) {
123123 return 86400 * days + 3600 * hours + 60 * minutes;
124 } else if (RE2::PartialMatch(output, "(\\d+) day(?:s|\\(s\\))?,\\s+(\\d+) hr(?:s|\\(s\\))?,", &days, &hours)) {
124 } else if (re_search(output, "(\\d+) day(?:s|\\(s\\))?,\\s+(\\d+) hr(?:s|\\(s\\))?,", &days, &hours)) {
125125 return 86400 * days + 3600 * hours;
126 } else if (RE2::PartialMatch(output, "(\\d+) day(?:s|\\(s\\))?,\\s+(\\d+) min(?:s|\\(s\\))?,", &days, &minutes)) {
126 } else if (re_search(output, "(\\d+) day(?:s|\\(s\\))?,\\s+(\\d+) min(?:s|\\(s\\))?,", &days, &minutes)) {
127127 return 86400 * days + 60 * minutes;
128 } else if (RE2::PartialMatch(output, "(\\d+) day(?:s|\\(s\\))?,", &days)) {
128 } else if (re_search(output, "(\\d+) day(?:s|\\(s\\))?,", &days)) {
129129 return 86400 * days;
130 } else if (RE2::PartialMatch(output, "up\\s+(\\d+):(\\d+),", &hours, &minutes)) {
130 } else if (re_search(output, "up\\s+(\\d+):(\\d+),", &hours, &minutes)) {
131131 return 3600 * hours + 60 * minutes;
132 } else if (RE2::PartialMatch(output, "(\\d+) hr(?:s|\\(s\\))?,", &hours)) {
132 } else if (re_search(output, "(\\d+) hr(?:s|\\(s\\))?,", &hours)) {
133133 return 3600 * hours;
134 } else if (RE2::PartialMatch(output, "(\\d+) min(?:s|\\(s\\))?,", &minutes)) {
134 } else if (re_search(output, "(\\d+) min(?:s|\\(s\\))?,", &minutes)) {
135135 return 60 * minutes;
136136 } else {
137137 return 0;
00 #include <facter/facts/resolver.hpp>
11 #include <facter/facts/collection.hpp>
22 #include <facter/logging/logging.hpp>
3 #include <re2/re2.h>
3 #include <facter/util/regex.hpp>
44
55 using namespace std;
6 using namespace re2;
76
87 LOG_DECLARE_NAMESPACE("facts.resolver");
98
4241 _resolving(false)
4342 {
4443 for (auto const& pattern : patterns) {
45 auto regex = unique_ptr<RE2>(new RE2(pattern));
44 auto regex = unique_ptr<util::re_adapter>(new util::re_adapter(pattern));
4645 if (!regex->error().empty()) {
4746 throw invalid_name_pattern_exception(regex->error());
4847 }
9089 {
9190 // Check to see if any of our regexes match
9291 for (auto const& regex : _regexes) {
93 if (RE2::PartialMatch(name, *regex)) {
92 if (re_search(name, *regex)) {
9493 return true;
9594 }
9695 }
00 #include <facter/util/directory.hpp>
11 #include <boost/filesystem.hpp>
2 #include <re2/re2.h>
2 #include <facter/util/regex.hpp>
33
44 using namespace std;
5 using namespace re2;
65 using namespace boost::filesystem;
76
87 namespace facter { namespace util {
98
109 void directory::each_file(string const& directory, function<bool(string const&)> callback, string const& pattern)
1110 {
12 RE2 regex(pattern);
11 re_adapter regex(pattern);
1312 if (!regex.ok()) {
1413 return;
1514 }
2827 if (!is_regular_file(it->status(ec))) {
2928 continue;
3029 }
31 if (RE2::PartialMatch(it->path().filename().string(), regex)) {
30 if (re_search(it->path().filename().string(), regex)) {
3231 if (!callback(it->path().string())) {
3332 break;
3433 }
3837
3938 void directory::each_subdirectory(string const& directory, function<bool(string const&)> callback, string const& pattern)
4039 {
41 RE2 regex(pattern);
40 re_adapter regex(pattern);
4241 if (!regex.ok()) {
4342 return;
4443 }
5756 if (!is_directory(it->status(ec))) {
5857 continue;
5958 }
60 if (RE2::PartialMatch(it->path().filename().string(), regex)) {
59 if (re_search(it->path().filename().string(), regex)) {
6160 if (!callback(it->path().string())) {
6261 break;
6362 }
55 #include <facter/util/string.hpp>
66 #include <log4cxx/logger.h>
77 #include <log4cxx/appenderskeleton.h>
8 #include <re2/re2.h>
8 #include <facter/util/regex.hpp>
99 #include <boost/algorithm/string/replace.hpp>
1010 #include <memory>
1111 #include <tuple>
2121 using namespace facter::util;
2222 using namespace facter::testing;
2323 using namespace log4cxx;
24 using namespace re2;
2524 using testing::ElementsAre;
2625
2726 struct ruby_log_appender : AppenderSkeleton
236235 ASSERT_EQ(expected_messages.size(), messages.size());
237236 for (size_t i = 0; i < expected_messages.size(); ++i) {
238237 ASSERT_EQ(expected_messages[i].first, messages[i].first);
239 ASSERT_TRUE(RE2::PartialMatch(messages[i].second, expected_messages[i].second));
238 ASSERT_TRUE(re_search(messages[i].second, expected_messages[i].second));
240239 }
241240 return;
242241 }