1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
"""dict implementation specialized for object loaded by the _pypyjson module.
Somewhat similar to MapDictStrategy, also uses a map.
"""
from rpython.rlib import jit, rerased, objectmodel, debug
from pypy.objspace.std.dictmultiobject import (
UnicodeDictStrategy, DictStrategy,
create_iterator_classes, W_DictObject)
def from_values_and_jsonmap(space, values_w, jsonmap):
if not objectmodel.we_are_translated():
assert len(values_w) == len(jsonmap.get_keys_in_order())
assert len(values_w) != 0
debug.make_sure_not_resized(values_w)
strategy = jsonmap.strategy_instance
if strategy is None:
jsonmap.strategy_instance = strategy = JsonDictStrategy(space, jsonmap)
storage = strategy.erase(values_w)
return W_DictObject(space, strategy, storage)
def devolve_jsonmap_dict(w_dict):
assert isinstance(w_dict, W_DictObject)
strategy = w_dict.get_strategy()
assert isinstance(strategy, JsonDictStrategy)
strategy.switch_to_unicode_strategy(w_dict)
def get_jsonmap_from_dict(w_dict):
assert isinstance(w_dict, W_DictObject)
strategy = w_dict.get_strategy()
assert isinstance(strategy, JsonDictStrategy)
return strategy.jsonmap
class JsonDictStrategy(DictStrategy):
erase, unerase = rerased.new_erasing_pair("jsondict")
erase = staticmethod(erase)
unerase = staticmethod(unerase)
_immutable_fields_ = ['jsonmap']
def __init__(self, space, jsonmap):
DictStrategy.__init__(self, space)
self.jsonmap = jsonmap
def wrap(self, w_key):
return w_key
def wrapkey(space, key):
return key
def get_empty_storage(self):
raise NotImplementedError("should not be reachable")
def is_correct_type(self, w_obj):
space = self.space
return space.is_w(space.type(w_obj), space.w_unicode)
def _never_equal_to(self, w_lookup_type):
return False
def length(self, w_dict):
return len(self.unerase(w_dict.dstorage))
def getitem(self, w_dict, w_key):
if self.is_correct_type(w_key):
return self.getitem_unicode(w_dict, w_key)
else:
self.switch_to_unicode_strategy(w_dict)
return w_dict.getitem(w_key)
def getitem_unicode(self, w_dict, w_key):
storage_w = self.unerase(w_dict.dstorage)
if jit.isconstant(w_key):
jit.promote(self)
index = self.jsonmap.get_index(w_key)
if index == -1:
return None
return storage_w[index]
def setitem(self, w_dict, w_key, w_value):
if self.is_correct_type(w_key):
storage_w = self.unerase(w_dict.dstorage)
index = self.jsonmap.get_index(w_key)
if index != -1:
storage_w[index] = w_value
return
self.switch_to_unicode_strategy(w_dict)
w_dict.setitem(w_key, w_value)
# for setitem_str use the default implementation
# because the jsonmap needs a wrapped key anyway
def setdefault(self, w_dict, w_key, w_default):
if self.is_correct_type(w_key):
w_result = self.getitem_unicode(w_dict, w_key)
if w_result is not None:
return w_result
self.switch_to_unicode_strategy(w_dict)
return w_dict.setdefault(w_key, w_default)
def delitem(self, w_dict, w_key):
self.switch_to_unicode_strategy(w_dict)
return w_dict.delitem(w_key)
def popitem(self, w_dict):
self.switch_to_unicode_strategy(w_dict)
return w_dict.popitem()
def switch_to_unicode_strategy(self, w_dict):
storage = self._make_unicode_dict(w_dict)
strategy = self.space.fromcache(UnicodeDictStrategy)
w_dict.set_strategy(strategy)
w_dict.dstorage = storage
def _make_unicode_dict(self, w_dict):
strategy = self.space.fromcache(UnicodeDictStrategy)
values_w = self.unerase(w_dict.dstorage)
storage = strategy.get_empty_storage()
d_new = strategy.unerase(storage)
keys_in_order = self.jsonmap.get_keys_in_order()
assert len(keys_in_order) == len(values_w)
for index, w_key in enumerate(keys_in_order):
assert w_key is not None
assert type(w_key) is self.space.UnicodeObjectCls
d_new[w_key] = values_w[index]
return storage
def copy(self, w_dict):
storage = self._make_unicode_dict(w_dict)
strategy = self.space.fromcache(UnicodeDictStrategy)
return W_DictObject(strategy.space, strategy, storage)
def w_keys(self, w_dict):
return self.space.newlist(self.jsonmap.get_keys_in_order())
def values(self, w_dict):
return self.unerase(w_dict.dstorage)[:] # to make resizable
def items(self, w_dict):
space = self.space
storage_w = self.unerase(w_dict.dstorage)
res = [None] * len(storage_w)
for index, w_key in enumerate(self.jsonmap.get_keys_in_order()):
res[index] = space.newtuple2(w_key, storage_w[index])
return res
def getiterkeys(self, w_dict):
return iter(self.jsonmap.get_keys_in_order())
def getitervalues(self, w_dict):
storage_w = self.unerase(w_dict.dstorage)
return iter(storage_w)
def getiteritems_with_hash(self, w_dict):
storage_w = self.unerase(w_dict.dstorage)
return ZipItemsWithHash(self.jsonmap.get_keys_in_order(), storage_w)
class ZipItemsWithHash(object):
def __init__(self, list1, list2):
assert len(list1) == len(list2)
self.list1 = list1
self.list2 = list2
self.i = 0
def __iter__(self):
return self
def next(self):
i = self.i
if i >= len(self.list1):
raise StopIteration
self.i = i + 1
w_key = self.list1[i]
return (w_key, self.list2[i], w_key.hash_w())
create_iterator_classes(JsonDictStrategy)
|