| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 | 
							- /*
 
-  * Public Domain Software
 
-  *
 
-  * I (Matthias Ladkau) am the author of the source code in this file.
 
-  * I have placed the source code in this file in the public domain.
 
-  *
 
-  * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
 
-  */
 
- /*
 
- Package datautil contains general data handling objects and helper methods.
 
- */
 
- package datautil
 
- import (
 
- 	"fmt"
 
- 	"strings"
 
- 	"sync"
 
- )
 
- /*
 
- RingBuffer is a classic thread-safe ringbuffer implementation. It stores
 
- abstract interface{} objects. It has specific methods so it can be used as
 
- a print logger.
 
- */
 
- type RingBuffer struct {
 
- 	data     []interface{} // Elements of this ring buffer
 
- 	size     int           // Size of the ring buffer
 
- 	first    int           // First item of the ring buffer
 
- 	last     int           // Last item of the ring buffer
 
- 	modCount int           // Check for modifications during iterations
 
- 	lock     *sync.RWMutex // Lock for RingBuffer
 
- }
 
- /*
 
- NewRingBuffer creates a new ringbuffer with a given size.
 
- */
 
- func NewRingBuffer(size int) *RingBuffer {
 
- 	return &RingBuffer{make([]interface{}, size), 0, 0, 0, 0, &sync.RWMutex{}}
 
- }
 
- /*
 
- Reset removes all content from the ringbuffer.
 
- */
 
- func (rb *RingBuffer) Reset() {
 
- 	rb.lock.Lock()
 
- 	defer rb.lock.Unlock()
 
- 	rb.data = make([]interface{}, cap(rb.data))
 
- 	rb.size = 0
 
- 	rb.first = 0
 
- 	rb.last = 0
 
- 	rb.modCount = 0
 
- }
 
- /*
 
- IsEmpty returns if this ringbuffer is empty.
 
- */
 
- func (rb *RingBuffer) IsEmpty() bool {
 
- 	rb.lock.RLock()
 
- 	defer rb.lock.RUnlock()
 
- 	return rb.size == 0
 
- }
 
- /*
 
- Size returns the size of the ringbuffer.
 
- */
 
- func (rb *RingBuffer) Size() int {
 
- 	rb.lock.RLock()
 
- 	defer rb.lock.RUnlock()
 
- 	return rb.size
 
- }
 
- /*
 
- Get returns an element of the ringbuffer from a given position.
 
- */
 
- func (rb *RingBuffer) Get(p int) interface{} {
 
- 	rb.lock.RLock()
 
- 	defer rb.lock.RUnlock()
 
- 	return rb.data[(rb.first+p)%len(rb.data)]
 
- }
 
- /*
 
- Add adds an item to the ringbuffer.
 
- */
 
- func (rb *RingBuffer) Add(e interface{}) {
 
- 	rb.lock.Lock()
 
- 	defer rb.lock.Unlock()
 
- 	ld := len(rb.data)
 
- 	rb.data[rb.last] = e
 
- 	rb.last = (rb.last + 1) % ld
 
- 	if rb.size == ld {
 
- 		rb.first = (rb.first + 1) % ld
 
- 	} else {
 
- 		rb.size++
 
- 	}
 
- 	rb.modCount++
 
- }
 
- /*
 
- Poll removes and returns the head of the ringbuffer.
 
- */
 
- func (rb *RingBuffer) Poll() interface{} {
 
- 	rb.lock.Lock()
 
- 	defer rb.lock.Unlock()
 
- 	if rb.size == 0 {
 
- 		return nil
 
- 	}
 
- 	i := rb.data[rb.first]
 
- 	rb.data[rb.first] = nil
 
- 	rb.size--
 
- 	rb.first = (rb.first + 1) % len(rb.data)
 
- 	rb.modCount++
 
- 	return i
 
- }
 
- /*
 
- Log writes the given arguments as strings into the ring buffer. Each line is a
 
- separate item.
 
- */
 
- func (rb *RingBuffer) Log(v ...interface{}) {
 
- 	lines := strings.Split(fmt.Sprint(v...), "\n")
 
- 	for _, line := range lines {
 
- 		rb.Add(line)
 
- 	}
 
- }
 
- /*
 
- Slice returns the contents of the buffer as a slice.
 
- */
 
- func (rb *RingBuffer) Slice() []interface{} {
 
- 	rb.lock.RLock()
 
- 	defer rb.lock.RUnlock()
 
- 	ld := len(rb.data)
 
- 	ret := make([]interface{}, rb.size)
 
- 	for i := 0; i < rb.size; i++ {
 
- 		ret[i] = rb.data[(i+rb.first)%ld]
 
- 	}
 
- 	return ret
 
- }
 
- /*
 
- StringSlice returns the contents of the buffer as a slice of strings.
 
- Each item of the buffer is a separate string.
 
- */
 
- func (rb *RingBuffer) StringSlice() []string {
 
- 	rb.lock.RLock()
 
- 	defer rb.lock.RUnlock()
 
- 	ld := len(rb.data)
 
- 	ret := make([]string, rb.size)
 
- 	for i := 0; i < rb.size; i++ {
 
- 		ret[i] = fmt.Sprint(rb.data[(i+rb.first)%ld])
 
- 	}
 
- 	return ret
 
- }
 
- /*
 
- String retusn the contents of the buffer as a string. Each item of the buffer is
 
- treated as a separate line.
 
- */
 
- func (rb *RingBuffer) String() string {
 
- 	return strings.Join(rb.StringSlice(), "\n")
 
- }
 
 
  |