Commit ce7434a4 by Maarten L. Hekkelman

Make boost::regex optional

parent ad7d876d
......@@ -96,7 +96,6 @@ else()
message("Not trying to recreate SymOpTable_data.hpp since CCP4 is not defined")
endif()
# set(CMAKE_DEBUG_POSTFIX d)
if(MSVC)
# make msvc standards compliant...
add_compile_options(/permissive-)
......@@ -148,11 +147,26 @@ else()
endif()
# 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(THREADS_PREFER_PTHREAD_FLAG)
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)
include(FindFilesystem)
......@@ -170,11 +184,8 @@ if(CIFPP_RECREATE_SYMOP_DATA)
# The tool to create the table
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})
if(Boost_INCLUDE_DIR)
target_include_directories(symop-map-generator PUBLIC ${Boost_INCLUDE_DIR})
endif()
target_link_libraries(symop-map-generator Threads::Threads
Boost::regex Boost::program_options ${CIFPP_REQUIRED_LIBRARIES})
set($ENV{CLIBD} ${CLIBD})
......@@ -250,6 +261,10 @@ set(project_headers
add_library(cifpp ${project_sources} ${project_headers} ${CMAKE_SOURCE_DIR}/src/structure/SymOpTable_data.hpp)
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
PUBLIC
"$<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 @@
#pragma once
#include <filesystem>
#include <list>
#include <mutex>
// duh.. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164
// #include <regex>
#include <boost/regex.hpp>
#include <cif++/utilities.hpp>
namespace cif
......@@ -63,12 +60,36 @@ enum class DDL_PrimitiveType
DDL_PrimitiveType map_to_primitive_type(std::string_view s);
struct regex_impl;
struct type_validator
{
std::string m_name;
DDL_PrimitiveType m_primitive_type;
// std::regex m_rx;
boost::regex m_rx;
regex_impl *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
{
......
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
try
{
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));
}
......
......@@ -28,7 +28,20 @@
#include <fstream>
#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/validate.hpp>
......@@ -37,13 +50,14 @@
namespace cif
{
extern int VERBOSE;
}
namespace cif
struct regex_impl : public regex
{
using cif::VERBOSE;
regex_impl(std::string_view rx)
: regex(rx.begin(), rx.end(), regex::extended | regex::optimize)
{
}
};
validation_error::validation_error(const std::string &msg)
: m_msg(msg)
......@@ -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 result = 0;
......@@ -191,7 +217,7 @@ void item_validator::operator()(std::string_view value) const
{
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);
if (not m_enums.empty())
......@@ -240,7 +266,7 @@ const type_validator *validator::get_validator_for_type(std::string_view typeCod
{
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())
result = &*i;
else if (VERBOSE > 4)
......@@ -409,7 +435,7 @@ const validator &validator_factory::operator[](std::string_view dictionary_name)
if (std::filesystem::exists(p, ec) and not ec)
{
gzstream::ifstream in(p);
gxrio::ifstream in(p);
if (not in.is_open())
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