Examples under Synth:new should not use SynthDef:play to make nodes
[supercollider.git] / lang / LangPrimSource / PyrUStringPrim.cpp
blobe7a4ee4492bec16a4bc778f8b6dfdd0134bd68b3
1 /*
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;
25 /**
26 * Structure represeting a compiled regular rexpression, plus the results
27 * of a match operation.
28 * @draft ICU 3.0
30 typedef struct URegularExpression URegularExpression;
32 #define U_HIDE_DRAFT_API 1
33 #ifdef SC_DARWIN
34 #define U_DISABLE_RENAMING 1
35 #endif
36 #include <unicode/uregex.h>
37 #include <unicode/ustring.h>
38 #include <unicode/udraft.h>
39 #include "PyrPrimitive.h"
40 #include "PyrKernel.h"
41 #include "GC.h"
42 #include <cstring>
43 #include <vector>
46 struct SCRegExRegion
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);
70 if (err){
71 free(string);
72 return err;
74 char *pattern = (char*)malloc(slotRawObject(b)->size + 1);
75 err = slotStrVal(b, pattern, slotRawObject(b)->size + 1);
76 if (err) return err;
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;
87 UParseError uerr;
88 URegularExpression *expression = uregex_open(regexStr, -1, flags, &uerr, &status);
90 if(!U_FAILURE(status)) {
91 int size = 0;
92 uregex_setText(expression, ustring, -1, &status);
93 std::vector<SCRegExRegion> what;
94 what.reserve(512);
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) {
104 int group = i;
105 int start = sc_clip(uregex_start(expression, i, &status), 0, stringsize) ;
106 if(U_FAILURE(status))
107 goto nilout;
108 int matched = true;
109 int end = sc_clip(uregex_end(expression, i, &status), 0, stringsize);
110 if(U_FAILURE(status))
111 goto nilout;
113 what.push_back(SCRegExRegion(start, end, group, matched));
114 ++size;
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);
144 array->size = 2;
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)
150 free(match);
154 free(pattern);
155 free(regexStr);
156 free(ustring);
157 free(string);
158 uregex_close(expression);
159 return errNone;
162 nilout:
163 free(string);
164 free(pattern);
165 free(regexStr);
166 free(ustring);
167 SetNil(a);
168 uregex_close(expression);
169 return errFailed;
172 void initUStringPrimitives()
174 int base, index = 0;
175 base = nextPrimitiveIndex();
176 definePrimitive(base, index++, "_String_FindRegexp", prString_FindRegexp, 3, 0);
179 #else
180 void initUStringPrimitives()
182 //other platforms?
184 #endif