| 1371 | } |
| 1372 | |
| 1373 | int cbm_gbuf_merge(cbm_gbuf_t *dst, cbm_gbuf_t *src) { |
| 1374 | if (!dst || !src) { |
| 1375 | return CBM_NOT_FOUND; |
| 1376 | } |
| 1377 | if (src->nodes.count == 0 && src->edges.count == 0) { |
| 1378 | return 0; |
| 1379 | } |
| 1380 | |
| 1381 | /* ID remap for QN-colliding nodes: "src_id" → (int64_t*) dst_id. |
| 1382 | * Only populated when a src node's QN already exists in dst. */ |
| 1383 | CBMHashTable *remap = NULL; |
| 1384 | |
| 1385 | for (int i = 0; i < src->nodes.count; i++) { |
| 1386 | cbm_gbuf_node_t *sn = src->nodes.items[i]; |
| 1387 | if (!sn->qualified_name) { |
| 1388 | continue; |
| 1389 | } |
| 1390 | |
| 1391 | /* Skip nodes deleted from QN index */ |
| 1392 | if (!cbm_ht_get(src->node_by_qn, sn->qualified_name)) { |
| 1393 | continue; |
| 1394 | } |
| 1395 | |
| 1396 | cbm_gbuf_node_t *existing = cbm_ht_get(dst->node_by_qn, sn->qualified_name); |
| 1397 | if (existing) { |
| 1398 | merge_update_existing(dst, existing, sn, &remap); |
| 1399 | } else { |
| 1400 | merge_copy_new_node(dst, sn); |
| 1401 | } |
| 1402 | } |
| 1403 | |
| 1404 | /* Merge edges with optional ID remapping */ |
| 1405 | merge_remap_edges(dst, src, remap); |
| 1406 | |
| 1407 | if (remap) { |
| 1408 | cbm_ht_foreach(remap, free_remap_entry, NULL); |
| 1409 | cbm_ht_free(remap); |
| 1410 | } |
| 1411 | |
| 1412 | return 0; |
| 1413 | } |
| 1414 | |
| 1415 | /* ── Dump / Flush ────────────────────────────────────────────────── */ |
| 1416 |
no test coverage detected