O''''Reilly Network For Information About''''s Book part 151 doc

6 55 0
O''''Reilly Network For Information About''''s Book part 151 doc

Đang tải... (xem toàn văn)

Thông tin tài liệu

+- +- Quantum | 444444443333333333222222222211111111110000000000 Offset | 765432109876543210987654321098765432109876543210 +- +- | 666666666666666666666666666666666666666666666666 | 999111111111111111111111111111111111111111111111 Address | 999000000000011111111112222222222333333333344444 | 789012345678901234567890123456789012345678901234 +- Of course, all of the item index entries from the one we are inserting to the last one now have the wrong offset; we have to add the size of the new item to these offsets, to account for the move we just did, which we do by calling AdjustOffset. We're almost done with this insertion. All we have left is to calculate the actual position of the new item in the quantum as the quantum buffer's address + the size of a quantum - the offset of this item, (4096+2048-28, or 6116) and store the result in DataTo. Then we can call BlockMove to copy the new item's data to that position, and finish up by setting the relative item number (which is the return value from this function) to ItemFound + 1 and returning it. The final quantum contents look like Figure insert3. Item index and data after item insertion (Figure insert3) +- | Item # Offset Type Index | + + | 1 | 5 + VARSTRING 4 | Item | 2 | 17 -+| VARSTRING 0 | Index | 3 | +-19 || VARSTRING 3 | | 4 | | 28-+|| VARSTRING 6 | | 5 | ++-40 ||| VARSTRING 1 | | 6 |+++-47 ||| VARSTRING 2 | | ++++ +++ + +- ||| ||+ + ||| |+ + | ||+ + + | | +- || + + | | | | || | | | | | |+ + | | | | | + + + + +-+ + + Quantum | | BaldwinP.O.Box 0335ChrysalisNYSteve Heller11510| Data | + + +- +- Quantum | 444444443333333333222222222211111111110000000000 Offset | 765432109876543210987654321098765432109876543210 +- +- | 666666666666666666666666666666666666666666666666 | 999111111111111111111111111111111111111111111111 Address | 999000000000011111111112222222222333333333344444 | 789012345678901234567890123456789012345678901234 +- The above scenario handles the case of reusing an item index slot. The code following the comment that says "must make a new item" deals with the case where we have to add a new item index element at the end of the index, which is somewhat simpler, as we don't have to move any preexisting data: our new item is the last in the quantum. When adding a new item, there are two subsidiary possibilities: that this is the first element in the item index, or that there are existing elements in the item index and we're adding a new one at the end. Of course, the simplest case of all is the one where there aren't any items in the quantum as yet. In this case, the offset of the new item is equal to its size. However, if there are some items in the quantum already, then the offset of the new item is equal to the offset of the last item in the quantum added to the size of the new item. Once we have calculated the offset, we can move the new item's data to its position in the quantum. Then we set the type and index of the new item and store it in the last position of the m_ItemIndex array, set the ItemNumber to one more than the number of items that were in the array before, increment the item count, and return the relative item number to the calling routine. Finally, whether we have reused an existing item or added a new one, we call UpdateFreeSpace to recompute the amount of free space in the quantum, then return the item number of the new item. The QuantumBlock::GetModifiableItem Function Now that we have seen how to add an item to a quantum, perhaps we should take a look at the function that allows us to get it back: GetModifiableItem (shown in Figure block.22). The QuantumBlock::GetModifiableItem Function (from quantum\block.cpp) (Figure block.22) codelist/block.22 As you might imagine, retrieving an item is simpler than storing the item in the first place, because we don't have to move anything around. We start with an assert that checks two conditions: that the item number is greater than 0 and that it is less than or equal to the item count. Once we have passed that sanity check, we decrement the item number to convert it to an index into the item index array, then retrieve the offset of the item from its item index entry. Then we calculate its actual starting address and length, which gives us the information necessary to create a ModifiableElement from the data. We do so, and return the result to the caller. The QuantumBlock::DeleteItem function The third fundamental operation that we can perform on an item is to delete it. This operation is used both when simply deleting an item from the main object and when changing the value of an item; to change an item, we actually delete the previous item and add a new one. So let's take a look at DeleteItem (shown in Figure block.23). The QuantumBlock::DeleteItem function (from quantum\block.cpp) (Figure block.23) codelist/block.23 After checking that the item number is legal and converting it to an index into the item index array, we determine whether the item to be deleted is the last one in the quantum. If so, we set its type to UNUSED_ITEM. While this would be sufficient to allow the reuse of this item index entry, if we stopped there, we would never be able to reduce the size of the item index; eventually, the quantum would fill up with unused item index entries, leaving no room for actual data. To prevent this, we clean up any trailing unused entries in the item index by searching backwards from the end of the item index, clearing any trailing unused entries to zeroes. 42 When we get to an item index entry that is in use, or to the beginning of the item index, we stop searching. At that point, we reset the item count to 1 more than the last value of the index in the loop. If that last loop index value was -1, then we have emptied the quantum, so we call Clear to reset it to an unused state. Finally, we call UpdateFreeSpace to recalculate the amount of free space in the quantum and return the result to the caller. That takes care of deleting the last item in a quantum, but what if we need to delete some other item? In that case, we extract the starting offset of the item to be deleted and calculate its length. For the first item, the item length is equal to the m_Offset field in the item, because the data for the first item in the quantum is stored at the end of the quantum, as illustrated in Figure itemref1. For other items, the item length is equal to the offset of the previous item subtracted from the offset of the current item. This may seem backward, as the figure shows that the second item is stored before the first, the third before the second, and so on. However, the offset of an item is defined as the distance in bytes from the start of the item to the first byte after the end of the quantum, which is always nonnegative. We also have to set the offset of this item to the offset of the previous item (if there is a previous item), which will indicate that this item's length is zero. For the first item, we can just set the offset to zero, since there is no previous item to worry about. Now we're ready to compute the offset of the last item, the source and destination addresses for the data to be moved into the deleted item's space, and the length of that data. We calculate the source address (DataFrom) as the address of the last item (m_Block->m_Data+BlockSize-LastItemOffset), the destination address (DataTo) as the source address added to the length of the item we are deleting (DataFrom+item length), and the number of bytes to move (DataLength) as the total length of all the items from the one we are deleting to the last item (LastItemOffset - StartingOffset) Then we call BlockMove to transfer the data and AdjustOffset to update the offsets of the other items. Next, we set the item's type to UNUSED_ITEM and its offset to the same value as the previous entry in the item index (or 0, if it is the first item) so that the length of the next item can be properly calculated. Finally, we call UpdateFreeSpace and return to the calling function. To make this clearer, let's look at what happens if we delete the item holding the state name from the example in Figure itemref4. Let's suppose the address of the quantum is 4096. The offset of the last item, marked by "^", is 41; substituting values in the expression for DataFrom, m_Block->m_Data+BlockSize- LastItemOffset equals 4096+2048-41, or 6103. The offset of the item we're deleting, marked by the "*", is 19, and the offset of the previous item (marked by the "&") is 17, which makes the item length 2; therefore, the DataTo address is 6103+2, or 6105. This is where the last item will start after the move, since we are removing the 2 bytes of the item being deleted. Finally, DataLength is the amount of data to be moved, which is the length of all the items with higher index numbers than the one being deleted, in this case 41-19, or 22. Sample IRA, etc., before deletion (Figure itemref4) +- | Quantum Item | Index Number Number | + + Item | 0 | 3 2 + + Reference | 1 | 3 4 + +-+ Array | 2 | 3 5 + +-+-+ (IRA) | 3 | 3 3 + + | | | | 4 | 3 1 + + | | | | | + + | | | | | +- | | | | | | | | | | +- | | | | | | Item # Offset Type Index | | | | | | + + | | | | | Item | 1 | 5 -+ VARSTRING 4 |± + | | | | Index | 2 | 17 +| VARSTRING 0 |± + + | | for | 3 | +-19 || VARSTRING 3 |± + | | Quantum | 4 | ++-34 || VARSTRING 1 |± + | 3 | 5 |+++-41 || VARSTRING 2 |± + | 6 |||| 41 || UNUSED 0 | | ++++ ++ + +- ||| |+ + ||| + + | ||+ + | | +- |+ + | | | | + + + +-+ + + Quantum | | Baldwin123 Main StreetNYSteve Heller11510| Data | + + +- ^ * & +- . item index entry. Then we calculate its actual starting address and length, which gives us the information necessary to create a ModifiableElement from the data. We do so, and return the result. item to be deleted and calculate its length. For the first item, the item length is equal to the m_Offset field in the item, because the data for the first item in the quantum is stored at. item. This may seem backward, as the figure shows that the second item is stored before the first, the third before the second, and so on. However, the offset of an item is defined as the distance

Ngày đăng: 07/07/2014, 08:20

Tài liệu cùng người dùng

Tài liệu liên quan