Esempio n. 1
0
        internal byte[] ToArray(int fcMin)
        {
            byte[] buf          = new byte[512];
            int    size         = _chpxList.Count;
            int    grpprlOffset = 511;
            int    offsetOffset = 0;
            int    fcOffset     = 0;

            // total size is currently the size of one FC
            int totalSize = FC_SIZE + 2;

            int index = 0;

            for (; index < size; index++)
            {
                int grpprlLength = (_chpxList[index]).GetGrpprl().Length;

                // check to see if we have enough room for an FC, the grpprl offset,
                // the grpprl size byte and the grpprl.
                totalSize += (FC_SIZE + 2 + grpprlLength);
                // if size is uneven we will have to add one so the first grpprl falls
                // on a word boundary
                if (totalSize > 511 + (index % 2))
                {
                    totalSize -= (FC_SIZE + 2 + grpprlLength);
                    break;
                }

                // grpprls must fall on word boundaries
                if ((1 + grpprlLength) % 2 > 0)
                {
                    totalSize += 1;
                }
            }

            // see if we couldn't fit some
            if (index != size)
            {
                _overFlow = new List <CHPX>();
                _overFlow.AddRange(_chpxList.GetRange(index, size - index));
            }

            // index should equal number of CHPXs that will be in this fkp now.
            buf[511] = (byte)index;

            offsetOffset = (FC_SIZE * index) + FC_SIZE;
            //grpprlOffset =  offsetOffset + index + (grpprlOffset % 2);

            CHPX chpx = null;

            for (int x = 0; x < index; x++)
            {
                chpx = (CHPX)_chpxList[x];
                byte[] grpprl = chpx.GetGrpprl();

                LittleEndian.PutInt(buf, fcOffset, chpx.StartBytes + fcMin);
                grpprlOffset     -= (1 + grpprl.Length);
                grpprlOffset     -= (grpprlOffset % 2);
                buf[offsetOffset] = (byte)(grpprlOffset / 2);
                buf[grpprlOffset] = (byte)grpprl.Length;
                Array.Copy(grpprl, 0, buf, grpprlOffset + 1, grpprl.Length);

                offsetOffset += 1;
                fcOffset     += FC_SIZE;
            }
            // put the last chpx's end in
            LittleEndian.PutInt(buf, fcOffset, chpx.EndBytes + fcMin);
            return(buf);
        }
Esempio n. 2
0
        public void Rebuild(ComplexFileTable complexFileTable)
        {
            long start = DateTime.Now.Ticks;

            if (complexFileTable != null)
            {
                SprmBuffer[] sprmBuffers = complexFileTable.GetGrpprls();

                // adding CHPX from fast-saved SPRMs
                foreach (TextPiece textPiece in complexFileTable.GetTextPieceTable()
                         .TextPieces)
                {
                    PropertyModifier prm = textPiece.PieceDescriptor.Prm;
                    if (!prm.IsComplex())
                    {
                        continue;
                    }
                    int igrpprl = prm.GetIgrpprl();

                    if (igrpprl < 0 || igrpprl >= sprmBuffers.Length)
                    {
                        logger.Log(POILogger.WARN, textPiece
                                   + "'s PRM references to unknown grpprl");
                        continue;
                    }

                    bool       hasChp     = false;
                    SprmBuffer sprmBuffer = sprmBuffers[igrpprl];
                    for (SprmIterator iterator = sprmBuffer.Iterator(); ; iterator
                         .HasNext())
                    {
                        SprmOperation sprmOperation = iterator.Next();
                        if (sprmOperation.Type == SprmOperation.TYPE_CHP)
                        {
                            hasChp = true;
                            break;
                        }
                    }

                    if (hasChp)
                    {
                        SprmBuffer newSprmBuffer;
                        newSprmBuffer = (SprmBuffer)sprmBuffer.Clone();


                        CHPX chpx = new CHPX(textPiece.Start,
                                             textPiece.End, newSprmBuffer);
                        _textRuns.Add(chpx);
                    }
                }
                logger.Log(POILogger.DEBUG,
                           "Merged with CHPX from complex file table in ",
                           DateTime.Now.Ticks - start,
                           " ms (", _textRuns.Count,
                           " elements in total)");
                start = DateTime.Now.Ticks;
            }

            List <CHPX> oldChpxSortedByStartPos = new List <CHPX>(_textRuns);

            oldChpxSortedByStartPos.Sort(
                (IComparer <CHPX>)PropertyNode.CHPXComparator.instance);

            logger.Log(POILogger.DEBUG, "CHPX sorted by start position in ",
                       DateTime.Now.Ticks - start, " ms");
            start = DateTime.Now.Ticks;

            Dictionary <CHPX, int> chpxToFileOrder = new Dictionary <CHPX, int>();

            int counter = 0;

            foreach (CHPX chpx in _textRuns)
            {
                chpxToFileOrder.Add(chpx, counter++);
            }


            logger.Log(POILogger.DEBUG, "CHPX's order map created in ",
                       DateTime.Now.Ticks - start, " ms");
            start = DateTime.Now.Ticks;

            List <int> textRunsBoundariesList;

            List <int> textRunsBoundariesSet = new List <int>();

            foreach (CHPX chpx in _textRuns)
            {
                textRunsBoundariesSet.Add(chpx.Start);
                textRunsBoundariesSet.Add(chpx.End);
            }
            textRunsBoundariesSet.Remove(0);
            textRunsBoundariesList = new List <int>(
                textRunsBoundariesSet);
            textRunsBoundariesList.Sort();


            logger.Log(POILogger.DEBUG, "Texts CHPX boundaries collected in ",
                       DateTime.Now.Ticks - start, " ms");
            start = DateTime.Now.Ticks;

            List <CHPX> newChpxs         = new List <CHPX>();
            int         lastTextRunStart = 0;

            foreach (int objBoundary in textRunsBoundariesList)
            {
                int boundary = objBoundary;

                int startInclusive = lastTextRunStart;
                int endExclusive   = boundary;
                lastTextRunStart = endExclusive;

                int startPosition = BinarySearch(oldChpxSortedByStartPos, boundary);
                startPosition = Math.Abs(startPosition);
                while (startPosition >= oldChpxSortedByStartPos.Count)
                {
                    startPosition--;
                }
                while (startPosition > 0 &&
                       oldChpxSortedByStartPos[startPosition].Start >= boundary)
                {
                    startPosition--;
                }

                List <CHPX> chpxs = new List <CHPX>();
                for (int c = startPosition; c < oldChpxSortedByStartPos.Count; c++)
                {
                    CHPX chpx = oldChpxSortedByStartPos[c];

                    if (boundary < chpx.Start)
                    {
                        break;
                    }

                    int left  = Math.Max(startInclusive, chpx.Start);
                    int right = Math.Min(endExclusive, chpx.End);

                    if (left < right)
                    {
                        chpxs.Add(chpx);
                    }
                }

                if (chpxs.Count == 0)
                {
                    logger.Log(POILogger.WARN, "Text piece [",
                               startInclusive, "; ",
                               endExclusive,
                               ") has no CHPX. Creating new one.");
                    // create it manually
                    CHPX chpx = new CHPX(startInclusive, endExclusive,
                                         new SprmBuffer(0));
                    newChpxs.Add(chpx);
                    continue;
                }

                if (chpxs.Count == 1)
                {
                    // can we reuse existing?
                    CHPX existing = chpxs[0];
                    if (existing.Start == startInclusive &&
                        existing.End == endExclusive)
                    {
                        newChpxs.Add(existing);
                        continue;
                    }
                }
                CHPXToFileComparer chpxFileOrderComparator = new CHPXToFileComparer(chpxToFileOrder);
                chpxs.Sort(chpxFileOrderComparator);

                SprmBuffer sprmBuffer = new SprmBuffer(0);
                foreach (CHPX chpx in chpxs)
                {
                    sprmBuffer.Append(chpx.GetGrpprl(), 0);
                }
                CHPX newChpx = new CHPX(startInclusive, endExclusive, sprmBuffer);
                newChpxs.Add(newChpx);

                continue;
            }
            this._textRuns = new List <CHPX>(newChpxs);

            logger.Log(POILogger.DEBUG, "CHPX rebuilded in ",
                       DateTime.Now.Ticks - start, " ms (",
                       _textRuns.Count, " elements)");
            start = DateTime.Now.Ticks;

            CHPX previous = null;

            for (int iterator = _textRuns.Count; iterator != 0;)
            {
                CHPX current = previous;

                previous = _textRuns[--iterator];
                if (current == null)
                {
                    continue;
                }

                if (previous.End == current.Start &&
                    Arrays
                    .Equals(previous.GetGrpprl(), current.GetGrpprl()))
                {
                    previous.End = current.End;
                    _textRuns.Remove(current);
                    continue;
                }

                previous = current;
            }

            logger.Log(POILogger.DEBUG, "CHPX compacted in ",
                       DateTime.Now.Ticks - start, " ms (",
                       _textRuns.Count, " elements)");
        }