public IfpRecord ReadIfpRecord
        (
            long offset
        )
        {
            IfpRecord result = IfpRecord.Read(Ifp, offset);

            return(result);
        }
        /// <summary>
        /// ibatrak чтение заголовка записи IFP (для подсчета количества ссылок)
        /// </summary>
        public static IfpRecord ReadLeader
        (
            Stream stream,
            long offset
        )
        {
            stream.Position = offset;

            IfpRecord result = new IfpRecord
            {
                LowOffset      = stream.ReadInt32Network(),
                HighOffset     = stream.ReadInt32Network(),
                TotalLinkCount = stream.ReadInt32Network(),
                BlockLinkCount = stream.ReadInt32Network(),
                Capacity       = stream.ReadInt32Network()
            };

            return(result);
        }
        /// <summary>
        /// Read the record.
        /// </summary>
        public static IfpRecord Read
        (
            [NotNull] Stream stream,
            long offset
        )
        {
            stream.Position = offset;

            IfpRecord result = new IfpRecord
            {
                LowOffset      = stream.ReadInt32Network(),
                HighOffset     = stream.ReadInt32Network(),
                TotalLinkCount = stream.ReadInt32Network(),
                BlockLinkCount = stream.ReadInt32Network(),
                Capacity       = stream.ReadInt32Network()
            };

            // ibatrak чтение вложенных записей в спец блоке
            // Специальный формат записи .ifp
            // В этом случае первой записью является специальный блок,
            // который представляет собой заголовок (обыкновенного формата),
            // в котором смещения имеют специальные значения = -1001
            if (result.LowOffset == -1001 && result.HighOffset == -1001)
            {
                // irbis64.dll делает так

                // читает первые 24 байта блока спец ссылок
                // (это 2 записи)
                // записи с реальными адресами идут через одну
                // берет вторую запись, адрес из нее в файле
                // и читает записеи IFP
                // по количеству result.BlockLinkCount

                // первую запись спец блока просто пропускаем,
                // читаем сразу вторую
                stream.Position += 12;

                SpecialPostingBlockEntry entry = new SpecialPostingBlockEntry
                {
                    Posting = stream.ReadInt32Network(),
                    Low     = stream.ReadInt32Network(),
                    High    = stream.ReadInt32Network()
                };

                stream.Position = entry.Offset;

                IfpRecord[] nestedRecords
                    = new IfpRecord[result.BlockLinkCount];
                for (int i = 0; i < result.BlockLinkCount; i++)
                {
                    var nestedRecord = Read(stream, stream.Position);
                    nestedRecords[i] = nestedRecord;

                    // Last record in the list must have
                    // negative offset values
                    if (nestedRecord.LowOffset == -1 &&
                        nestedRecord.HighOffset == -1)
                    {
                        if (i != result.BlockLinkCount - 1)
                        {
                            throw new InvalidOperationException
                                  (
                                      "IFP reading error"
                                  );
                        }
                        break;
                    }
                    if (nestedRecord.FullOffset < 0)
                    {
                        throw new InvalidOperationException
                              (
                                  "IFP reading error"
                              );
                    }

                    stream.Position = nestedRecord.FullOffset;
                }

                TermLink[] links = nestedRecords
                                   .SelectMany(r => r.Links)
                                   .ToArray();
                if (links.Length != result.TotalLinkCount)
                {
                    throw new InvalidOperationException
                          (
                              "IFP reading error"
                          );
                }
                result.Links.AddRange(links);

                return(result);
            }
            //ibatrak до сюда

            for (int i = 0; i < result.BlockLinkCount; i++)
            {
                TermLink link = TermLink.Read(stream);
                result.Links.Add(link);
            }

            return(result);
        }
        public TermLink[] SearchStart
        (
            [CanBeNull] string key
        )
        {
            List <TermLink> result = new List <TermLink>();

            if (string.IsNullOrEmpty(key))
            {
                return(new TermLink[0]);
            }

            key = key.ToUpperInvariant();

            NodeRecord firstNode   = ReadNode(1);
            NodeRecord rootNode    = ReadNode(firstNode.Leader.Number);
            NodeRecord currentNode = rootNode;

            NodeItem goodItem = null;

            while (true)
            {
                bool found  = false;
                bool beyond = false;

                foreach (NodeItem item in currentNode.Items)
                {
                    int compareResult = string.CompareOrdinal(item.Text, key);
                    if (compareResult > 0)
                    {
                        beyond = true;
                        break;
                    }

                    goodItem = item;
                    found    = true;
                }
                if (goodItem == null)
                {
                    break;
                }
                if (found)
                {
                    if (beyond || (currentNode.Leader.Next == -1))
                    {
                        if (goodItem.RefersToLeaf)
                        {
                            goto FOUND;
                        }
                        currentNode = ReadNode(goodItem.LowOffset);
                    }
                    else
                    {
                        currentNode = ReadNext(currentNode);
                    }
                }
                else
                {
                    if (goodItem.RefersToLeaf)
                    {
                        goto FOUND;
                    }
                    currentNode = ReadNode(goodItem.LowOffset);
                }
                //Console.WriteLine(currentNode);
            }

FOUND:
            if (goodItem != null)
            {
                currentNode = ReadLeaf(goodItem.LowOffset);
                while (true)
                {
                    foreach (NodeItem item in currentNode.Items)
                    {
                        int compareResult = string.CompareOrdinal(item.Text, key);
                        if (compareResult >= 0)
                        {
                            bool starts = item.Text.StartsWith(key);
                            if ((compareResult > 0) && !starts)
                            {
                                goto DONE;
                            }
                            if (starts)
                            {
                                IfpRecord ifp = ReadIfpRecord(item.FullOffset);
                                result.AddRange(ifp.Links);
                            }
                        }
                    }
                    if (currentNode.Leader.Next > 0)
                    {
                        currentNode = ReadNext(currentNode);
                    }
                }
            }

DONE:
            return(result
                   .Distinct()
                   .ToArray());
        }
        public TermLink[] SearchExact
        (
            [CanBeNull] string key
        )
        {
            if (string.IsNullOrEmpty(key))
            {
                return(new TermLink[0]);
            }

            key = key.ToUpperInvariant();

            NodeRecord firstNode   = ReadNode(1);
            NodeRecord rootNode    = ReadNode(firstNode.Leader.Number);
            NodeRecord currentNode = rootNode;

            NodeItem goodItem = null;

            while (true)
            {
                bool found  = false;
                bool beyond = false;

                foreach (NodeItem item in currentNode.Items)
                {
                    int compareResult = string.CompareOrdinal(item.Text, key);
                    if (compareResult > 0)
                    {
                        beyond = true;
                        break;
                    }

                    goodItem = item;
                    found    = true;

                    if ((compareResult == 0) &&
                        currentNode.IsLeaf)
                    {
                        goto FOUND;
                    }
                }
                if (goodItem == null)
                {
                    break;
                }
                if (found)
                {
                    if (beyond || (currentNode.Leader.Next == -1))
                    {
                        currentNode = goodItem.RefersToLeaf
                            ? ReadLeaf(goodItem.LowOffset)
                            : ReadNode(goodItem.LowOffset);
                    }
                    else
                    {
                        currentNode = ReadNext(currentNode);
                    }
                }
                else
                {
                    currentNode = goodItem.RefersToLeaf
                        ? ReadLeaf(goodItem.LowOffset)
                        : ReadNode(goodItem.LowOffset);
                }
                //Console.WriteLine(currentNode);
            }

FOUND:
            if (goodItem != null)
            {
                IfpRecord ifp = ReadIfpRecord(goodItem.FullOffset);
                return(ifp.Links.ToArray());
            }

            return(new TermLink[0]);
        }
Exemple #6
0
        public TermLink[] SearchExact
        (
            [CanBeNull] string key
        )
        {
            if (string.IsNullOrEmpty(key))
            {
                return(new TermLink[0]);
            }

            try
            {
                key = key.ToUpperInvariant();

                NodeRecord firstNode   = ReadNode(1);
                NodeRecord rootNode    = ReadNode(firstNode.Leader.Number);
                NodeRecord currentNode = rootNode;

                NodeItem goodItem = null;
                while (true)
                {
                    bool found  = false;
                    bool beyond = false;

                    foreach (NodeItem item in currentNode.Items)
                    {
                        int compareResult = string.CompareOrdinal(item.Text, key);
                        if (compareResult > 0)
                        {
                            beyond = true;
                            break;
                        }

                        goodItem = item;
                        found    = true;

                        if (compareResult == 0 &&
                            currentNode.IsLeaf)
                        {
                            goto FOUND;
                        }
                    }
                    if (goodItem == null)
                    {
                        break;
                    }
                    if (found)
                    {
                        if (beyond || currentNode.Leader.Next == -1)
                        {
                            currentNode = goodItem.RefersToLeaf
                                ? ReadLeaf(goodItem.LowOffset)
                                : ReadNode(goodItem.LowOffset);
                        }
                        else
                        {
                            currentNode = ReadNext(currentNode);
                        }
                    }
                    else
                    {
                        currentNode = goodItem.RefersToLeaf
                            ? ReadLeaf(goodItem.LowOffset)
                            : ReadNode(goodItem.LowOffset);
                    }
                    //Console.WriteLine(currentNode);
                }

FOUND:
                if (goodItem != null)
                {
                    // ibatrak записи могут иметь ссылки на следующие

                    List <TermLink> result = new List <TermLink>();
                    long            offset = goodItem.FullOffset;
                    while (offset > 0)
                    {
                        IfpRecord ifp = ReadIfpRecord(offset);
                        result.AddRange(ifp.Links);
                        offset = ifp.FullOffset > 0
                            ? ifp.FullOffset
                            : 0;
                    }

                    return(result
                           .Distinct()
                           .ToArray());
                    //ibatrak до сюда
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }

            return(new TermLink[0]);
        }