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); }
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)"); }