保存/序列化boost或std regex

时间:2013-09-11 23:09:57

标签: c++ regex boost std

是否可以序列化/反序列化并将正则表达式保存/加载到文件中?

我们有一个非常耗时的过程构建了一些正则表达式,我想知道我们是否可以通过保存和加载来节省一些时间。

3 个答案:

答案 0 :(得分:7)

不,这可能是不可能的,因为无论如何它都需要你重新编译正则表达式。

但是,如果使用boost :: xpressive,则可以通过正则表达式的表达式模板构造在编译期间编译正则表达式。这将使正则表达式编译时间完全消失。

Boost Xpressive

但是,使用多余的时间使用的真正原因几乎可以肯定是你通过使用回溯正则表达式引擎不正确地使用正则表达式。

RE2是一种传统的自动机正则表达式引擎,它不使用回溯,而是直接构造NFA或DFA。如果您没有使用反向引用或许多基于非正则表达式的“特征”,则使用RE2将显示许多极端情况的速度增加数量级。

如果您正在使用这些功能,您应该知道它们将严格控制您的匹配速度,并且它们几乎肯定是您寻求消除速度减慢的主要原因。

答案 1 :(得分:2)

使用boost / stl regex类很难实现。问题是所述类的内部结构。

  1. 实现如何存储类属性?按地址,价值?
  2. 编译器引入了哪些额外的填充,如果有的话?
  3. 是否有任何平台对齐问题?
  4. 等...
  5. 帮助说明问题的难度。尝试找到C ++类实例的大小。

    regex pattern( "^Corvusoft$" );
    
    printf( "%lu\n", sizeof( pattern ) );  //32
    
    regex alternative( "C" );
    
    printf( "%lu\n", sizeof( alternative ) );  //32
    

    替代解决方案1 ​​

    在构建时创建包含所需正则表达式和链接的库,或者通过dlopen api动态打开并加载库。然后,您将使用prelink之类的工具来确保它们已经在内存中;预编译。

    替代解决方案2

    使用C regex.h。

    您可以使用regex_t POD结构并将其内容写入二进制或内存映射文件。稍后您可以将这些数据值映射回新的regex_t结构,完全避免重新编译正则表达式。

    #include <regex.h>
    
    regex_t pattern;
    int result = 0;
    
    result = regcomp( &pattern, "^Corvusoft$", 0 );
    
    if ( result )
    {
       fprintf( stderr, "Failed to compile regular expression pattern\n" );
    }
    
    TODO: walk structure and write to binary/memory mapped file.
    

    替代解决方案3

    按照@ Alice的建议并使用Boost.Xpressive

答案 2 :(得分:0)

可以序列化一个boost :: regex:

#include <string>
#include <iostream>
#include <sstream>

#include <boost/regex.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/split_free.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

namespace boost
{
  namespace serialization
  {
    template<class Archive, class charT, class traits>
    inline void save(Archive & ar, 
                     const boost::basic_regex<charT, traits> & t, 
                     const unsigned int /* file_version */)
    {
      std::basic_string<charT> str = t.str();
      typename boost::basic_regex<charT, traits>::flag_type flags = t.flags();
//      typename boost::basic_regex<charT, traits>::locale_type loc = t.getloc();
      ar & str;
      ar & flags;
//      ar & loc;
    }

    template<class Archive, class charT, class traits>
    inline void load(Archive & ar, 
                     boost::basic_regex<charT, traits> & t, 
                     const unsigned int /* file_version */)
    {
      std::basic_string<charT> str;
      typename boost::basic_regex<charT, traits>::flag_type flags;
//      typename boost::basic_regex<charT, traits>::locale_type loc;
      ar & str;
      ar & flags;
//      ar & loc;
      t.assign(str, flags);
//      t.imbue(loc);
    }

    template<class Archive, class charT, class traits>
    inline void serialize(Archive & ar, 
                          boost::basic_regex<charT, traits> & t, 
                          const unsigned int file_version)
    {
      boost::serialization::split_free(ar, t, file_version);
    }
  }
}

int main(int argc, char ** argv)
{
  std::stringstream os;

  {
    boost::regex re("<a\\s+href=\"([\\-:\\w\\d\\.\\/]+)\">");
    boost::archive::text_oarchive oar(os);
    oar & re;
  }

  os.seekg(std::ios_base::beg);

  boost::regex re;
  boost::cmatch matches;
  boost::archive::text_iarchive iar(os);

  iar & re;

  boost::regex_search("<a href=\"https://stackoverflow.com/questions/18752807/save-serialize-boost-or-std-regexes\">example</a>", matches, re);

  std::cout << matches[1] << std::endl;

}

但这并不意味着与从字符串重构正则表达式相比,您将获得任何性能提升。

注意:为简单起见,我遗漏了std :: locale的东西