@@ -366,6 +366,11 @@ struct BaseLoc
366366 uint [] lines; // / For each line, the file offset at which it starts. At index 0 there's always a 0 entry.
367367 BaseLoc[] substitutions; // / Substitutions from #line / #file directives
368368
369+ // / Cache for the last line lookup
370+ private size_t lastLineIndex = 0 ;
371+ // / Cache for the last substitution lookup
372+ private size_t lastSubstIndex = 0 ;
373+
369374 // / Register that a new line starts at `offset` bytes from the start of the source file
370375 void newLine (uint offset)
371376 {
@@ -421,16 +426,72 @@ struct BaseLoc
421426
422427 private size_t getSubstitutionIndex (uint offset) @nogc
423428 {
429+ if (substitutions.length <= 1 )
430+ return 0 ;
431+
432+ // Check if the offset falls within the current cached substitution or the next one
433+ if (lastSubstIndex < substitutions.length - 1 )
434+ {
435+ // For the current substitution's range
436+ if (substitutions[lastSubstIndex].startIndex <= offset &&
437+ (lastSubstIndex == substitutions.length - 1 ||
438+ substitutions[lastSubstIndex + 1 ].startIndex > offset))
439+ return lastSubstIndex;
440+
441+ // For the next substitution's range
442+ if (lastSubstIndex + 1 < substitutions.length - 1 &&
443+ substitutions[lastSubstIndex + 1 ].startIndex <= offset &&
444+ substitutions[lastSubstIndex + 2 ].startIndex > offset)
445+ {
446+ lastSubstIndex++ ;
447+ return lastSubstIndex;
448+ }
449+
450+ // For the previous substitution's range
451+ if (lastSubstIndex > 0 &&
452+ substitutions[lastSubstIndex - 1 ].startIndex <= offset &&
453+ substitutions[lastSubstIndex].startIndex > offset)
454+ {
455+ lastSubstIndex-- ;
456+ return lastSubstIndex;
457+ }
458+ }
459+ else if (lastSubstIndex == substitutions.length - 1 &&
460+ substitutions[lastSubstIndex].startIndex <= offset)
461+ {
462+ // Last substitution case
463+ return lastSubstIndex;
464+ }
465+
466+ // Fall back to binary search, but start near
424467 size_t lo = 0 ;
425- size_t hi = substitutions.length + - 1 ;
468+ size_t hi = substitutions.length - 1 ;
469+
470+ // Adjust the range based on the offset relative to lastSubstIndex
471+ if (offset < substitutions[lastSubstIndex].startIndex)
472+ {
473+ // Search backward
474+ lo = 0 ;
475+ hi = lastSubstIndex;
476+ }
477+ else
478+ {
479+ // Search forward
480+ lo = lastSubstIndex;
481+ hi = substitutions.length - 1 ;
482+ }
483+
426484 size_t mid = 0 ;
427485 while (lo <= hi)
428486 {
429487 mid = lo + (hi - lo) / 2 ;
430488 if (substitutions[mid].startIndex <= offset)
431489 {
432490 if (mid == substitutions.length - 1 || substitutions[mid + 1 ].startIndex > offset)
491+ {
492+ lastSubstIndex = mid; // Update cache
433493 return mid;
494+ }
434495
435496 lo = mid + 1 ;
436497 }
@@ -443,18 +504,62 @@ struct BaseLoc
443504 }
444505
445506 // / Binary search the index in `this.lines` corresponding to `offset`
507+ // / lastLineIndex cache to avoid full binary search when possible
446508 private size_t getLineIndex (uint offset) @nogc
447509 {
510+ if (lines.length <= 1 )
511+ return 0 ;
512+
513+ if (lastLineIndex < lines.length - 1 )
514+ {
515+ if (lines[lastLineIndex] <= offset && offset < lines[lastLineIndex + 1 ])
516+ return lastLineIndex;
517+
518+ if (lastLineIndex + 1 < lines.length - 1 &&
519+ lines[lastLineIndex + 1 ] <= offset && offset < lines[lastLineIndex + 2 ])
520+ {
521+ lastLineIndex++ ;
522+ return lastLineIndex;
523+ }
524+
525+ if (lastLineIndex > 0 &&
526+ lines[lastLineIndex - 1 ] <= offset && offset < lines[lastLineIndex])
527+ {
528+ lastLineIndex-- ;
529+ return lastLineIndex;
530+ }
531+ }
532+ else if (lastLineIndex == lines.length - 1 && lines[lastLineIndex] <= offset)
533+ {
534+ return lastLineIndex;
535+ }
536+
537+ // Fall back to binary search
448538 size_t lo = 0 ;
449- size_t hi = lines.length + - 1 ;
539+ size_t hi = lines.length - 1 ;
540+
541+ if (offset < lines[lastLineIndex])
542+ {
543+ lo = 0 ;
544+ hi = lastLineIndex;
545+ }
546+ else
547+ {
548+ lo = lastLineIndex;
549+ hi = lines.length - 1 ;
550+ }
551+
450552 size_t mid = 0 ;
451553 while (lo <= hi)
452554 {
453555 mid = lo + (hi - lo) / 2 ;
454556 if (lines[mid] <= offset)
455557 {
456558 if (mid == lines.length - 1 || lines[mid + 1 ] > offset)
559+ {
560+ lastLineIndex = mid; // Update cache
457561 return mid;
562+ }
458563
459564 lo = mid + 1 ;
460565 }
0 commit comments