/// <summary> /// Adds, updates, or removes a map entry. /// </summary> /// <param name="offset">File offset at which the address changes.</param> /// <param name="addr">24-bit address.</param> public void Set(int offset, int addr) { Debug.Assert(offset >= 0); if (addr == -1) { if (offset != 0) // ignore attempts to remove entry at offset zero { Remove(offset); } return; } Debug.Assert(addr >= 0 && addr < 0x01000000); // 24-bit address space int i; for (i = 0; i < mAddrList.Count; i++) { AddressMapEntry ad = mAddrList[i]; if (ad.Offset == offset) { // update existing ad.Addr = addr; mAddrList[i] = ad; return; } else if (ad.Offset > offset) { // The i'th entry is one past the interesting part. break; } } // Carve a chunk out of the previous entry. AddressMapEntry prev = mAddrList[i - 1]; int prevOldLen = prev.Length; int prevNewLen = offset - prev.Offset; prev.Length = prevNewLen; mAddrList[i - 1] = prev; mAddrList.Insert(i, new AddressMapEntry(offset, addr, prevOldLen - prevNewLen)); DebugValidate(); }
/// <summary> /// Internal consistency checks. /// </summary> private void DebugValidate() { if (mAddrList.Count < 1) { throw new Exception("AddressMap: empty"); } if (mAddrList[0].Offset != 0) { throw new Exception("AddressMap: bad offset 0"); } if (mAddrList.Count == 1) { if (mAddrList[0].Length != mTotalLength) { throw new Exception("AddressMap: single entry len bad"); } } else { int totalLen = 0; for (int i = 0; i < mAddrList.Count; i++) { AddressMapEntry ent = mAddrList[i]; if (i != 0) { if (ent.Offset != mAddrList[i - 1].Offset + mAddrList[i - 1].Length) { throw new Exception("Bad offset step to " + i); } } totalLen += ent.Length; } if (totalLen != mTotalLength) { throw new Exception("AddressMap: bad length sum (" + totalLen + " vs " + mTotalLength + ")"); } } }
/// <summary> /// Removes an entry from the set. /// </summary> /// <param name="offset">The initial offset of the mapping to remove. This /// must be the initial value, not a mid-range value.</param> /// <returns>True if something was removed.</returns> public bool Remove(int offset) { if (offset == 0) { throw new Exception("Not allowed to remove entry 0"); } for (int i = 1; i < mAddrList.Count; i++) { if (mAddrList[i].Offset == offset) { // Add the length to the previous entry. AddressMapEntry prev = mAddrList[i - 1]; prev.Length += mAddrList[i].Length; mAddrList[i - 1] = prev; mAddrList.RemoveAt(i); DebugValidate(); return(true); } } return(false); }
// Copy constructor. public AddressMapEntry(AddressMapEntry src) { Offset = src.Offset; Addr = src.Addr; Length = src.Length; }