Edouard@2741: #!/usr/bin/env python
Edouard@2741: # -*- coding: utf-8 -*-
Edouard@2741: 
Edouard@2741: # This file is part of Beremiz
Edouard@2741: # Copyright (C) 2021: Edouard TISSERANT
Edouard@2741: #
Edouard@2741: # See COPYING file for copyrights details.
Edouard@2741: 
Edouard@2741: # Based on Eelco Hoogendoorn stackoverflow answer about RingBuffer with numpy
Edouard@2741: 
Edouard@2741: import numpy as np
Edouard@2741: 
Edouard@2741: 
Edouard@2741: class RingBuffer(object):
Edouard@2742:     def __init__(self, width=None, size=131072, padding=None):
Edouard@2741:         self.size = size
Edouard@2741:         self.padding = size if padding is None else padding
Edouard@2741:         shape = (self.size+self.padding,)
Edouard@2741:         if width :
Edouard@2741:             shape += (width,)
Edouard@2741:         self.buffer = np.zeros(shape)
Edouard@2742:         self.cursor = 0
Edouard@2741: 
Edouard@2741:     def append(self, data):
Edouard@2741:         """this is an O(n) operation"""
Edouard@2742:         data = data[-self.size:]
Edouard@2741:         n = len(data)
Edouard@2742:         if self.size + self.padding - self.cursor < n:
Edouard@2742:             self.compact()
Edouard@2742:         self.buffer[self.cursor:][:n] = data
Edouard@2742:         self.cursor += n
Edouard@2741: 
Edouard@2741:     @property
Edouard@2741:     def count(self):
Edouard@2742:         return min(self.size, self.cursor)
Edouard@2741: 
Edouard@2741:     @property
Edouard@2741:     def view(self):
Edouard@2741:         """this is always an O(1) operation"""
Edouard@2742:         return self.buffer[max(0, self.cursor - self.size):][:self.count]
Edouard@2741: 
Edouard@2741:     def compact(self):
Edouard@2741:         """
Edouard@2741:         note: only when this function is called, is an O(size) performance hit incurred,
Edouard@2741:         and this cost is amortized over the whole padding space
Edouard@2741:         """
Edouard@2741:         print 'compacting'
Edouard@2742:         self.buffer[:self.count] = self.view
Edouard@2742:         self.cursor -= self.size
Edouard@2741: