Commit ce7434a4 by Maarten L. Hekkelman

Make boost::regex optional

parent ad7d876d
...@@ -96,7 +96,6 @@ else() ...@@ -96,7 +96,6 @@ else()
message("Not trying to recreate SymOpTable_data.hpp since CCP4 is not defined") message("Not trying to recreate SymOpTable_data.hpp since CCP4 is not defined")
endif() endif()
# set(CMAKE_DEBUG_POSTFIX d)
if(MSVC) if(MSVC)
# make msvc standards compliant... # make msvc standards compliant...
add_compile_options(/permissive-) add_compile_options(/permissive-)
...@@ -148,11 +147,26 @@ else() ...@@ -148,11 +147,26 @@ else()
endif() endif()
# Libraries # Libraries
# Start by finding out if std:regex is usable. Note that the current
# implementation in GCC is not acceptable, it crashes on long lines.
try_run(STD_REGEX_RUNNING STD_REGEX_COMPILING
${CMAKE_CURRENT_BINARY_DIR}/test ${CMAKE_SOURCE_DIR}/cmake/test-rx.cpp)
if(STD_REGEX_RUNNING STREQUAL FAILED_TO_RUN)
message(WARNING "You are probably trying to compile using the g++ standard library which contains a crashing std::regex implementation. Will try to use boost::regex instead")
set(NEED_BOOST_REGEX ON)
endif()
set(CMAKE_THREAD_PREFER_PTHREAD) set(CMAKE_THREAD_PREFER_PTHREAD)
set(THREADS_PREFER_PTHREAD_FLAG) set(THREADS_PREFER_PTHREAD_FLAG)
find_package(Threads) find_package(Threads)
find_package(Boost 1.70.0 REQUIRED COMPONENTS system regex program_options) if(NEED_BOOST_REGEX)
find_package(Boost 1.70.0 REQUIRED COMPONENTS system regex)
endif()
find_package(gxrio REQUIRED) find_package(gxrio REQUIRED)
include(FindFilesystem) include(FindFilesystem)
...@@ -170,11 +184,8 @@ if(CIFPP_RECREATE_SYMOP_DATA) ...@@ -170,11 +184,8 @@ if(CIFPP_RECREATE_SYMOP_DATA)
# The tool to create the table # The tool to create the table
add_executable(symop-map-generator "${CMAKE_SOURCE_DIR}/tools/symop-map-generator.cpp") add_executable(symop-map-generator "${CMAKE_SOURCE_DIR}/tools/symop-map-generator.cpp")
target_link_libraries(symop-map-generator Threads::Threads ${Boost_LIBRARIES} ${CIFPP_REQUIRED_LIBRARIES}) target_link_libraries(symop-map-generator Threads::Threads
Boost::regex Boost::program_options ${CIFPP_REQUIRED_LIBRARIES})
if(Boost_INCLUDE_DIR)
target_include_directories(symop-map-generator PUBLIC ${Boost_INCLUDE_DIR})
endif()
set($ENV{CLIBD} ${CLIBD}) set($ENV{CLIBD} ${CLIBD})
...@@ -250,6 +261,10 @@ set(project_headers ...@@ -250,6 +261,10 @@ set(project_headers
add_library(cifpp ${project_sources} ${project_headers} ${CMAKE_SOURCE_DIR}/src/structure/SymOpTable_data.hpp) add_library(cifpp ${project_sources} ${project_headers} ${CMAKE_SOURCE_DIR}/src/structure/SymOpTable_data.hpp)
set_target_properties(cifpp PROPERTIES POSITION_INDEPENDENT_CODE ON) set_target_properties(cifpp PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(NEED_BOOST_REGEX)
target_compile_definitions(cifpp PUBLIC USE_BOOST_REGEX=1)
endif()
target_include_directories(cifpp target_include_directories(cifpp
PUBLIC PUBLIC
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>" "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
......
// See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164
#include <iostream>
#include <regex>
int main()
{
std::string s(100'000, '*');
std::smatch m;
std::regex r("^(.*?)$");
std::regex_search(s, m, r);
std::cout << s.substr(0, 10) << std::endl;
std::cout << m.str(1).substr(0, 10) << std::endl;
return 0;
}
...@@ -27,12 +27,9 @@ ...@@ -27,12 +27,9 @@
#pragma once #pragma once
#include <filesystem> #include <filesystem>
#include <list>
#include <mutex> #include <mutex>
// duh.. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164
// #include <regex>
#include <boost/regex.hpp>
#include <cif++/utilities.hpp> #include <cif++/utilities.hpp>
namespace cif namespace cif
...@@ -63,12 +60,36 @@ enum class DDL_PrimitiveType ...@@ -63,12 +60,36 @@ enum class DDL_PrimitiveType
DDL_PrimitiveType map_to_primitive_type(std::string_view s); DDL_PrimitiveType map_to_primitive_type(std::string_view s);
struct regex_impl;
struct type_validator struct type_validator
{ {
std::string m_name; std::string m_name;
DDL_PrimitiveType m_primitive_type; DDL_PrimitiveType m_primitive_type;
// std::regex m_rx; regex_impl *m_rx;
boost::regex m_rx;
type_validator() = delete;
type_validator(std::string_view name, DDL_PrimitiveType type, std::string_view rx);
type_validator(const type_validator &) = delete;
type_validator(type_validator &&rhs)
: m_name(std::move(rhs.m_name))
, m_primitive_type(rhs.m_primitive_type)
{
m_rx = std::exchange(rhs.m_rx, nullptr);
}
type_validator &operator=(const type_validator &) = delete;
type_validator &operator=(type_validator &&rhs)
{
m_name = std::move(rhs.m_name);
m_primitive_type = rhs.m_primitive_type;
m_rx = std::exchange(rhs.m_rx, nullptr);
return *this;
}
~type_validator();
bool operator<(const type_validator &rhs) const bool operator<(const type_validator &rhs) const
{ {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -450,7 +450,7 @@ class dictionary_parser : public parser ...@@ -450,7 +450,7 @@ class dictionary_parser : public parser
try try
{ {
type_validator v = { type_validator v = {
code, map_to_primitive_type(primitiveCode), boost::regex(construct, boost::regex::extended | boost::regex::optimize)}; code, map_to_primitive_type(primitiveCode), construct};
m_validator.add_type_validator(std::move(v)); m_validator.add_type_validator(std::move(v));
} }
......
...@@ -28,7 +28,20 @@ ...@@ -28,7 +28,20 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <gzstream/gzstream.hpp> // The validator depends on regular expressions. Unfortunately,
// the implementation of std::regex in g++ is buggy and crashes
// on reading the pdbx dictionary. Therefore, in case g++ is used
// the code will use boost::regex instead.
#if USE_BOOST_REGEX
#include <boost/regex.hpp>
using boost::regex;
#else
#include <regex>
using std::regex;
#endif
#include <gxrio.hpp>
#include <cif++/cif/dictionary_parser.hpp> #include <cif++/cif/dictionary_parser.hpp>
#include <cif++/cif/validate.hpp> #include <cif++/cif/validate.hpp>
...@@ -37,13 +50,14 @@ ...@@ -37,13 +50,14 @@
namespace cif namespace cif
{ {
extern int VERBOSE;
}
namespace cif struct regex_impl : public regex
{ {
regex_impl(std::string_view rx)
using cif::VERBOSE; : regex(rx.begin(), rx.end(), regex::extended | regex::optimize)
{
}
};
validation_error::validation_error(const std::string &msg) validation_error::validation_error(const std::string &msg)
: m_msg(msg) : m_msg(msg)
...@@ -73,6 +87,18 @@ DDL_PrimitiveType map_to_primitive_type(std::string_view s) ...@@ -73,6 +87,18 @@ DDL_PrimitiveType map_to_primitive_type(std::string_view s)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
type_validator::type_validator(std::string_view name, DDL_PrimitiveType type, std::string_view rx)
: m_name(name)
, m_primitive_type(type)
, m_rx(new regex_impl(rx))
{
}
type_validator::~type_validator()
{
delete m_rx;
}
int type_validator::compare(std::string_view a, std::string_view b) const int type_validator::compare(std::string_view a, std::string_view b) const
{ {
int result = 0; int result = 0;
...@@ -191,7 +217,7 @@ void item_validator::operator()(std::string_view value) const ...@@ -191,7 +217,7 @@ void item_validator::operator()(std::string_view value) const
{ {
if (not value.empty() and value != "?" and value != ".") if (not value.empty() and value != "?" and value != ".")
{ {
if (m_type != nullptr and not regex_match(value.begin(), value.end(), m_type->m_rx)) if (m_type != nullptr and not regex_match(value.begin(), value.end(), *m_type->m_rx))
throw validation_error(m_category->m_name, m_tag, "Value '" + std::string{value} + "' does not match type expression for type " + m_type->m_name); throw validation_error(m_category->m_name, m_tag, "Value '" + std::string{value} + "' does not match type expression for type " + m_type->m_name);
if (not m_enums.empty()) if (not m_enums.empty())
...@@ -240,7 +266,7 @@ const type_validator *validator::get_validator_for_type(std::string_view typeCod ...@@ -240,7 +266,7 @@ const type_validator *validator::get_validator_for_type(std::string_view typeCod
{ {
const type_validator *result = nullptr; const type_validator *result = nullptr;
auto i = m_type_validators.find(type_validator{std::string(typeCode), DDL_PrimitiveType::Char, boost::regex()}); auto i = m_type_validators.find(type_validator{std::string(typeCode), DDL_PrimitiveType::Char, {}});
if (i != m_type_validators.end()) if (i != m_type_validators.end())
result = &*i; result = &*i;
else if (VERBOSE > 4) else if (VERBOSE > 4)
...@@ -409,7 +435,7 @@ const validator &validator_factory::operator[](std::string_view dictionary_name) ...@@ -409,7 +435,7 @@ const validator &validator_factory::operator[](std::string_view dictionary_name)
if (std::filesystem::exists(p, ec) and not ec) if (std::filesystem::exists(p, ec) and not ec)
{ {
gzstream::ifstream in(p); gxrio::ifstream in(p);
if (not in.is_open()) if (not in.is_open())
throw std::runtime_error("Could not open dictionary (" + p.string() + ")"); throw std::runtime_error("Could not open dictionary (" + p.string() + ")");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment