Commits

Ronny Pfannschmidt committed bf771d0

interface changes, pass over 300 tests

Comments (0)

Files changed (1)

 ffi = cffi.FFI()
 ffi.cdef("""
     typedef int wchar;
+
 """) #XXX better
 
 typecodes = {
 
 missing = object()
 
+def buffer(array, ctype, start=0, items=None):
+    if items is None:
+        items = len(array)
+    assert (start+items) <= len(array)
+    return ffi.buffer(array+start, items*ffi.sizeof(ctype))
 
 class cffi_array(object):
     __slots__ = [
         '_len', '_capacity', '_data',
-        '_ctype', '_arraytype',
+        'ctype', 'arraytype',
         '__weakref__',
     ]
 
     def __new__(cls, ctype):
         self = object.__new__(cls)
-        self._ctype = ctype
-        self._arraytype = ffi.getctype(self._ctype, '[]')
+        self.ctype = ctype
+        self.arraytype = ffi.getctype(self.ctype, '[]')
         self._len = 0
         self._capacity = 0
         self._data = ffi.NULL
 
     def _realloc(self, new_size):
         assert new_size > self._len
-        new = ffi.new(self._arraytype, new_size)
+        new = ffi.new(self.arraytype, new_size)
         #XXX: memcopy
         #XXX: downsizing?
 
         if self._data is not ffi.NULL:
-            ffi.buffer(new, ffi.sizeof(self._data))[:] = ffi.buffer(self._data)
+                target = buffer(new, self.ctype, items=self._len)
+                target[:] = buffer(self._data, self.ctype, items=self._len)
 
         self._data = new
         self._capacity = new_size
 
+
     def __buffer__(self):
-        return ffi.buffer(self,self._len * self.itemsize)
+        return buffer(self._data, self.ctype, items=self._len)
+
+    def __getitem__(self, index):
+        if isinstance(index, (int, long)):
+            if index >= self._len:
+                raise IndexError(index)
+            if index < 0:
+                return self._data[len(self)+index]
+            else:
+                return self._data[index]
+        elif isinstance(index, slice):
+            copy = array(self.typecode)
+            #XXX: negative step & co
+            if index.step:
+                for i in range(index.start or 0, index.stop or self._len, index.step):
+                    copy.append(i)
+                    return copy
+            else:
+                start = index.start or 0
+                items = (index.stop or self._len) - start
+                buf = buffer(self._data, self.ctype, start, items)
+                copy._append_buffer(buf, items)
+            return copy
+
 
     @property
     def itemsize(self):
-        return ffi.sizeof(self._ctype)
+        return ffi.sizeof(self.ctype)
 
     def __len__(self):
         return self._len
     def byteswap(self):
         pass
 
-    def __getitem__(self, index):
-        if index >= self._len:
-            raise IndexError(index)
-        if index < 0:
-            return self._data[len(self)+index]
-        else:
-            return self._data[index]
+    def _make_hole(self, start, size):
+        if (self._capacity-self._len) < size:
+            self._realloc(self._len + size*2)
+
+        #XXX: memmove
+        for i in range(self._len, start, -1):
+            self._data[i+size] = self._data[i]
 
 
     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]
+        size = start - end
+        delta = item_count - size
+        if not delta:
+            return
+        elif delta > 0:
+            self._make_hole(end, item_count - size)
+        elif delfa < 0:
+            remove = size - item_count
+            del self[end-size+item_count:end]
+
+        self._len += delta
 
     def __setitem__(self, index, val):
         if val is None:
         if isinstance(index, (int, long)):
             if index < 0:
                 self._data[len(self)+index] = val
+            elif index < self._len:
+                self._data[index] = val
             else:
-                self._data[index] = val
+                raise IndexError(index)
         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__())
+            if not index.step:
+                self._prepare_assign(index.start or 0, index.stop or len(self), len(val))
+                self._assign_buffer(index.start or 0, val.__buffer__())
+            else:
+                raise NotImplementedError
 
 
+    def pop(self, index=missing):
+        if index is missing:
+            if self._len:
+                self._len-=1
+                return self._data[self._len]
+            raise IndexError("cant pop empty array")
+        elif isinstance(index, (int,long)):
+            if index < self._len:
+                data = self[index]
+                del self[index]
+                return data
+            raise IndexError(index)
+        raise TypeError("if given the index must be a integer") #XXX bad error
+
+    def remove(self, value):
+        for i, v in enumerate(self):
+            if v == value:
+                del self[i]
+
     def count(self, item):
         return sum(1 for x in self if x == item)
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.