File: PathPattern.h

package info (click to toggle)
lsp-plugins 1.2.5-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 91,856 kB
  • sloc: cpp: 427,831; xml: 57,779; makefile: 9,961; php: 1,005; sh: 18
file content (256 lines) | stat: -rw-r--r-- 13,408 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/*
 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
 *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
 *
 * This file is part of lsp-runtime-lib
 * Created on: 15 окт. 2020 г.
 *
 * lsp-runtime-lib is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * lsp-runtime-lib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with lsp-runtime-lib. If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef LSP_PLUG_IN_IO_PATHPATTERN_H_
#define LSP_PLUG_IN_IO_PATHPATTERN_H_

#include <lsp-plug.in/runtime/version.h>
#include <lsp-plug.in/runtime/LSPString.h>
#include <lsp-plug.in/io/Path.h>
#include <lsp-plug.in/common/status.h>
#include <lsp-plug.in/lltl/parray.h>
#include <lsp-plug.in/lltl/darray.h>

namespace lsp
{
    namespace io
    {
        //
        // The pattern for the file name.
        //
        // Syntax:
        //   *             - Any character sequence except '/' or '\'
        //   ?             - Any character except '/' or '\'
        //   / or \        - Path separator
        //   `/            - Escaped character '/' (Available for escaping: '*', '?', '`', '/', '\', '&', '|', '(', ')' )
        //   name.ext      - Strict match of characters to 'name.ext'
        //   ... & ...     - Conjunction of two conditions
        //   ... | ...     - Disjunction of two conditions
        //   ! ...         - Negotation of match
        //   **/ or **\     - Any path
        //   ( ... )       - Pattern group
        //
        // Example:
        //   **/((*.c|*.h)&(test-*)) - matches any source/header C files for any subdirectory starting with 'test-' prefix
        class PathPattern
        {
            public:
                enum flags
                {
                    INVERSE         = 1 << 0,
                    MATCH_CASE      = 1 << 1,
                    FULL_PATH       = 1 << 2,

                    NONE            = 0
                };

            protected:
                enum command_t
                {
                    CMD_SEQUENCE,       // cmd1 cmd2 ...
                    CMD_AND,            // ... & ...
                    CMD_OR,             // ... | ...
                    CMD_PATTERN,        // ... text ...
                    CMD_ANY,            // ... * ...
                    CMD_ANYPATH,        // ... **/ ...
                };

                enum matcher_type_t
                {
                    M_PATTERN,
                    M_ANY,
                    M_ANYPATH,
                    M_BOOL,
                    M_SEQUENCE,
                    M_BRUTE
                };

                enum token_type_t
                {
                    T_GROUP_START,      // (
                    T_IGROUP_START,     // !(
                    T_GROUP_END,        // )
                    T_OR,               // |
                    T_AND,              // &
                    T_NOT,              // !
                    T_TEXT,             // text
                    T_ANY,              // *
                    T_ANYPATH,          // **/
                    T_EOF               // <eof>
                };

                typedef struct cmd_t
                {
                    command_t               nCommand;   // Command
                    size_t                  nStart;     // Start of character sequence
                    size_t                  nLength;    // Length of character sequence
                    ssize_t                 nChars;     // Actual length in characters (without escaping)
                    bool                    bInverse;   // Inverse condition flag
                    lltl::parray<cmd_t>     sChildren;
                } cmd_t;

                typedef struct tokenizer_t
                {
                    ssize_t                 nToken;

                    const LSPString        *pMask;
                    size_t                  nPosition;
                    size_t                  nStart;     // Start position of token data
                    size_t                  nLength;    // Length of character sequence
                    ssize_t                 nChars;     // Actual length in characters (without escaping)
                } token_t;

            protected:
                struct matcher_t;

                typedef struct pos_t
                {
                    size_t                  start;
                    size_t                  count;
                } pos_t;

                typedef bool        (*match_match_t)(matcher_t *m, size_t start, size_t count);

                typedef struct matcher_t
                {
                    matcher_type_t          type;       // Type of matcher
                    match_match_t           match;

                    const cmd_t            *cmd;        // Command
                    const LSPString        *pat;        // Pattern data
                    const LSPString        *str;        // Destination string to match
                    size_t                  flags;      // Flags
                } matcher_t;

                typedef struct any_matcher_t : public matcher_t
                {
                    ssize_t                 bad;        // Index of last bad character
                    ssize_t                 good;       // Index of last good match
                } any_matcher_t;

                typedef struct bool_matcher_t : public matcher_t
                {
                    lltl::parray<matcher_t> cond;       // List of additionally checked conditions
                } bool_matcher_t;

                typedef struct mregion_t
                {
                    size_t                  start;      // Start of the region
                    matcher_t              *matcher;    // Matcher assigned to the region
                    const cmd_t            *cmd;        // Command
                } mregion_t;

                typedef struct sequence_matcher_t: public matcher_t
                {
                    size_t                  prefix;     // Number of fixed prefixes
                    size_t                  postfix;    // Number of fixed postfixes
                    lltl::darray<mregion_t> fixed;      // Fixed text regions
                    lltl::parray<matcher_t> var;        // Variable text regions
                } sequence_matcher_t;

                typedef struct brute_matcher_t: public matcher_t
                {
                    lltl::darray<mregion_t> items;      // Matching regions
                } brute_matcher_t;

            protected:
                LSPString                   sMask;
                cmd_t                      *pRoot;
                size_t                      nFlags;

            private:
                PathPattern & operator = (const PathPattern &);

            protected:
                status_t                    parse(const LSPString *pattern, size_t flags = NONE);
                bool                        match_full(const LSPString *path) const;

                static ssize_t              get_token(tokenizer_t *it);
                static inline void          next_token(tokenizer_t *it);
                static status_t             parse_not(cmd_t **dst, tokenizer_t *it);
                static status_t             parse_and(cmd_t **dst, tokenizer_t *it);
                static status_t             parse_or(cmd_t **dst, tokenizer_t *it);
                static status_t             parse_sequence(cmd_t **dst, tokenizer_t *it);
                static void                 destroy_cmd(cmd_t *cmd);
                static status_t             merge_simple(cmd_t **out, command_t type, command_t cmd, tokenizer_t *it);
                static status_t             merge_step(cmd_t **out, cmd_t *next, command_t type);
                static status_t             merge_last(cmd_t **dst, cmd_t *out, cmd_t *next, ssize_t tok);

                static matcher_t           *create_matcher(const matcher_t *src, const cmd_t *cmd);
                static bool                 add_range_matcher(sequence_matcher_t *sm, const pos_t *pos);
                static void                 destroy_matcher(matcher_t *match);

                static bool                 pattern_matcher_match(matcher_t *m, size_t start, size_t count);
                static bool                 any_matcher_match(matcher_t *m, size_t start, size_t count);
                static bool                 anypath_matcher_match(matcher_t *m, size_t start, size_t count);
                static bool                 and_matcher_match(matcher_t *m, size_t start, size_t count);
                static bool                 or_matcher_match(matcher_t *m, size_t start, size_t count);
                static bool                 sequence_matcher_match(matcher_t *m, size_t start, size_t count);
                static bool                 brute_matcher_match(matcher_t *m, size_t start, size_t count);

                static bool                 check_pattern_case(const lsp_wchar_t *pat, const lsp_wchar_t *s, size_t len);
                static bool                 check_pattern_nocase(const lsp_wchar_t *pat, const lsp_wchar_t *s, size_t len);
                static ssize_t              seek_pattern_case(const lsp_wchar_t *pat, const lsp_wchar_t *s, size_t len, ssize_t rounds);
                static ssize_t              seek_pattern_nocase(const lsp_wchar_t *pat, const lsp_wchar_t *s, size_t len, ssize_t rounds);

                static ssize_t              sequence_check_prefix(sequence_matcher_t *sm, size_t start, size_t count);
                static ssize_t              sequence_check_postfix(sequence_matcher_t *sm, size_t start, size_t count);
                static bool                 sequence_alloc_fixed(sequence_matcher_t *sm, size_t idx, size_t start, size_t count);
                static bool                 sequence_next_fixed(sequence_matcher_t *sm, size_t start, size_t count);
                static bool                 sequence_match_variable(sequence_matcher_t *sm, size_t start, size_t count);

                static bool                 brute_match_variable(brute_matcher_t *bm, size_t start, size_t count);
                static bool                 brute_next_variable(brute_matcher_t *bm, size_t start, size_t count);

            public:
                explicit PathPattern();
                ~PathPattern();

            public:
                status_t                    set(const PathPattern *src)                                 { return parse(&src->sMask, src->nFlags);   }
                status_t                    set(const Path *pattern, size_t flags = NONE)               { return parse(pattern->as_string(), flags);}
                status_t                    set(const LSPString *pattern, size_t flags = NONE)          { return parse(pattern, flags);             }
                status_t                    set(const char *pattern, size_t flags = NONE);

                inline const char          *get_utf8() const                                            { return sMask.get_utf8();                  }
                inline const LSPString     *get() const                                                 { return &sMask;                            }
                inline status_t             get(LSPString *mask) const                                  { return (mask != NULL) ? mask->set(&sMask) : STATUS_BAD_ARGUMENTS; }
                inline status_t             get(Path *mask) const                                       { return (mask != NULL) ? mask->set(&sMask) : STATUS_BAD_ARGUMENTS; }

                inline size_t               flags() const                                               { return nFlags;                            }
                size_t                      set_flags(size_t flags);

                inline status_t             set_pattern(const PathPattern *src)                         { return set(&src->sMask, nFlags);          }
                inline status_t             set_pattern(const LSPString *pattern)                       { return set(pattern, nFlags);              }
                inline status_t             set_pattern(const Path *pattern)                            { return set(pattern, nFlags);              }
                inline status_t             set_pattern(const char *pattern)                            { return set(pattern, nFlags);              }

                bool                        test(const char *path) const;
                bool                        test(const LSPString *path) const;
                bool                        test(const Path *path) const;

                void                        swap(PathPattern *dst);
                inline void                 swap(PathPattern &dst)                                      { swap(&dst);                               }
        };
    }
} /* namespace lsp */

#endif /* LSP_PLUG_IN_IO_PATHPATTERN_H_ */