Back to index

courier  0.68.2
maildirsearch.h
Go to the documentation of this file.
00001 #ifndef maildir_search_h
00002 #define maildir_search_h
00003 
00004 /*
00005 ** Copyright 2002-2011 Double Precision, Inc.
00006 ** See COPYING for distribution information.
00007 */
00008 
00009 
00010 /*
00011 ** A deterministic automaton-based search mechanism.  Search for a particular
00012 ** string in a middle of a larger body of text.
00013 **
00014 ** Allocate a struct maildir_searchengine by yourself, and call
00015 ** maildir_search_init() to initialize.
00016 **
00017 ** Call maildir_search_destroy() to release any allocated memory.
00018 **
00019 ** Call maildir_search_start_str() to prep the structure for a particular search
00020 ** string. Alternatively, call maildir_search_start_unicode() to specify the
00021 ** search string as unicode characters. Alternatively,
00022 ** call maildir_search_start_str_chset() to specify the search string in
00023 ** a specific character. The search string get converted to unicode, then
00024 ** converted to lowercase characters, removing leading/trailing whitespace,
00025 ** and replacing multiple occurences of whitespace in the search string with
00026 ** a single space character.
00027 **
00028 ** Call maildir_search_reset() to start the search, then call
00029 ** maildir_search_step() for each character in the text. Use
00030 ** maildir_search_step_unicode() if the search string was specified via
00031 ** maildir_search_start_unicode(). Use maildir_search_step_unicode_lc() if
00032 ** the search string was specified using via maildir_search_start_str_chset().
00033 **
00034 ** Call maildir_search_found() to check if the search string is found.
00035 */
00036 
00037 #include "config.h"
00038 
00039 #include "../unicode/unicode.h"
00040 
00041 #include <string.h>
00042 #include <stdlib.h>
00043 
00044 #ifdef  __cplusplus
00045 extern "C" {
00046 #endif
00047 
00048 struct maildir_searchengine {
00049        unicode_char *string;
00050        size_t string_l;
00051        const unicode_char *ptr;
00052        unsigned *r;    /* Retry backoff indexes */
00053        unsigned i;
00054        int spc;
00055        } ;
00056 
00057 #define maildir_search_init(sei) (memset((sei), 0, sizeof(struct maildir_searchengine)))
00058 
00059 #define maildir_search_destroy(sei) do { if ((sei)->string) free((sei)->string); if ( (sei)->r) free( (sei)->r); } while (0)
00060 
00061 int maildir_search_start_str(struct maildir_searchengine *engine,
00062                           const char *string);
00063 int maildir_search_start_str_chset(struct maildir_searchengine *engine,
00064                                const char *string,
00065                                const char *chset);
00066 int maildir_search_start_unicode(struct maildir_searchengine *engine,
00067                              const unicode_char *string);
00068 
00069 
00070 #define       maildir_search_reset(si)    ((si)->i=0, (si)->ptr=(si)->string)
00071 
00072 #define       maildir_search_found(si)    ((si)->ptr && \
00073                                    (si)->ptr[(si)->i] == '\0')
00074 #define maildir_search_len(si)            ((si)->string_l)
00075 
00076 #define maildir_search_step_unicode(sie,ch) do \
00077         {\
00078                 if ( (sie)->ptr && (sie)->ptr[(sie)->i]) \
00079                 {\
00080                         for (;;) \
00081                         {\
00082                                 if ( (unicode_char)(sie)->ptr[(sie)->i] == (unicode_char)(ch) )\
00083                                         { (sie)->i++; break; }\
00084                                 if ( (sie)->i == 0) break;\
00085                                 (sie)->i=(sie)->r[(sie)->i];\
00086                         }\
00087                 }\
00088         } while (0)
00089 
00090 #define maildir_search_step_unicode_lc(sie,ch) do       \
00091        {                                         \
00092               unicode_char c=(ch);               \
00093               int spc=0;                         \
00094                                                  \
00095                                                                \
00096               if (c == ' ' || c == '\t' || c == '\r' || c == '\n')    \
00097               {                                                \
00098                      c=' ';                                    \
00099                      spc=1;                                    \
00100               }                                                \
00101                                                                \
00102               if (spc && (sie)->spc)                                  \
00103                      ;                                         \
00104               else                                             \
00105               {                                                \
00106                      c=unicode_lc(c);                          \
00107                      maildir_search_step_unicode((sie),c);            \
00108               }                                                \
00109                                                                \
00110               (sie)->spc=spc;                                         \
00111        } while(0)
00112 
00113 #define maildir_search_step(sie,ch) \
00114        maildir_search_step_unicode((sie), ((unsigned char)(ch)))
00115 
00116 #define maildir_search_atstart(sie) ((sie)->i == 0)
00117 
00118 #ifdef  __cplusplus
00119 }
00120 
00121 /* A C++ wrapper for the above */
00122 
00123 #if HAVE_VECTOR
00124 #include <vector>
00125 #else
00126 #if HAVE_VECTOR_H
00127 #include <vector.h>
00128 #endif
00129 #endif
00130 
00131 #include <string>
00132 
00133 namespace mail {
00134 
00135 class Search {
00136 
00137        struct maildir_searchengine sei;
00138 
00139        std::string String;
00140 
00141        std::vector<unsigned> rbuf;
00142  public:
00143        Search();
00144        virtual ~Search();
00145 
00146        size_t getSearchLen()
00147        {
00148               return maildir_search_len(&sei);
00149        }
00150 
00151        bool setString(std::string s, std::string chset)
00152        {
00153               String=s;
00154               return maildir_search_start_str_chset(&sei, s.c_str(),
00155                                                 chset.c_str()) == 0;
00156        }
00157 
00158        void reset()
00159        {
00160               maildir_search_reset(&sei);
00161        }
00162 
00163        void operator<<(char c) { maildir_search_step(&sei, c); }
00164 
00165        void operator<<(unicode_char ch)
00166        {
00167               maildir_search_step_unicode_lc(&sei, ch);
00168        }
00169 
00170        bool atstart() { return maildir_search_atstart(&sei); }
00171        operator bool() { return maildir_search_found(&sei); }
00172 
00173        bool operator !() { return ! operator bool(); }
00174 
00175  private:
00176        Search(const Search &); /* UNDEFINED */
00177 
00178        Search &operator=(const Search &); /* UNDEFINED */
00179 
00180 };
00181 
00182 }
00183 
00184 #endif
00185 
00186 #endif
00187