package com.ctc.wstx.io;

import java.io.IOException;
import java.io.Reader;

import javax.xml.stream.XMLStreamException;

import com.ctc.wstx.api.ReaderConfig;
import com.ctc.wstx.util.TextBuffer;

Specialized input source that can "branch" input it reads; essentially both giving out read data AND also writing it out to a Writer.

Currently this Reader is only used as the main-level Reader, to allow for branching of internal DTD subset to a text buffer if necessary.

/** * Specialized input source that can "branch" input it reads; essentially * both giving out read data AND also writing it out to a Writer. *<p> * Currently this Reader is only used as the main-level Reader, to allow for * branching of internal DTD subset to a text buffer if necessary. */
public final class BranchingReaderSource extends ReaderSource { // // // Branching information TextBuffer mBranchBuffer = null; int mBranchStartOffset = 0; boolean mConvertLFs = false;
Flag that indicates that last char from previous buffer was '\r', and that following '\n' (if there is one) needs to be ignored.
/** * Flag that indicates that last char from previous buffer was * '\r', and that following '\n' (if there is one) needs to be * ignored. */
boolean mGotCR = false; public BranchingReaderSource(ReaderConfig cfg, String pubId, SystemId sysId, Reader r, boolean realClose) { /* null -> no parent, * null -> not from explicit entity (no id/name) */ super(cfg, null, null, pubId, sysId, r, realClose); } @Override public int readInto(WstxInputData reader) throws IOException, XMLStreamException { // Need to flush out branched content? if (mBranchBuffer != null) { if (mInputLast > mBranchStartOffset) { appendBranched(mBranchStartOffset, mInputLast); } mBranchStartOffset = 0; } return super.readInto(reader); } @Override public boolean readMore(WstxInputData reader, int minAmount) throws IOException, XMLStreamException { // Existing data to output to branch? if (mBranchBuffer != null) { int ptr = reader.mInputPtr; int currAmount = mInputLast - ptr; if (currAmount > 0) { if (ptr > mBranchStartOffset) { appendBranched(mBranchStartOffset, ptr); } mBranchStartOffset = 0; } } return super.readMore(reader, minAmount); } /* ////////////////////////////////////////////////// // Branching methods; used mostly to make a copy // of parsed internal subsets. ////////////////////////////////////////////////// */ public void startBranch(TextBuffer tb, int startOffset, boolean convertLFs) { mBranchBuffer = tb; mBranchStartOffset = startOffset; mConvertLFs = convertLFs; mGotCR = false; }
Currently this input source does not implement branching
/** * Currently this input source does not implement branching */
public void endBranch(int endOffset) { if (mBranchBuffer != null) { if (endOffset > mBranchStartOffset) { appendBranched(mBranchStartOffset, endOffset); } // Let's also make sure no branching is done from this point on: mBranchBuffer = null; } } /* ////////////////////////////////////////////////// // Internal methods ////////////////////////////////////////////////// */ private void appendBranched(int startOffset, int pastEnd) { // Main tricky thing here is just replacing of linefeeds... if (mConvertLFs) { char[] inBuf = mBuffer; /* this will also unshare() and ensure there's room for at * least one more char */ char[] outBuf = mBranchBuffer.getCurrentSegment(); int outPtr = mBranchBuffer.getCurrentSegmentSize(); // Pending \n to skip? if (mGotCR) { if (inBuf[startOffset] == '\n') { ++startOffset; } } while (startOffset < pastEnd) { char c = inBuf[startOffset++]; if (c == '\r') { if (startOffset < pastEnd) { if (inBuf[startOffset] == '\n') { ++startOffset; } } else { mGotCR = true; } c = '\n'; } // Ok, let's add char to output: outBuf[outPtr++] = c; // Need more room? if (outPtr >= outBuf.length) { outBuf = mBranchBuffer.finishCurrentSegment(); outPtr = 0; } } mBranchBuffer.setCurrentLength(outPtr); } else { mBranchBuffer.append(mBuffer, startOffset, pastEnd-startOffset); } } }