1. artgins
  2. ginsfsm

Source

ginsfsm / ginsfsm / circular.py

The default branch has multiple heads

# -*- coding: utf-8 -*-
""" Porting of GSMG.C
"""
import logging

from ginsfsm.utils import string_to_bytearray

DEFAULT_CIRCULAR_SIZE = 8 * 1021


class CircularError(Exception):
    """ Raised when Circular have problems."""


class Circular(object):
    def __init__(self, size=DEFAULT_CIRCULAR_SIZE):
        """ Circular buffer.
        """
        self.size = size
        self.start = 0
        self.count = 0
        self.data = bytearray(size)

    def __str__(self):
        return "size %d, count %d, start %d, data %s" % (
            self.size,
            self.count,
            self.start,
            self.data,
        )

    def putdata(self, data):
        """ WRITING to gmsg.
            Add 'ln' bytes to the message tail.
            Return number of written bytes.
        """
        data = string_to_bytearray(data)
        ln = len(data)
        if ln > self.freebytes():
            logging.error("ERROR circular putchar: FULL buffer")
            raise CircularError(
                "ERROR full buffer, not space for %d bytes" % (ln,))
        tail = (self.start + self.count) % self.size
        self.data[tail:ln] = data[:]
        self.count += ln
        return ln

    def getdata(self, ln):
        """ READING : Pull 'ln' bytes.
            Read from the reading current position.
            Return the pulled data or None.
        """
        if ln <= 0:
            return None
        if ln <= self.count:
            data = self.data[self.start:ln]
            self.count -= ln
            self.start = (self.start + ln) % self.size
            return data

        return None

    def bytesleft(self):
        """READING: Return number of bytes pending of reading
        """
        return self.count

    def freebytes(self):
        """ WRITTING: Return number of free byte space to write.
        """
        free_bytes = self.size - self.count
        return free_bytes