[Jython-checkins] jython: Avoid PyString range-test in concatenation and join.
jeff.allen
jython-checkins at python.org
Tue Dec 2 23:11:53 CET 2014
https://hg.python.org/jython/rev/521823de34a5
changeset: 7427:521823de34a5
user: Jeff Allen <ja.py at farowl.co.uk>
date: Mon Dec 01 23:53:59 2014 +0000
summary:
Avoid PyString range-test in concatenation and join.
Adds private constructor for use when we can guarantee bytes.
Apply in __add__ and join.
files:
src/org/python/core/PyString.java | 57 +++++++++++++-----
1 files changed, 41 insertions(+), 16 deletions(-)
diff --git a/src/org/python/core/PyString.java b/src/org/python/core/PyString.java
--- a/src/org/python/core/PyString.java
+++ b/src/org/python/core/PyString.java
@@ -39,7 +39,7 @@
// for PyJavaClass.init()
public PyString() {
- this(TYPE, "");
+ this("", true);
}
/**
@@ -52,7 +52,7 @@
public PyString(PyType subType, String string) {
super(subType);
if (string == null) {
- throw new IllegalArgumentException("Cannot create PyString from null!");
+ throw new IllegalArgumentException("Cannot create PyString from null");
} else if (!isBytes(string)) {
throw new IllegalArgumentException("Cannot create PyString with non-byte value");
}
@@ -72,6 +72,23 @@
}
/**
+ * Local-use constructor in which the client is allowed to guarantee that the
+ * <code>String</code> argument contains only characters in the byte range. We do not then
+ * range-check the characters.
+ *
+ * @param string a Java String to be wrapped (not null)
+ * @param isBytes true if the client guarantees we are dealing with bytes
+ */
+ private PyString(String string, boolean isBytes) {
+ super(TYPE);
+ if (isBytes || isBytes(string)) {
+ this.string = string;
+ } else {
+ throw new IllegalArgumentException("Cannot create PyString with non-byte value");
+ }
+ }
+
+ /**
* Determine whether a string consists entirely of characters in the range 0 to 255. Only such
* characters are allowed in the <code>PyString</code> (<code>str</code>) type, when it is not a
* {@link PyUnicode}.
@@ -228,7 +245,7 @@
if (getClass() == PyString.class) {
return this;
}
- return new PyString(getString());
+ return new PyString(getString(), true);
}
@Override
@@ -785,6 +802,18 @@
* <b>not</b> a <code>unicode</code>.
*
* @param obj to coerce to a String
+ * @return coerced value or <code>null</code> if it can't be (including <code>unicode</code>)
+ */
+ private static String asStringOrNull(PyObject obj) {
+ return (obj instanceof PyUnicode) ? null : asUTF16StringOrNull(obj);
+ }
+
+ /**
+ * Return a String equivalent to the argument. This is a helper function to those methods that
+ * accept any byte array type (any object that supports a one-dimensional byte buffer), but
+ * <b>not</b> a <code>unicode</code>.
+ *
+ * @param obj to coerce to a String
* @return coerced value
* @throws PyException if the coercion fails (including <code>unicode</code>)
*/
@@ -917,21 +946,17 @@
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.str___add___doc)
final PyObject str___add__(PyObject other) {
-
- if (other instanceof PyUnicode) {
+ // Expect other to be some kind of byte-like object.
+ String otherStr = asStringOrNull(other);
+ if (otherStr != null) {
+ // Yes it is: concatenate as strings, which are guaranteed byte-like.
+ return new PyString(getString().concat(otherStr), true);
+ } else if (other instanceof PyUnicode) {
// Convert self to PyUnicode and escalate the problem
return decode().__add__(other);
-
} else {
- // Some kind of object with the buffer API
- String otherStr = asUTF16StringOrNull(other);
- if (otherStr == null) {
- // Allow PyObject._basic_add to pick up the pieces or raise informative error
- return null;
- } else {
- // Concatenate as strings
- return new PyString(getString().concat(otherStr));
- }
+ // Allow PyObject._basic_add to pick up the pieces or raise informative error
+ return null;
}
}
@@ -3161,7 +3186,7 @@
}
buf.append(((PyString)item).getString());
}
- return new PyString(buf.toString());
+ return new PyString(buf.toString(), true); // Guaranteed to be byte-like
}
final PyUnicode unicodeJoin(PyObject obj) {
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list