@@ -406,11 +406,31 @@ private static string EmitIndexOfAnyValues(char[] asciiChars, Dictionary<string,
406
406
407
407
string fieldName = hexBitmap switch
408
408
{
409
+ "FFFFFFFF000000000000000000000080" => "s_asciiControl" ,
410
+ "000000000000FF030000000000000000" => "s_asciiDigits" ,
409
411
"0000000000000000FEFFFF07FEFFFF07" => "s_asciiLetters" ,
410
412
"000000000000FF03FEFFFF07FEFFFF07" => "s_asciiLettersAndDigits" ,
411
413
"000000000000FF037E0000007E000000" => "s_asciiHexDigits" ,
412
414
"000000000000FF03000000007E000000" => "s_asciiHexDigitsLower" ,
413
415
"000000000000FF037E00000000000000" => "s_asciiHexDigitsUpper" ,
416
+ "00000000EEF7008C010000B800000028" => "s_asciiPunctuation" ,
417
+ "00000000010000000000000000000000" => "s_asciiSeparators" ,
418
+ "00000000100800700000004001000050" => "s_asciiSymbols" ,
419
+ "003E0000010000000000000000000000" => "s_asciiWhiteSpace" ,
420
+ "000000000000FF03FEFFFF87FEFFFF07" => "s_asciiWordChars" ,
421
+
422
+ "00000000FFFFFFFFFFFFFFFFFFFFFF7F" => "s_asciiExceptControl" ,
423
+ "FFFFFFFFFFFF00FCFFFFFFFFFFFFFFFF" => "s_asciiExceptDigits" ,
424
+ "FFFFFFFFFFFFFFFF010000F8010000F8" => "s_asciiExceptLetters" ,
425
+ "FFFFFFFFFFFF00FC010000F8010000F8" => "s_asciiExceptLettersAndDigits" ,
426
+ "FFFFFFFFFFFFFFFFFFFFFFFF010000F8" => "s_asciiExceptLower" ,
427
+ "FFFFFFFF1108FF73FEFFFF47FFFFFFD7" => "s_asciiExceptPunctuation" ,
428
+ "FFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFF" => "s_asciiExceptSeparators" ,
429
+ "FFFFFFFFEFF7FF8FFFFFFFBFFEFFFFAF" => "s_asciiExceptSymbols" ,
430
+ "FFFFFFFFFFFFFFFF010000F8FFFFFFFF" => "s_asciiExceptUpper" ,
431
+ "FFC1FFFFFEFFFFFFFFFFFFFFFFFFFFFF" => "s_asciiExceptWhiteSpace" ,
432
+ "FFFFFFFFFFFF00FC01000078010000F8" => "s_asciiExceptWordChars" ,
433
+
414
434
_ => $ "s_ascii_{ hexBitmap . TrimStart ( '0' ) } "
415
435
} ;
416
436
@@ -446,7 +466,6 @@ private static string EmitIndexOfAnyCustomHelper(string set, Dictionary<string,
446
466
}
447
467
}
448
468
449
- string fieldName = EmitIndexOfAnyValues ( asciiChars . ToArray ( ) , requiredHelpers ) ;
450
469
string ? helperName = set switch
451
470
{
452
471
RegexCharClass . DigitClass => "IndexOfAnyDigit" ,
@@ -461,68 +480,82 @@ private static string EmitIndexOfAnyCustomHelper(string set, Dictionary<string,
461
480
RegexCharClass . SymbolClass => "IndexOfAnySymbol" ,
462
481
RegexCharClass . UpperClass => "IndexOfAnyUpper" ,
463
482
RegexCharClass . WordClass => "IndexOfAnyWordChar" ,
483
+
484
+ RegexCharClass . NotDigitClass => "IndexOfAnyExceptDigit" ,
485
+ RegexCharClass . NotControlClass => "IndexOfAnyExceptControl" ,
486
+ RegexCharClass . NotLetterClass => "IndexOfAnyExceptLetter" ,
487
+ RegexCharClass . NotLetterOrDigitClass => "IndexOfAnyExceptLetterOrDigit" ,
488
+ RegexCharClass . NotLowerClass => "IndexOfAnyExceptLower" ,
489
+ RegexCharClass . NotNumberClass => "IndexOfAnyExceptNumber" ,
490
+ RegexCharClass . NotPunctuationClass => "IndexOfAnyExceptPunctuation" ,
491
+ RegexCharClass . NotSeparatorClass => "IndexOfAnyExceptSeparator" ,
492
+ RegexCharClass . NotSpaceClass => "IndexOfAnyExceptWhiteSpace" ,
493
+ RegexCharClass . NotSymbolClass => "IndexOfAnyExceptSymbol" ,
494
+ RegexCharClass . NotUpperClass => "IndexOfAnyExceptUpper" ,
495
+ RegexCharClass . NotWordClass => "IndexOfAnyExceptWordChar" ,
496
+
464
497
_ => null ,
465
498
} ;
466
499
if ( helperName is null )
467
500
{
468
501
using ( SHA256 sha = SHA256 . Create ( ) )
469
502
{
503
+ #pragma warning disable CA1850 // SHA256.HashData isn't available on netstandard2.0
470
504
helperName = $ "IndexOfNonAsciiOrAny_{ BitConverter . ToString ( sha . ComputeHash ( Encoding . UTF8 . GetBytes ( set ) ) ) . Replace ( "-" , "" ) } ";
505
+ #pragma warning restore CA1850
471
506
}
472
507
}
473
508
474
509
if ( ! requiredHelpers . ContainsKey ( helperName ) )
475
510
{
476
511
var additionalDeclarations = new HashSet < string > ( ) ;
477
-
478
- var lines = new List < string > ( )
479
- {
480
- $ "/// <summary>Finds the next index of any character that matches { EscapeXmlComment ( DescribeSet ( set ) ) } .</summary>",
481
- $ "[MethodImpl(MethodImplOptions.AggressiveInlining)]",
482
- $ "internal static int { helperName } (this ReadOnlySpan<char> span)",
483
- $ "{{",
484
- $ " int i = span.IndexOfAnyExcept({ fieldName } );",
485
- $ " if ((uint)i < (uint)span.Length)",
486
- $ " {{",
487
- $ " if (span[i] <= 0x7f)",
488
- $ " {{",
489
- $ " return i;",
490
- $ " }}",
491
- $ "" ,
492
- $ " do",
493
- $ " {{",
494
- $ " if ({ MatchCharacterClass ( "span[i]" , set , negate : false , additionalDeclarations , requiredHelpers ) } )",
495
- $ " {{",
496
- $ " return i;",
497
- $ " }}",
498
- $ " i++;",
499
- $ " }}",
500
- $ " while ((uint)i < (uint)span.Length);",
501
- $ " }}",
502
- $ "" ,
503
- $ " return -1;",
504
- $ "}}",
505
- } ;
506
-
507
- // The below insert positions must be kept in sync with the lines above.
508
-
512
+ string matchExpr = MatchCharacterClass ( "span[i]" , set , negate : false , additionalDeclarations , requiredHelpers ) ;
513
+
514
+ var lines = new List < string > ( ) ;
515
+ lines . Add ( $ "/// <summary>Finds the next index of any character that matches { EscapeXmlComment ( DescribeSet ( set ) ) } .</summary>") ;
516
+ lines . Add ( $ "[MethodImpl(MethodImplOptions.AggressiveInlining)]") ;
517
+ lines . Add ( $ "internal static int { helperName } (this ReadOnlySpan<char> span)") ;
518
+ lines . Add ( $ "{{") ;
519
+ int uncheckedStart = lines . Count ;
520
+ lines . Add ( asciiChars . Count == 128 ?
521
+ $ " int i = span.IndexOfAnyExceptInRange('\0 ', '\u007f ');" :
522
+ $ " int i = span.IndexOfAnyExcept({ EmitIndexOfAnyValues ( asciiChars . ToArray ( ) , requiredHelpers ) } );") ;
523
+ lines . Add ( $ " if ((uint)i < (uint)span.Length)") ;
524
+ lines . Add ( $ " {{") ;
525
+ lines . Add ( $ " if (span[i] <= 0x7f)") ;
526
+ lines . Add ( $ " {{") ;
527
+ lines . Add ( $ " return i;") ;
528
+ lines . Add ( $ " }}") ;
529
+ lines . Add ( $ "" ) ;
509
530
if ( additionalDeclarations . Count > 0 )
510
531
{
511
- lines . InsertRange ( 12 , additionalDeclarations . Select ( s => $ " { s } ") ) ;
512
- }
532
+ lines . AddRange ( additionalDeclarations . Select ( s => $ " { s } ") ) ;
533
+ }
534
+ lines . Add ( $ " do") ;
535
+ lines . Add ( $ " {{") ;
536
+ lines . Add ( $ " if ({ matchExpr } )") ;
537
+ lines . Add ( $ " {{") ;
538
+ lines . Add ( $ " return i;") ;
539
+ lines . Add ( $ " }}") ;
540
+ lines . Add ( $ " i++;") ;
541
+ lines . Add ( $ " }}") ;
542
+ lines . Add ( $ " while ((uint)i < (uint)span.Length);") ;
543
+ lines . Add ( $ " }}") ;
544
+ lines . Add ( $ "" ) ;
545
+ lines . Add ( $ " return -1;") ;
546
+ lines . Add ( $ "}}") ;
513
547
514
548
if ( checkOverflow )
515
549
{
516
- lines . Insert ( 4 , " unchecked" ) ;
517
- lines . Insert ( 5 , " {" ) ;
518
- for ( int i = 6 ; i < lines . Count - 1 ; i ++ )
550
+ lines . Insert ( uncheckedStart , " unchecked" ) ;
551
+ lines . Insert ( uncheckedStart + 1 , " {" ) ;
552
+ for ( int i = uncheckedStart + 2 ; i < lines . Count - 1 ; i ++ )
519
553
{
520
554
lines [ i ] = $ " { lines [ i ] } ";
521
555
}
522
556
lines . Insert ( lines . Count - 1 , " }" ) ;
523
557
}
524
558
525
-
526
559
requiredHelpers . Add ( helperName , lines . ToArray ( ) ) ;
527
560
}
528
561
0 commit comments