struct rb_node *RBTreeSearch(struct rb_tree *rb, rb_key_t key) { //same as Binary Search Tree's search operation struct rb_node *x = rb->root; while (x != rb->nil) { if (keyCmp(x->key, key) > 0) x = x->left; else if (keyCmp(x->key, key) < 0) x = x->right; else break; } return x; }
apiRetVal hashMapOpen::remove (hashNodeKey *key, void **data) { uint32_t hashKey; hashNode *node = NULL, *prevNode = NULL; hashKey = getHashKey(key); if (hashKey > tableLength) { return API_RETVAL_INVALID_INPUT; } node = hashTable[hashKey]; while (node) { if (keyCmp(key, &node->nodeKey)) { *data = node->data; if (!prevNode) { // This is the first node. hashTable[hashKey] = node->next; } else { prevNode->next = node->next; } free(node); return (API_RETVAL_SUCCESS); } prevNode = node; node = node->next; } return API_RETVAL_DATA_NOT_FOUND; }
Index fileGetIndex(struct Container * container, struct Key * pk) { int readBufferSize = 1; const int sizeOfRecord = sizeof(struct Record); const int sizeOfHeader = sizeof(struct Header); struct Record rec; unsigned int index=0; int readedValue; printf("iterating records: %i\n", container->records); for (; index < container->records; ++index) { int seekTo = sizeOfHeader+sizeOfRecord*index; fseek(container->storage->base[FILE_BASE_IND]->handle, seekTo, SEEK_SET); printf("seekTo %i, ind:%i\n", seekTo, index); readedValue = fread(&rec, sizeof(struct Record), readBufferSize, container->storage->base[FILE_BASE_IND]->handle); //mmap/read might be better if (keyCmp(&rec.key, pk)) { printf("found pk match\n"); break; } } if (readedValue) { printf("rec->pk:%u, index:%u\n", pk->pk, index); } return index; }
/* * Wrapper for the function comparing by order metadata. As * qsort is not stable returning 0 on missing order may * mess up the original order. */ int elektraKeyCmpOrderWrapper (const void * a, const void * b) { const Key ** ka = (const Key **)a; const Key ** kb = (const Key **)b; int orderResult = elektraKeyCmpOrder (*ka, *kb); /* comparing the order meta could not order the keys * revert to comparing the names instead */ if (orderResult == 0) return keyCmp (*ka, *kb); return orderResult; }
/** * Information about the relation in the hierarchy between * two keys. * * Unlike keyCmp() the number gives information * about hierarchical information. * * * - If the keys are the same 0 is returned. * So it is the key itself. @verbatim user/key user/key @endverbatim * *@code keySetName (key, "user/key/folder"); keySetName (check, "user/key/folder"); succeed_if (keyRel (key, check) == 0, "should be same"); *@endcode * * @note this relation can be checked with keyCmp() too. * * * - If the key is direct below the other one 1 is returned. * That means that, in terms of hierarchy, no other key is * between them - it is a direct child. @verbatim user/key/folder user/key/folder/child @endverbatim * *@code keySetName (key, "user/key/folder"); keySetName (check, "user/key/folder/child"); succeed_if (keyRel (key, check) == 1, "should be direct below"); *@endcode * * * - If the key is below the other one, but not directly 2 is returned. * This is also called grand-child. @verbatim user/key/folder user/key/folder/any/depth/deeper/grand-child @endverbatim * * *@code keySetName (key, "user/key/folder"); keySetName (check, "user/key/folder/any/depth/deeper/grand-child"); succeed_if (keyRel (key, check) >= 2, "should be below (but not direct)"); succeed_if (keyRel (key, check) > 0, "should be below"); succeed_if (keyRel (key, check) >= 0, "should be the same or below"); *@endcode * * * - If a invalid or null ptr key is passed, -1 is returned * * * - If the keys have no relations, but are not invalid, -2 is returned. * * * - If the keys are in the same hierarchy, a value smaller then -2 is returned. * It means that the key is not below. @verbatim user/key/myself user/key/sibling @endverbatim * * @code keySetName (key, "user/key/folder"); keySetName (check, "user/notsame/folder"); succeed_if (keyRel (key, check) < -2, "key is not below, but same namespace"); * @endcode * * @code * @endcode * * * TODO Below is an idea how it could be extended: * It could continue the search into the other direction * if any (grand-)parents are equal. * * - If the keys are direct below a key which is next to the key, -2 is returned. * This is also called nephew. (TODO not implemented) * @verbatim user/key/myself user/key/sibling @endverbatim * * - If the keys are direct below a key which is next to the key, -2 is returned. * This is also called nephew. (TODO not implemented) * @verbatim user/key/myself user/key/sibling/nephew @endverbatim * * - If the keys are below a key which is next to the key, -3 is returned. * This is also called grand-nephew. (TODO not implemented) @verbatim user/key/myself user/key/sibling/any/depth/deeper/grand-nephew @endverbatim * * The same holds true for the other direction, but with negative values. * For no relation INT_MIN is returned. * * @note to check if the keys are the same, you must use * keyCmp() == 0! * keyRel() does not give you the information if it did not * find a relation or if it is the same key. * * @return depending on the relation * @retval 2 if below * @retval 1 if direct below * @retval 0 if the same * @retval -1 on null or invalid keys * @retval -2 if none of any other relation * @retval -3 if same hierarchy (none of those below) * @retval -4 if sibling (in same hierarchy) * @retval -5 if nephew (in same hierarchy) * * @param key the key object to work with * @param check the second key object to check the relation with * @ingroup keytest */ int keyRel (const Key * key, const Key * check) { if (!key || !check) return -1; if (!key->key || !check->key) return -1; if (!keyCmp (key, check)) return 0; if (keyIsDirectBelow (key, check)) return 1; if (keyIsBelow (key, check)) return 2; if (keyIsUser (key) && keyIsUser (check)) return -3; if (keyIsSystem (key) && keyIsSystem (check)) return -3; // if (keyIsSibling(key, check)) return -4; // if (keyIsNephew(key, check)) return -5; return -2; }
void RBTreeInsert(struct rb_tree *rb, rb_key_t key) { struct rb_node *z = createRBNode(key, RED); struct rb_node *x, *y; rb->size++; y = rb->nil; x = rb->root; while (x != rb->nil) { y = x; if (keyCmp(x->key, key) > 0) x = x->left; else x = x->right; } z->p = y; if (y == rb->nil) rb->root = z; else if (keyCmp(y->key, key) > 0) y->left = z; else y->right = z; z->left = rb->nil; z->right = rb->nil; RBTreeInsertFixup(rb, z); }
static void test_lookupNoascading () { printf ("Test lookup without cascading\n"); Key * specKey = keyNew ("/abc", KEY_CASCADING_NAME, KEY_END); Key * d = keyDup (specKey); keySetString (d, "dup"); succeed_if_same_string (keyName (specKey), "/abc"); succeed_if_same_string (keyName (d), "/abc"); succeed_if (!keyCmp (d, specKey), "comparision to duplicate failed"); succeed_if_same_string (keyName (d), "/abc"); succeed_if_same_string (keyName (specKey), "/abc"); KeySet * ks = ksNew (20, d, KS_END); Key * k = ksLookup (ks, specKey, KDB_O_NOCASCADING); succeed_if_same_string (keyName (specKey), "/abc"); succeed_if (k != 0, "did not find cascading key"); succeed_if (k != specKey, "should not be specKey"); succeed_if (k == d, "should be dup key"); Key * a = keyNew (keyName (specKey), KEY_CASCADING_NAME, KEY_VALUE, "a", KEY_END); ksAppendKey (ks, a); for (int i = 0; i < 5; ++i) { k = ksLookup (ks, specKey, KDB_O_NOCASCADING); succeed_if (keyGetNameSize (specKey) == 5, "size of spec key wrong"); succeed_if_same_string (keyName (specKey), "/abc"); succeed_if (k != 0, "did not find cascading key"); succeed_if (k != specKey, "should not be specKey"); succeed_if (k == a, "should be dup key"); // search without cascading k = ksLookup (ks, specKey, 0); succeed_if (keyGetNameSize (specKey) == 5, "size of spec key wrong"); succeed_if_same_string (keyName (specKey), "/abc"); succeed_if (k != 0, "did not find cascading key"); succeed_if (k != specKey, "should not be specKey"); succeed_if (k == a, "should be dup key"); } ksDel (ks); keyDel (specKey); }
static CondResult evalMultipleConditions (Key * key, const Key * meta, const Key * suffixList, Key * parentKey, KeySet * returned) { int countSucceeded = 0; int countFailed = 0; int countNoexpr = 0; KeySet * condKS = elektraMetaArrayToKS (key, keyName (meta)); Key * c; CondResult result = FALSE; while ((c = ksNext (condKS)) != NULL) { if (!keyCmp (c, meta)) continue; result = evaluateKey (c, suffixList, parentKey, key, returned, CONDITION); if (result == TRUE) ++countSucceeded; else if (result == ERROR) ++countFailed; else if (result == NOEXPR) ++countNoexpr; } ksDel (condKS); if (!strcmp (keyBaseName (meta), "all")) { // all conditions must evaluate to TRUE if (countFailed || countNoexpr) return ERROR; else return TRUE; } else if (!strcmp (keyBaseName (meta), "any")) { // at least one conditional must evaluate to TRUE if (countSucceeded) return TRUE; else return ERROR; } else { // no condition must evaluate to FALSE if (countFailed) return ERROR; else return TRUE; } }
static void flushConvertedKeys (Key * target, KeySet * converted, KeySet * orig) { if (ksGetSize (converted) == 0) return; ksRewind (converted); Key * current; Key * appendTarget; while ((current = ksNext (converted))) { appendTarget = target; const char * metaName = keyString (keyGetMeta (current, CONVERT_METANAME)); Key * currentDup = keyDup (current); Key * targetDup = keyDup (appendTarget); keySetBaseName (currentDup, 0); keySetBaseName (targetDup, 0); /* the convert key request to be converted to a key * on the same level, but the target is below or above */ if (keyGetMeta (current, CONVERT_APPEND_SAMELEVEL) && keyCmp (currentDup, targetDup)) { appendTarget = 0; } keyDel (currentDup); keyDel (targetDup); /* no target key was found of the target * was discarded for some reason. Revert to the parent */ if (!appendTarget) { appendTarget = findNearestParent (current, orig); } elektraKeyAppendMetaLine (appendTarget, metaName, keyString (current)); removeKeyFromResult (current, target, orig); } ksClear (converted); }
apiRetVal hashMapOpen::find (hashNodeKey *key, void **data) { uint32_t hashKey; hashNode *node = NULL; hashKey = getHashKey(key); if (hashKey > tableLength) { return API_RETVAL_INVALID_INPUT; } node = hashTable[hashKey]; while (node) { if (keyCmp(key, &node->nodeKey)) { *data = node->data; return (API_RETVAL_SUCCESS); } node = node->next; } return API_RETVAL_DATA_NOT_FOUND; }