1 | /* Copyright Vladimir Prus 2003. Distributed under the Boost */ |
---|
2 | /* Software License, Version 1.0. (See accompanying */ |
---|
3 | /* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ |
---|
4 | |
---|
5 | #include "../native.h" |
---|
6 | #include "../timestamp.h" |
---|
7 | #include "../newstr.h" |
---|
8 | #include "../strings.h" |
---|
9 | #include "../regexp.h" |
---|
10 | #include "../compile.h" |
---|
11 | |
---|
12 | /* |
---|
13 | rule transform ( list * : pattern : indices * ) |
---|
14 | { |
---|
15 | indices ?= 1 ; |
---|
16 | local result ; |
---|
17 | for local e in $(list) |
---|
18 | { |
---|
19 | local m = [ MATCH $(pattern) : $(e) ] ; |
---|
20 | if $(m) |
---|
21 | { |
---|
22 | result += $(m[$(indices)]) ; |
---|
23 | } |
---|
24 | } |
---|
25 | return $(result) ; |
---|
26 | } |
---|
27 | */ |
---|
28 | LIST *regex_transform( PARSE *parse, FRAME *frame ) |
---|
29 | { |
---|
30 | LIST* l = lol_get( frame->args, 0 ); |
---|
31 | LIST* pattern = lol_get( frame->args, 1 ); |
---|
32 | LIST* indices_list = lol_get(frame->args, 2); |
---|
33 | int* indices = 0; |
---|
34 | int size; |
---|
35 | int* p; |
---|
36 | LIST* result = 0; |
---|
37 | |
---|
38 | string buf[1]; |
---|
39 | string_new(buf); |
---|
40 | |
---|
41 | if (indices_list) |
---|
42 | { |
---|
43 | size = list_length(indices_list); |
---|
44 | indices = (int*)malloc(size*sizeof(int)); |
---|
45 | for(p = indices; indices_list; indices_list = indices_list->next) |
---|
46 | { |
---|
47 | *p++ = atoi(indices_list->string); |
---|
48 | } |
---|
49 | } |
---|
50 | else |
---|
51 | { |
---|
52 | size = 1; |
---|
53 | indices = (int*)malloc(sizeof(int)); |
---|
54 | *indices = 1; |
---|
55 | } |
---|
56 | |
---|
57 | { |
---|
58 | /* Result is cached and intentionally never freed */ |
---|
59 | regexp *re = regex_compile( pattern->string ); |
---|
60 | |
---|
61 | for(; l; l = l->next) |
---|
62 | { |
---|
63 | if( regexec( re, l->string ) ) |
---|
64 | { |
---|
65 | int i = 0; |
---|
66 | for(; i < size; ++i) |
---|
67 | { |
---|
68 | int index = indices[i]; |
---|
69 | /* Skip empty submatches. Not sure it's right in all cases, |
---|
70 | but surely is right for the case for which this routine |
---|
71 | is optimized -- header scanning. |
---|
72 | */ |
---|
73 | if (re->startp[index] != re->endp[index]) |
---|
74 | { |
---|
75 | string_append_range( buf, re->startp[index], re->endp[index] ); |
---|
76 | result = list_new( result, newstr( buf->value ) ); |
---|
77 | string_truncate( buf, 0 ); |
---|
78 | } |
---|
79 | } |
---|
80 | } |
---|
81 | } |
---|
82 | string_free( buf ); |
---|
83 | } |
---|
84 | |
---|
85 | free(indices); |
---|
86 | |
---|
87 | return result; |
---|
88 | } |
---|
89 | |
---|
90 | void init_regex() |
---|
91 | { |
---|
92 | { |
---|
93 | char* args[] = { "list", "*", ":", "pattern", ":", "indices", "*", 0 }; |
---|
94 | declare_native_rule("regex", "transform", args, regex_transform, 2); |
---|
95 | } |
---|
96 | } |
---|