| 1321 | } |
| 1322 | |
| 1323 | int cbm_gbuf_merge(cbm_gbuf_t *dst, cbm_gbuf_t *src) { |
| 1324 | if (!dst || !src) { |
| 1325 | return CBM_NOT_FOUND; |
| 1326 | } |
| 1327 | if (src->nodes.count == 0 && src->edges.count == 0) { |
| 1328 | return 0; |
| 1329 | } |
| 1330 | |
| 1331 | /* ID remap for QN-colliding nodes: "src_id" → (int64_t*) dst_id. |
| 1332 | * Only populated when a src node's QN already exists in dst. */ |
| 1333 | CBMHashTable *remap = NULL; |
| 1334 | |
| 1335 | for (int i = 0; i < src->nodes.count; i++) { |
| 1336 | cbm_gbuf_node_t *sn = src->nodes.items[i]; |
| 1337 | if (!sn->qualified_name) { |
| 1338 | continue; |
| 1339 | } |
| 1340 | |
| 1341 | /* Skip nodes deleted from QN index */ |
| 1342 | if (!cbm_ht_get(src->node_by_qn, sn->qualified_name)) { |
| 1343 | continue; |
| 1344 | } |
| 1345 | |
| 1346 | cbm_gbuf_node_t *existing = cbm_ht_get(dst->node_by_qn, sn->qualified_name); |
| 1347 | if (existing) { |
| 1348 | merge_update_existing(dst, existing, sn, &remap); |
| 1349 | } else { |
| 1350 | merge_copy_new_node(dst, sn); |
| 1351 | } |
| 1352 | } |
| 1353 | |
| 1354 | /* Merge edges with optional ID remapping */ |
| 1355 | merge_remap_edges(dst, src, remap); |
| 1356 | |
| 1357 | if (remap) { |
| 1358 | cbm_ht_foreach(remap, free_remap_entry, NULL); |
| 1359 | cbm_ht_free(remap); |
| 1360 | } |
| 1361 | |
| 1362 | return 0; |
| 1363 | } |
| 1364 | |
| 1365 | /* ── Dump / Flush ────────────────────────────────────────────────── */ |
| 1366 |
no test coverage detected