* xmlHashUpdateInternal: * @hash: hash table * @key: first string key * @key2: second string key * @key3: third string key * @payload: pointer to the payload * @dealloc: deallocator function for replaced item or NULL * @update: whether existing entries should be updated * * Internal function to add or update hash entries. */
| 421 | * Internal function to add or update hash entries. |
| 422 | */ |
| 423 | ATTRIBUTE_NO_SANITIZE_INTEGER |
| 424 | static int |
| 425 | xmlHashUpdateInternal(xmlHashTablePtr hash, const xmlChar *key, |
| 426 | const xmlChar *key2, const xmlChar *key3, |
| 427 | void *payload, xmlHashDeallocator dealloc, int update) { |
| 428 | xmlChar *copy, *copy2, *copy3; |
| 429 | xmlHashEntry *entry = NULL; |
| 430 | size_t lengths[3]; |
| 431 | unsigned hashValue; |
| 432 | int found = 0; |
| 433 | |
| 434 | if ((hash == NULL) || (key == NULL)) |
| 435 | return(-1); |
| 436 | |
| 437 | /* |
| 438 | * Check for an existing entry |
| 439 | */ |
| 440 | hashValue = xmlHashValue(hash->randomSeed, key, key2, key3, lengths); |
| 441 | if (hash->size > 0) |
| 442 | entry = xmlHashFindEntry(hash, key, key2, key3, hashValue, &found); |
| 443 | if (found) { |
| 444 | if (update) { |
| 445 | if (dealloc) |
| 446 | dealloc(entry->payload, entry->key); |
| 447 | entry->payload = payload; |
| 448 | } |
| 449 | |
| 450 | return(0); |
| 451 | } |
| 452 | |
| 453 | /* |
| 454 | * Grow the hash table if needed |
| 455 | */ |
| 456 | if (hash->nbElems + 1 > hash->size / MAX_FILL_DENOM * MAX_FILL_NUM) { |
| 457 | unsigned newSize, mask, displ, pos; |
| 458 | |
| 459 | if (hash->size == 0) { |
| 460 | newSize = MIN_HASH_SIZE; |
| 461 | } else { |
| 462 | /* This guarantees that nbElems < INT_MAX */ |
| 463 | if (hash->size >= MAX_HASH_SIZE) |
| 464 | return(-1); |
| 465 | newSize = hash->size * 2; |
| 466 | } |
| 467 | if (xmlHashGrow(hash, newSize) != 0) |
| 468 | return(-1); |
| 469 | |
| 470 | /* |
| 471 | * Find new entry |
| 472 | */ |
| 473 | mask = hash->size - 1; |
| 474 | displ = 0; |
| 475 | pos = hashValue & mask; |
| 476 | entry = &hash->table[pos]; |
| 477 | |
| 478 | if (entry->hashValue != 0) { |
| 479 | do { |
| 480 | displ++; |
no test coverage detected