2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 Primitives for regular expression search by Florian Schmidt, adapted to ICU by Jan Trutzschler
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #if !defined(SC_WIN32) && !defined(SC_IPHONE)
24 struct URegularExpression
;
26 * Structure represeting a compiled regular rexpression, plus the results
27 * of a match operation.
30 typedef struct URegularExpression URegularExpression
;
32 #define U_HIDE_DRAFT_API 1
34 #define U_DISABLE_RENAMING 1
36 #include <unicode/uregex.h>
37 #include <unicode/ustring.h>
38 #include <unicode/udraft.h>
39 #include "PyrPrimitive.h"
40 #include "PyrKernel.h"
48 SCRegExRegion(int start
, int end
, int group
, int matched
):
49 start(start
), end(end
), group(group
), matched(matched
)
52 int start
, end
, group
, matched
;
55 typedef struct SCRegExRegion SCRegExRegion
;
57 static int prString_FindRegexp(struct VMGlobals
*g
, int numArgsPushed
)
59 PyrSlot
*a
= g
->sp
- 2; // source string
60 PyrSlot
*b
= g
->sp
- 1; // pattern
61 PyrSlot
*c
= g
->sp
; // offset
63 if (!isKindOfSlot(b
, class_string
) || (NotInt(c
))) return errWrongType
;
64 // post("prString_FindRegexp\n");
65 int offset
= slotRawInt(c
);
66 int stringsize
= slotRawObject(a
)->size
+ 1;
67 int patternsize
= slotRawObject(b
)->size
+ 1;
68 char *string
= (char*)malloc(slotRawObject(a
)->size
+ 1);
69 int err
= slotStrVal(a
, string
, slotRawObject(a
)->size
+ 1);
74 char *pattern
= (char*)malloc(slotRawObject(b
)->size
+ 1);
75 err
= slotStrVal(b
, pattern
, slotRawObject(b
)->size
+ 1);
77 UErrorCode status
= (UErrorCode
)0;
79 UChar
*regexStr
= (UChar
*)malloc((patternsize
)*sizeof(UChar
));
80 u_charsToUChars (pattern
, regexStr
, patternsize
);
82 UChar
*ustring
= (UChar
*)malloc((stringsize
)*sizeof(UChar
));
83 u_charsToUChars (string
+offset
, ustring
, stringsize
-offset
);
85 unsigned flags
= UREGEX_MULTILINE
;
88 URegularExpression
*expression
= uregex_open(regexStr
, -1, flags
, &uerr
, &status
);
90 if(!U_FAILURE(status
)) {
92 uregex_setText(expression
, ustring
, -1, &status
);
93 std::vector
<SCRegExRegion
> what
;
96 int32_t groups
= uregex_groupCount(expression
, &status
) + 1;
97 if(U_FAILURE(status
)) goto nilout
;
98 // post("groups: %i\n", groups);
99 while (uregex_findNext(expression
, &status
))
101 if(U_FAILURE(status
)) goto nilout
;
103 for(int i
=0; i
< groups
; ++i
) {
105 int start
= sc_clip(uregex_start(expression
, i
, &status
), 0, stringsize
) ;
106 if(U_FAILURE(status
))
109 int end
= sc_clip(uregex_end(expression
, i
, &status
), 0, stringsize
);
110 if(U_FAILURE(status
))
113 what
.push_back(SCRegExRegion(start
, end
, group
, matched
));
118 PyrObject
*result_array
= newPyrArray(g
->gc
, size
, 0, true);
119 result_array
->size
= 0;
120 SetObject(a
, result_array
);
122 if (size
>0) //(matched)
124 const int stackBufSize
= 4096;
125 char match_buffer
[stackBufSize
];
126 for (int i
= 0; i
< size
; i
++)
128 assert(what
[i
].matched
);
130 int match_start
= what
[i
].start
;
131 int match_length
= what
[i
].end
- what
[i
].start
;
132 // post("for i:%i, start %i, end %i\n", i, what[i].start, what[i].end);
133 char * match
= match_length
< stackBufSize
? match_buffer
: (char*)malloc(match_length
+1);
135 strncpy(match
, string
+ offset
+ match_start
, match_length
);
136 match
[match_length
] = 0;
137 PyrObject
*array
= newPyrArray(g
->gc
, 2, 0, true);
138 SetObject(result_array
->slots
+ i
, array
);
139 result_array
->size
++;
140 g
->gc
->GCWrite(result_array
, array
);
142 PyrObject
*matched_string
= (PyrObject
*)newPyrString(g
->gc
, match
, 0, true);
145 SetInt(array
->slots
, match_start
+ offset
);
146 SetObject(array
->slots
+1, matched_string
);
147 g
->gc
->GCWrite(array
, matched_string
);
149 if (match_length
>= stackBufSize
)
158 uregex_close(expression
);
168 uregex_close(expression
);
172 void initUStringPrimitives()
175 base
= nextPrimitiveIndex();
176 definePrimitive(base
, index
++, "_String_FindRegexp", prString_FindRegexp
, 3, 0);
180 void initUStringPrimitives()