Changeset 39838 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Jan 23, 2012 4:05:23 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/CFGM.cpp
r39530 r39838 1203 1203 1204 1204 /** 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 */ 1211 VMMR3DECL(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 /** 1205 1321 * Insert subtree. 1206 1322 * … … 1228 1344 AssertReturn(!pSubTree->pParent, VERR_INVALID_PARAMETER); 1229 1345 AssertReturn(pSubTree->pVM, VERR_INVALID_PARAMETER); 1230 AssertReturn(pSubTree->pParent != pSubTree->pVM->cfgm.s.pRoot, VERR_INVALID_PARAMETER);1231 1346 Assert(!pSubTree->pNext); 1232 1347 Assert(!pSubTree->pPrev); … … 1254 1369 } 1255 1370 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 */ 1387 VMMR3DECL(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; 1256 1421 } 1257 1422
Note:
See TracChangeset
for help on using the changeset viewer.