| 1386 | } |
| 1387 | |
| 1388 | void RcxController::performRealignment(uint64_t structId, int targetAlign) { |
| 1389 | auto& tree = m_doc->tree; |
| 1390 | int rootIdx = tree.indexOfId(structId); |
| 1391 | if (rootIdx < 0) return; |
| 1392 | |
| 1393 | // Gather direct children sorted by offset |
| 1394 | QVector<int> kids = tree.childrenOf(structId); |
| 1395 | std::sort(kids.begin(), kids.end(), [&](int a, int b) { |
| 1396 | return tree.nodes[a].offset < tree.nodes[b].offset; |
| 1397 | }); |
| 1398 | |
| 1399 | // Separate into real nodes (non-Padding) and padding nodes |
| 1400 | struct NodeInfo { uint64_t id; int offset; int size; }; |
| 1401 | QVector<NodeInfo> realNodes; |
| 1402 | QVector<uint64_t> padIds; |
| 1403 | |
| 1404 | for (int ci : kids) { |
| 1405 | const Node& child = tree.nodes[ci]; |
| 1406 | int sz = (child.kind == NodeKind::Struct || child.kind == NodeKind::Array) |
| 1407 | ? tree.structSpan(child.id) : child.byteSize(); |
| 1408 | if (child.kind == NodeKind::Padding) |
| 1409 | padIds.append(child.id); |
| 1410 | else |
| 1411 | realNodes.append({child.id, child.offset, sz}); |
| 1412 | } |
| 1413 | |
| 1414 | auto roundUp = [](int x, int align) -> int { |
| 1415 | return align <= 1 ? x : ((x + align - 1) / align) * align; |
| 1416 | }; |
| 1417 | |
| 1418 | // Compute new offsets for real nodes |
| 1419 | struct OffChange { uint64_t id; int oldOff; int newOff; }; |
| 1420 | QVector<OffChange> offChanges; |
| 1421 | int cursor = 0; |
| 1422 | for (auto& rn : realNodes) { |
| 1423 | int newOff = roundUp(cursor, targetAlign); |
| 1424 | if (newOff != rn.offset) |
| 1425 | offChanges.append({rn.id, rn.offset, newOff}); |
| 1426 | rn.offset = newOff; // update local copy for gap computation |
| 1427 | cursor = newOff + rn.size; |
| 1428 | } |
| 1429 | |
| 1430 | // Compute where padding is needed (gaps between consecutive nodes) |
| 1431 | struct PadInsert { int offset; int size; }; |
| 1432 | QVector<PadInsert> padsNeeded; |
| 1433 | |
| 1434 | for (int i = 0; i < realNodes.size(); i++) { |
| 1435 | int gapStart = (i == 0) ? 0 : realNodes[i - 1].offset + realNodes[i - 1].size; |
| 1436 | int gapEnd = realNodes[i].offset; |
| 1437 | if (gapEnd > gapStart) |
| 1438 | padsNeeded.append({gapStart, gapEnd - gapStart}); |
| 1439 | } |
| 1440 | |
| 1441 | // Check if anything actually changes |
| 1442 | if (offChanges.isEmpty() && padIds.isEmpty() && padsNeeded.isEmpty()) |
| 1443 | return; |
| 1444 | |
| 1445 | // Apply as undoable macro |
nothing calls this directly
no test coverage detected