From: <pj...@us...> - 2009-10-29 04:57:55
|
Revision: 6930 http://jython.svn.sourceforge.net/jython/?rev=6930&view=rev Author: pjenvey Date: 2009-10-29 04:57:43 +0000 (Thu, 29 Oct 2009) Log Message: ----------- expose PyStringMap so unsuspecting users of it avoid reflection costs Modified Paths: -------------- trunk/jython/CoreExposed.includes trunk/jython/src/org/python/core/PyStringMap.java Modified: trunk/jython/CoreExposed.includes =================================================================== --- trunk/jython/CoreExposed.includes 2009-10-29 04:28:03 UTC (rev 6929) +++ trunk/jython/CoreExposed.includes 2009-10-29 04:57:43 UTC (rev 6930) @@ -37,6 +37,7 @@ org/python/core/PySlot.class org/python/core/PyStaticMethod.class org/python/core/PyString.class +org/python/core/PyStringMap.class org/python/core/PySuper.class org/python/core/PyTraceback.class org/python/core/PyTuple.class Modified: trunk/jython/src/org/python/core/PyStringMap.java =================================================================== --- trunk/jython/src/org/python/core/PyStringMap.java 2009-10-29 04:28:03 UTC (rev 6929) +++ trunk/jython/src/org/python/core/PyStringMap.java 2009-10-29 04:57:43 UTC (rev 6930) @@ -1,4 +1,7 @@ -// Copyright (c) Corporation for National Research Initiatives +/* + * Copyright (c) Corporation for National Research Initiatives + * Copyright (c) Jython Developers + */ package org.python.core; import java.util.Collection; @@ -9,14 +12,25 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; +import org.python.expose.MethodType; import org.python.util.Generic; /** * Special fast dict implementation for __dict__ instances. Allows interned String keys in addition * to PyObject unlike PyDictionary. */ +@ExposedType(name = "stringmap", isBaseType = false) public class PyStringMap extends PyObject { + /** + * TYPE computed lazily, PyStringMap is used early in the bootstrap process and + * statically calling fromClass(PyStringMap.class) is unsafe. + */ + private static PyType lazyType; + private final ConcurrentMap<Object, PyObject> table; public PyStringMap() { @@ -24,11 +38,13 @@ } public PyStringMap(int capacity) { + super(getLazyType()); table = new ConcurrentHashMap<Object, PyObject>(capacity, Generic.CHM_LOAD_FACTOR, Generic.CHM_CONCURRENCY_LEVEL); } public PyStringMap(Map<Object, PyObject> map) { + super(getLazyType()); table = Generic.concurrentMap(); table.putAll(map); } @@ -40,14 +56,37 @@ } } + private static PyType getLazyType() { + if (lazyType == null) { + lazyType = PyType.fromClass(PyStringMap.class); + } + return lazyType; + } + + @ExposedNew + final static PyObject stringmap_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + PyStringMap map = new PyStringMap(); + map.stringmap_update(args, keywords); + return map; + } + + @Override public int __len__() { + return stringmap___len__(); + } + + @ExposedMethod(doc = BuiltinDocs.dict___len___doc) + final int stringmap___len__() { return table.size(); } + @Override public boolean __nonzero__() { return table.size() != 0; } + @Override public PyObject __finditem__(String key) { if (key == null) { return null; @@ -55,6 +94,7 @@ return table.get(key); } + @Override public PyObject __finditem__(PyObject key) { if (key instanceof PyString) { return __finditem__(((PyString)key).internedString()); @@ -71,7 +111,13 @@ } } + @Override public PyObject __getitem__(PyObject key) { + return stringmap___getitem__(key); + } + + @ExposedMethod(doc = BuiltinDocs.dict___getitem___doc) + final PyObject stringmap___getitem__(PyObject key) { if (key instanceof PyString) { return __getitem__(((PyString)key).internedString()); } else { @@ -84,10 +130,17 @@ } } + @Override public PyObject __iter__() { - return iterkeys(); + return stringmap___iter__(); } + @ExposedMethod(doc = BuiltinDocs.dict___iter___doc) + final PyObject stringmap___iter__() { + return stringmap_iterkeys(); + } + + @Override public void __setitem__(String key, PyObject value) { if (value == null) { table.remove(key); @@ -96,7 +149,13 @@ } } + @Override public void __setitem__(PyObject key, PyObject value) { + stringmap___setitem__(key, value); + } + + @ExposedMethod(doc = BuiltinDocs.dict___setitem___doc) + final void stringmap___setitem__(PyObject key, PyObject value) { if (value == null) { table.remove(pyToKey(key)); } else if (key instanceof PyString) { @@ -106,6 +165,7 @@ } } + @Override public void __delitem__(String key) { Object ret = table.remove(key); if (ret == null) { @@ -113,7 +173,13 @@ } } + @Override public void __delitem__(PyObject key) { + stringmap___delitem__(key); + } + + @ExposedMethod(doc = BuiltinDocs.dict___delitem___doc) + final void stringmap___delitem__(PyObject key) { if (key instanceof PyString) { __delitem__(((PyString)key).internedString()); } else { @@ -128,10 +194,21 @@ * Remove all items from the dictionary. */ public void clear() { + stringmap_clear(); + } + + @ExposedMethod(doc = BuiltinDocs.dict_clear_doc) + final void stringmap_clear() { table.clear(); } + @Override public String toString() { + return stringmap_toString(); + } + + @ExposedMethod(names = {"__repr__", "__str__"}, doc = BuiltinDocs.dict___str___doc) + final String stringmap_toString() { ThreadState ts = Py.getThreadState(); if (!ts.enterRepr(this)) { return "{...}"; @@ -158,7 +235,13 @@ return buf.toString(); } + @Override public int __cmp__(PyObject other) { + return stringmap___cmp__(other); + } + + @ExposedMethod(type = MethodType.CMP, doc = BuiltinDocs.dict___cmp___doc) + final int stringmap___cmp__(PyObject other) { if (!(other instanceof PyStringMap || other instanceof PyDictionary)) { return -2; } @@ -204,26 +287,42 @@ } public boolean has_key(PyObject key) { + return stringmap_has_key(key); + } + + @ExposedMethod(doc = BuiltinDocs.dict_has_key_doc) + final boolean stringmap_has_key(PyObject key) { return table.containsKey(pyToKey(key)); } + @Override + public boolean __contains__(PyObject o) { + return stringmap___contains__(o); + } + + @ExposedMethod(doc = BuiltinDocs.dict___contains___doc) + final boolean stringmap___contains__(PyObject o) { + return stringmap_has_key(o); + } + /** - * Return this[key] if the key exists in the mapping, default_object is returned otherwise. + * Return this[key] if the key exists in the mapping, defaultObj is returned otherwise. * * @param key * the key to lookup in the mapping. - * @param default_object + * @param defaultObj * the value to return if the key does not exists in the mapping. */ - public PyObject get(PyObject key, PyObject default_object) { - PyObject o = __finditem__(key); - if (o == null) { - return default_object; - } else { - return o; - } + public PyObject get(PyObject key, PyObject defaultObj) { + return stringmap_get(key, defaultObj); } + @ExposedMethod(defaults = "Py.None", doc = BuiltinDocs.dict_get_doc) + final PyObject stringmap_get(PyObject key, PyObject defaultObj) { + PyObject obj = __finditem__(key); + return obj == null ? defaultObj : obj; + } + /** * Return this[key] if the key exists in the mapping, None is returned otherwise. * @@ -231,20 +330,30 @@ * the key to lookup in the mapping. */ public PyObject get(PyObject key) { - return get(key, Py.None); + return stringmap_get(key, Py.None); } /** * Return a shallow copy of the dictionary. */ public PyStringMap copy() { + return stringmap_copy(); + } + + @ExposedMethod(doc = BuiltinDocs.dict_copy_doc) + final PyStringMap stringmap_copy() { return new PyStringMap(table); } + public void update(PyObject other) { + stringmap_update(new PyObject[] {other}, Py.NoKeywords); + } + /** * Insert all the key:value pairs from <code>dict</code> into this mapping. */ - public void update(PyObject[] args, String[] keywords) { + @ExposedMethod(doc = BuiltinDocs.dict_update_doc) + final void stringmap_update(PyObject[] args, String[] keywords) { int nargs = args.length - keywords.length; if (nargs > 1) { throw PyBuiltinCallable.DefaultInfo.unexpectedCall(nargs, false, "update", 0, 1); @@ -339,19 +448,25 @@ * the default value to insert in the mapping if key does not already exist. */ public PyObject setdefault(PyObject key, PyObject failobj) { + return stringmap_setdefault(key, failobj); + } + + @ExposedMethod(defaults = "Py.None", doc = BuiltinDocs.dict_setdefault_doc) + final PyObject stringmap_setdefault(PyObject key, PyObject failobj) { Object internedKey = (key instanceof PyString) ? ((PyString)key).internedString() : key; PyObject oldValue = table.putIfAbsent(internedKey, failobj); - if (oldValue == null) { - return failobj; - } else { - return oldValue; - } + return oldValue == null ? failobj : oldValue; } /** * Return a random (key, value) tuple pair and remove the pair from the mapping. */ public PyObject popitem() { + return stringmap_popitem(); + } + + @ExposedMethod(doc = BuiltinDocs.dict_popitem_doc) + final PyObject stringmap_popitem() { Iterator<Entry<Object, PyObject>> it = table.entrySet().iterator(); if (!it.hasNext()) { throw Py.KeyError("popitem(): dictionary is empty"); @@ -366,10 +481,15 @@ if (table.size() == 0) { throw Py.KeyError("pop(): dictionary is empty"); } - return pop(key, null); + return stringmap_pop(key, null); } public PyObject pop(PyObject key, PyObject failobj) { + return stringmap_pop(key, failobj); + } + + @ExposedMethod(defaults = "null", doc = BuiltinDocs.dict_pop_doc) + final PyObject stringmap_pop(PyObject key, PyObject failobj) { PyObject value = table.remove(pyToKey(key)); if (value == null) { if (failobj == null) { @@ -385,9 +505,14 @@ * Return a copy of the mappings list of (key, value) tuple pairs. */ public PyList items() { - return new PyList(iteritems()); + return stringmap_items(); } + @ExposedMethod(doc = BuiltinDocs.dict_items_doc) + final PyList stringmap_items() { + return new PyList(stringmap_iteritems()); + } + private PyTuple itemTuple(Entry<Object, PyObject> entry) { return new PyTuple(keyToPy(entry.getKey()), entry.getValue()); } @@ -397,6 +522,11 @@ * storing String or PyObject objects */ public PyList keys() { + return stringmap_keys(); + } + + @ExposedMethod(doc = BuiltinDocs.dict_keys_doc) + final PyList stringmap_keys() { PyObject[] keyArray = new PyObject[table.size()]; int i = 0; for (Object key : table.keySet()) { @@ -409,6 +539,11 @@ * Return a copy of the mappings list of values. */ public PyList values() { + return stringmap_values(); + } + + @ExposedMethod(doc = BuiltinDocs.dict_values_doc) + final PyList stringmap_values() { return new PyList(table.values()); } @@ -416,15 +551,25 @@ * return an iterator over (key, value) pairs */ public PyObject iteritems() { + return stringmap_iteritems(); + } + + @ExposedMethod(doc = BuiltinDocs.dict_iteritems_doc) + final PyObject stringmap_iteritems() { return new ItemsIter(table.entrySet()); } /** * return an iterator over the keys */ - // Python allows one to change the dict while iterating over it, - // including deletion. Java does not. Can we resolve with CHM? public PyObject iterkeys() { + return stringmap_iterkeys(); + } + + @ExposedMethod(doc = BuiltinDocs.dict_iterkeys_doc) + final PyObject stringmap_iterkeys() { + // Python allows one to change the dict while iterating over it, including + // deletion. Java does not. Can we resolve with CHM? return new KeysIter(table.keySet()); } @@ -432,10 +577,25 @@ * return an iterator over the values */ public PyObject itervalues() { + return stringmap_itervalues(); + } + + @ExposedMethod(doc = BuiltinDocs.dict_itervalues_doc) + final PyObject stringmap_itervalues() { return new ValuesIter(table.values()); } @Override + public int hashCode() { + return stringmap___hash__(); + } + + @ExposedMethod(doc = BuiltinDocs.dict___hash___doc) + final int stringmap___hash__() { + throw Py.TypeError(String.format("unhashable type: '%.200s'", getType().fastGetName())); + } + + @Override public boolean isMappingType() { return true; } @@ -456,6 +616,7 @@ size = c.size(); } + @Override public PyObject __iternext__() { if (table.size() != size) { throw Py.RuntimeError("dictionary changed size during iteration"); @@ -475,7 +636,8 @@ super(c); } - public PyObject stringMapNext() { + @Override + public PyObject stringMapNext() { return iterator.next(); } } @@ -486,6 +648,7 @@ super(s); } + @Override protected PyObject stringMapNext() { return keyToPy(iterator.next()); } @@ -497,6 +660,7 @@ super(s); } + @Override public PyObject stringMapNext() { return itemTuple(iterator.next()); } @@ -517,8 +681,4 @@ return pyKey; } } - - public int hashCode() { - throw Py.TypeError(String.format("unhashable type: '%.200s'", getType().fastGetName())); - } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |