regexp.hpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:20k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: regexp.hpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:38:40  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. #ifndef UTIL___REGEXP__HPP
  10. #define UTIL___REGEXP__HPP
  11. /*  $Id: regexp.hpp,v 1000.2 2004/06/01 19:38:40 gouriano Exp $
  12.  * ===========================================================================
  13.  *
  14.  *                            PUBLIC DOMAIN NOTICE
  15.  *               National Center for Biotechnology Information
  16.  *
  17.  *  This software/database is a "United States Government Work" under the
  18.  *  terms of the United States Copyright Act.  It was written as part of
  19.  *  the author's official duties as a United States Government employee and
  20.  *  thus cannot be copyrighted.  This software/database is freely available
  21.  *  to the public for use. The National Library of Medicine and the U.S.
  22.  *  Government have not placed any restriction on its use or reproduction.
  23.  *
  24.  *  Although all reasonable efforts have been taken to ensure the accuracy
  25.  *  and reliability of the software and data, the NLM and the U.S.
  26.  *  Government do not and cannot warrant the performance or results that
  27.  *  may be obtained by using this software or data. The NLM and the U.S.
  28.  *  Government disclaim all warranties, express or implied, including
  29.  *  warranties of performance, merchantability or fitness for any particular
  30.  *  purpose.
  31.  *
  32.  *  Please cite the author in any work or product based on this material.
  33.  *
  34.  * ===========================================================================
  35.  *
  36.  * Authors:  Clifford Clausen
  37.  *
  38.  */
  39. /// @file regexp.hpp
  40. /// C++ wrappers for the Perl-compatible regular expression (PCRE) library.
  41. ///
  42. /// CRegexp     -  wrapper class for the PCRE library.
  43. /// CRegexpUtil -  utility functions.
  44. ///
  45. /// For more details see PCRE documentation: http://www.pcre.org/pcre.txt
  46. #include <corelib/ncbistd.hpp>
  47. #ifdef NCBI_COMPILER_MSVC
  48. #include <util/regexp/pcre.h>
  49. #else
  50. #include <pcre.h>
  51. #endif
  52. /** @addtogroup Regexp
  53.  *
  54.  * @{
  55.  */
  56. BEGIN_NCBI_SCOPE
  57. /// Specifies the maximum number of subpatterns that can be found.
  58. const size_t kRegexpMaxSubPatterns = 100;
  59. /////////////////////////////////////////////////////////////////////////////
  60. ///
  61. /// CRegexp --
  62. ///
  63. /// Define a wrapper class for the Perl-compatible regular expression (PCRE)
  64. /// library.
  65. ///
  66. /// Internally, this class holds a compiled regular expression used for
  67. /// matching with strings passed as an argument to the GetMatch()
  68. /// member function. The regular expression is passed as a argument
  69. /// to the constructor or to the Set() member function.
  70. ///
  71. /// Throw exception on error.
  72. class NCBI_XREGEXP_EXPORT CRegexp
  73. {
  74. public:
  75.     /// Type definitions used for code clarity.
  76.     typedef int TCompile;     ///< Compilation options.
  77.     typedef int TMatch;       ///< Match options.
  78.     /// Flags for compile regular expressions.
  79.     ///
  80.     /// PCRE compiler flags used in the constructor and in Set().
  81.     /// If eCompile_ignore_case is set, matches are case insensitive.
  82.     /// If eCompile_dotall is set, a dot metacharater in the pattern matches
  83.     /// all characters, including newlines. Without it, newlines are excluded.
  84.     /// If eCompile_newline is set then ^ matches the start of a line and
  85.     /// $ matches the end of a line. If not set, ^ matches only the start
  86.     /// of the entire string and $ matches only the end of the entire string.
  87.     /// If eCompile_ungreedy inverts the "greediness" of the quantifiers so
  88.     /// that they are not greedy by default, but become greedy if followed by
  89.     /// "?".
  90.     /// It is not compatible with Perl. 
  91.     ///
  92.     /// The settings can be changed from within the pattern by a sequence of
  93.     /// Perl option letters enclosed between "(?" and ")".
  94.     /// The option letters are:
  95.     ///   i  for PCRE_CASELESS
  96.     ///   m  for PCRE_MULTILINE
  97.     ///   s  for PCRE_DOTALL
  98.     ///   x  for PCRE_EXTENDED
  99.     ///   U  for PCRE_UNGREEDY
  100.     enum ECompile {
  101.         eCompile_default     = 0,
  102.         eCompile_ignore_case = PCRE_CASELESS,
  103.         eCompile_dotall      = PCRE_DOTALL,
  104.         eCompile_newline     = PCRE_MULTILINE,
  105.         eCompile_ungreedy    = PCRE_UNGREEDY
  106.     };
  107.     /// Flags for match string against a pre-compiled pattern.
  108.     ///
  109.     /// Setting eMatch_not_begin causes ^ not to match before the
  110.     /// first character of a line. Without setting eCompile_newline,
  111.     /// ^ won't match anything if eMatch_not_begin is set.
  112.     /// Setting eMatch_not_end causes $ not to match immediately before a new
  113.     /// line. Without setting eCompile_newline, $ won't match anything
  114.     /// if eMatch_not_end is set.
  115.     enum EMatch {
  116.         eMatch_default   = 0,
  117.         eMatch_not_begin = PCRE_NOTBOL,      ///< ^ won't match string begin.
  118.         eMatch_not_end   = PCRE_NOTEOL,      ///< $ won't match string end.
  119.         eMatch_not_both  = PCRE_NOTBOL | PCRE_NOTEOL
  120.     };
  121.     /// Constructor.
  122.     ///
  123.     /// Set and compile the PCRE pattern specified by argument according
  124.     /// to compile options. Also allocate memory for compiled PCRE.
  125.     /// @param pattern
  126.     ///   Perl regular expression to compile.
  127.     /// @param flags
  128.     ///   Regular expression compilation flags.
  129.     /// @sa
  130.     ///   ECompile
  131.     CRegexp(const string& pattern, TCompile flags = 0);
  132.     /// Destructor.
  133.     ///
  134.     /// Deallocate compiled Perl-compatible regular expression.
  135.     virtual ~CRegexp();
  136.     /// Set and compile PCRE.
  137.     ///
  138.     /// Set and compile the PCRE pattern specified by argument according
  139.     /// to compile options. Also deallocate/allocate memory for compiled PCRE.
  140.     /// @param pattern
  141.     ///   Perl regular expression to compile.
  142.     /// @param flags
  143.     ///   Regular expression compilation flags.
  144.     /// @sa
  145.     ///   ECompile
  146.     void Set(const string& pattern, TCompile flags = 0);
  147.     /// Get matching pattern and subpatterns.
  148.     ///
  149.     /// Return a string corresponding to the match to pattern or subpattern.
  150.     /// Set noreturn to true when GetSub() or GetResults() will be used
  151.     /// to retrieve pattern and subpatterns. Calling GetMatch() causes
  152.     /// the entire search to be performed again. If you want to retrieve
  153.     /// a different pattern/subpattern from an already performed search,
  154.     /// it is more efficient to use GetSub or GetResults.
  155.     /// @param str
  156.     ///   String to search.
  157.     /// @param offset
  158.     ///   Starting offset in str.
  159.     /// @param idx
  160.     ///   (Sub) match to return.
  161.     ///   Use idx = 0 for complete pattern. Use idx > 0 for subpatterns.
  162.     /// @param flags
  163.     ///   Flags to match.
  164.     /// @param noreturn
  165.     ///   Return empty string if noreturn is true.
  166.     /// @return
  167.     ///   Return (sub) match with number idx or empty string when no match
  168.     ///   found or if noreturn is true.
  169.     /// @sa
  170.     ///   EMatch, GetSub(), GetResult()
  171.     string GetMatch(
  172.         const string& str,
  173.         TSeqPos       offset   = 0,
  174.         size_t        idx      = 0,
  175.         TMatch        flags    = 0,
  176.         bool          noreturn = false
  177.     );
  178.     /// Get pattern/subpattern from previous GetMatch().
  179.     ///
  180.     /// Should only be called after GetMatch() has been called with the
  181.     /// same string. GetMatch() internally stores locations on string where
  182.     /// pattern and subpatterns were found. 
  183.     /// @param str
  184.     ///   String to search.
  185.     /// @param idx
  186.     ///   (Sub) match to return.
  187.     /// @return
  188.     ///   Return the substring at location of pattern match (idx 0) or
  189.     ///   subpattern match (idx > 0). Return empty string when no match.
  190.     /// @sa
  191.     ///   GetMatch(), GetResult()
  192.     string GetSub(const string& str, size_t idx = 0) const;
  193.     /// Get number of patterns + subpatterns.
  194.     ///
  195.     /// @return
  196.     ///   Return the number of patterns + subpatterns found as a result
  197.     ///   of the most recent GetMatch() call.
  198.     /// @sa
  199.     ///   GetMatch()
  200.     int NumFound() const;
  201.     /// Get location of pattern/subpattern.
  202.     ///
  203.     /// @param idx
  204.     ///   Index of pattern/subpattern to obtaining.
  205.     ///   Use idx = 0 for pattern, idx > 0 for sub patterns.
  206.     /// @return
  207.     ///   Return array where index 0 is location of first character in
  208.     ///   pattern/sub pattern and index 1 is 1 beyond last character in
  209.     ///   pattern/sub pattern.
  210.     ///   Throws if called with idx >= NumFound().
  211.     /// @sa
  212.     ///   GetMatch(), NumFound()
  213.     const int* GetResults(size_t idx) const;
  214. private:
  215.     // Disable copy constructor and assignment operator.
  216.     CRegexp(const CRegexp &);
  217.     void operator= (const CRegexp &);
  218.     /// Pointer to compiled PCRE pattern.
  219.     pcre*  m_PReg;
  220.     /// Array of locations of patterns/subpatterns resulting from
  221.     /// the last call to GetMatch(). Also contains 1/3 extra space used
  222.     /// internally by the PCRE C library.
  223.     int m_Results[(kRegexpMaxSubPatterns +1) * 3];
  224.     /// The total number of pattern + subpatterns resulting from
  225.     /// the last call to GetMatch.
  226.     int m_NumFound;
  227. };
  228. /////////////////////////////////////////////////////////////////////////////
  229. ///
  230. /// CRegexpUtil --
  231. ///
  232. /// Throw exception on error.
  233. class NCBI_XREGEXP_EXPORT CRegexpUtil
  234. {
  235. public:
  236.     /// Constructor.
  237.     ///
  238.     /// Set string for processing.
  239.     /// @param str
  240.     ///   String to process.
  241.     /// @sa
  242.     ///   Exists(), Extract(), Replace(), ReplaceRange()
  243.     CRegexpUtil(const string& str = kEmptyStr);
  244.     /// Reset the content of the string to process.
  245.     ///
  246.     /// @param str
  247.     ///   String to process.
  248.     /// @sa
  249.     ///   operator =
  250.     void Reset(const string& str);
  251.     /// Reset the content of the string to process.
  252.     ///
  253.     /// The same as Reset().
  254.     /// @param str
  255.     ///   String to process.
  256.     /// @sa
  257.     ///   Reset()
  258.     void operator= (const string& str);
  259.     /// Get result string.
  260.     ///
  261.     /// @sa
  262.     ///   operator string
  263.     string GetResult(void);
  264.     /// Get result string.
  265.     ///
  266.     /// The same as GetResult().
  267.     /// @sa
  268.     ///   GetResult()
  269.     operator string(void);
  270.  
  271.     /// Check existence substring which match a specified pattern.
  272.     ///
  273.     /// @param pattern
  274.     ///   Perl regular expression to search.
  275.     /// @param compile_flags
  276.     ///   Regular expression compilation flags.
  277.     /// @param match_flags
  278.     ///   Flags to match.
  279.     /// @return
  280.     ///   Return TRUE if  a string corresponding to the match to pattern or
  281.     ///   subpattern.
  282.     /// @sa
  283.     ///   CRegexp, CRegexp::GetMatch()
  284.     bool Exists(
  285.         const string&      pattern,
  286.         CRegexp::TCompile  compile_flags = CRegexp::eCompile_default,
  287.         CRegexp::TMatch    match_flags   = CRegexp::eMatch_default
  288.     );
  289.     /// Get matching pattern/subpattern from string.
  290.     ///
  291.     /// @param pattern
  292.     ///   Perl regular expression to search.
  293.     /// @param compile_flags
  294.     ///   Regular expression compilation flags.
  295.     /// @param match_flags
  296.     ///   Flags to match.
  297.     /// @param pattern_idx
  298.     ///   Index of pattern/subpattern to extract.
  299.     ///   Use pattern_idx = 0 for pattern, pattern_idx > 0 for sub patterns.
  300.     /// @return
  301.     ///   Return the substring at location of pattern/subpatter match with
  302.     ///   index pattern_idx. Return empty string when no match.
  303.     /// @sa
  304.     ///   CRegexp, CRegexp::GetMatch()
  305.     string Extract(
  306.         const string&      pattern,
  307.         CRegexp::TCompile  compile_flags = CRegexp::eCompile_default,
  308.         CRegexp::TMatch    match_flags   = CRegexp::eMatch_default,
  309.         size_t             pattern_idx   = 0
  310.     );
  311.     /// Replace occurrences of a substring within a string by pattern.
  312.     ///
  313.     /// @param search
  314.     ///   Reqular expression to match a substring value that is replaced.
  315.     /// @param replace
  316.     ///   Replace "search" substring with this value. The matched subpatterns
  317.     ///   (if any) can be found and inserted into replace string using
  318.     ///   variables $1, $2, $3, and so forth. The variable can be enclosed
  319.     ///   in the curly brackets {}, that will be deleted on substitution.
  320.     /// @param compile_flags
  321.     ///   Regular expression compilation flags.
  322.     /// @param match_flags
  323.     ///   Flags to match.
  324.     /// @param max_replace
  325.     ///   Replace no more than "max_replace" occurrences of substring "search".
  326.     ///   If "max_replace" is zero (default), then replace all occurrences with
  327.     ///   "replace".
  328.     /// @return
  329.     ///   Return the count of replacements.
  330.     /// @sa
  331.     ///   CRegexp, ReplaceRange()
  332.     size_t Replace(
  333.         const string&      search,
  334.         const string&      replace,
  335.         CRegexp::TCompile  compile_flags = CRegexp::eCompile_default,
  336.         CRegexp::TMatch    match_flags   = CRegexp::eMatch_default,
  337.         size_t             max_replace   = 0
  338.     );
  339.     //
  340.     // Range functions.
  341.     //
  342.     /// Range processing type.
  343.     /// Defines which part of the specified range should be processed.
  344.     enum ERange {
  345.         eInside,    ///< Process substrings inside range.
  346.         eOutside    ///< Process substrings outside range.
  347.     };
  348.     /// Set new range for range-dependent functions.
  349.     ///
  350.     /// The mached string will be splitted up by "delimeter".
  351.     /// And then in range-dependent functions every part (substring) is checked
  352.     /// to fall into the range, specified by start and end adresses.
  353.     ///
  354.     /// The addresses works similare the Unix utility SED, except that regular
  355.     /// expressions is Perl-compatible:
  356.     ///    - empty address in the range correspond to any substring.
  357.     ///    - command with one address correspond to any substring that matches
  358.     ///      the address.
  359.     ///    - command with two addresses correspond to inclusive range from the
  360.     ///      start address to through the next pattern space that maches the
  361.     ///      end address.
  362.     ///
  363.     /// Specified range have effect only for range-dependent functions.
  364.     /// Otherwise range is ignored.
  365.     /// @param addr_start
  366.     ///   Regular expression which assign a starting address of range.
  367.     /// @param addr_end
  368.     ///   Regular expression which assign an ending address of range.
  369.     ///   Should be empty if the start address is empty.
  370.     /// @param delimiter
  371.     ///   Split a source string by "delimiter.
  372.      /// @sa
  373.     ///   ClearRange, ReplaceRange()
  374.     void SetRange(
  375.         const string&  addr_start = kEmptyStr,
  376.         const string&  addr_end   = kEmptyStr,
  377.         const string&  delimiter  = "n"
  378.     );
  379.     /// Clear range for range-dependent functions.
  380.     ///
  381.     /// Have the same effect as SetRange() without parameters.
  382.     /// @sa
  383.     ///   SetRange()
  384.     void ClearRange(void);
  385.     /// Replace all occurrences of a substring within a string by pattern.
  386.     ///
  387.     /// Use range specified by SetRange() method. Work like SED command s/.
  388.     /// @param search
  389.     ///   Reqular expression to match a substring value that is replaced.
  390.     /// @param replace
  391.     ///   Replace "search" substring with this value. The matched subpatterns
  392.     ///   (if any) can be found and inserted into replace string using
  393.     ///   variables $1, $2, $3, and so forth. The variable can be enclosed
  394.     ///   in the curly brackets {}, that will be deleted on substitution.
  395.     /// @param compile_flags
  396.     ///   Regular expression compilation flags.
  397.     /// @param match_flags
  398.     ///   Flags to match.
  399.     /// @param process_within
  400.     ///   Define which part of the range should be processed.
  401.     /// @param max_replace
  402.     ///   Replace no more than "max_replace" occurrences of substring "search"
  403.     ///   in the every substring. If "max_replace" is zero (default),
  404.     ///   then replace all occurrences with "replace".
  405.     /// @return
  406.     ///   Return the count of replacements.
  407.     /// @sa
  408.     ///   ERange, SetRange(), ClearRange()
  409.     size_t ReplaceRange(
  410.         const string&       search,
  411.         const string&       replace,
  412.         CRegexp::TCompile   compile_flags  = CRegexp::eCompile_default,
  413.         CRegexp::TMatch     match_flags    = CRegexp::eMatch_default,
  414.         CRegexpUtil::ERange process_within = eInside,
  415.         size_t              max_replace    = 0
  416.     );
  417. private:
  418.     /// Divide source string to substrings by delimiter.
  419.     /// If delimiter is empty string that use early defined delimiter.
  420.     void x_Divide(const string& delimiter = kEmptyStr);
  421.     /// Join substrings back to entire string.
  422.     void x_Join(void);
  423. private:
  424.     string       m_Content;       ///< Content string.
  425.     list<string> m_ContentList;   ///< Content list.
  426.     bool         m_IsDivided;     ///< TRUE if m_ContentList is newer than
  427.                                   ///< m_Content, and FALSE otherwise.
  428.     string       m_RangeStart;    ///< Regexp to determine start of range.
  429.     string       m_RangeEnd;      ///< Regexp to determine end of range.
  430.     string       m_Delimiter;     ///< Delimiter used to split string.
  431. };
  432. //////////////////////////////////////////////////////////////////////////////
  433. //
  434. // Inline
  435. //
  436. //
  437. // CRegexp
  438. //
  439. inline
  440. int CRegexp::NumFound() const
  441. {
  442.     return m_NumFound;
  443. }
  444. inline
  445. const int* CRegexp::GetResults(size_t idx) const
  446. {
  447.     if ((int)idx >= m_NumFound) {
  448.         throw runtime_error("idx >= NumFound()");
  449.     }
  450.     return m_Results + 2 * idx;
  451. }
  452. //
  453. // CRegexpUtil
  454. //
  455. inline
  456. string CRegexpUtil::GetResult(void)
  457. {
  458.     if ( m_IsDivided ) {
  459.         x_Join();
  460.     }
  461.     return m_Content;
  462. }
  463. inline
  464. void CRegexpUtil::Reset(const string& str)
  465. {
  466.     m_Content   = str;
  467.     m_IsDivided = false;
  468.     m_ContentList.clear();
  469. }
  470. inline
  471. CRegexpUtil::operator string(void)
  472. {
  473.     return GetResult();
  474. }
  475. inline
  476. void CRegexpUtil::operator= (const string& str)
  477. {
  478.     Reset(str);
  479. }
  480. inline
  481. void CRegexpUtil::ClearRange(void)
  482. {
  483.     SetRange();
  484. }
  485. inline
  486. bool CRegexpUtil::Exists(
  487.     const string&     pattern,
  488.     CRegexp::TCompile compile_flags,
  489.     CRegexp::TMatch   match_flags)
  490. {
  491.     // Fill shure that string is not divided
  492.     x_Join();
  493.     // Check the pattern existence
  494.     CRegexp re(pattern, compile_flags);
  495.     re.GetMatch(m_Content.c_str(), 0, match_flags, 0, true);
  496.     return re.NumFound() > 0;
  497. }
  498. inline
  499. string CRegexpUtil::Extract(
  500.     const string&     pattern,
  501.     CRegexp::TCompile compile_flags,
  502.     CRegexp::TMatch   match_flags,
  503.     size_t            pattern_idx)
  504. {
  505.     // Fill shure that string is not divided
  506.     x_Join();
  507.     // Get the pattern/subpattern
  508.     CRegexp re(pattern, compile_flags);
  509.     return re.GetMatch(m_Content.c_str(), 0, pattern_idx, match_flags);
  510. }
  511. END_NCBI_SCOPE
  512. /*
  513.  * ===========================================================================
  514.  * $Log: regexp.hpp,v $
  515.  * Revision 1000.2  2004/06/01 19:38:40  gouriano
  516.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.10
  517.  *
  518.  * Revision 1.10  2004/04/05 16:54:26  ucko
  519.  * Include the internal pcre.h when using MSVC until its build system
  520.  * catches up.
  521.  *
  522.  * Revision 1.9  2004/04/05 15:54:12  ucko
  523.  * Default to using external versions of zlib, bzlib, and libpcre if available.
  524.  *
  525.  * Revision 1.8  2004/03/12 13:57:13  dicuccio
  526.  * Renamed NCBI_REGEXP_EXPORT -> NXBI_XREGEXP_EXPORT to match library name
  527.  *
  528.  * Revision 1.7  2004/03/11 22:54:48  gorelenk
  529.  * Changed export prefix of all classes to NCBI_REGEXP_EXPORT.
  530.  *
  531.  * Revision 1.6  2003/11/07 13:38:51  ivanov
  532.  * Comments changes
  533.  *
  534.  * Revision 1.5  2003/11/06 16:12:10  ivanov
  535.  * Added CRegexpUtil class.
  536.  * Added some new CRegExp::ECompile flags.
  537.  * Added more comments; Some formal code rearrangement.
  538.  *
  539.  * Revision 1.4  2003/07/16 19:15:05  clausen
  540.  * Added TCompile and TMatch and fixed comments
  541.  *
  542.  * Revision 1.3  2003/07/07 13:50:59  kuznets
  543.  * Added DLL export/import instruction
  544.  *
  545.  * Revision 1.2  2003/06/20 18:32:42  clausen
  546.  * Changed to native interface for regexp
  547.  *
  548.  * Revision 1.1  2003/06/03 14:47:46  clausen
  549.  * Initial version
  550.  *
  551.  * ===========================================================================
  552.  */
  553. #endif  /* UTIL___REGEXP__HPP */