Switch from std::regex to boost::regex

This commit is contained in:
Yorick van Pelt 2023-02-06 16:36:57 +01:00
parent dda0e34ecf
commit d2f5e263e3
No known key found for this signature in database
GPG key ID: D8D3CC6D951384DE
3 changed files with 41 additions and 20 deletions

View file

@ -154,7 +154,7 @@
configureFlags = configureFlags =
lib.optionals stdenv.isLinux [ lib.optionals stdenv.isLinux [
"--with-boost=${boost}/lib" "--with-boost=${boost-nix}/lib"
"--with-sandbox-shell=${sh}/bin/busybox" "--with-sandbox-shell=${sh}/bin/busybox"
] ]
++ lib.optionals (stdenv.isLinux && !(isStatic && stdenv.system == "aarch64-linux")) [ ++ lib.optionals (stdenv.isLinux && !(isStatic && stdenv.system == "aarch64-linux")) [
@ -202,7 +202,7 @@
version = libgit2.lastModifiedDate; version = libgit2.lastModifiedDate;
cmakeFlags = (attrs.cmakeFlags or []) ++ ["-DUSE_SSH=exec"]; cmakeFlags = (attrs.cmakeFlags or []) ++ ["-DUSE_SSH=exec"];
})) }))
boost boost-nix
lowdown-nix lowdown-nix
libsodium libsodium
] ]
@ -423,14 +423,14 @@
propagatedBuildInputs = propagatedDeps; propagatedBuildInputs = propagatedDeps;
disallowedReferences = [ boost ]; disallowedReferences = [ boost-nix ];
preConfigure = lib.optionalString (! currentStdenv.hostPlatform.isStatic) preConfigure = lib.optionalString (! currentStdenv.hostPlatform.isStatic)
'' ''
# Copy libboost_context so we don't get all of Boost in our closure. # Copy libboost_context so we don't get all of Boost in our closure.
# https://github.com/NixOS/nixpkgs/issues/45462 # https://github.com/NixOS/nixpkgs/issues/45462
mkdir -p $out/lib mkdir -p $out/lib
cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib cp -pd ${boost-nix}/lib/{libboost_context*,libboost_thread*,libboost_system*,libboost_regex*} $out/lib
rm -f $out/lib/*.a rm -f $out/lib/*.a
${lib.optionalString currentStdenv.hostPlatform.isLinux '' ${lib.optionalString currentStdenv.hostPlatform.isLinux ''
chmod u+w $out/lib/*.so.* chmod u+w $out/lib/*.so.*
@ -440,9 +440,9 @@
for LIB in $out/lib/*.dylib; do for LIB in $out/lib/*.dylib; do
chmod u+w $LIB chmod u+w $LIB
install_name_tool -id $LIB $LIB install_name_tool -id $LIB $LIB
install_name_tool -delete_rpath ${boost}/lib/ $LIB || true install_name_tool -delete_rpath ${boost-nix}/lib/ $LIB || true
done done
install_name_tool -change ${boost}/lib/libboost_system.dylib $out/lib/libboost_system.dylib $out/lib/libboost_thread.dylib install_name_tool -change ${boost-nix}/lib/libboost_system.dylib $out/lib/libboost_system.dylib $out/lib/libboost_thread.dylib
''} ''}
''; '';
@ -470,9 +470,13 @@
''} ''}
${lib.optionalString currentStdenv.isDarwin '' ${lib.optionalString currentStdenv.isDarwin ''
install_name_tool \ install_name_tool \
-change ${boost}/lib/libboost_context.dylib \ -change ${boost-nix}/lib/libboost_context.dylib \
$out/lib/libboost_context.dylib \ $out/lib/libboost_context.dylib \
$out/lib/libnixutil.dylib $out/lib/libnixutil.dylib
install_name_tool \
-change ${boost-nix}/lib/libboost_regex.dylib \
$out/lib/libboost_regex.dylib \
$out/lib/libnixexpr.dylib
''} ''}
''; '';
@ -495,6 +499,12 @@
meta.mainProgram = "nix"; meta.mainProgram = "nix";
}); });
boost-nix = final.boost.override {
# enableIcu arg is not yet supported
# but will be with next nixpkgs update
enableIcu = false;
};
lowdown-nix = with final; currentStdenv.mkDerivation rec { lowdown-nix = with final; currentStdenv.mkDerivation rec {
name = "lowdown-0.9.0"; name = "lowdown-0.9.0";

View file

@ -16,7 +16,7 @@ libexpr_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/lib
libexpr_LIBS = libutil libstore libfetchers libexpr_LIBS = libutil libstore libfetchers
libexpr_LDFLAGS += -lboost_context -pthread libexpr_LDFLAGS += -lboost_context -lboost_regex -pthread
ifdef HOST_LINUX ifdef HOST_LINUX
libexpr_LDFLAGS += -ldl libexpr_LDFLAGS += -ldl
endif endif

View file

@ -16,6 +16,7 @@
#include "primops.hh" #include "primops.hh"
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
#include <boost/regex.hpp>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <sys/types.h> #include <sys/types.h>
@ -24,7 +25,6 @@
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <regex>
#include <dlfcn.h> #include <dlfcn.h>
#include <cmath> #include <cmath>
@ -3885,19 +3885,30 @@ static RegisterPrimOp primop_convertHash({
.fun = prim_convertHash, .fun = prim_convertHash,
}); });
// regex aliases, switch between boost and std
using regex = boost::regex;
using regex_error = boost::regex_error;
using cmatch = boost::cmatch;
using cregex_iterator = boost::cregex_iterator;
namespace regex_constants = boost::regex_constants;
// overloaded function alias
constexpr auto regex_match = [] (auto &&...args) {
return boost::regex_match(std::forward<decltype(args)>(args)...);
};
struct RegexCache struct RegexCache
{ {
// TODO use C++20 transparent comparison when available // TODO use C++20 transparent comparison when available
std::unordered_map<std::string_view, std::regex> cache; std::unordered_map<std::string_view, regex> cache;
std::list<std::string> keys; std::list<std::string> keys;
std::regex get(std::string_view re) regex get(std::string_view re)
{ {
auto it = cache.find(re); auto it = cache.find(re);
if (it != cache.end()) if (it != cache.end())
return it->second; return it->second;
keys.emplace_back(re); keys.emplace_back(re);
return cache.emplace(keys.back(), std::regex(keys.back(), std::regex::extended)).first->second; return cache.emplace(keys.back(), regex(keys.back(), regex::extended)).first->second;
} }
}; };
@ -3917,8 +3928,8 @@ void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v)
NixStringContext context; NixStringContext context;
const auto str = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.match"); const auto str = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.match");
std::cmatch match; cmatch match;
if (!std::regex_match(str.begin(), str.end(), match, regex)) { if (!regex_match(str.begin(), str.end(), match, regex)) {
v.mkNull(); v.mkNull();
return; return;
} }
@ -3933,8 +3944,8 @@ void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v)
(v.listElems()[i] = state.allocValue())->mkString(match[i + 1].str()); (v.listElems()[i] = state.allocValue())->mkString(match[i + 1].str());
} }
} catch (std::regex_error & e) { } catch (regex_error & e) {
if (e.code() == std::regex_constants::error_space) { if (e.code() == regex_constants::error_space) {
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++ // limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
state.debugThrowLastTrace(EvalError({ state.debugThrowLastTrace(EvalError({
.msg = hintfmt("memory limit exceeded by regular expression '%s'", re), .msg = hintfmt("memory limit exceeded by regular expression '%s'", re),
@ -3997,8 +4008,8 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v)
NixStringContext context; NixStringContext context;
const auto str = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.split"); const auto str = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.split");
auto begin = std::cregex_iterator(str.begin(), str.end(), regex); auto begin = cregex_iterator(str.begin(), str.end(), regex);
auto end = std::cregex_iterator(); auto end = cregex_iterator();
// Any matches results are surrounded by non-matching results. // Any matches results are surrounded by non-matching results.
const size_t len = std::distance(begin, end); const size_t len = std::distance(begin, end);
@ -4037,8 +4048,8 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v)
assert(idx == 2 * len + 1); assert(idx == 2 * len + 1);
} catch (std::regex_error & e) { } catch (regex_error & e) {
if (e.code() == std::regex_constants::error_space) { if (e.code() == regex_constants::error_space) {
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++ // limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
state.debugThrowLastTrace(EvalError({ state.debugThrowLastTrace(EvalError({
.msg = hintfmt("memory limit exceeded by regular expression '%s'", re), .msg = hintfmt("memory limit exceeded by regular expression '%s'", re),