VirtualBox

Changeset 39838 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Jan 23, 2012 4:05:23 PM (13 years ago)
Author:
vboxsync
Message:

CFGM: Added CFGMR3DuplicateSubTree and CFGMR3ReplaceSubTree (untested).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/CFGM.cpp

    r39530 r39838  
    12031203
    12041204/**
     1205 * Duplicates a CFGM sub-tree or a full tree.
     1206 *
     1207 * @returns Pointer to the root node.  NULL if we run out of memory or the
     1208 *          input parameter is NULL.
     1209 * @param   pRoot       The root of the tree to duplicate.
     1210 */
     1211VMMR3DECL(PCFGMNODE) CFGMR3DuplicateSubTree(PCFGMNODE pRoot)
     1212{
     1213    AssertPtrReturn(pRoot, NULL);
     1214
     1215    /*
     1216     * Create a new tree.
     1217     */
     1218    PCFGMNODE pNewRoot = CFGMR3CreateTree(pRoot->pVM);
     1219    if (!pNewRoot)
     1220        return pNewRoot;
     1221
     1222    /*
     1223     * Duplicate the content.
     1224     */
     1225    int         rc      = VINF_SUCCESS;
     1226    PCFGMNODE   pSrcCur = pRoot;
     1227    PCFGMNODE   pDstCur = pNewRoot;
     1228    for (;;)
     1229    {
     1230        if (   !pDstCur->pFirstChild
     1231            && !pDstCur->pFirstLeaf)
     1232        {
     1233            /*
     1234             * Values first.
     1235             */
     1236            /** @todo this isn't the most efficient way to do it. */
     1237            for (PCFGMLEAF pLeaf = pSrcCur->pFirstLeaf; pLeaf && RT_SUCCESS(rc); pLeaf = pLeaf->pNext)
     1238            {
     1239                switch (pLeaf->enmType)
     1240                {
     1241                    case CFGMVALUETYPE_INTEGER:
     1242                        rc = CFGMR3InsertInteger(pDstCur, pLeaf->szName, pLeaf->Value.Integer.u64);
     1243                        break;
     1244
     1245                    case CFGMVALUETYPE_BYTES:
     1246                        rc = CFGMR3InsertBytes(pDstCur, pLeaf->szName, pLeaf->Value.Bytes.pau8, pLeaf->Value.Bytes.cb);
     1247                        break;
     1248
     1249                    case CFGMVALUETYPE_STRING:
     1250                        rc = CFGMR3InsertStringN(pDstCur, pLeaf->szName, pLeaf->Value.String.psz, pLeaf->Value.String.cb - 1);
     1251                        break;
     1252
     1253                    default:
     1254                        rc = VERR_CFGM_IPE_1;
     1255                        AssertMsgFailed(("Invalid value type %d\n", pLeaf->enmType));
     1256                        break;
     1257                }
     1258            }
     1259
     1260            /*
     1261             * Insert immediate child nodes.
     1262             */
     1263            /** @todo this isn't the most efficient way to do it. */
     1264            for (PCFGMNODE pChild = pSrcCur->pFirstChild; pChild && RT_SUCCESS(rc); pChild = pChild->pNext)
     1265                rc = CFGMR3InsertNode(pDstCur, pChild->szName, NULL);
     1266
     1267            AssertLogRelRCBreak(rc);
     1268        }
     1269
     1270        /*
     1271         * Deep copy of the children.
     1272         */
     1273        if (pSrcCur->pFirstChild)
     1274        {
     1275            Assert(pDstCur->pFirstChild && !strcmp(pDstCur->pFirstChild->szName, pSrcCur->pFirstChild->szName));
     1276            pSrcCur = pSrcCur->pFirstChild;
     1277            pDstCur = pDstCur->pFirstChild;
     1278        }
     1279        /*
     1280         * If it's the root node, we're done.
     1281         */
     1282        else if (pSrcCur == pRoot)
     1283            break;
     1284        else
     1285        {
     1286            /*
     1287             * Upon reaching the end of a sibling list, we must ascend and
     1288             * resume the sibiling walk on an previous level.
     1289             */
     1290            if (!pSrcCur->pNext)
     1291            {
     1292                do
     1293                {
     1294                    pSrcCur = pSrcCur->pParent;
     1295                    pDstCur = pDstCur->pParent;
     1296                } while (!pSrcCur->pNext && pSrcCur != pRoot);
     1297                if (pSrcCur == pRoot)
     1298                    break;
     1299            }
     1300
     1301            /*
     1302             * Next sibling.
     1303             */
     1304            Assert(pDstCur->pNext && !strcmp(pDstCur->pNext->szName, pSrcCur->pNext->szName));
     1305            pSrcCur = pSrcCur->pNext;
     1306            pDstCur = pDstCur->pNext;
     1307        }
     1308    }
     1309
     1310    if (RT_FAILURE(rc))
     1311    {
     1312        CFGMR3RemoveNode(pNewRoot);
     1313        return NULL;
     1314    }
     1315
     1316    return pNewRoot;
     1317}
     1318
     1319
     1320/**
    12051321 * Insert subtree.
    12061322 *
     
    12281344    AssertReturn(!pSubTree->pParent, VERR_INVALID_PARAMETER);
    12291345    AssertReturn(pSubTree->pVM, VERR_INVALID_PARAMETER);
    1230     AssertReturn(pSubTree->pParent != pSubTree->pVM->cfgm.s.pRoot, VERR_INVALID_PARAMETER);
    12311346    Assert(!pSubTree->pNext);
    12321347    Assert(!pSubTree->pPrev);
     
    12541369    }
    12551370    return rc;
     1371}
     1372
     1373
     1374/**
     1375 * Replaces a (sub-)tree with new one.
     1376 *
     1377 * This function removes the exiting (sub-)tree, completely freeing it in the
     1378 * process, and inserts (no duplication) the specified tree.  The tree can
     1379 * either be created by CFGMR3CreateTree or CFGMR3DuplicateSubTree.
     1380 *
     1381 * @returns VBox status code.
     1382 * @param   pRoot       The sub-tree to replace.  This node will remain valid
     1383 *                      after the call.
     1384 * @param   pNewRoot    The tree to replace @a pRoot with.  This not will
     1385 *                      become invalid after a successful call.
     1386 */
     1387VMMR3DECL(int) CFGMR3ReplaceSubTree(PCFGMNODE pRoot, PCFGMNODE pNewRoot)
     1388{
     1389    /*
     1390     * Validate input.
     1391     */
     1392    AssertPtrReturn(pRoot, VERR_INVALID_POINTER);
     1393    AssertPtrReturn(pNewRoot, VERR_INVALID_POINTER);
     1394    AssertReturn(!pNewRoot->pParent, VERR_INVALID_PARAMETER);
     1395    AssertReturn(pNewRoot->pVM, VERR_INVALID_PARAMETER);
     1396    AssertReturn(pNewRoot->pVM == pRoot->pVM, VERR_INVALID_PARAMETER);
     1397    AssertReturn(!pNewRoot->pNext, VERR_INVALID_PARAMETER);
     1398    AssertReturn(!pNewRoot->pPrev, VERR_INVALID_PARAMETER);
     1399
     1400    /*
     1401     * Free the current properties fo pRoot.
     1402     */
     1403    while (pRoot->pFirstChild)
     1404        CFGMR3RemoveNode(pRoot->pFirstChild);
     1405
     1406    while (pRoot->pFirstLeaf)
     1407        cfgmR3RemoveLeaf(pRoot, pRoot->pFirstLeaf);
     1408
     1409    /*
     1410     * Copy all the properties from the new root to the current one.
     1411     */
     1412    pRoot->pFirstLeaf       = pNewRoot->pFirstLeaf;
     1413    pRoot->pFirstChild      = pNewRoot->pFirstChild;
     1414
     1415    pNewRoot->pFirstLeaf    = NULL;
     1416    pNewRoot->pFirstChild   = NULL;
     1417    pNewRoot->pVM           = NULL;
     1418    MMR3HeapFree(pNewRoot);
     1419
     1420    return VINF_SUCCESS;
    12561421}
    12571422
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette