MCPcopy Create free account
hub / github.com/antirez/ds4 / raxRemoveChildAtPtr

Function raxRemoveChildAtPtr

rax.c:1141–1205  ·  view source on GitHub ↗

Low level child removal from node. 'childptr' must point to the child * pointer stored inside the parent node, and is used directly instead of * searching by child value. The new node pointer (after the child * removal) is returned. Note that this function does not fix the pointer * of the parent node in its parent, so this task is up to the caller. * The function never fails for out of memor

Source from the content-addressed store, hash-verified

1139 * of the parent node in its parent, so this task is up to the caller.
1140 * The function never fails for out of memory. */
1141static inline raxNode *raxRemoveChildAtPtr(raxNode *parent, raxNode **childptr) {
1142 debugnode("raxRemoveChild before", parent);
1143 /* If parent is a compressed node (having a single child, as for definition
1144 * of the data structure), the removal of the child consists into turning
1145 * it into a normal node without children. */
1146 if (parent->iscompr) {
1147 void *data = NULL;
1148 if (parent->iskey) data = raxGetData(parent);
1149 parent->isnull = 0;
1150 parent->iscompr = 0;
1151 parent->size = 0;
1152 parent->leafbitmap = 0;
1153 if (parent->iskey) raxSetData(parent,data);
1154 debugnode("raxRemoveChild after", parent);
1155 return parent;
1156 }
1157
1158 /* Otherwise we need to scan for the child pointer and memmove()
1159 * accordingly.
1160 *
1161 * 1. To start we seek the first element in both the children
1162 * pointers and edge bytes in the node. */
1163 raxNode **cp = raxNodeFirstChildPtr(parent);
1164 raxNode **c = childptr;
1165 unsigned char *e = parent->data + (c - cp);
1166
1167 /* 3. Remove the edge and the pointer by memmoving the remaining children
1168 * pointer and edge bytes one position before. */
1169 int taillen = parent->size - (e - parent->data) - 1;
1170 debugf("raxRemoveChild tail len: %d\n", taillen);
1171 memmove(e,e+1,taillen);
1172
1173 /* Compute the shift, that is the amount of bytes we should move our
1174 * child pointers to the left, since the removal of one edge character
1175 * and the corresponding padding change, may change the layout.
1176 * We just check if in the old version of the node there was at the
1177 * end just a single byte and all padding: in that case removing one char
1178 * will remove a whole sizeof(void*) word. */
1179 size_t shift = ((parent->size+4) % sizeof(void*)) == 1 ? sizeof(void*) : 0;
1180
1181 /* Move the children pointers before the deletion point. */
1182 if (shift)
1183 memmove(((char*)cp)-shift,cp,(parent->size-taillen-1)*sizeof(raxNode**));
1184
1185 /* Move the remaining "tail" pointers at the right position as well. */
1186 size_t valuelen = (parent->iskey && !parent->isnull) ? sizeof(void*) : 0;
1187 memmove(((char*)c)-shift,c+1,taillen*sizeof(raxNode**)+valuelen);
1188
1189 /* 4. Update size and shift the leaf bitmap accordingly. Bits above
1190 * the removed position shift down by one. */
1191 int pos = (int)(e - parent->data);
1192 parent->size--;
1193 if (parent->leafbitmap && pos < 13) {
1194 uint16_t above = parent->leafbitmap & ~((1u << (pos+1)) - 1);
1195 uint16_t below = pos ? (parent->leafbitmap & ((1u << pos) - 1)) : 0;
1196 parent->leafbitmap = below | (above >> 1);
1197 }
1198

Callers 2

raxRemoveChildFunction · 0.85
raxRemoveFunction · 0.85

Calls 2

raxGetDataFunction · 0.85
raxSetDataFunction · 0.85

Tested by

no test coverage detected