From ca4ad3882f63f911462d6a2987f2d37fce0130de Mon Sep 17 00:00:00 2001 From: Jeremy Fincher Date: Tue, 22 Apr 2003 08:27:11 +0000 Subject: [PATCH] Initial import. --- src/structures.py | 105 ++++++++++++++++++++++++++++++++ test/test_structures.py | 129 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 src/structures.py create mode 100644 test/test_structures.py diff --git a/src/structures.py b/src/structures.py new file mode 100644 index 000000000..7bb394d71 --- /dev/null +++ b/src/structures.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python + +### +# Copyright (c) 2002, Jeremiah Fincher +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions, and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions, and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the author of this software nor the name of +# contributors to this software may be used to endorse or promote products +# derived from this software without specific prior written consent. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +### + +""" +Data structures for Python. +""" + +import types + +__all__ = ['RingBuffer'] + +class RingBuffer(object): + #__slots__ = ('L', 'i') + def __init__(self, maxSize, seq=()): +## if not maxSize and seq: +## maxSize = len(seq) + if maxSize <= 0: + raise ValueError, 'maxSize must be > 0.' + self.i = maxSize + self.L = [] + for elt in seq: + self.append(elt) + + def __len__(self): + return len(self.L) + + def __nonzero__(self): + return len(self) > 0 + + def __contains__(self, elt): + return elt in self.L + + def append(self, elt): + if len(self) >= self.i: + self.__class__ = _FullRingBuffer + self.i = 0 + self.append(elt) + else: + self.L.append(elt) + + def extend(self, seq): + for elt in seq: + self.append(elt) + + def __getitem__(self, idx): + if type(idx) == types.SliceType: + pass + else: + return self.L[idx] + + def __setitem__(self, idx, elt): + self.L[idx] = elt + + def __repr__(self): + return 'RingBuffer(%r, %r)' % (self.i, list(self)) + +class _FullRingBuffer(RingBuffer): + #__slots__ = ('L', 'i') + def append(self, elt): + self.L[self.i] = elt + self.i += 1 + self.i %= len(self.L) + def __getitem__(self, oidx): + (m, idx) = divmod(oidx, len(self.L)) + if m and m != -1: + raise IndexError, oidx + idx = (idx + self.i) % len(self.L) + return self.L[idx] + def __setitem__(self, oidx, elt): + (m, idx) = divmod(oidx, len(self.L)) + if m and m != -1: + raise IndexError, oidx + idx = (idx + self.i) % len(self.L) + self.L[idx] = elt + + def __repr__(self): + return 'RingBuffer(%r, %r)' % (len(self.L), list(self)) diff --git a/test/test_structures.py b/test/test_structures.py new file mode 100644 index 000000000..c0edd9e39 --- /dev/null +++ b/test/test_structures.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python + +### +# Copyright (c) 2002, Jeremiah Fincher +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions, and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions, and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the author of this software nor the name of +# contributors to this software may be used to endorse or promote products +# derived from this software without specific prior written consent. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +### + +from test import * + +from structures import * + +class RingBufferTestCase(unittest.TestCase): + def testInit(self): + self.assertRaises(ValueError, RingBuffer, -1) + self.assertRaises(ValueError, RingBuffer, 0) + self.assertEqual(range(10), list(RingBuffer(10, range(10)))) + + def testLen(self): + b = RingBuffer(3) + self.assertEqual(0, len(b)) + b.append(1) + self.assertEqual(1, len(b)) + b.append(2) + self.assertEqual(2, len(b)) + b.append(3) + self.assertEqual(3, len(b)) + b.append(4) + self.assertEqual(3, len(b)) + b.append(5) + self.assertEqual(3, len(b)) + + def testNonzero(self): + b = RingBuffer(3) + self.failIf(b) + b.append(1) + self.failUnless(b) + + def testAppend(self): + b = RingBuffer(3) + self.assertEqual([], list(b)) + b.append(1) + self.assertEqual([1], list(b)) + b.append(2) + self.assertEqual([1, 2], list(b)) + b.append(3) + self.assertEqual([1, 2, 3], list(b)) + b.append(4) + self.assertEqual([2, 3, 4], list(b)) + b.append(5) + self.assertEqual([3, 4, 5], list(b)) + b.append(6) + self.assertEqual([4, 5, 6], list(b)) + + def testContains(self): + b = RingBuffer(3, range(3)) + self.failUnless(0 in b) + self.failUnless(1 in b) + self.failUnless(2 in b) + self.failIf(3 in b) + + def testGetitem(self): + L = range(10) + b = RingBuffer(len(L), L) + for i in range(len(b)): + self.assertEqual(L[i], b[i]) + for i in range(len(b)): + b.append(i) + for i in range(len(b)): + self.assertEqual(L[i], b[i]) + + def testSetitem(self): + L = range(10) + b = RingBuffer(len(L), [0]*len(L)) + for i in range(len(b)): + b[i] = i + for i in range(len(b)): + self.assertEqual(b[i], i) + for i in range(len(b)): + b.append(0) + for i in range(len(b)): + b[i] = i + for i in range(len(b)): + self.assertEqual(b[i], i) + + def testExtend(self): + b = RingBuffer(3, range(3)) + self.assertEqual(list(b), range(3)) + b.extend(range(6)) + self.assertEqual(list(b), range(6)[3:]) + + def testRepr(self): + b = RingBuffer(3) + self.assertEqual(repr(b), 'RingBuffer(3, [])') + b.append(1) + self.assertEqual(repr(b), 'RingBuffer(3, [1])') + b.append(2) + self.assertEqual(repr(b), 'RingBuffer(3, [1, 2])') + b.append(3) + self.assertEqual(repr(b), 'RingBuffer(3, [1, 2, 3])') + b.append(4) + self.assertEqual(repr(b), 'RingBuffer(3, [2, 3, 4])') + b.append(5) + self.assertEqual(repr(b), 'RingBuffer(3, [3, 4, 5])') + b.append(6) + self.assertEqual(repr(b), 'RingBuffer(3, [4, 5, 6])')