* xmlHashScanFull: * @hash: hash table * @scan: scanner function for items in the hash * @data: extra data passed to @scan * * Scan the hash @table and apply @scan to each value. */
| 1007 | * Scan the hash @table and apply @scan to each value. |
| 1008 | */ |
| 1009 | void |
| 1010 | xmlHashScanFull(xmlHashTablePtr hash, xmlHashScannerFull scan, void *data) { |
| 1011 | const xmlHashEntry *entry, *end; |
| 1012 | xmlHashEntry old; |
| 1013 | unsigned i; |
| 1014 | |
| 1015 | if ((hash == NULL) || (hash->size == 0) || (scan == NULL)) |
| 1016 | return; |
| 1017 | |
| 1018 | /* |
| 1019 | * We must handle the case that a scanned entry is removed when executing |
| 1020 | * the callback (xmlCleanSpecialAttr and possibly other places). |
| 1021 | * |
| 1022 | * Find the start of a probe sequence to avoid scanning entries twice if |
| 1023 | * a deletion happens. |
| 1024 | */ |
| 1025 | entry = hash->table; |
| 1026 | end = &hash->table[hash->size]; |
| 1027 | while (entry->hashValue != 0) { |
| 1028 | if (++entry >= end) |
| 1029 | entry = hash->table; |
| 1030 | } |
| 1031 | |
| 1032 | for (i = 0; i < hash->size; i++) { |
| 1033 | if ((entry->hashValue != 0) && (entry->payload != NULL)) { |
| 1034 | /* |
| 1035 | * Make sure to rescan after a possible deletion. |
| 1036 | */ |
| 1037 | do { |
| 1038 | old = *entry; |
| 1039 | scan(entry->payload, data, entry->key, entry->key2, entry->key3); |
| 1040 | } while ((entry->hashValue != 0) && |
| 1041 | (entry->payload != NULL) && |
| 1042 | ((entry->key != old.key) || |
| 1043 | (entry->key2 != old.key2) || |
| 1044 | (entry->key3 != old.key3))); |
| 1045 | } |
| 1046 | if (++entry >= end) |
| 1047 | entry = hash->table; |
| 1048 | } |
| 1049 | } |
| 1050 | |
| 1051 | /** |
| 1052 | * xmlHashScan3: |
no test coverage detected