[Jython-checkins] jython: Implement bytearray.startswith and endswith.
frank.wierzbicki
jython-checkins at python.org
Wed May 30 05:17:20 CEST 2012
http://hg.python.org/jython/rev/7e26c04c05d5
changeset: 6676:7e26c04c05d5
user: Jeff Allen <ja...py at farowl.co.uk>
date: Sun May 27 15:47:40 2012 +0100
summary:
Implement bytearray.startswith and endswith.
The score against test_bytes now stands at 2 failures and 61 errors.
files:
src/org/python/core/BaseBytes.java | 118 +++++++++++++++
src/org/python/core/PyByteArray.java | 109 +++++++++++++
2 files changed, 227 insertions(+), 0 deletions(-)
diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java
--- a/src/org/python/core/BaseBytes.java
+++ b/src/org/python/core/BaseBytes.java
@@ -747,9 +747,35 @@
public void copyTo(byte[] dest, int destPos) throws ArrayIndexOutOfBoundsException;
/**
+ * Test whether this View has the given prefix, that is, that the first bytes of this View
+ * match all the bytes of the given prefix. By implication, the test returns false if there
+ * are too few bytes in this view.
+ *
+ * @param prefix pattern to match
+ * @return true if and only if this view has the given prefix
+ */
+ public boolean startswith(View prefix);
+
+ /**
+ * Test whether the slice <code>[offset:]</code> of this View has the given prefix, that is,
+ * that the bytes of this View from index <code>offset</code> match all the bytes of the
+ * give prefix. By implication, the test returns false if the offset puts the start or end
+ * of the prefix outside this view (when <code>offset<0</code> or
+ * <code>offset+prefix.size()>size()</code>). Python slice semantics are <em>not</em>
+ * applied to <code>offset</code>.
+ *
+ * @param prefix pattern to match
+ * @param offset at which to start the comparison in this view
+ * @return true if and only if the slice [offset:<code>]</code> this view has the given
+ * prefix
+ */
+ public boolean startswith(View prefix, int offset);
+
+ /**
* The standard memoryview out of bounds message (does not refer to the underlying type).
*/
public static final String OUT_OF_BOUNDS = "index out of bounds";
+
}
/**
@@ -805,6 +831,46 @@
dest[p++] = byteAt(i);
}
}
+
+ /**
+ * Test whether this View has the given prefix, that is, that the first bytes of this View
+ * match all the bytes of the given prefix. This class provides an implementation of
+ * {@link View#startswith(View)} that simply returns <code>startswith(prefix,0)</code>
+ */
+ @Override
+ public boolean startswith(View prefix) {
+ return startswith(prefix, 0);
+ }
+
+ /**
+ * Test whether this View has the given prefix, that is, that the first bytes of this View
+ * match all the bytes of the given prefix. This class provides an implementation of
+ * {@link View#startswith(View,int)} that loops over
+ * <code>byteAt(i+offset)==prefix.byteAt(i)</code>
+ */
+ @Override
+ public boolean startswith(View prefix, int offset) {
+ int j = offset; // index in this
+ if (j < 0) {
+ // // Start of prefix is outside this view
+ return false;
+ } else {
+ int len = prefix.size();
+ if (j + len > this.size()) {
+ // End of prefix is outside this view
+ return false;
+ } else {
+ // Last resort: we have actually to look at the bytes!
+ for (int i = 0; i < len; i++) {
+ if (byteAt(j++) != prefix.byteAt(i)) {
+ return false;
+ }
+ }
+ return true; // They must all have matched
+ }
+ }
+ }
+
}
/**
@@ -1452,6 +1518,58 @@
}
/**
+ * Almost ready-to-expose implementation serving both Python
+ * <code>startswith( prefix [, start [, end ]] )</code> and
+ * <code>endswith( suffix [, start [, end ]] )</code>. An extra boolean argument specifies which
+ * to implement on a given call, that is, whether the target is a suffix or prefix. The target
+ * may also be a tuple of targets.
+ *
+ * @param target prefix or suffix sequence to find (of a type viewable as a byte sequence) or a
+ * tuple of those.
+ * @param start of slice to search.
+ * @param end of slice to search.
+ * @param endswith true if we are doing endswith, false if startswith.
+ * @return true if and only if this bytearray ends with (one of) <code>target</code>.
+ */
+ protected final synchronized boolean basebytes_starts_or_endswith(PyObject target,
+ PyObject start,
+ PyObject end,
+ boolean endswith) {
+ /*
+ * This cheap trick saves us from maintaining two almost identical methods and mirrors
+ * CPython's _bytearray_tailmatch().
+ *
+ * Start with a view of the slice we are searching.
+ */
+ View v = new ViewOfBytes(this).slice(start, end);
+ int len = v.size();
+ int offset = 0;
+
+ if (target instanceof PyTuple) {
+ // target is a tuple of suffixes/prefixes and only one need match
+ for (PyObject s : ((PyTuple)target).getList()) {
+ // Error if not something we can treat as a view of bytes
+ View vt = getViewOrError(s);
+ if (endswith) {
+ offset = len - vt.size();
+ }
+ if (v.startswith(vt, offset)) {
+ return true;
+ }
+ }
+ return false; // None of them matched
+
+ } else {
+ // Error if target is not something we can treat as a view of bytes
+ View vt = getViewOrError(target);
+ if (endswith) {
+ offset = len - vt.size();
+ }
+ return v.startswith(vt, offset);
+ }
+ }
+
+ /**
* Copy the bytes of a byte array to the characters of a String with no change in ordinal value.
* This could also be described as 'latin-1' decoding of the byte array to a String.
*
diff --git a/src/org/python/core/PyByteArray.java b/src/org/python/core/PyByteArray.java
--- a/src/org/python/core/PyByteArray.java
+++ b/src/org/python/core/PyByteArray.java
@@ -881,6 +881,60 @@
return basebytes_count(sub, start, end);
}
+ /**
+ * Implementation of Python <code>endswith(suffix)</code>.
+ *
+ * When <code>suffix</code> is of a type that may be treated as an array of bytes, return
+ * <code>true</code> if and only if this bytearray ends with the <code>suffix</code>.
+ * <code>suffix</code> can also be a tuple of suffixes to look for.
+ *
+ * @param suffix byte array to match, or object viewable as such, or a tuple of them
+ * @return true if and only if this bytearray ends with the suffix (or one of them)
+ */
+ public boolean endswith(PyObject suffix) {
+ return basebytes_starts_or_endswith(suffix, null, null, true);
+ }
+
+ /**
+ * Implementation of Python <code>endswith( suffix [, start ] )</code>.
+ *
+ * When <code>suffix</code> is of a type that may be treated as an array of bytes, return
+ * <code>true</code> if and only if this bytearray ends with the <code>suffix</code>.
+ * <code>suffix</code> can also be a tuple of suffixes to look for. With optional
+ * <code>start</code> (which may be <code>null</code> or <code>Py.None</code>), define the
+ * effective bytearray to be the slice <code>[start:]</code> of this bytearray.
+ *
+ * @param suffix byte array to match, or object viewable as such, or a tuple of them
+ * @param start of slice in this bytearray to match
+ * @return true if and only if this[start:] ends with the suffix (or one of them)
+ */
+ public boolean endswith(PyObject suffix, PyObject start) {
+ return basebytes_starts_or_endswith(suffix, start, null, true);
+ }
+
+ /**
+ * Implementation of Python <code>endswith( suffix [, start [, end ]] )</code>.
+ *
+ * When <code>suffix</code> is of a type that may be treated as an array of bytes, return
+ * <code>true</code> if and only if this bytearray ends with the <code>suffix</code>.
+ * <code>suffix</code> can also be a tuple of suffixes to look for. With optional
+ * <code>start</code> and <code>end</code> (which may be <code>null</code> or
+ * <code>Py.None</code>), define the effective bytearray to be the slice
+ * <code>[start:end]</code> of this bytearray.
+ *
+ * @param suffix byte array to match, or object viewable as such, or a tuple of them
+ * @param start of slice in this bytearray to match
+ * @param end of slice in this bytearray to match
+ * @return true if and only if this[start:end] ends with the suffix (or one of them)
+ */
+ public boolean endswith(PyObject suffix, PyObject start, PyObject end) {
+ return basebytes_starts_or_endswith(suffix, start, end, true);
+ }
+
+ @ExposedMethod(defaults = {"null", "null"}, doc = BuiltinDocs.bytearray_endswith_doc)
+ final boolean bytearray_endswith(PyObject suffix, PyObject start, PyObject end) {
+ return basebytes_starts_or_endswith(suffix, start, end, true);
+ }
/**
* Append the elements in the argument sequence to the end of the array, equivalent to:
@@ -1200,6 +1254,61 @@
return pos;
}
+ /**
+ * Implementation of Python <code>startswith(prefix)</code>.
+ *
+ * When <code>prefix</code> is of a type that may be treated as an array of bytes, return
+ * <code>true</code> if and only if this bytearray starts with the <code>prefix</code>.
+ * <code>prefix</code> can also be a tuple of prefixes to look for.
+ *
+ * @param prefix byte array to match, or object viewable as such, or a tuple of them
+ * @return true if and only if this bytearray starts with the prefix (or one of them)
+ */
+ public boolean startswith(PyObject prefix) {
+ return basebytes_starts_or_endswith(prefix, null, null, false);
+ }
+
+ /**
+ * Implementation of Python <code>startswith( prefix [, start ] )</code>.
+ *
+ * When <code>prefix</code> is of a type that may be treated as an array of bytes, return
+ * <code>true</code> if and only if this bytearray starts with the <code>prefix</code>.
+ * <code>prefix</code> can also be a tuple of prefixes to look for. With optional
+ * <code>start</code> (which may be <code>null</code> or <code>Py.None</code>), define the
+ * effective bytearray to be the slice <code>[start:]</code> of this bytearray.
+ *
+ * @param prefix byte array to match, or object viewable as such, or a tuple of them
+ * @param start of slice in this bytearray to match
+ * @return true if and only if this[start:] starts with the prefix (or one of them)
+ */
+ public boolean startswith(PyObject prefix, PyObject start) {
+ return basebytes_starts_or_endswith(prefix, start, null, false);
+ }
+
+ /**
+ * Implementation of Python <code>startswith( prefix [, start [, end ]] )</code>.
+ *
+ * When <code>prefix</code> is of a type that may be treated as an array of bytes, return
+ * <code>true</code> if and only if this bytearray starts with the <code>prefix</code>.
+ * <code>prefix</code> can also be a tuple of prefixes to look for. With optional
+ * <code>start</code> and <code>end</code> (which may be <code>null</code> or
+ * <code>Py.None</code>), define the effective bytearray to be the slice
+ * <code>[start:end]</code> of this bytearray.
+ *
+ * @param prefix byte array to match, or object viewable as such, or a tuple of them
+ * @param start of slice in this bytearray to match
+ * @param end of slice in this bytearray to match
+ * @return true if and only if this[start:end] starts with the prefix (or one of them)
+ */
+ public boolean startswith(PyObject prefix, PyObject start, PyObject end) {
+ return basebytes_starts_or_endswith(prefix, start, end, false);
+ }
+
+ @ExposedMethod(defaults = {"null", "null"}, doc = BuiltinDocs.bytearray_startswith_doc)
+ final boolean bytearray_startswith(PyObject prefix, PyObject start, PyObject end) {
+ return basebytes_starts_or_endswith(prefix, start, end, false);
+ }
+
// Based on PyList and not yet properly implemented.
//
// @Override
--
Repository URL: http://hg.python.org/jython
More information about the Jython-checkins
mailing list