2 * Copyright 2005 Timo Hirvonen
14 struct list_head node
;
30 static void simplify(struct list_head
*head
)
32 struct list_head
*item
;
35 while (item
!= head
) {
36 struct list_head
*i
, *next
;
44 gi
= container_of(i
, struct glob_item
, node
);
45 if (gi
->type
== GLOB_STAR
) {
47 } else if (gi
->type
== GLOB_QMARK
) {
59 /* move all qmarks to front and
60 * if there are >1 stars remove all but the last */
61 struct list_head
*insert_after
= item
->prev
;
67 gi
= container_of(i
, struct glob_item
, node
);
69 if (gi
->type
== GLOB_QMARK
) {
71 list_add(&gi
->node
, insert_after
);
80 gi
= container_of(i
, struct glob_item
, node
);
82 if (gi
->type
== GLOB_STAR
) {
94 void glob_compile(struct list_head
*head
, const char *pattern
)
100 struct glob_item
*item
;
102 if (pattern
[i
] == '*') {
103 item
= xnew(struct glob_item
, 1);
104 item
->type
= GLOB_STAR
;
106 } else if (pattern
[i
] == '?') {
107 item
= xnew(struct glob_item
, 1);
108 item
->type
= GLOB_QMARK
;
117 if (pattern
[i
] == '\\') {
122 } else if (pattern
[i
] == '*') {
124 } else if (pattern
[i
] == '?') {
132 item
= xmalloc(sizeof(struct glob_item
) + len
+ 1);
133 item
->type
= GLOB_TEXT
;
139 if (pattern
[i
] == '\\') {
142 str
[j
++] = pattern
[i
++];
147 str
[j
++] = pattern
[i
++];
152 list_add_tail(&item
->node
, head
);
157 void glob_free(struct list_head
*head
)
159 struct list_head
*item
= head
->next
;
161 while (item
!= head
) {
162 struct glob_item
*gi
;
163 struct list_head
*next
= item
->next
;
165 gi
= container_of(item
, struct glob_item
, node
);
171 static int do_glob_match(struct list_head
*head
, struct list_head
*first
, const char *text
)
173 struct list_head
*item
= first
;
175 while (item
!= head
) {
176 struct glob_item
*gitem
;
178 gitem
= container_of(item
, struct glob_item
, node
);
179 if (gitem
->type
== GLOB_TEXT
) {
180 int len
= u_strlen(gitem
->text
);
182 if (u_strncasecmp(gitem
->text
, text
, len
))
184 text
+= strlen(gitem
->text
);
185 } else if (gitem
->type
== GLOB_QMARK
) {
189 u_get_char(text
, &idx
, &u
);
193 } else if (gitem
->type
== GLOB_STAR
) {
194 /* after star there MUST be normal text (or nothing),
195 * question marks have been moved before this star and
196 * other stars have been sripped (see simplify)
198 struct list_head
*next
;
199 struct glob_item
*next_gi
;
205 /* this star was the last item => matched */
208 next_gi
= container_of(next
, struct glob_item
, node
);
209 BUG_ON(next_gi
->type
!= GLOB_TEXT
);
215 pos
= u_strcasestr(text
, t
);
218 if (do_glob_match(head
, next
->next
, pos
+ tlen
))
228 int glob_match(struct list_head
*head
, const char *text
)
230 return do_glob_match(head
, head
->next
, text
);