Recursive insertion method. On success returns either 'this', or a new node that replaces 'this'. On failure (i.e. callback returned nullptr) returns nullptr.
| 169 | // Recursive insertion method. On success returns either 'this', or a new node that |
| 170 | // replaces 'this'. On failure (i.e. callback returned nullptr) returns nullptr. |
| 171 | MutableInterior* insert(const Target &target, unsigned shift) { |
| 172 | assert_precondition(shift + kBitShift < 8*sizeof(hash_t));//FIX: //TODO: Handle hash collisions |
| 173 | unsigned bitNo = childBitNumber(target.hash, shift); |
| 174 | if (!hasChild(bitNo)) { |
| 175 | // No child -- add a leaf: |
| 176 | Value val = (*target.insertCallback)(nullptr); |
| 177 | if (!val) |
| 178 | return nullptr; |
| 179 | return addChild(bitNo, new MutableLeaf(target, val)); |
| 180 | } |
| 181 | NodeRef &childRef = childForBitNumber(bitNo); |
| 182 | if (childRef.isLeaf()) { |
| 183 | if (childRef.matches(target)) { |
| 184 | // Leaf node matches this key; update or copy it: |
| 185 | Value val = (*target.insertCallback)(childRef.value()); |
| 186 | if (!val) |
| 187 | return nullptr; |
| 188 | if (childRef.isMutable()) |
| 189 | ((MutableLeaf*)childRef.asMutable())->_value = val; |
| 190 | else |
| 191 | childRef = new MutableLeaf(target, val); |
| 192 | return this; |
| 193 | } else { |
| 194 | // Nope, need to promote the leaf to an interior node & add new key: |
| 195 | MutableInterior *node = promoteLeaf(childRef, shift); |
| 196 | auto insertedNode = node->insert(target, shift+kBitShift); |
| 197 | if (!insertedNode) { |
| 198 | delete node; |
| 199 | return nullptr; |
| 200 | } |
| 201 | childRef = insertedNode; |
| 202 | return this; |
| 203 | } |
| 204 | } else { |
| 205 | // Progress down to interior node... |
| 206 | auto child = (MutableInterior*)childRef.asMutable(); |
| 207 | if (!child) |
| 208 | child = mutableCopy(&childRef.asImmutable()->interior, 1); |
| 209 | child = child->insert(target, shift+kBitShift); |
| 210 | if (child) |
| 211 | childRef = child; |
| 212 | //FIX: This can leak if child is created by mutableCopy, but then |
| 213 | return this; |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | |
| 218 | bool remove(Target target, unsigned shift) { |