------ art_2163_31291114.1193766520716
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
First attempt
- plain gap buffer implementation without much optimization
- only basic operations
- O(n)
Regards
Holger
# Solution to ruby quiz #145
# http://www.rubyquiz.com/quiz145.html
# by Holger
#
# GapBuffer works similar to StringCaret
#
# Some remarks:
# - if gap size is zero before insert it will be set to 64
# - data buffer will never shrink -> gap might be very large
# - lazy up and down methods, but cursor remains in same column (if fits in
line)
class GapBuffer
# data is in @data
# gap starts @gap_start
# gap ends @gap_start + @gap_len
def initialize(data , i
@data ata
@gap_start
@gap_len
@GAP "*64
end
def insert_before(ch)
if @gap_len.zero?
@data[@gap_start, 0] GAP
@gap_len GAP.length
end
@data[@gap_start] h
@gap_start +
@gap_len -
end
def insert_after(ch)
if @gap_len.zero?
@data[@gap_start, 0] GAP
@gap_len GAP.length
end
@data[@gap_start+@gap_len-1] h
@gap_len -
end
def delete_before
return if @gap_start.zero?
@gap_start -
@gap_len +
@data[@gap_start]
end
def delete_after
return if @gap_start+@gap_len > data.length
@gap_len +
@data[@gap_start+@gap_len-1]
end
def left
return if @gap_start.zero?
@data[@gap_start+@gap_len-1] data[@gap_start-1]
@gap_start -
@data[@gap_start]
end
def right
return if @gap_start+@gap_len>
ata.length
@data[@gap_start] data[@gap_start + @gap_len]
@gap_start +
@data[@gap_start - 1]
end
def up
col olumn
cursor gap_start-col
return if cursor.zero?
cursor_line data.rindex(?\n, cursor-2)
cursor_line if cursor_line.nil?
cursor_line + ol+1
if cursor_line > cursor-1
cursor_line ursor-1
end
left while @gap_start > cursor_line
true
end
def down
col olumn
cursor data.index(?\n, @gap_start + @gap_len)
return if cursor.nil?
cursor_line ursor+1+col
cursor data.index(?\n, cursor+1)
cursor data.length if cursor.nil?
cursor_line ursor if cursor_line > cursor
right while @gap_start + @gap_len < cursor_line
true
end
def position
@gap_start
end
def column
lbreak data.rindex(?\n, @gap_start-1)
lbreak.nil? ? @gap_start : (@gap_start-(lbreak+1))
end
def to_s
return @data[0, @gap_start]+@data[@gap_start+@gap_len, @data.length-@gap
_start-@gap_len]
end
end
GapBuffer.new: 1000x100
insert_before 0.266000 0.000000 0.266000 ( 0.266000)
left 0.328000 0.000000 0.328000 ( 0.328000)
right 0.406000 0.000000 0.406000 ( 0.407000)
up 0.375000 0.000000 0.375000 ( 0.375000)
down 0.422000 0.000000 0.422000 ( 0.421000)
insert_after 0.391000 0.000000 0.391000 ( 0.391000)
delete_before 0.234000 0.000000 0.234000 ( 0.234000)
delete_after 0.313000 0.000000 0.313000 ( 0.313000)
total 2.735000 0.000000 2.735000 ( 2.735000)
GapBuffer.new: 2000x100
insert_before 0.547000 0.000000 0.547000 ( 0.547000)
left 0.672000 0.000000 0.672000 ( 0.671000)
right 0.796000 0.000000 0.796000 ( 0.797000)
up 0.735000 0.000000 0.735000 ( 0.735000)
down 0.875000 0.000000 0.875000 ( 0.875000)
insert_after 0.797000 0.000000 0.797000 ( 0.796000)
delete_before 0.468000 0.000000 0.468000 ( 0.469000)
delete_after 0.610000 0.000000 0.610000 ( 0.609000)
total 5.500000 0.000000 5.500000 ( 5.499000)
GapBuffer.new: 3000x100
insert_before 0.890000 0.000000 0.890000 ( 0.891000)
left 1.016000 0.000000 1.016000 ( 1.015000)
right 1.188000 0.000000 1.188000 ( 1.188000)
up 1.140000 0.000000 1.140000 ( 1.140000)
down 1.360000 0.000000 1.360000 ( 1.360000)
insert_after 1.156000 0.016000 1.172000 ( 1.171000)
delete_before 0.797000 0.000000 0.797000 ( 0.813000)
delete_after 0.953000 0.000000 0.953000 ( 0.953000)
total 8.500000 0.016000 8.516000 ( 8.531000)
------ art_2163_31291114.1193766520716--