@@ -87,25 +87,62 @@ def inspect
8787 "#<RBS::Buffer:#{ __id__ } @name=#{ name } , @content=#{ content . bytesize } bytes, @lines=#{ ranges . size } lines,>"
8888 end
8989
90+ def character_offset ( byte_offset )
91+ top = top_buffer
92+ return top . character_offset ( byte_offset ) unless top . equal? ( self )
93+
94+ keys , vals = ( @character_offset_cache ||= [ [ 0 ] , [ 0 ] ] )
95+
96+ idx = keys . bsearch_index { |k | k > byte_offset }
97+ lo = idx ? idx - 1 : keys . size - 1
98+
99+ base_byte = keys [ lo ]
100+ base_char = vals [ lo ]
101+ delta = byte_offset - base_byte
102+ return base_char if delta == 0
103+
104+ result = base_char + ( content . byteslice ( base_byte , delta ) or raise ) . length
105+
106+ if base_byte == keys [ -1 ]
107+ keys << byte_offset
108+ vals << result
109+ end
110+
111+ result
112+ end
113+
90114 def rbs_location ( location , loc2 = nil )
115+ top = top_buffer
91116 if loc2
92- Location . new ( self . top_buffer , location . start_character_offset , loc2 . end_character_offset )
117+ Location . new ( top , character_offset ( location . start_offset ) , character_offset ( loc2 . end_offset ) )
93118 else
94- Location . new ( self . top_buffer , location . start_character_offset , location . end_character_offset )
119+ Location . new ( top , character_offset ( location . start_offset ) , character_offset ( location . end_offset ) )
95120 end
96121 end
97122
98- def sub_buffer ( lines :)
123+ def sub_buffer ( lines :, byte_lines_hint : nil )
99124 buf = +""
100- lines . each_with_index do |range , index |
101- start_pos = range . begin
102- end_pos = range . end
103- slice = content [ start_pos ...end_pos ] or raise
104- if slice . include? ( "\n " )
105- raise "Line #{ index + 1 } cannot contain newline character."
125+
126+ if byte_lines_hint
127+ byte_lines_hint . each_with_index do |range , index |
128+ slice = content . byteslice ( range . begin , range . end - range . begin ) or raise
129+ if slice . include? ( "\n " )
130+ raise "Line #{ index + 1 } cannot contain newline character."
131+ end
132+ buf << slice
133+ buf << "\n "
134+ end
135+ else
136+ lines . each_with_index do |range , index |
137+ start_pos = range . begin
138+ end_pos = range . end
139+ slice = content [ start_pos ...end_pos ] or raise
140+ if slice . include? ( "\n " )
141+ raise "Line #{ index + 1 } cannot contain newline character."
142+ end
143+ buf << slice
144+ buf << "\n "
106145 end
107- buf << slice
108- buf << "\n "
109146 end
110147
111148 buf . chomp!
0 commit comments