package org.python.core; import java.io.Serializable; /** * Handles all the index checking and manipulation for get, set and del operations on a sequence. */ public abstract class SequenceIndexDelegate implements Serializable { public abstract int len(); public abstract PyObject getItem(int idx); public abstract void setItem(int idx, PyObject value); public abstract void delItem(int idx); public abstract PyObject getSlice(int start, int stop, int step); public abstract void setSlice(int start, int stop, int step, PyObject value); public abstract void delItems(int start, int stop); public abstract String getTypeName(); public void checkIdxAndSetItem(PyObject idx, PyObject value) { if (idx.isIndex()) { checkIdxAndSetItem(idx.asIndex(Py.IndexError), value); } else if (idx instanceof PySlice) { checkIdxAndSetSlice((PySlice)idx, value); } else { throw Py.TypeError(getTypeName() + " indices must be integers"); } } public void checkIdxAndSetSlice(PySlice slice, PyObject value) { int[] indices = slice.indicesEx(len()); if ((slice.step != Py.None) && value.__len__() != indices[3]) { throw Py.ValueError(String.format("attempt to assign sequence of size %d to extended " + "slice of size %d", value.__len__(), indices[3])); } setSlice(indices[0], indices[1], indices[2], value); } public void checkIdxAndSetItem(int idx, PyObject value) { setItem(checkIdx(idx), value); } public void checkIdxAndDelItem(PyObject idx) { if (idx.isIndex()) { delItem(checkIdx(idx.asIndex(Py.IndexError))); } else if (idx instanceof PySlice) { int[] indices = ((PySlice)idx).indicesEx(len()); delSlice(indices[0], indices[1], indices[2]); } else { throw Py.TypeError(getTypeName() + " indices must be integers"); } } public PyObject checkIdxAndGetItem(PyObject idx) { PyObject res = checkIdxAndFindItem(idx); if (res == null) { throw Py.IndexError("index out of range: " + idx); } return res; } public PyObject checkIdxAndFindItem(PyObject idx) { if (idx.isIndex()) { return checkIdxAndFindItem(idx.asIndex(Py.IndexError)); } else if (idx instanceof PySlice) { return getSlice((PySlice)idx); } else { throw Py.TypeError(getTypeName() + " indices must be integers"); } } public PyObject getSlice(PySlice slice) { int[] indices = slice.indicesEx(len()); return getSlice(indices[0], indices[1], indices[2]); } public PyObject checkIdxAndFindItem(int idx) { idx = fixindex(idx); if(idx == -1) { return null; } else { return getItem(idx); } } private int checkIdx(int idx) { int i = fixindex(idx); if (i == -1) { throw Py.IndexError(getTypeName() + " assignment index out of range"); } return i; } int fixindex(int index) { int l = len(); if(index < 0) { index += l; } if(index < 0 || index >= l) { return -1; } else { return index; } } private void delSlice(int start, int stop, int step) { if(step == 1) { if (stop > start) { delItems(start, stop); } } else if(step > 1) { for(int i = start; i < stop; i += step) { delItem(i); i--; stop--; } } else if(step < 0) { for(int i = start; i >= 0 && i >= stop; i += step) { delItem(i); } } } }