public void TestBasics()
		{
            OrdinalList list = new OrdinalList();
            Assert.IsFalse(list.IsReadOnly);
            list.Ceiling = 0;

			for (int i = 512; i >= 0; i--)
				list.Add(i);

            int offset = 0;
            foreach (int item in list)
                Assert.AreEqual(offset++, item);

            Assert.AreEqual(513, offset);
            Assert.AreEqual(513, list.Count);
			Assert.AreEqual(519, list.Ceiling);

            list.Clear();
            list.AddRange(new int[] { 5, 10, 20 });
            list.AddRange(new int[] { });

            Assert.AreEqual(3, list.Count);
            Assert.AreEqual(23, list.Ceiling);

            Assert.IsTrue(list.Contains(20));
            Assert.IsTrue(list.Remove(20));

            Assert.IsFalse(list.Contains(20));
            Assert.IsFalse(list.Remove(20));

            Assert.AreEqual(2, list.Count);

            int[] items = new int[2];
            list.CopyTo(items, 0);
            Assert.AreEqual(5, items[0]);
            Assert.AreEqual(10, items[1]);

            items = list.ToArray();
            Assert.AreEqual(5, items[0]);
            Assert.AreEqual(10, items[1]);

            byte[] bits = list.ToByteArray();
            Assert.AreEqual(3, bits.Length);
            Assert.AreEqual(2, new OrdinalList(bits).Count);

            List<int> tmp = new List<int>();
            foreach (int i in list)
                tmp.Add(i);
            Assert.AreEqual(2, tmp.Count);
            Assert.AreEqual(5, tmp[0]);
            Assert.AreEqual(10, tmp[1]);
        }
Beispiel #2
0
        /// <summary>
        /// Allocates a handle for data, you MUST call Write to commit the handle, otherwise the handle
        /// may be reallocated after closing and re-opening this file.  If you do not intend to commit
        /// the handle by writing to it, you should still call Delete() so that it may be reused.
        /// </summary>
        public uint Create()
        {
            uint handle = 0;

            lock (_sync)
            {
                while (handle == 0)
                {
                    foreach (int i in _freeHandles.EnumerateFrom(_prevFreeHandle))
                    {
                        _freeHandles.Remove(i);
                        _prevFreeHandle = i + 1;
                        handle          = (uint)i;
                        break;
                    }
                    if (handle == 0)
                    {
                        AddSection();
                    }
                }
            }

            HandleRef href    = new HandleRef(handle, BlockSize);
            uint      blockId = _sections[href.Section][href.Offset];

            if (blockId != 0)
            {
                throw new InvalidDataException();
            }

            return(handle);
        }
        private uint TakeBlocks(int blocksNeeded)
        {
            lock (_sync)
            {
                bool resized = false;
                while (true)
                {
                    int found = 0;
                    int last  = int.MinValue;
                    int first = int.MaxValue;
                    foreach (int free in _freeBlocks.EnumerateFrom(_prevFreeBlock))
                    {
                        if (_reservedBlocks.Contains(free))
                        {
                            continue;
                        }

                        first = Math.Min(first, free);
                        found = (last + 1 != free) ? 1 : found + 1;
                        last  = free;
                        if (found == blocksNeeded)
                        {
                            _prevFreeBlock = first;

                            int start = free - (blocksNeeded - 1);
                            for (int i = start; i <= free; i++)
                            {
                                _freeBlocks.Remove(i);
                            }

                            uint blockId = (uint)start;
                            blockId |= ((uint)Math.Min(16, blocksNeeded) - 1 << 28) & 0xF0000000u;
                            return(blockId);
                        }
                    }
                    if (resized)
                    {
                        throw new ArgumentOutOfRangeException("length");
                    }

                    resized = true;
                    AddSection();
                }
            }
        }
Beispiel #4
0
        private uint TakeBlocks(int blocksNeeded)
        {
            lock (_sync)
            {
                bool rescan       = false;
                bool resized      = false;
                int  startingFrom = _prevFreeBlock;
                int  endingBefore = int.MaxValue;
                while (true)
                {
                    int found = 0;
                    int last  = int.MinValue;
                    int first = int.MaxValue;
                    foreach (int free in _freeBlocks.EnumerateRange(startingFrom, endingBefore))
                    {
                        if (_reservedBlocks.Contains(free))
                        {
                            continue;
                        }

                        if (found == 0)
                        {
                            _prevFreeBlock = free;
                            if (!resized && rescan)
                            {
                                _firstFreeBlock = free;
                            }
                        }

                        first = Math.Min(first, free);
                        found = (last + 1 != free) ? 1 : found + 1;
                        last  = free;
                        if (found == blocksNeeded)
                        {
                            int start = free - (blocksNeeded - 1);
                            for (int i = start; i <= free; i++)
                            {
                                _freeBlocks.Remove(i);
                            }

                            uint blockId = (uint)start;
                            blockId |= ((uint)Math.Min(16, blocksNeeded) - 1 << 28) & 0xF0000000u;
                            return(blockId);
                        }
                    }
                    if (resized)
                    {
                        throw new ArgumentOutOfRangeException("length");
                    }

                    if (!rescan && _firstFreeBlock < startingFrom)
                    {
                        rescan       = true;
                        endingBefore = startingFrom + blocksNeeded - 1;
                        startingFrom = _firstFreeBlock;
                    }
                    else
                    {
                        resized      = true;
                        startingFrom = AddSection();
                        endingBefore = int.MaxValue;
                    }
                }
            }
        }