1218 |
} |
} |
1219 |
|
|
1220 |
/** |
/** |
1221 |
|
* Returns subchunk at supplied @a pos position within this chunk list. |
1222 |
|
* If supplied @a pos is out of bounds then @c NULL is returned. The |
1223 |
|
* returned subchunk can either by an ordinary data chunk or a list chunk. |
1224 |
|
* |
1225 |
|
* @param pos - position of sought subchunk within this list |
1226 |
|
* @returns pointer to the subchunk or NULL if supplied position is not |
1227 |
|
* within the valid range of this list |
1228 |
|
*/ |
1229 |
|
Chunk* List::GetSubChunkAt(size_t pos) { |
1230 |
|
if (!pSubChunks) LoadSubChunks(); |
1231 |
|
if (pos >= pSubChunks->size()) return NULL; |
1232 |
|
return (*pSubChunks)[pos]; |
1233 |
|
} |
1234 |
|
|
1235 |
|
/** |
1236 |
* Returns subchunk with chunk ID <i>\a ChunkID</i> within this chunk |
* Returns subchunk with chunk ID <i>\a ChunkID</i> within this chunk |
1237 |
* list. Use this method if you expect only one subchunk of that type in |
* list. Use this method if you expect only one subchunk of that type in |
1238 |
* the list. It there are more than one, it's undetermined which one of |
* the list. It there are more than one, it's undetermined which one of |
1252 |
} |
} |
1253 |
|
|
1254 |
/** |
/** |
1255 |
|
* Returns sublist chunk with list type <i>\a ListType</i> at supplied |
1256 |
|
* @a pos position among all subchunks of type <i>\a ListType</i> within |
1257 |
|
* this chunk list. If supplied @a pos is out of bounds then @c NULL is |
1258 |
|
* returned. |
1259 |
|
* |
1260 |
|
* @param pos - position of sought sublist within this list |
1261 |
|
* @returns pointer to the sublist or NULL if if supplied position is not |
1262 |
|
* within valid range |
1263 |
|
*/ |
1264 |
|
List* List::GetSubListAt(size_t pos) { |
1265 |
|
if (!pSubChunks) LoadSubChunks(); |
1266 |
|
if (pos >= pSubChunks->size()) return NULL; |
1267 |
|
for (size_t iCk = 0, iLst = 0; iCk < pSubChunks->size(); ++iCk) { |
1268 |
|
Chunk* pChunk = (*pSubChunks)[iCk]; |
1269 |
|
if (pChunk->GetChunkID() != CHUNK_ID_LIST) continue; |
1270 |
|
if (iLst == pos) return (List*) pChunk; |
1271 |
|
++iLst; |
1272 |
|
} |
1273 |
|
return NULL; |
1274 |
|
} |
1275 |
|
|
1276 |
|
/** |
1277 |
* Returns sublist chunk with list type <i>\a ListType</i> within this |
* Returns sublist chunk with list type <i>\a ListType</i> within this |
1278 |
* chunk list. Use this method if you expect only one sublist chunk of |
* chunk list. Use this method if you expect only one sublist chunk of |
1279 |
* that type in the list. If there are more than one, it's undetermined |
* that type in the list. If there are more than one, it's undetermined |
1309 |
* |
* |
1310 |
* @returns pointer to the first subchunk within the list, NULL |
* @returns pointer to the first subchunk within the list, NULL |
1311 |
* otherwise |
* otherwise |
1312 |
|
* @deprecated This method is not reentrant-safe, use GetSubChunkAt() |
1313 |
|
* instead. |
1314 |
*/ |
*/ |
1315 |
Chunk* List::GetFirstSubChunk() { |
Chunk* List::GetFirstSubChunk() { |
1316 |
#if DEBUG_RIFF |
#if DEBUG_RIFF |
1328 |
* |
* |
1329 |
* @returns pointer to the next subchunk within the list or NULL if |
* @returns pointer to the next subchunk within the list or NULL if |
1330 |
* end of list is reached |
* end of list is reached |
1331 |
|
* @deprecated This method is not reentrant-safe, use GetSubChunkAt() |
1332 |
|
* instead. |
1333 |
*/ |
*/ |
1334 |
Chunk* List::GetNextSubChunk() { |
Chunk* List::GetNextSubChunk() { |
1335 |
#if DEBUG_RIFF |
#if DEBUG_RIFF |
1348 |
* |
* |
1349 |
* @returns pointer to the first sublist within the list, NULL |
* @returns pointer to the first sublist within the list, NULL |
1350 |
* otherwise |
* otherwise |
1351 |
|
* @deprecated This method is not reentrant-safe, use GetSubListAt() |
1352 |
|
* instead. |
1353 |
*/ |
*/ |
1354 |
List* List::GetFirstSubList() { |
List* List::GetFirstSubList() { |
1355 |
#if DEBUG_RIFF |
#if DEBUG_RIFF |
1372 |
* |
* |
1373 |
* @returns pointer to the next sublist within the list, NULL if |
* @returns pointer to the next sublist within the list, NULL if |
1374 |
* end of list is reached |
* end of list is reached |
1375 |
|
* @deprecated This method is not reentrant-safe, use GetSubListAt() |
1376 |
|
* instead. |
1377 |
*/ |
*/ |
1378 |
List* List::GetNextSubList() { |
List* List::GetNextSubList() { |
1379 |
#if DEBUG_RIFF |
#if DEBUG_RIFF |
1479 |
*/ |
*/ |
1480 |
void List::MoveSubChunk(Chunk* pSrc, Chunk* pDst) { |
void List::MoveSubChunk(Chunk* pSrc, Chunk* pDst) { |
1481 |
if (!pSubChunks) LoadSubChunks(); |
if (!pSubChunks) LoadSubChunks(); |
1482 |
pSubChunks->remove(pSrc); |
for (size_t i = 0; i < pSubChunks->size(); ++i) { |
1483 |
ChunkList::iterator iter = find(pSubChunks->begin(), pSubChunks->end(), pDst); |
if ((*pSubChunks)[i] == pSrc) { |
1484 |
pSubChunks->insert(iter, pSrc); |
pSubChunks->erase(pSubChunks->begin() + i); |
1485 |
|
ChunkList::iterator iter = |
1486 |
|
find(pSubChunks->begin(), pSubChunks->end(), pDst); |
1487 |
|
pSubChunks->insert(iter, pSrc); |
1488 |
|
return; |
1489 |
|
} |
1490 |
|
} |
1491 |
} |
} |
1492 |
|
|
1493 |
/** @brief Moves a sub chunk from this list to another list. |
/** @brief Moves a sub chunk from this list to another list. |
1502 |
if (pNewParent == this || !pNewParent) return; |
if (pNewParent == this || !pNewParent) return; |
1503 |
if (!pSubChunks) LoadSubChunks(); |
if (!pSubChunks) LoadSubChunks(); |
1504 |
if (!pNewParent->pSubChunks) pNewParent->LoadSubChunks(); |
if (!pNewParent->pSubChunks) pNewParent->LoadSubChunks(); |
1505 |
pSubChunks->remove(pSrc); |
ChunkList::iterator iter = |
1506 |
|
find(pSubChunks->begin(), pSubChunks->end(), pSrc); |
1507 |
|
if (iter == pSubChunks->end()) return; |
1508 |
|
pSubChunks->erase(iter); |
1509 |
pNewParent->pSubChunks->push_back(pSrc); |
pNewParent->pSubChunks->push_back(pSrc); |
1510 |
// update chunk id map of this List |
// update chunk id map of this List |
1511 |
if ((*pSubChunksMap)[pSrc->GetChunkID()] == pSrc) { |
if ((*pSubChunksMap)[pSrc->GetChunkID()] == pSrc) { |
1555 |
*/ |
*/ |
1556 |
void List::DeleteSubChunk(Chunk* pSubChunk) { |
void List::DeleteSubChunk(Chunk* pSubChunk) { |
1557 |
if (!pSubChunks) LoadSubChunks(); |
if (!pSubChunks) LoadSubChunks(); |
1558 |
pSubChunks->remove(pSubChunk); |
ChunkList::iterator iter = |
1559 |
|
find(pSubChunks->begin(), pSubChunks->end(), pSubChunk); |
1560 |
|
if (iter == pSubChunks->end()) return; |
1561 |
|
pSubChunks->erase(iter); |
1562 |
if ((*pSubChunksMap)[pSubChunk->GetChunkID()] == pSubChunk) { |
if ((*pSubChunksMap)[pSubChunk->GetChunkID()] == pSubChunk) { |
1563 |
pSubChunksMap->erase(pSubChunk->GetChunkID()); |
pSubChunksMap->erase(pSubChunk->GetChunkID()); |
1564 |
// try to find another chunk of the same chunk ID |
// try to find another chunk of the same chunk ID |
1690 |
void List::LoadSubChunksRecursively(progress_t* pProgress) { |
void List::LoadSubChunksRecursively(progress_t* pProgress) { |
1691 |
const int n = (int) CountSubLists(); |
const int n = (int) CountSubLists(); |
1692 |
int i = 0; |
int i = 0; |
1693 |
for (List* pList = GetFirstSubList(); pList; pList = GetNextSubList(), ++i) { |
for (List* pList = GetSubListAt(i); pList; pList = GetSubListAt(++i)) { |
1694 |
if (pProgress) { |
if (pProgress) { |
1695 |
// divide local progress into subprogress |
// divide local progress into subprogress |
1696 |
progress_t subprogress; |
progress_t subprogress; |
2439 |
} |
} |
2440 |
|
|
2441 |
void File::Cleanup() { |
void File::Cleanup() { |
2442 |
const Handle hRead = FileHandle(); |
if (IsIOPerThread()) { |
2443 |
if (_isValidHandle(hRead)) _close(hRead); |
for (auto it = io.byThread.begin(); it != io.byThread.end(); ++it) { |
2444 |
|
_close(it->second.hRead); |
2445 |
|
} |
2446 |
|
} else { |
2447 |
|
_close(io.hRead); |
2448 |
|
} |
2449 |
DeleteChunkList(); |
DeleteChunkList(); |
2450 |
pFile = NULL; |
pFile = NULL; |
2451 |
} |
} |