예제 #1
0
        public void Index(ushort id, ByteBlock oldValue, ByteBlock newValue)
        {
            RangeSet oldValueWords = _splitter.Split(oldValue);
            RangeSet newValueWords = _splitter.Split(newValue);

            for (int i = 0; i < oldValueWords.Count; ++i)
            {
                Range     word      = oldValueWords.Ranges[i];
                ByteBlock wordBlock = new ByteBlock(oldValue.Array, word.Index, word.Length);
                RemoveWord(id, wordBlock);
            }

            for (int i = 0; i < newValueWords.Count; ++i)
            {
                Range     word      = newValueWords.Ranges[i];
                ByteBlock wordBlock = new ByteBlock(newValue.Array, word.Index, word.Length);
                AddWord(id, wordBlock);
            }
        }
예제 #2
0
            /// <summary>
            ///  Get the IDs listed in the set for a given word and add them
            ///  to a result ShortSet.
            /// </summary>
            /// <param name="setId">ID of set/word to add</param>
            /// <param name="result">ShortSet to which to add results</param>
            public unsafe void GetInSet(ushort setId, ShortSet result)
            {
                ByteBlock set = _sets[setId];

                fixed(byte *array = set.Array)
                {
                    if (set.Length < DenseSetLengthCutoff)
                    {
                        // Sparse Set: Add values as individual ushorts.
                        ushort *valuesForWord = (ushort *)(array + set.Index);
                        ushort  usedLength    = FindUsedLength(valuesForWord, (ushort)(set.Length / 2));
                        result.Or(valuesForWord, usedLength);
                    }
                    else
                    {
                        // Dense Set: Add values as ulong bits.
                        ulong *bitsForWord = (ulong *)(array + set.Index);
                        result.Or(bitsForWord, (ushort)(set.Length / 8));
                    }
                }
            }
예제 #3
0
        /// <summary>
        ///  Return the ByteBlock representation of the current value (cached).
        /// </summary>
        /// <returns>ByteBlock equivalent of value</returns>
        private ByteBlock ToByteBlock()
        {
            if (_cachedByteBlock.IsZero())
            {
                if (_value is ByteBlock)
                {
                    _cachedByteBlock = (ByteBlock)_value;
                }
                if (_value is ValueTypeReference <ByteBlock> )
                {
                    _cachedByteBlock = (_value as ValueTypeReference <ByteBlock>).Value;
                }
                else if (_value is string)
                {
                    _cachedByteBlock = (ByteBlock)(string)_value;
                }
                else if (_value is byte[])
                {
                    _cachedByteBlock = (ByteBlock)(byte[])_value;
                }
                else if (_value is DateTime)
                {
                    _cachedByteBlock = (ByteBlock)(((DateTime)_value).ToString("u", CultureInfo.InvariantCulture));
                }
                else if (_value is ValueTypeReference <DateTime> )
                {
                    _cachedByteBlock = (ByteBlock)((_value as ValueTypeReference <DateTime>).Value.ToString("u", CultureInfo.InvariantCulture));
                }
                else
                {
                    _cachedByteBlock = (ByteBlock)_value.ToString();
                }
            }

            return(_cachedByteBlock);
        }
예제 #4
0
            /// <summary>
            ///  Add a given item to a given set.
            /// </summary>
            /// <param name="setId">SetID (WordID) of word to add item to.</param>
            /// <param name="itemId">ItemID to add for word</param>
            public unsafe void AddToSet(ushort setId, ushort itemId)
            {
                ByteBlock set = _sets[setId];

                fixed(byte *array = set.Array)
                {
                    if (set.Length < DenseSetLengthCutoff)
                    {
                        // Sparse Set: Add values as individual ushorts.
                        ushort *valuesForWord   = (ushort *)(array + set.Index);
                        ushort  availableLength = (ushort)(set.Length / 2);
                        ushort  usedLength      = FindUsedLength(valuesForWord, availableLength);

                        // If this value was already added, stop
                        if (usedLength > 0 && valuesForWord[usedLength - 1] == itemId)
                        {
                            return;
                        }

                        if (usedLength < availableLength)
                        {
                            // Set not full - append the new value
                            valuesForWord[usedLength] = itemId;
                        }
                        else
                        {
                            // Set is full - create a new one
                            if (set.Length * 2 >= DenseSetLengthCutoff)
                            {
                                // At cutoff - convert to dense set
                                byte[] newDenseBlock = new byte[ushort.MaxValue / 8];
                                fixed(byte *newArray = newDenseBlock)
                                {
                                    ulong *newBits = (ulong *)(newArray);

                                    for (int i = 0; i < usedLength; ++i)
                                    {
                                        ushort id = valuesForWord[i];
                                        newBits[id / 64] |= (ShortSet.FirstBit >> id % 64);
                                    }

                                    newBits[itemId / 64] |= (ShortSet.FirstBit >> itemId % 64);
                                }

                                _sets[setId] = newDenseBlock;
                            }
                            else
                            {
                                // Below cutoff - keep sparse set
                                byte[] newBlock = new byte[Math.Max(2, set.Length * 2)];

                                // Copy current values
                                set.CopyTo(newBlock);

                                fixed(byte *newArray = newBlock)
                                {
                                    ushort *newValues = (ushort *)newArray;

                                    // Add new value
                                    newValues[usedLength] = itemId;

                                    // Pad remainder with sentinel maxvalue
                                    for (int i = usedLength + 1; i < newBlock.Length / 2; ++i)
                                    {
                                        newValues[i] = ushort.MaxValue;
                                    }
                                }

                                _sets[setId] = newBlock;
                            }
                        }
                    }
                    else
                    {
                        // Dense Set: Turn on the bit for the value
                        ulong *bitsForWord = (ulong *)(array + set.Index);
                        bitsForWord[itemId / 64] |= (ShortSet.FirstBit >> itemId % 64);
                    }
                }
            }