1 | /* |
2 | * This Source Code Form is subject to the terms of the Mozilla Public |
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
5 | * |
6 | * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V. |
7 | */ |
8 | |
9 | /* |
10 | * M.L. Kersten |
11 | * String multiplexes |
12 | * [TODO: property propagations] |
13 | * The collection of routines provided here are map operations |
14 | * for the atom string primitives. |
15 | * |
16 | * In line with the batcalc module, we assume that if two bat operands |
17 | * are provided that they are aligned. |
18 | */ |
19 | #include "monetdb_config.h" |
20 | #include "gdk.h" |
21 | #include <ctype.h> |
22 | #include <string.h> |
23 | #include "mal_exception.h" |
24 | #include "str.h" |
25 | |
26 | mal_export str STRbatPrefix(bat *ret, const bat *l, const bat *r); |
27 | mal_export str STRbatPrefixcst(bat *ret, const bat *l, const str *cst); |
28 | mal_export str STRbatSuffix(bat *ret, const bat *l, const bat *r); |
29 | mal_export str STRbatSuffixcst(bat *ret, const bat *l, const str *cst); |
30 | mal_export str STRbatstrSearch(bat *ret, const bat *l, const bat *r); |
31 | mal_export str STRbatstrSearchcst(bat *ret, const bat *l, const str *cst); |
32 | mal_export str STRbatRstrSearch(bat *ret, const bat *l, const bat *r); |
33 | mal_export str STRbatRstrSearchcst(bat *ret, const bat *l, const str *cst); |
34 | mal_export str STRbatTail(bat *ret, const bat *l, const bat *r); |
35 | mal_export str STRbatTailcst(bat *ret, const bat *l, const int *cst); |
36 | mal_export str STRbatWChrAt(bat *ret, const bat *l, const bat *r); |
37 | mal_export str STRbatWChrAtcst(bat *ret, const bat *l, const int *cst); |
38 | mal_export str STRbatSubstitutecst(bat *ret, const bat *l, const str *arg2, const str *arg3, const bit *rep); |
39 | |
40 | mal_export str STRbatLower(bat *ret, const bat *l); |
41 | mal_export str STRbatUpper(bat *ret, const bat *l); |
42 | mal_export str STRbatStrip(bat *ret, const bat *l); |
43 | mal_export str STRbatLtrim(bat *ret, const bat *l); |
44 | mal_export str STRbatRtrim(bat *ret, const bat *l); |
45 | mal_export str STRbatStrip2_const(bat *ret, const bat *l, const str *s2); |
46 | mal_export str STRbatLtrim2_const(bat *ret, const bat *l, const str *s2); |
47 | mal_export str STRbatRtrim2_const(bat *ret, const bat *l, const str *s2); |
48 | mal_export str STRbatStrip2_bat(bat *ret, const bat *l, const bat *l2); |
49 | mal_export str STRbatLtrim2_bat(bat *ret, const bat *l, const bat *l2); |
50 | mal_export str STRbatRtrim2_bat(bat *ret, const bat *l, const bat *l2); |
51 | |
52 | mal_export str STRbatLpad_const(bat *ret, const bat *l, const int *n); |
53 | mal_export str STRbatRpad_const(bat *ret, const bat *l, const int *n); |
54 | mal_export str STRbatLpad_bat(bat *ret, const bat *l, const bat *n); |
55 | mal_export str STRbatRpad_bat(bat *ret, const bat *l, const bat *n); |
56 | mal_export str STRbatLpad2_const_const(bat *ret, const bat *l, const int *n, const str *s2); |
57 | mal_export str STRbatRpad2_const_const(bat *ret, const bat *l, const int *n, const str *s2); |
58 | mal_export str STRbatLpad2_bat_const(bat *ret, const bat *l, const bat *n, const str *s2); |
59 | mal_export str STRbatRpad2_bat_const(bat *ret, const bat *l, const bat *n, const str *s2); |
60 | mal_export str STRbatLpad2_const_bat(bat *ret, const bat *l, const int *n, const bat *l2); |
61 | mal_export str STRbatRpad2_const_bat(bat *ret, const bat *l, const int *n, const bat *l2); |
62 | mal_export str STRbatLpad2_bat_bat(bat *ret, const bat *l, const bat *n, const bat *l2); |
63 | mal_export str STRbatRpad2_bat_bat(bat *ret, const bat *l, const bat *n, const bat *l2); |
64 | |
65 | mal_export str STRbatLength(bat *ret, const bat *l); |
66 | mal_export str STRbatBytes(bat *ret, const bat *l); |
67 | |
68 | mal_export str STRbatsubstringcst(bat *ret, const bat *bid, const int *start, const int *length); |
69 | mal_export str STRbatsubstring(bat *ret, const bat *l, const bat *r, const bat *t); |
70 | |
71 | |
72 | #define prepareOperand(X,Y,Z) \ |
73 | if( (X= BATdescriptor(*Y)) == NULL ) \ |
74 | throw(MAL, Z, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
75 | #define prepareOperand2(X,Y,A,B,Z) \ |
76 | if( (X= BATdescriptor(*Y)) == NULL ) \ |
77 | throw(MAL, Z, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); \ |
78 | if( (A= BATdescriptor(*B)) == NULL ){ \ |
79 | BBPunfix(X->batCacheid); \ |
80 | throw(MAL, Z, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); \ |
81 | } |
82 | #define prepareOperand3(X,Y,A,B,I,J,Z) \ |
83 | if( (X= BATdescriptor(*Y)) == NULL ) \ |
84 | throw(MAL, Z, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); \ |
85 | if( (A= BATdescriptor(*B)) == NULL ){ \ |
86 | BBPunfix(X->batCacheid); \ |
87 | throw(MAL, Z, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); \ |
88 | } \ |
89 | if( (I= BATdescriptor(*J)) == NULL ){ \ |
90 | BBPunfix(X->batCacheid); \ |
91 | BBPunfix(A->batCacheid); \ |
92 | throw(MAL, Z, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); \ |
93 | } |
94 | #define prepareResult(X,Y,T,Z) \ |
95 | X= COLnew((Y)->hseqbase,T,BATcount(Y), TRANSIENT); \ |
96 | if( X == NULL){ \ |
97 | BBPunfix(Y->batCacheid); \ |
98 | throw(MAL, Z, SQLSTATE(HY001) MAL_MALLOC_FAIL); \ |
99 | } \ |
100 | X->tsorted=false; \ |
101 | X->trevsorted=false; |
102 | #define prepareResult2(X,Y,A,T,Z) \ |
103 | X= COLnew((Y)->hseqbase,T,BATcount(Y), TRANSIENT); \ |
104 | if( X == NULL){ \ |
105 | BBPunfix(Y->batCacheid); \ |
106 | BBPunfix(A->batCacheid); \ |
107 | throw(MAL, Z, SQLSTATE(HY001) MAL_MALLOC_FAIL); \ |
108 | } \ |
109 | X->tsorted=false; \ |
110 | X->trevsorted=false; |
111 | #define finalizeResult(X,Y,Z) \ |
112 | (Y)->theap.dirty |= BATcount(Y) > 0; \ |
113 | *X = (Y)->batCacheid; \ |
114 | BBPkeepref(*(X)); \ |
115 | BBPunfix(Z->batCacheid); |
116 | |
117 | static str |
118 | do_batstr_int(bat *ret, const bat *l, const char *name, str (*func)(int *, const str *)) |
119 | { |
120 | BATiter bi; |
121 | BAT *bn, *b; |
122 | BUN p, q; |
123 | str x; |
124 | int y; |
125 | str msg = MAL_SUCCEED; |
126 | |
127 | prepareOperand(b, l, name); |
128 | prepareResult(bn, b, TYPE_int, name); |
129 | |
130 | bi = bat_iterator(b); |
131 | |
132 | BATloop(b, p, q) { |
133 | x = (str) BUNtvar(bi, p); |
134 | if (x == 0 || strcmp(x, str_nil) == 0) { |
135 | y = int_nil; |
136 | bn->tnonil = false; |
137 | bn->tnil = true; |
138 | } else if ((msg = (*func)(&y, &x)) != MAL_SUCCEED) { |
139 | goto bunins_failed; |
140 | } |
141 | bunfastappTYPE(int, bn, &y); |
142 | } |
143 | finalizeResult(ret, bn, b); |
144 | return MAL_SUCCEED; |
145 | bunins_failed: |
146 | BBPunfix(b->batCacheid); |
147 | BBPunfix(bn->batCacheid); |
148 | if (msg != MAL_SUCCEED) |
149 | return msg; |
150 | throw(MAL, name, OPERATION_FAILED " During bulk operation" ); |
151 | } |
152 | |
153 | str |
154 | STRbatLength(bat *ret, const bat *l) |
155 | { |
156 | return do_batstr_int(ret, l, "batstr.Length" , STRLength); |
157 | } |
158 | |
159 | str |
160 | STRbatBytes(bat *ret, const bat *l) |
161 | { |
162 | return do_batstr_int(ret, l, "batstr.Bytes" , STRBytes); |
163 | } |
164 | |
165 | static str |
166 | do_batstr_str(bat *ret, const bat *l, const char *name, str (*func)(str *, const str *)) |
167 | { |
168 | BATiter bi; |
169 | BAT *bn, *b; |
170 | BUN p, q; |
171 | str x, y; |
172 | str msg = MAL_SUCCEED; |
173 | |
174 | prepareOperand(b, l, name); |
175 | prepareResult(bn, b, TYPE_str, name); |
176 | |
177 | bi = bat_iterator(b); |
178 | |
179 | BATloop(b, p, q) { |
180 | y = NULL; |
181 | x = (str) BUNtvar(bi, p); |
182 | if (x != 0 && strcmp(x, str_nil) != 0 && |
183 | (msg = (*func)(&y, &x)) != MAL_SUCCEED) |
184 | goto bunins_failed1; |
185 | if (y == NULL) |
186 | y = (str) str_nil; |
187 | bunfastappVAR(bn, y); |
188 | if (y == str_nil) { |
189 | bn->tnonil = false; |
190 | bn->tnil = true; |
191 | } else |
192 | GDKfree(y); |
193 | } |
194 | finalizeResult(ret, bn, b); |
195 | return MAL_SUCCEED; |
196 | bunins_failed: |
197 | if (y != str_nil) |
198 | GDKfree(y); |
199 | bunins_failed1: |
200 | BBPunfix(b->batCacheid); |
201 | BBPunfix(bn->batCacheid); |
202 | if (msg != MAL_SUCCEED) |
203 | return msg; |
204 | throw(MAL, name, OPERATION_FAILED " During bulk operation" ); |
205 | } |
206 | |
207 | /* Input: a BAT of strings 'l' and a constant string 's2' |
208 | * Output type: str (a BAT of strings) |
209 | */ |
210 | static str |
211 | do_batstr_conststr_str(bat *ret, const bat *l, const str *s2, const char *name, str (*func)(str *, const str *, const str *)) |
212 | { |
213 | BATiter bi; |
214 | BAT *bn, *b; |
215 | BUN p, q; |
216 | str x, y; |
217 | str msg = MAL_SUCCEED; |
218 | |
219 | prepareOperand(b, l, name); |
220 | prepareResult(bn, b, TYPE_str, name); |
221 | |
222 | bi = bat_iterator(b); |
223 | |
224 | BATloop(b, p, q) { |
225 | y = NULL; |
226 | x = (str) BUNtvar(bi, p); |
227 | if (x != 0 && strcmp(x, str_nil) != 0 && |
228 | (msg = (*func)(&y, &x, s2)) != MAL_SUCCEED) |
229 | goto bunins_failed1; |
230 | if (y == NULL) |
231 | y = (str) str_nil; |
232 | bunfastappVAR(bn, y); |
233 | if (y == str_nil) { |
234 | bn->tnonil = false; |
235 | bn->tnil = true; |
236 | } else |
237 | GDKfree(y); |
238 | } |
239 | finalizeResult(ret, bn, b); |
240 | return MAL_SUCCEED; |
241 | bunins_failed: |
242 | if (y != str_nil) |
243 | GDKfree(y); |
244 | bunins_failed1: |
245 | BBPunfix(b->batCacheid); |
246 | BBPunfix(bn->batCacheid); |
247 | if (msg != MAL_SUCCEED) |
248 | return msg; |
249 | throw(MAL, name, OPERATION_FAILED " During bulk operation" ); |
250 | } |
251 | |
252 | /* Input: two BATs of strings 'l' and 'l2' |
253 | * Output type: str (a BAT of strings) |
254 | */ |
255 | static str |
256 | do_batstr_batstr_str(bat *ret, const bat *l, const bat *l2, const char *name, str (*func)(str *, const str *, const str *)) |
257 | { |
258 | BATiter bi, bi2; |
259 | BAT *bn, *b, *b2; |
260 | BUN p, q; |
261 | str x, x2, y; |
262 | str msg = MAL_SUCCEED; |
263 | |
264 | prepareOperand2(b, l, b2, l2, name); |
265 | if(BATcount(b) != BATcount(b2)) { |
266 | BBPunfix(b->batCacheid); |
267 | BBPunfix(b2->batCacheid); |
268 | throw(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size" ); |
269 | } |
270 | prepareResult2(bn, b, b2, TYPE_str, name); |
271 | |
272 | bi = bat_iterator(b); |
273 | bi2 = bat_iterator(b2); |
274 | |
275 | BATloop(b, p, q) { |
276 | y = NULL; |
277 | x = (str) BUNtvar(bi, p); |
278 | x2 = (str) BUNtvar(bi2, p); |
279 | if (x != 0 && strcmp(x, str_nil) != 0 && |
280 | x2 != 0 && strcmp(x2, str_nil) != 0 && |
281 | (msg = (*func)(&y, &x, &x2)) != MAL_SUCCEED) |
282 | goto bunins_failed1; |
283 | if (y == NULL) |
284 | y = (str) str_nil; |
285 | bunfastappVAR(bn, y); |
286 | if (y == str_nil) { |
287 | bn->tnonil = false; |
288 | bn->tnil = true; |
289 | } else |
290 | GDKfree(y); |
291 | } |
292 | finalizeResult(ret, bn, b); |
293 | return MAL_SUCCEED; |
294 | bunins_failed: |
295 | if (y != str_nil) |
296 | GDKfree(y); |
297 | bunins_failed1: |
298 | BBPunfix(b->batCacheid); |
299 | BBPunfix(b2->batCacheid); |
300 | BBPunfix(bn->batCacheid); |
301 | if (msg != MAL_SUCCEED) |
302 | return msg; |
303 | throw(MAL, name, OPERATION_FAILED " During bulk operation" ); |
304 | } |
305 | |
306 | /* Input: a BAT of strings 'l' and a constant int 'n' |
307 | * Output type: str (a BAT of strings) |
308 | */ |
309 | static str |
310 | do_batstr_constint_str(bat *ret, const bat *l, const int *n, const char *name, str (*func)(str *, const str *, const int *)) |
311 | { |
312 | BATiter bi; |
313 | BAT *bn, *b; |
314 | BUN p, q; |
315 | str x, y; |
316 | str msg = MAL_SUCCEED; |
317 | |
318 | prepareOperand(b, l, name); |
319 | prepareResult(bn, b, TYPE_str, name); |
320 | |
321 | bi = bat_iterator(b); |
322 | |
323 | BATloop(b, p, q) { |
324 | y = NULL; |
325 | x = (str) BUNtvar(bi, p); |
326 | if (x != 0 && strcmp(x, str_nil) != 0 && |
327 | (msg = (*func)(&y, &x, n)) != MAL_SUCCEED) |
328 | goto bunins_failed1; |
329 | if (y == NULL) |
330 | y = (str) str_nil; |
331 | bunfastappVAR(bn, y); |
332 | if (y == str_nil) { |
333 | bn->tnonil = false; |
334 | bn->tnil = true; |
335 | } else |
336 | GDKfree(y); |
337 | } |
338 | finalizeResult(ret, bn, b); |
339 | return MAL_SUCCEED; |
340 | bunins_failed: |
341 | if (y != str_nil) |
342 | GDKfree(y); |
343 | bunins_failed1: |
344 | BBPunfix(b->batCacheid); |
345 | BBPunfix(bn->batCacheid); |
346 | if (msg != MAL_SUCCEED) |
347 | return msg; |
348 | throw(MAL, name, OPERATION_FAILED " During bulk operation" ); |
349 | } |
350 | |
351 | /* Input: a BAT of strings 'l' and a BAT of integers 'n' |
352 | * Output type: str (a BAT of strings) |
353 | */ |
354 | static str |
355 | do_batstr_batint_str(bat *ret, const bat *l, const bat *n, const char *name, str (*func)(str *, const str *, const int *)) |
356 | { |
357 | BATiter bi, bi2; |
358 | BAT *bn, *b, *b2; |
359 | BUN p, q; |
360 | int nn; |
361 | str x, y; |
362 | str msg = MAL_SUCCEED; |
363 | |
364 | prepareOperand2(b, l, b2, n, name); |
365 | if(BATcount(b) != BATcount(b2)) { |
366 | BBPunfix(b->batCacheid); |
367 | BBPunfix(b2->batCacheid); |
368 | throw(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size" ); |
369 | } |
370 | prepareResult2(bn, b, b2, TYPE_str, name); |
371 | |
372 | bi = bat_iterator(b); |
373 | bi2 = bat_iterator(b2); |
374 | |
375 | BATloop(b, p, q) { |
376 | y = NULL; |
377 | x = (str) BUNtvar(bi, p); |
378 | nn = *(int *)BUNtloc(bi2, p); |
379 | if (x != 0 && strcmp(x, str_nil) != 0 && |
380 | (msg = (*func)(&y, &x, &nn)) != MAL_SUCCEED) |
381 | goto bunins_failed1; |
382 | if (y == NULL) |
383 | y = (str) str_nil; |
384 | bunfastappVAR(bn, y); |
385 | if (y == str_nil) { |
386 | bn->tnonil = false; |
387 | bn->tnil = true; |
388 | } else |
389 | GDKfree(y); |
390 | } |
391 | finalizeResult(ret, bn, b); |
392 | return MAL_SUCCEED; |
393 | bunins_failed: |
394 | if (y != str_nil) |
395 | GDKfree(y); |
396 | bunins_failed1: |
397 | BBPunfix(b->batCacheid); |
398 | BBPunfix(b2->batCacheid); |
399 | BBPunfix(bn->batCacheid); |
400 | if (msg != MAL_SUCCEED) |
401 | return msg; |
402 | throw(MAL, name, OPERATION_FAILED " During bulk operation" ); |
403 | } |
404 | |
405 | /* Input: a BAT of strings 'l', a constant int 'n' and a constant str 's2' |
406 | * Output type: str (a BAT of strings) |
407 | */ |
408 | static str |
409 | do_batstr_constint_conststr_str(bat *ret, const bat *l, const int *n, const str *s2, const char *name, str (*func)(str *, const str *, const int *, const str *)) |
410 | { |
411 | BATiter bi; |
412 | BAT *bn, *b; |
413 | BUN p, q; |
414 | str x, y; |
415 | str msg = MAL_SUCCEED; |
416 | |
417 | prepareOperand(b, l, name); |
418 | prepareResult(bn, b, TYPE_str, name); |
419 | |
420 | bi = bat_iterator(b); |
421 | |
422 | BATloop(b, p, q) { |
423 | y = NULL; |
424 | x = (str) BUNtvar(bi, p); |
425 | if (x != 0 && strcmp(x, str_nil) != 0 && |
426 | (msg = (*func)(&y, &x, n, s2)) != MAL_SUCCEED) |
427 | goto bunins_failed1; |
428 | if (y == NULL) |
429 | y = (str) str_nil; |
430 | bunfastappVAR(bn, y); |
431 | if (y == str_nil) { |
432 | bn->tnonil = false; |
433 | bn->tnil = true; |
434 | } else |
435 | GDKfree(y); |
436 | } |
437 | finalizeResult(ret, bn, b); |
438 | return MAL_SUCCEED; |
439 | bunins_failed: |
440 | if (y != str_nil) |
441 | GDKfree(y); |
442 | bunins_failed1: |
443 | BBPunfix(b->batCacheid); |
444 | BBPunfix(bn->batCacheid); |
445 | if (msg != MAL_SUCCEED) |
446 | return msg; |
447 | throw(MAL, name, OPERATION_FAILED " During bulk operation" ); |
448 | } |
449 | |
450 | /* Input: a BAT of strings 'l', a BAT of integers 'n' and a constant str 's2' |
451 | * Output type: str (a BAT of strings) |
452 | */ |
453 | static str |
454 | do_batstr_batint_conststr_str(bat *ret, const bat *l, const bat *n, const str *s2, const char *name, str (*func)(str *, const str *, const int *, const str *)) |
455 | { |
456 | BATiter bi, bi2; |
457 | BAT *bn, *b, *b2; |
458 | BUN p, q; |
459 | int nn; |
460 | str x, y; |
461 | str msg = MAL_SUCCEED; |
462 | |
463 | prepareOperand2(b, l, b2, n, name); |
464 | if(BATcount(b) != BATcount(b2)) { |
465 | BBPunfix(b->batCacheid); |
466 | BBPunfix(b2->batCacheid); |
467 | throw(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size" ); |
468 | } |
469 | prepareResult(bn, b, TYPE_str, name); |
470 | |
471 | bi = bat_iterator(b); |
472 | bi2 = bat_iterator(b2); |
473 | |
474 | BATloop(b, p, q) { |
475 | y = NULL; |
476 | x = (str) BUNtvar(bi, p); |
477 | nn = *(int *)BUNtloc(bi2, p); |
478 | if (x != 0 && strcmp(x, str_nil) != 0 && |
479 | (msg = (*func)(&y, &x, &nn, s2)) != MAL_SUCCEED) |
480 | goto bunins_failed1; |
481 | if (y == NULL) |
482 | y = (str) str_nil; |
483 | bunfastappVAR(bn, y); |
484 | if (y == str_nil) { |
485 | bn->tnonil = false; |
486 | bn->tnil = true; |
487 | } else |
488 | GDKfree(y); |
489 | } |
490 | finalizeResult(ret, bn, b); |
491 | return MAL_SUCCEED; |
492 | bunins_failed: |
493 | if (y != str_nil) |
494 | GDKfree(y); |
495 | bunins_failed1: |
496 | BBPunfix(b->batCacheid); |
497 | BBPunfix(b2->batCacheid); |
498 | BBPunfix(bn->batCacheid); |
499 | if (msg != MAL_SUCCEED) |
500 | return msg; |
501 | throw(MAL, name, OPERATION_FAILED " During bulk operation" ); |
502 | } |
503 | |
504 | /* Input: a BAT of strings 'l', a constant int 'n' and a BAT of strings 'l2' |
505 | * Output type: str (a BAT of strings) |
506 | */ |
507 | static str |
508 | do_batstr_constint_batstr_str(bat *ret, const bat *l, const int *n, const bat *l2, const char *name, str (*func)(str *, const str *, const int *, const str *)) |
509 | { |
510 | BATiter bi, bi2; |
511 | BAT *bn, *b, *b2; |
512 | BUN p, q; |
513 | str x, x2, y; |
514 | str msg = MAL_SUCCEED; |
515 | |
516 | prepareOperand2(b, l, b2, l2, name); |
517 | if(BATcount(b) != BATcount(b2)) { |
518 | BBPunfix(b->batCacheid); |
519 | BBPunfix(b2->batCacheid); |
520 | throw(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size" ); |
521 | } |
522 | prepareResult(bn, b, TYPE_str, name); |
523 | |
524 | bi = bat_iterator(b); |
525 | bi2 = bat_iterator(b2); |
526 | |
527 | BATloop(b, p, q) { |
528 | y = NULL; |
529 | x = (str) BUNtvar(bi, p); |
530 | x2 = (str) BUNtvar(bi2, p); |
531 | if (x != 0 && strcmp(x, str_nil) != 0 && |
532 | x2 != 0 && strcmp(x2, str_nil) != 0 && |
533 | (msg = (*func)(&y, &x, n, &x2)) != MAL_SUCCEED) |
534 | goto bunins_failed1; |
535 | if (y == NULL) |
536 | y = (str) str_nil; |
537 | bunfastappVAR(bn, y); |
538 | if (y == str_nil) { |
539 | bn->tnonil = false; |
540 | bn->tnil = true; |
541 | } else |
542 | GDKfree(y); |
543 | } |
544 | finalizeResult(ret, bn, b); |
545 | return MAL_SUCCEED; |
546 | bunins_failed: |
547 | if (y != str_nil) |
548 | GDKfree(y); |
549 | bunins_failed1: |
550 | BBPunfix(b->batCacheid); |
551 | BBPunfix(b2->batCacheid); |
552 | BBPunfix(bn->batCacheid); |
553 | if (msg != MAL_SUCCEED) |
554 | return msg; |
555 | throw(MAL, name, OPERATION_FAILED " During bulk operation" ); |
556 | } |
557 | |
558 | /* Input: a BAT of strings 'l', a BAT of int 'n' and a BAT of strings 'l2' |
559 | * Output type: str (a BAT of strings) |
560 | */ |
561 | static str |
562 | do_batstr_batint_batstr_str(bat *ret, const bat *l, const bat *n, const bat *l2, const char *name, str (*func)(str *, const str *, const int *, const str *)) |
563 | { |
564 | BATiter bi, bi2, bi3; |
565 | BAT *bn, *b, *b2, *b3; |
566 | BUN p, q; |
567 | int nn; |
568 | str x, x2, y; |
569 | str msg = MAL_SUCCEED; |
570 | |
571 | |
572 | prepareOperand3(b, l, b2, n, b3, l2, name); |
573 | if (BATcount(b) != BATcount(b2) || BATcount(b) != BATcount(b3)) { |
574 | BBPunfix(b->batCacheid); |
575 | BBPunfix(b2->batCacheid); |
576 | BBPunfix(b3->batCacheid); |
577 | throw(MAL, name, ILLEGAL_ARGUMENT " Requires bats of identical size" ); |
578 | } |
579 | bn = COLnew(b->hseqbase, TYPE_str, BATcount(b), TRANSIENT); |
580 | if (bn == NULL) { |
581 | BBPunfix(b->batCacheid); |
582 | BBPunfix(b2->batCacheid); |
583 | BBPunfix(b3->batCacheid); |
584 | throw(MAL, name, SQLSTATE(HY001) MAL_MALLOC_FAIL); |
585 | } |
586 | bn->tsorted=false; |
587 | bn->trevsorted=false; |
588 | |
589 | bi = bat_iterator(b); |
590 | bi2 = bat_iterator(b2); |
591 | bi3 = bat_iterator(b3); |
592 | |
593 | BATloop(b, p, q) { |
594 | y = NULL; |
595 | x = (str) BUNtvar(bi, p); |
596 | nn = *(int *)BUNtloc(bi2, p); |
597 | x2 = (str) BUNtvar(bi3, p); |
598 | if (x != 0 && strcmp(x, str_nil) != 0 && |
599 | x2 != 0 && strcmp(x2, str_nil) != 0 && |
600 | (msg = (*func)(&y, &x, &nn, &x2)) != MAL_SUCCEED) |
601 | goto bunins_failed1; |
602 | if (y == NULL) |
603 | y = (str) str_nil; |
604 | bunfastappVAR(bn, y); |
605 | if (y == str_nil) { |
606 | bn->tnonil = false; |
607 | bn->tnil = true; |
608 | } else |
609 | GDKfree(y); |
610 | } |
611 | finalizeResult(ret, bn, b); |
612 | return MAL_SUCCEED; |
613 | bunins_failed: |
614 | if (y != str_nil) |
615 | GDKfree(y); |
616 | bunins_failed1: |
617 | BBPunfix(b->batCacheid); |
618 | BBPunfix(b2->batCacheid); |
619 | BBPunfix(b3->batCacheid); |
620 | BBPunfix(bn->batCacheid); |
621 | if (msg != MAL_SUCCEED) |
622 | return msg; |
623 | throw(MAL, name, OPERATION_FAILED " During bulk operation" ); |
624 | } |
625 | |
626 | str |
627 | STRbatLower(bat *ret, const bat *l) |
628 | { |
629 | return do_batstr_str(ret, l, "batstr.Lower" , STRLower); |
630 | } |
631 | |
632 | str |
633 | STRbatUpper(bat *ret, const bat *l) |
634 | { |
635 | return do_batstr_str(ret, l, "batstr.Upper" , STRUpper); |
636 | } |
637 | |
638 | str |
639 | STRbatStrip(bat *ret, const bat *l) |
640 | { |
641 | return do_batstr_str(ret, l, "batstr.Strip" , STRStrip); |
642 | } |
643 | |
644 | str |
645 | STRbatLtrim(bat *ret, const bat *l) |
646 | { |
647 | return do_batstr_str(ret, l, "batstr.Ltrim" , STRLtrim); |
648 | } |
649 | |
650 | str |
651 | STRbatRtrim(bat *ret, const bat *l) |
652 | { |
653 | return do_batstr_str(ret, l, "batstr.Rtrim" , STRRtrim); |
654 | } |
655 | |
656 | str |
657 | STRbatStrip2_const(bat *ret, const bat *l, const str *s2) |
658 | { |
659 | return do_batstr_conststr_str(ret, l, s2, "batstr.Strip" , STRStrip2); |
660 | } |
661 | |
662 | str |
663 | STRbatLtrim2_const(bat *ret, const bat *l, const str *s2) |
664 | { |
665 | return do_batstr_conststr_str(ret, l, s2, "batstr.Ltrim" , STRLtrim2); |
666 | } |
667 | |
668 | str |
669 | STRbatRtrim2_const(bat *ret, const bat *l, const str *s2) |
670 | { |
671 | return do_batstr_conststr_str(ret, l, s2, "batstr.Rtrim" , STRRtrim2); |
672 | } |
673 | |
674 | str |
675 | STRbatStrip2_bat(bat *ret, const bat *l, const bat *l2) |
676 | { |
677 | return do_batstr_batstr_str(ret, l, l2, "batstr.Strip" , STRStrip2); |
678 | } |
679 | |
680 | str |
681 | STRbatLtrim2_bat(bat *ret, const bat *l, const bat *l2) |
682 | { |
683 | return do_batstr_batstr_str(ret, l, l2, "batstr.Ltrim" , STRLtrim2); |
684 | } |
685 | |
686 | str |
687 | STRbatRtrim2_bat(bat *ret, const bat *l, const bat *l2) |
688 | { |
689 | return do_batstr_batstr_str(ret, l, l2, "batstr.Rtrim" , STRRtrim2); |
690 | } |
691 | |
692 | str |
693 | STRbatLpad_const(bat *ret, const bat *l, const int *n) |
694 | { |
695 | return do_batstr_constint_str(ret, l, n, "batstr.Lpad" , STRLpad); |
696 | } |
697 | |
698 | str |
699 | STRbatRpad_const(bat *ret, const bat *l, const int *n) |
700 | { |
701 | return do_batstr_constint_str(ret, l, n, "batstr.Rpad" , STRRpad); |
702 | } |
703 | |
704 | str |
705 | STRbatLpad_bat(bat *ret, const bat *l, const bat *n) |
706 | { |
707 | return do_batstr_batint_str(ret, l, n, "batstr.Lpad" , STRLpad); |
708 | } |
709 | |
710 | str |
711 | STRbatRpad_bat(bat *ret, const bat *l, const bat *n) |
712 | { |
713 | return do_batstr_batint_str(ret, l, n, "batstr.Rpad" , STRRpad); |
714 | } |
715 | |
716 | str |
717 | STRbatLpad2_const_const(bat *ret, const bat *l, const int *n, const str *s2) |
718 | { |
719 | return do_batstr_constint_conststr_str(ret, l, n, s2, "batstr.Lpad" , STRLpad2); |
720 | } |
721 | |
722 | str |
723 | STRbatRpad2_const_const(bat *ret, const bat *l, const int *n, const str *s2) |
724 | { |
725 | return do_batstr_constint_conststr_str(ret, l, n, s2, "batstr.Rpad" , STRRpad2); |
726 | } |
727 | |
728 | str |
729 | STRbatLpad2_bat_const(bat *ret, const bat *l, const bat *n, const str *s2) |
730 | { |
731 | return do_batstr_batint_conststr_str(ret, l, n, s2, "batstr.Lpad" , STRLpad2); |
732 | } |
733 | |
734 | str |
735 | STRbatRpad2_bat_const(bat *ret, const bat *l, const bat *n, const str *s2) |
736 | { |
737 | return do_batstr_batint_conststr_str(ret, l, n, s2, "batstr.Rpad" , STRRpad2); |
738 | } |
739 | |
740 | str |
741 | STRbatLpad2_const_bat(bat *ret, const bat *l, const int *n, const bat *l2) |
742 | { |
743 | return do_batstr_constint_batstr_str(ret, l, n, l2, "batstr.Lpad" , STRLpad2); |
744 | } |
745 | |
746 | str |
747 | STRbatRpad2_const_bat(bat *ret, const bat *l, const int *n, const bat *l2) |
748 | { |
749 | return do_batstr_constint_batstr_str(ret, l, n, l2, "batstr.Rpad" , STRRpad2); |
750 | } |
751 | |
752 | str |
753 | STRbatLpad2_bat_bat(bat *ret, const bat *l, const bat *n, const bat *l2) |
754 | { |
755 | return do_batstr_batint_batstr_str(ret, l, n, l2, "batstr.Lpad" , STRLpad2); |
756 | } |
757 | |
758 | str |
759 | STRbatRpad2_bat_bat(bat *ret, const bat *l, const bat *n, const bat *l2) |
760 | { |
761 | return do_batstr_batint_batstr_str(ret, l, n, l2, "batstr.Rpad" , STRRpad2); |
762 | } |
763 | |
764 | /* |
765 | * A general assumption in all cases is the bats are synchronized on their |
766 | * head column. This is not checked and may be mis-used to deploy the |
767 | * implementation for shifted window arithmetic as well. |
768 | */ |
769 | |
770 | str STRbatPrefix(bat *ret, const bat *l, const bat *r) |
771 | { |
772 | BATiter lefti, righti; |
773 | BAT *bn, *left, *right; |
774 | BUN p,q; |
775 | bit v; |
776 | |
777 | prepareOperand2(left,l,right,r,"batstr.startsWith" ); |
778 | if(BATcount(left) != BATcount(right)) { |
779 | BBPunfix(left->batCacheid); |
780 | BBPunfix(right->batCacheid); |
781 | throw(MAL, "batstr.startsWith" , ILLEGAL_ARGUMENT " Requires bats of identical size" ); |
782 | } |
783 | prepareResult2(bn,left,right,TYPE_bit,"batstr.startsWith" ); |
784 | |
785 | lefti = bat_iterator(left); |
786 | righti = bat_iterator(right); |
787 | |
788 | BATloop(left, p, q) { |
789 | str tl = (str) BUNtvar(lefti,p); |
790 | str tr = (str) BUNtvar(righti,p); |
791 | STRPrefix(&v, &tl, &tr); |
792 | bunfastappTYPE(bit, bn, &v); |
793 | } |
794 | bn->tnonil = false; |
795 | BBPunfix(right->batCacheid); |
796 | finalizeResult(ret,bn,left); |
797 | return MAL_SUCCEED; |
798 | |
799 | bunins_failed: |
800 | BBPunfix(left->batCacheid); |
801 | BBPunfix(right->batCacheid); |
802 | BBPunfix(*ret); |
803 | throw(MAL, "batstr.startsWith" , OPERATION_FAILED " During bulk operation" ); |
804 | } |
805 | |
806 | str STRbatPrefixcst(bat *ret, const bat *l, const str *cst) |
807 | { |
808 | BATiter lefti; |
809 | BAT *bn, *left; |
810 | BUN p,q; |
811 | bit v; |
812 | |
813 | prepareOperand(left,l,"batstr.startsWith" ); |
814 | prepareResult(bn,left,TYPE_bit,"batstr.startsWith" ); |
815 | |
816 | lefti = bat_iterator(left); |
817 | |
818 | BATloop(left, p, q) { |
819 | str tl = (str) BUNtvar(lefti,p); |
820 | STRPrefix(&v, &tl, cst); |
821 | bunfastappTYPE(bit, bn, &v); |
822 | } |
823 | bn->tnonil = false; |
824 | finalizeResult(ret,bn,left); |
825 | return MAL_SUCCEED; |
826 | |
827 | bunins_failed: |
828 | BBPunfix(left->batCacheid); |
829 | BBPunfix(*ret); |
830 | throw(MAL, "batstr.startsWith" , OPERATION_FAILED " During bulk operation" ); |
831 | } |
832 | |
833 | str STRbatSuffix(bat *ret, const bat *l, const bat *r) |
834 | { |
835 | BATiter lefti, righti; |
836 | BAT *bn, *left, *right; |
837 | BUN p,q; |
838 | bit v; |
839 | |
840 | prepareOperand2(left,l,right,r,"batstr.endsWith" ); |
841 | if(BATcount(left) != BATcount(right)) { |
842 | BBPunfix(left->batCacheid); |
843 | BBPunfix(right->batCacheid); |
844 | throw(MAL, "batstr.endsWith" , ILLEGAL_ARGUMENT " Requires bats of identical size" ); |
845 | } |
846 | prepareResult2(bn,left,right,TYPE_bit,"batstr.endsWith" ); |
847 | |
848 | lefti = bat_iterator(left); |
849 | righti = bat_iterator(right); |
850 | |
851 | BATloop(left, p, q) { |
852 | str tl = (str) BUNtvar(lefti,p); |
853 | str tr = (str) BUNtvar(righti,p); |
854 | STRSuffix(&v, &tl, &tr); |
855 | bunfastappTYPE(bit, bn, &v); |
856 | } |
857 | bn->tnonil = false; |
858 | BBPunfix(right->batCacheid); |
859 | finalizeResult(ret,bn,left); |
860 | return MAL_SUCCEED; |
861 | |
862 | bunins_failed: |
863 | BBPunfix(left->batCacheid); |
864 | BBPunfix(right->batCacheid); |
865 | BBPunfix(*ret); |
866 | throw(MAL, "batstr.endsWith" , OPERATION_FAILED " During bulk operation" ); |
867 | } |
868 | |
869 | str STRbatSuffixcst(bat *ret, const bat *l, const str *cst) |
870 | { |
871 | BATiter lefti; |
872 | BAT *bn, *left; |
873 | BUN p,q; |
874 | bit v; |
875 | |
876 | prepareOperand(left,l,"batstr.endsWith" ); |
877 | prepareResult(bn,left,TYPE_bit,"batstr.endsWith" ); |
878 | |
879 | lefti = bat_iterator(left); |
880 | |
881 | BATloop(left, p, q) { |
882 | str tl = (str) BUNtvar(lefti,p); |
883 | STRSuffix(&v, &tl, cst); |
884 | bunfastappTYPE(bit, bn, &v); |
885 | } |
886 | bn->tnonil = false; |
887 | finalizeResult(ret,bn,left); |
888 | return MAL_SUCCEED; |
889 | |
890 | bunins_failed: |
891 | BBPunfix(left->batCacheid); |
892 | BBPunfix(*ret); |
893 | throw(MAL, "batstr.endsWith" , OPERATION_FAILED " During bulk operation" ); |
894 | } |
895 | |
896 | str STRbatstrSearch(bat *ret, const bat *l, const bat *r) |
897 | { |
898 | BATiter lefti, righti; |
899 | BAT *bn, *left, *right; |
900 | BUN p,q; |
901 | int v; |
902 | |
903 | prepareOperand2(left,l,right,r,"batstr.search" ); |
904 | if(BATcount(left) != BATcount(right)) { |
905 | BBPunfix(left->batCacheid); |
906 | BBPunfix(right->batCacheid); |
907 | throw(MAL, "batstr.search" , ILLEGAL_ARGUMENT " Requires bats of identical size" ); |
908 | } |
909 | prepareResult2(bn,left,right,TYPE_int,"batstr.search" ); |
910 | |
911 | lefti = bat_iterator(left); |
912 | righti = bat_iterator(right); |
913 | |
914 | BATloop(left, p, q) { |
915 | str tl = (str) BUNtvar(lefti,p); |
916 | str tr = (str) BUNtvar(righti,p); |
917 | STRstrSearch(&v, &tl, &tr); |
918 | bunfastappTYPE(int, bn, &v); |
919 | } |
920 | bn->tnonil = false; |
921 | BBPunfix(right->batCacheid); |
922 | finalizeResult(ret,bn,left); |
923 | return MAL_SUCCEED; |
924 | |
925 | bunins_failed: |
926 | BBPunfix(left->batCacheid); |
927 | BBPunfix(right->batCacheid); |
928 | BBPunfix(*ret); |
929 | throw(MAL, "batstr.search" , OPERATION_FAILED " During bulk operation" ); |
930 | } |
931 | |
932 | str STRbatstrSearchcst(bat *ret, const bat *l, const str *cst) |
933 | { |
934 | BATiter lefti; |
935 | BAT *bn, *left; |
936 | BUN p,q; |
937 | int v; |
938 | |
939 | prepareOperand(left,l,"batstr.search" ); |
940 | prepareResult(bn,left,TYPE_int,"batstr.search" ); |
941 | |
942 | lefti = bat_iterator(left); |
943 | |
944 | BATloop(left, p, q) { |
945 | str tl = (str) BUNtvar(lefti,p); |
946 | STRstrSearch(&v, &tl, cst); |
947 | bunfastappTYPE(int, bn, &v); |
948 | } |
949 | bn->tnonil = false; |
950 | finalizeResult(ret,bn,left); |
951 | return MAL_SUCCEED; |
952 | |
953 | bunins_failed: |
954 | BBPunfix(left->batCacheid); |
955 | BBPunfix(*ret); |
956 | throw(MAL, "batstr.search" , OPERATION_FAILED " During bulk operation" ); |
957 | } |
958 | |
959 | str STRbatRstrSearch(bat *ret, const bat *l, const bat *r) |
960 | { |
961 | BATiter lefti, righti; |
962 | BAT *bn, *left, *right; |
963 | BUN p,q; |
964 | int v; |
965 | |
966 | prepareOperand2(left,l,right,r,"batstr.r_search" ); |
967 | if(BATcount(left) != BATcount(right)) { |
968 | BBPunfix(left->batCacheid); |
969 | BBPunfix(right->batCacheid); |
970 | throw(MAL, "batstr.r_search" , ILLEGAL_ARGUMENT " Requires bats of identical size" ); |
971 | } |
972 | prepareResult2(bn,left,right,TYPE_int,"batstr.r_search" ); |
973 | |
974 | lefti = bat_iterator(left); |
975 | righti = bat_iterator(right); |
976 | |
977 | BATloop(left, p, q) { |
978 | str tl = (str) BUNtvar(lefti,p); |
979 | str tr = (str) BUNtvar(righti,p); |
980 | STRReverseStrSearch(&v, &tl, &tr); |
981 | bunfastappTYPE(int, bn, &v); |
982 | } |
983 | bn->tnonil = false; |
984 | BBPunfix(right->batCacheid); |
985 | finalizeResult(ret,bn,left); |
986 | return MAL_SUCCEED; |
987 | |
988 | bunins_failed: |
989 | BBPunfix(left->batCacheid); |
990 | BBPunfix(right->batCacheid); |
991 | BBPunfix(*ret); |
992 | throw(MAL, "batstr.r_search" , OPERATION_FAILED " During bulk operation" ); |
993 | } |
994 | |
995 | str STRbatRstrSearchcst(bat *ret, const bat *l, const str *cst) |
996 | { |
997 | BATiter lefti; |
998 | BAT *bn, *left; |
999 | BUN p,q; |
1000 | int v; |
1001 | |
1002 | prepareOperand(left,l,"batstr.r_search" ); |
1003 | prepareResult(bn,left,TYPE_int,"batstr.r_search" ); |
1004 | |
1005 | lefti = bat_iterator(left); |
1006 | |
1007 | BATloop(left, p, q) { |
1008 | str tl = (str) BUNtvar(lefti,p); |
1009 | STRReverseStrSearch(&v, &tl, cst); |
1010 | bunfastappTYPE(int, bn, &v); |
1011 | } |
1012 | bn->tnonil = false; |
1013 | finalizeResult(ret,bn,left); |
1014 | return MAL_SUCCEED; |
1015 | |
1016 | bunins_failed: |
1017 | BBPunfix(left->batCacheid); |
1018 | BBPunfix(*ret); |
1019 | throw(MAL, "batstr.r_search" , OPERATION_FAILED " During bulk operation" ); |
1020 | } |
1021 | |
1022 | str STRbatTail(bat *ret, const bat *l, const bat *r) |
1023 | { |
1024 | BATiter lefti, righti; |
1025 | BAT *bn, *left, *right; |
1026 | BUN p,q; |
1027 | str v; |
1028 | str msg = MAL_SUCCEED; |
1029 | |
1030 | prepareOperand2(left,l,right,r,"batstr.string" ); |
1031 | if(BATcount(left) != BATcount(right)) { |
1032 | BBPunfix(left->batCacheid); |
1033 | BBPunfix(right->batCacheid); |
1034 | throw(MAL, "batstr.string" , ILLEGAL_ARGUMENT " Requires bats of identical size" ); |
1035 | } |
1036 | prepareResult2(bn,left,right,TYPE_str,"batstr.string" ); |
1037 | |
1038 | lefti = bat_iterator(left); |
1039 | righti = bat_iterator(right); |
1040 | |
1041 | BATloop(left, p, q) { |
1042 | str tl = (str) BUNtvar(lefti,p); |
1043 | int *tr = (int *) BUNtloc(righti,p); |
1044 | if ((msg = STRTail(&v, &tl, tr)) != MAL_SUCCEED) |
1045 | goto bunins_failed; |
1046 | bunfastappVAR(bn, v); |
1047 | GDKfree(v); |
1048 | } |
1049 | bn->tnonil = false; |
1050 | BBPunfix(right->batCacheid); |
1051 | finalizeResult(ret,bn,left); |
1052 | return MAL_SUCCEED; |
1053 | |
1054 | bunins_failed: |
1055 | BBPunfix(left->batCacheid); |
1056 | BBPunfix(right->batCacheid); |
1057 | BBPunfix(*ret); |
1058 | if (msg) |
1059 | return msg; |
1060 | GDKfree(v); |
1061 | throw(MAL, "batstr.string" , OPERATION_FAILED " During bulk operation" ); |
1062 | } |
1063 | |
1064 | str STRbatTailcst(bat *ret, const bat *l, const int *cst) |
1065 | { |
1066 | BATiter lefti; |
1067 | BAT *bn, *left; |
1068 | BUN p,q; |
1069 | str v; |
1070 | str msg = MAL_SUCCEED; |
1071 | |
1072 | prepareOperand(left,l,"batstr.string" ); |
1073 | prepareResult(bn,left,TYPE_str,"batstr.string" ); |
1074 | |
1075 | lefti = bat_iterator(left); |
1076 | |
1077 | BATloop(left, p, q) { |
1078 | str tl = (str) BUNtvar(lefti,p); |
1079 | if ((msg = STRTail(&v, &tl, cst)) != MAL_SUCCEED) |
1080 | goto bunins_failed; |
1081 | bunfastappVAR(bn, v); |
1082 | GDKfree(v); |
1083 | } |
1084 | bn->tnonil = false; |
1085 | finalizeResult(ret,bn,left); |
1086 | return MAL_SUCCEED; |
1087 | |
1088 | bunins_failed: |
1089 | BBPunfix(left->batCacheid); |
1090 | BBPunfix(*ret); |
1091 | if (msg) |
1092 | return msg; |
1093 | GDKfree(v); |
1094 | throw(MAL, "batstr.string" , OPERATION_FAILED " During bulk operation" ); |
1095 | } |
1096 | |
1097 | str STRbatWChrAt(bat *ret, const bat *l, const bat *r) |
1098 | { |
1099 | BATiter lefti, righti; |
1100 | BAT *bn, *left, *right; |
1101 | BUN p,q; |
1102 | int v; |
1103 | |
1104 | prepareOperand2(left,l,right,r,"batstr.unicodeAt" ); |
1105 | if(BATcount(left) != BATcount(right)) { |
1106 | BBPunfix(left->batCacheid); |
1107 | BBPunfix(right->batCacheid); |
1108 | throw(MAL, "batstr.unicodeAt" , ILLEGAL_ARGUMENT " Requires bats of identical size" ); |
1109 | } |
1110 | prepareResult2(bn,left,right,TYPE_int,"batstr.unicodeAt" ); |
1111 | |
1112 | lefti = bat_iterator(left); |
1113 | righti = bat_iterator(right); |
1114 | |
1115 | BATloop(left, p, q) { |
1116 | str tl = (str) BUNtvar(lefti,p); |
1117 | ptr tr = BUNtail(righti,p); |
1118 | STRWChrAt(&v, &tl, tr); |
1119 | bunfastappTYPE(int, bn, &v); |
1120 | } |
1121 | bn->tnonil = false; |
1122 | BBPunfix(right->batCacheid); |
1123 | finalizeResult(ret,bn,left); |
1124 | return MAL_SUCCEED; |
1125 | |
1126 | bunins_failed: |
1127 | BBPunfix(left->batCacheid); |
1128 | BBPunfix(right->batCacheid); |
1129 | BBPunfix(*ret); |
1130 | throw(MAL, "batstr.unicodeAt" , OPERATION_FAILED " During bulk operation" ); |
1131 | } |
1132 | |
1133 | str STRbatWChrAtcst(bat *ret, const bat *l, const int *cst) |
1134 | { |
1135 | BATiter lefti; |
1136 | BAT *bn, *left; |
1137 | BUN p,q; |
1138 | int v; |
1139 | |
1140 | prepareOperand(left,l,"batstr.unicodeAt" ); |
1141 | prepareResult(bn,left,TYPE_int,"batstr.unicodeAt" ); |
1142 | |
1143 | lefti = bat_iterator(left); |
1144 | |
1145 | BATloop(left, p, q) { |
1146 | str tl = (str) BUNtvar(lefti,p); |
1147 | STRWChrAt(&v, &tl, cst); |
1148 | bunfastappTYPE(int, bn, &v); |
1149 | } |
1150 | bn->tnonil = false; |
1151 | finalizeResult(ret,bn,left); |
1152 | return MAL_SUCCEED; |
1153 | |
1154 | bunins_failed: |
1155 | BBPunfix(left->batCacheid); |
1156 | BBPunfix(*ret); |
1157 | throw(MAL, "batstr.unicodeAt" , OPERATION_FAILED " During bulk operation" ); |
1158 | } |
1159 | |
1160 | str |
1161 | STRbatSubstitutecst(bat *ret, const bat *l, const str *arg2, const str *arg3, const bit *rep) |
1162 | { |
1163 | BATiter bi; |
1164 | BAT *bn, *b; |
1165 | BUN p, q; |
1166 | str x; |
1167 | str y; |
1168 | str err = MAL_SUCCEED; |
1169 | |
1170 | prepareOperand(b, l, "subString" ); |
1171 | prepareResult(bn, b, TYPE_int, "subString" ); |
1172 | |
1173 | bi = bat_iterator(b); |
1174 | |
1175 | BATloop(b, p, q) { |
1176 | y = (str) str_nil; |
1177 | x = (str) BUNtvar(bi, p); |
1178 | if (x != 0 && strcmp(x, str_nil) != 0 && |
1179 | (err = STRSubstitute(&y, &x, arg2, arg3, rep)) != MAL_SUCCEED) |
1180 | goto bunins_failed; |
1181 | bunfastappVAR(bn, y); |
1182 | if (y != str_nil) |
1183 | GDKfree(y); |
1184 | } |
1185 | bn->tnonil = false; |
1186 | finalizeResult(ret, bn, b); |
1187 | return MAL_SUCCEED; |
1188 | bunins_failed: |
1189 | if (err == MAL_SUCCEED && y != str_nil) |
1190 | GDKfree(y); |
1191 | BBPunfix(b->batCacheid); |
1192 | BBPunfix(bn->batCacheid); |
1193 | if (err) |
1194 | return err; |
1195 | throw(MAL, "batstr.subString" , OPERATION_FAILED " During bulk operation" ); |
1196 | } |
1197 | |
1198 | /* |
1199 | * The substring functions require slightly different arguments |
1200 | */ |
1201 | str |
1202 | STRbatsubstringcst(bat *ret, const bat *bid, const int *start, const int *length) |
1203 | { |
1204 | BATiter bi; |
1205 | BAT *b,*bn; |
1206 | BUN p, q; |
1207 | str res; |
1208 | char *msg = MAL_SUCCEED; |
1209 | |
1210 | if( (b= BATdescriptor(*bid)) == NULL) |
1211 | throw(MAL, "batstr.substring" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1212 | bn= COLnew(b->hseqbase, TYPE_str, BATcount(b)/10+5, TRANSIENT); |
1213 | if (bn == NULL) { |
1214 | BBPunfix(b->batCacheid); |
1215 | throw(MAL, "batstr.substring" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
1216 | } |
1217 | bn->tsorted = b->tsorted; |
1218 | bn->trevsorted = b->trevsorted; |
1219 | |
1220 | bi = bat_iterator(b); |
1221 | BATloop(b, p, q) { |
1222 | str t = (str) BUNtvar(bi, p); |
1223 | |
1224 | if ((msg = STRsubstring(&res, &t, start, length)) != MAL_SUCCEED || |
1225 | BUNappend(bn, (ptr)res, false) != GDK_SUCCEED) { |
1226 | BBPunfix(b->batCacheid); |
1227 | BBPunfix(bn->batCacheid); |
1228 | if (msg != MAL_SUCCEED) |
1229 | return msg; |
1230 | GDKfree(res); |
1231 | throw(MAL, "batstr.substring" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
1232 | } |
1233 | GDKfree(res); |
1234 | } |
1235 | |
1236 | bn->tnonil = false; |
1237 | *ret = bn->batCacheid; |
1238 | BBPkeepref(bn->batCacheid); |
1239 | BBPunfix(b->batCacheid); |
1240 | return msg; |
1241 | } |
1242 | |
1243 | str STRbatsubstring(bat *ret, const bat *l, const bat *r, const bat *t) |
1244 | { |
1245 | BATiter lefti, starti, lengthi; |
1246 | BAT *bn, *left, *start, *length; |
1247 | BUN p,q; |
1248 | str v; |
1249 | |
1250 | if( (left= BATdescriptor(*l)) == NULL ) |
1251 | throw(MAL, "batstr.substring" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1252 | if( (start= BATdescriptor(*r)) == NULL ){ |
1253 | BBPunfix(left->batCacheid); |
1254 | throw(MAL, "batstr.substring" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1255 | } |
1256 | if( (length= BATdescriptor(*t)) == NULL ){ |
1257 | BBPunfix(left->batCacheid); |
1258 | BBPunfix(start->batCacheid); |
1259 | throw(MAL, "batstr.substring" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1260 | } |
1261 | if (BATcount(left) != BATcount(start) || |
1262 | BATcount(left) != BATcount(length)) { |
1263 | BBPunfix(left->batCacheid); |
1264 | BBPunfix(start->batCacheid); |
1265 | BBPunfix(length->batCacheid); |
1266 | throw(MAL, "batstr.substring" , ILLEGAL_ARGUMENT " Requires bats of identical size" ); |
1267 | } |
1268 | |
1269 | bn= COLnew(left->hseqbase, TYPE_str,BATcount(left), TRANSIENT); |
1270 | if( bn == NULL){ |
1271 | BBPunfix(left->batCacheid); |
1272 | BBPunfix(start->batCacheid); |
1273 | BBPunfix(length->batCacheid); |
1274 | throw(MAL, "batstr.substring" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
1275 | } |
1276 | |
1277 | bn->tsorted=false; |
1278 | bn->trevsorted=false; |
1279 | |
1280 | lefti = bat_iterator(left); |
1281 | starti = bat_iterator(start); |
1282 | lengthi = bat_iterator(length); |
1283 | BATloop(left, p, q) { |
1284 | str tl = (str) BUNtvar(lefti,p); |
1285 | int *t1 = (int *) BUNtloc(starti,p); |
1286 | int *t2 = (int *) BUNtloc(lengthi,p); |
1287 | str msg; |
1288 | if ((msg = STRsubstring(&v, &tl, t1, t2)) != MAL_SUCCEED || |
1289 | BUNappend(bn, v, false) != GDK_SUCCEED) { |
1290 | BBPunfix(left->batCacheid); |
1291 | BBPunfix(start->batCacheid); |
1292 | BBPreclaim(bn); |
1293 | if (msg) |
1294 | return msg; |
1295 | GDKfree(v); |
1296 | throw(MAL, "batstr.substring" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
1297 | } |
1298 | GDKfree(v); |
1299 | } |
1300 | bn->tnonil = false; |
1301 | BBPunfix(start->batCacheid); |
1302 | BBPunfix(length->batCacheid); |
1303 | finalizeResult(ret,bn,left); |
1304 | return MAL_SUCCEED; |
1305 | } |
1306 | |