]> git.8kb.co.uk Git - dataflex/df32func/blob - src/df32/regex.inc
Amend functionality of antiquated matrix methods and minor changes to matrix parsing...
[dataflex/df32func] / src / df32 / regex.inc
1 //-------------------------------------------------------------------------\r
2 // regex.inc\r
3 //      This file contains DataFlex functions to provide basic regex \r
4 //      functionality based on the GNU POSIX regex library, and accessed\r
5 //      via Win32 API calls to df32func.dll.  \r
6 //      See df32func.h for external function definitions.\r
7 //\r
8 // This file is to be included when using Win32 capabilities in df32func.mk\r
9 //\r
10 // Copyright (c) 2006-2015, glyn@8kb.co.uk\r
11 // \r
12 // df32func/regex.inc\r
13 //-------------------------------------------------------------------------\r
14 \r
15 #IFDEF __df32func_h__\r
16 #ELSE\r
17     #INCLUDE df32func.h\r
18 #ENDIF\r
19 \r
20 //-------------------------------------------------------------------------\r
21 // Functions\r
22 //-------------------------------------------------------------------------\r
23 \r
24 // All the regex function accept a set of flags, this can be one or more of:\r
25 //      g = Perform match against each substring rather than just the first (greedy)\r
26 //      n = Perform newline-sensitive matching\r
27 //      i = Perform cases insensitive matching\r
28 \r
29 //Purely check if a regex expression produces match in the input string\r
30 // Returns 1 on match, 0 on no match\r
31 //    E.g\r
32 //    move (regexp_match('the quick brown fox jumps over the lazy dog.', 'fox', 'g'))\r
33 function regexp_match global string str string pattern string flags returns integer\r
34     local integer l_iReturn\r
35     local pointer l_pStr l_pPattern l_pFlags\r
36     \r
37     getaddress of str to l_pStr\r
38     getaddress of pattern to l_pPattern\r
39     getaddress of flags to l_pFlags\r
40     \r
41     move (RegexpMatch(l_pStr, l_pPattern, l_pFlags, ERRORS_TO_STDERR)) to l_iReturn\r
42     \r
43     function_return l_iReturn\r
44 end_function   \r
45 \r
46 //Return a string containing all regex matches in the input string\r
47 //    E.g\r
48 //    move (regexp_matches('the quick brown fox jumps over the la\{zy d"og.', 'fox|(the)|brown|(la\\\{zy)|(d"og)', 'g')) to myString\r
49 function regexp_matches global string str string pattern string flags returns string\r
50     local integer l_iReturn\r
51     local pointer l_pStr l_pPattern l_pFlags l_pOut\r
52     local string l_sOut l_sReturn\r
53     \r
54     move "" to l_sReturn\r
55     getaddress of str to l_pStr\r
56     getaddress of pattern to l_pPattern\r
57     getaddress of flags to l_pFlags\r
58     zerostring MAX_DFREGEX_BUFFER to l_sOut\r
59     getaddress of l_sOut to l_pOut\r
60     \r
61     move (RegexpMatches(l_pStr, l_pPattern, l_pFlags, l_pOut, MAX_DFREGEX_BUFFER, ERRORS_TO_STDERR)) to l_iReturn\r
62     \r
63     if (l_iReturn = 0);\r
64         move (cstring(l_sOut)) To l_sReturn\r
65     else begin\r
66         if (l_iReturn = -1);\r
67             custom_error ERROR_CODE_REGEX_BUFFER_OVERFLOW$ ERROR_MSG_REGEX_BUFFER_OVERFLOW MAX_DFREGEX_BUFFER           \r
68         if (l_iReturn = -2);\r
69                         custom_error ERROR_CODE_REGEX_COMPILE_FAILURE$ ERROR_MSG_REGEX_COMPILE_FAILURE\r
70         move "" to l_sReturn\r
71     end\r
72     \r
73     function_return l_sReturn\r
74 end_function \r
75 \r
76 //Perform a replacement on the input string all matches with the given pattern\r
77 //    E.g.\r
78 //    move (regexp_replace('22 quick brown foxes jump over the 44 lazy dogs.', '([0-9]*).* (foxes) .* ([0-9]*) .* (dogs).*', 'SELECT build_data(\1,\2), build_data(\3,\4);', 'g')) to myString\r
79 function regexp_replace global string str string pattern string replacement string flags returns string\r
80     local integer l_iReturn\r
81     local pointer l_pStr l_pPattern l_pFlags l_pReplacement l_pOut\r
82     local string l_sOut l_sReturn\r
83     \r
84     move "" to l_sReturn\r
85     getaddress of str to l_pStr\r
86     getaddress of pattern to l_pPattern\r
87     getaddress of flags to l_pFlags\r
88     getaddress of replacement to l_pReplacement\r
89     zerostring MAX_DFREGEX_BUFFER to l_sOut\r
90     getaddress of l_sOut to l_pOut\r
91     \r
92     move (RegexpReplace(l_pStr, l_pPattern, l_pReplacement, l_pFlags, l_pOut, MAX_DFREGEX_BUFFER, ERRORS_TO_STDERR)) to l_iReturn\r
93     \r
94     if (l_iReturn = 0);\r
95         move (cstring(l_sOut)) To l_sReturn\r
96     else begin\r
97         if (l_iReturn = -1);\r
98             custom_error ERROR_CODE_REGEX_BUFFER_OVERFLOW$ ERROR_MSG_REGEX_BUFFER_OVERFLOW MAX_DFREGEX_BUFFER           \r
99         if (l_iReturn = -2);\r
100                         custom_error ERROR_CODE_REGEX_COMPILE_FAILURE$ ERROR_MSG_REGEX_COMPILE_FAILURE\r
101         move "" to l_sReturn\r
102     end\r
103             \r
104     function_return l_sReturn\r
105 end_function \r
106 \r
107 // Parse an output string from regexp_matches to get the result count\r
108 //    E.g\r
109 //    move (regexp_matches_count(myRegexMatchesOutput)) to myInt\r
110 function regexp_matches_count global string argv returns integer\r
111     local integer l_iCount l_i\r
112     local string l_sChar l_sLast\r
113     \r
114     move "" to l_sChar\r
115     move "" to l_sLast\r
116     for l_i from 0 to (length(argv))\r
117         move (mid(argv,1,l_i)) to l_sChar\r
118         if ((l_sChar = '{') and (l_sLast <> '\')) increment l_iCount\r
119         move l_sChar to l_sLast\r
120     loop\r
121     \r
122     function_return l_iCount\r
123 end_function\r
124 \r
125 // Parse an output string from regexp_matches to get the result at an index\r
126 // This can then be treated as csv data.\r
127 //    E.g\r
128 //    move (regexp_matches_item(myRegexMatchesOutput,muInt)) to myString\r
129 //    object mt is a StringTokenizer\r
130 //    end_object\r
131 //    move (regexp_matches_count(myString)) to myCount\r
132 //    for i from 1 to myCount\r
133 //        move (regexp_matches_item(myString,i)) to bufString\r
134 //        send delete_data to mt    \r
135 //        send set_string_csv to mt bufString\r
136 //        get token_count of mt to myTokenCount\r
137 //        for j from 0 to myTokenCount\r
138 //            get token_value of mt item j to bufString\r
139 //           showln i "-" j ")" buf\r
140 //        loop\r
141 //  loop\r
142 function regexp_matches_item global string argv integer argv2 returns string\r
143     local integer l_iCount l_i\r
144     local string l_sChar l_sLast l_sReturn\r
145     \r
146     move "" to l_sChar\r
147     move "" to l_sLast\r
148     move "" to l_sReturn\r
149     for l_i from 0 to (length(argv))\r
150         move (mid(argv,1,l_i)) to l_sChar\r
151         move (mid(argv,1,l_i-1)) to l_sLast\r
152         if ((l_sChar = '{') and (l_sLast <> '\')) increment l_iCount        \r
153         if ((l_sChar = '}') and (l_sLast <> '\') and (l_iCount = argv2)) break\r
154         if (((l_sChar = '{') and (l_sLast <> '\')) or (l_iCount < argv2)) break begin\r
155         \r
156         append l_sReturn l_sChar\r
157     loop\r
158     \r
159     function_return l_sReturn\r
160 end_function\r
161 \r
162 // Parse an output string from regexp_matches to get the result at an index\r
163 // stripping out all escaping.\r
164 //    E.g\r
165 //    move (regexp_matches_item_stripped(myRegexMatchesOutput,muInt)) to myString\r
166 function regexp_matches_item_stripped global string argv integer argv2 returns string\r
167     local integer l_iCount l_i l_iOpen l_iQuot\r
168     local string l_sChar l_sLast l_sNext l_sBuf\r
169     \r
170     move 0 to l_iCount\r
171     move 0 to l_iOpen\r
172     move 0 to l_iQuot\r
173     move "" to l_sLast\r
174     for l_i from 0 to (length(argv))\r
175         move (mid(argv,1,l_i)) to l_sChar\r
176         move (mid(argv,1,l_i-1)) to l_sLast\r
177         \r
178         if ((l_sChar = '{') and (l_sLast <> '\')) increment l_iCount        \r
179         if (l_iCount <> argv2) break begin\r
180 \r
181         move (mid(argv,1,l_i+1)) to l_sNext\r
182         \r
183         if ((l_sChar = '{') and not (l_iQuot)) begin\r
184             move 1 to l_iOpen\r
185             move "" to l_sBuf   \r
186         end     \r
187         else if ((l_sChar = '}') and not (l_iQuot)) begin\r
188             move 0 to l_iOpen\r
189         end \r
190         else if ((l_sChar = '"') and (l_sLast <> '\')) begin\r
191             if (l_iQuot) move 0 to l_iQuot\r
192             else move 1 to l_iQuot\r
193         end\r
194         if ((l_sChar = ',') and not (l_iOpen)) break begin\r
195         if (((l_sChar = '{') or (l_sChar = '}')) and not (l_iQuot)) break begin\r
196         if ((l_sChar = '"') and (l_sLast <> '\')) break begin\r
197         if ((l_iQuot) and (l_sChar = '\') and ((l_sNext = '"') or (l_sNext = '\'))) break begin\r
198         \r
199         append l_sBuf l_sChar       \r
200     loop\r
201     \r
202     function_return l_sBuf\r
203 end_function\r