@@ -326,6 +326,67 @@ static REBSER *make_binary(REBVAL *arg, REBOOL make)
326
326
return ((int )LO_CASE (* (REBYTE * )v2 )) - ((int )LO_CASE (* (REBYTE * )v1 ));
327
327
}
328
328
329
+ // WARNING! Not re-entrant. !!! Must find a way to push it on stack?
330
+ static struct {
331
+ REBFLG cased ;
332
+ REBFLG reverse ;
333
+ REBCNT offset ;
334
+ REBVAL * compare ;
335
+ REBFLG wide ;
336
+ } sort_flags = {0 };
337
+
338
+ /***********************************************************************
339
+ **
340
+ */ static int Compare_Call (const void * p1 , const void * p2 )
341
+ /*
342
+ ***********************************************************************/
343
+ {
344
+ REBVAL * v1 ;
345
+ REBVAL * v2 ;
346
+ REBVAL * val ;
347
+ REBVAL * tmp ;
348
+
349
+ // O: is there better way how to temporary use 2 values?
350
+ DS_SKIP ; v1 = DS_TOP ;
351
+ DS_SKIP ; v2 = DS_TOP ;
352
+
353
+ if (sort_flags .wide ) {
354
+ SET_CHAR (v1 , (int )(* (REBCHR * )p2 ));
355
+ SET_CHAR (v2 , (int )(* (REBCHR * )p1 ));
356
+ } else {
357
+ SET_CHAR (v1 , (int )(* (REBYTE * )p2 ));
358
+ SET_CHAR (v2 , (int )(* (REBYTE * )p1 ));
359
+ }
360
+
361
+ if (sort_flags .reverse ) {
362
+ tmp = v1 ;
363
+ v1 = v2 ;
364
+ v2 = tmp ;
365
+ }
366
+
367
+ val = Apply_Func (0 , sort_flags .compare , v1 , v2 , 0 );
368
+
369
+ // v1 and v2 no more needed...
370
+ DS_POP ;
371
+ DS_POP ;
372
+
373
+ if (IS_LOGIC (val )) {
374
+ if (IS_TRUE (val )) return 1 ;
375
+ return -1 ;
376
+ }
377
+ if (IS_INTEGER (val )) {
378
+ if (VAL_INT64 (val ) < 0 ) return 1 ;
379
+ if (VAL_INT64 (val ) == 0 ) return 0 ;
380
+ return -1 ;
381
+ }
382
+ if (IS_DECIMAL (val )) {
383
+ if (VAL_DECIMAL (val ) < 0 ) return 1 ;
384
+ if (VAL_DECIMAL (val ) == 0 ) return 0 ;
385
+ return -1 ;
386
+ }
387
+ return -1 ;
388
+ }
389
+
329
390
330
391
/***********************************************************************
331
392
**
@@ -336,6 +397,7 @@ static REBSER *make_binary(REBVAL *arg, REBOOL make)
336
397
REBCNT len ;
337
398
REBCNT skip = 1 ;
338
399
REBCNT size = 1 ;
400
+ REBSER * args ;
339
401
int (* sfunc )(const void * v1 , const void * v2 );
340
402
341
403
// Determine length of sort:
@@ -351,7 +413,23 @@ static REBSER *make_binary(REBVAL *arg, REBOOL make)
351
413
352
414
// Use fast quicksort library function:
353
415
if (skip > 1 ) len /= skip , size *= skip ;
354
- if (ccase ) {
416
+
417
+ if (ANY_FUNC (compv )) {
418
+ // Check argument types of comparator function.
419
+ args = VAL_FUNC_ARGS (compv );
420
+ if (BLK_LEN (args ) > 1 && !TYPE_CHECK (BLK_SKIP (args , 1 ), REB_CHAR ))
421
+ Trap3 (RE_EXPECT_ARG , Of_Type (compv ), BLK_SKIP (args , 1 ), Get_Type_Word (REB_CHAR ));
422
+ if (BLK_LEN (args ) > 2 && !TYPE_CHECK (BLK_SKIP (args , 2 ), REB_CHAR ))
423
+ Trap3 (RE_EXPECT_ARG , Of_Type (compv ), BLK_SKIP (args , 2 ), Get_Type_Word (REB_CHAR ));
424
+ sort_flags .cased = ccase ;
425
+ sort_flags .reverse = rev ;
426
+ sort_flags .compare = 0 ;
427
+ sort_flags .offset = 0 ;
428
+ sort_flags .compare = compv ;
429
+ sort_flags .wide = 1 < SERIES_WIDE (VAL_SERIES (string ));
430
+ sfunc = Compare_Call ;
431
+
432
+ } else if (ccase ) {
355
433
sfunc = rev ? Compare_Chr_Cased_Rev : Compare_Chr_Cased ;
356
434
} else {
357
435
sfunc = rev ? Compare_Chr_Uncased_Rev : Compare_Chr_Uncased ;
0 commit comments