A simple circular buffer with reverse iterator (Lua)

> Coding, hacking, computer graphics, game dev, and such...
User avatar
fips
Site Admin
Posts: 166
Joined: Wed Nov 12, 2008 9:49 pm
Location: Prague
Contact:

A simple circular buffer with reverse iterator (Lua)

Post by fips »

This is just a small code snippet showing a simple circular buffer with reverse iterator that I've coded up for my forthcoming IoT NodeMcu-based project. Its purpose is to provide fixed and efficient storage for data coming from sensors, so in my case it basically represents history of N most recent values with additional convenience of the reverse iterator for easy FIFO access. I haven't coded in Lua for some time, so it was quite refreshing to come up with this. I especially like how iterators can make use of closures for tracking state, which makes the implementation pretty simple end easy to read. What I don't like about Lua that much is the infamous 1-based indexing, which feels unnatural to me, especially when dealing with modular arithmetic for index wrapping.

Code: Select all

--[CODE BY FIPS @ 4FIPS.COM, (c) 2016 FILIP STOKLAS, MIT-LICENSED]

History = {}

function History.new(max_size)
   local hist = { __index = History }
   setmetatable(hist, hist)
   hist.max_size = max_size
   hist.size = 0
   hist.cursor = 1
   return hist
end

function History:push(value)
  if self.size < self.max_size then
    table.insert(self, value)
    self.size = self.size + 1
  else
    self[self.cursor] = value
    self.cursor = self.cursor % self.max_size + 1
  end
end

function History:iterator()
  local i = 0
  return function()
    i = i + 1
    if i <= self.size then
      return self[(self.cursor - i - 1) % self.size + 1]
    end
  end
end

hist = History.new(5)
hist:push(10)
hist:push(20)
hist:push(30)
hist:push(40)
hist:push(50)
hist:push(60)
hist:push(70)

print("Raw (wrapped) values:")
for i, v in ipairs(hist) do
  print(v)
end

print("")

print("History values:")
for v in hist:iterator() do
  print(v)
end

--[[
output:
Raw (wrapped) values:
60
70
30
40
50

History values:
70
60
50
40
30
--]]