1. Python CFFI
  2. Untitled project
  3. array-experiment

Commits

Ronny Pfannschmidt  committed fb6b132

create a cffi_array baseclass, one more passing test

  • Participants
  • Parent commits 731a913
  • Branches default

Comments (0)

Files changed (1)

File array.py

View file
 missing = object()
 
 
-class array(object):
+class cffi_array(object):
     __slots__ = [
         '_len', '_capacity', '_data',
-        'typecode', '_ctype', '_arraytype',
+        '_ctype', '_arraytype',
         '__weakref__',
     ]
 
-    def __new__(cls, typecode, initializer=missing, **kw):
+    def __new__(cls, ctype):
         self = object.__new__(cls)
-        self.typecode = typecode
-        self._ctype = typecode2ctype(typecode)
+        self._ctype = ctype
         self._arraytype = ffi.getctype(self._ctype, '[]')
         self._len = 0
         self._capacity = 0
         self._data = ffi.NULL
-        if initializer is not missing:
-            if isinstance(initializer, str):
-                self.fromstring(initializer)
-            else:
-                self.extend(initializer)
         return self
 
-    def buffer_info(self):
-        return 0, self._len
-
-    def byteswap(self):
-        pass
-
     def _realloc(self, new_size):
         assert new_size > self._len
         new = ffi.new(self._arraytype, new_size)
         self._capacity = new_size
 
     def __buffer__(self):
-        return ffi.buffer(self)
-    
+        return ffi.buffer(self,self._len * self.itemsize)
+
     @property
     def itemsize(self):
         return ffi.sizeof(self._ctype)
     def __len__(self):
         return self._len
 
+    def append(self, item):
+        #XXX: checksize
+        if self._len == self._capacity:
+            self._realloc(self._capacity*2 or 4)
+        self._data[self._len] = item
+        self._len += 1
+
+
+class array(cffi_array):
+    __slots__ = [
+        'typecode',
+    ]
+
+    def __new__(cls, typecode, initializer=missing, **kw):
+        ctype = typecode2ctype(typecode)
+        self = cffi_array.__new__(cls, ctype)
+        self.typecode = typecode
+        if initializer is not missing:
+            if isinstance(initializer, str):
+                self.fromstring(initializer)
+            else:
+                self.extend(initializer)
+        return self
+
+    def buffer_info(self):
+        return 0, self._len
+
+    def byteswap(self):
+        pass
+
     def __getitem__(self, index):
         if index >= self._len:
             raise IndexError(index)
         else:
             return self._data[index]
 
+
+    def _prepare_assign(self, start, end, item_count):
+        size = start-end
+        if size < item_count:
+            self._move_after(stop, slice_size-item_count)
+        else:
+            del self[slice.end-slice_size+item_count:slice.end]
+
     def __setitem__(self, index, val):
         if val is None:
             raise TypeError
-        if index < 0:
-            self._data[len(self)+index] = val
-        else:
-            self._data[index] = val
+        if isinstance(index, (int, long)):
+            if index < 0:
+                self._data[len(self)+index] = val
+            else:
+                self._data[index] = val
+        elif isinstance(index, slice):
+            #XXX: expensive, memmove/copy
+            # also takes care of self assign
+            val = array(self.typecode, val)
+            self._prepare_assign(index, len(val))
+            self._assign_buffer(index.start, val.__buffer__())
+
 
     def count(self, item):
         return sum(1 for x in self if x == item)
 
 
+    def _swap(self, a, b):
+        tmp = self[a]
+        self[a] = self[b]
+        self[b] = tmp
+
     def reverse(self):
         for i in range(len(self)/2):
-            self._data[i], self._data[len(self)-i-1] = self._data[len(self)-i-1], self._data[i]
+            self._swap(i, -i-1)
 
     def __gt__(self, other):
         return list(self)>list(other) #XXX: evil
             return False
         return all(a == b for a, b in zip(self, other))
 
-    def append(self, item):
-        #XXX: checksize
-        if self._len == self._capacity:
-            self._realloc(self._capacity*2 or 4)
-        self._data[self._len] = item
-        self._len += 1
-
     def extend(self, items):
         if isinstance(items, array):
             if items.typecode == self.typecode:
     
     def _append_buffer(self, data, count):
         self._prepare_extend(count)
+        self._assign_buffer(self._len, data)
+        self._len +=count
+
+    def _assign_buffer(self, start, data):
+        start = start*self.itemsize
         assign = ffi.buffer(self._data)
-        start = self._len*self.itemsize
         assign[start:start+len(data)] = data
-        self._len +=count
 
     def fromfile(self, fp, n):
         if not isinstance(fp, file):