@@ -385,12 +385,21 @@ abstract final class _StringBase implements String {
385385
386386 int indexOf (Pattern pattern, [int start = 0 ]) {
387387 if ((start < 0 ) || (start > this .length)) {
388- throw new RangeError .range (start, 0 , this .length, "start" );
388+ throw RangeError .range (start, 0 , this .length, "start" );
389389 }
390390 if (pattern is String ) {
391391 String other = pattern;
392- int maxIndex = this .length - other.length;
393- // TODO: Use an efficient string search (e.g. BMH).
392+ var otherLength = other.length;
393+ if (otherLength == 0 ) return start;
394+ if (otherLength == 1 ) {
395+ int codeUnit = other.codeUnitAt (0 );
396+ for (var index = start; index < this .length; index++ ) {
397+ if (codeUnit == this .codeUnitAt (index)) return index;
398+ }
399+ return - 1 ;
400+ }
401+ int maxIndex = this .length - otherLength;
402+ // TODO: Use an efficient string search (e.g., BMH).
394403 for (int index = start; index <= maxIndex; index++ ) {
395404 if (_substringMatches (index, other)) {
396405 return index;
@@ -399,8 +408,6 @@ abstract final class _StringBase implements String {
399408 return - 1 ;
400409 }
401410 for (int i = start; i <= this .length; i++ ) {
402- // TODO(11276); This has quadratic behavior because matchAsPrefix tries
403- // to find a later match too. Optimize matchAsPrefix to avoid this.
404411 if (pattern.matchAsPrefix (this , i) != null ) return i;
405412 }
406413 return - 1 ;
@@ -424,8 +431,6 @@ abstract final class _StringBase implements String {
424431 return - 1 ;
425432 }
426433 for (int i = start; i >= 0 ; i-- ) {
427- // TODO(11276); This has quadratic behavior because matchAsPrefix tries
428- // to find a later match too. Optimize matchAsPrefix to avoid this.
429434 if (pattern.matchAsPrefix (this , i) != null ) return i;
430435 }
431436 return - 1 ;
@@ -604,30 +609,17 @@ abstract final class _StringBase implements String {
604609 }
605610
606611 bool contains (Pattern pattern, [int startIndex = 0 ]) {
607- if (pattern is String ) {
608- if (startIndex < 0 || startIndex > this .length) {
609- throw new RangeError .range (startIndex, 0 , this .length);
610- }
612+ if (startIndex >= 0 && startIndex <= this .length) {
611613 return indexOf (pattern, startIndex) >= 0 ;
612614 }
613- return pattern. allMatches ( this .substring ( startIndex)).isNotEmpty ;
615+ throw RangeError . range (startIndex, 0 , this .length, " startIndex" ) ;
614616 }
615617
616618 String replaceFirst (
617619 Pattern pattern,
618620 String replacement, [
619621 int startIndex = 0 ,
620622 ]) {
621- // TODO: Remove these null checks once all code is opted into strong nonnullable mode.
622- if (pattern == null ) {
623- throw new ArgumentError .notNull ("pattern" );
624- }
625- if (replacement == null ) {
626- throw new ArgumentError .notNull ("replacement" );
627- }
628- if (startIndex == null ) {
629- throw new ArgumentError .notNull ("startIndex" );
630- }
631623 RangeError .checkValueInInterval (startIndex, 0 , this .length, "startIndex" );
632624 Iterator iterator =
633625 startIndex == 0
@@ -708,7 +700,7 @@ abstract final class _StringBase implements String {
708700 if (replacementIsOneByte &&
709701 length < _maxJoinReplaceOneByteStringLength &&
710702 this ._isOneByte) {
711- // TODO(lrn) : Is there a cut-off point, or is runtime always faster?
703+ // TODO: Is there a cut-off point, or is runtime always faster?
712704 return _joinReplaceAllOneByteResult (this , matches, length);
713705 }
714706 return _joinReplaceAllResult (this , matches, length, replacementIsOneByte);
0 commit comments