in daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/dfa/TextDelimitedParser.scala [267:398]
protected def parseRemainder(
state: PState,
input: DataInputStream,
fieldEsc: DFAField,
startBlock: DFADelimiter,
endBlock: DFADelimiter,
delimIter: DelimiterIterator,
isDelimRequired: Boolean
): Maybe[ParseResult] = {
val lmt = new LongestMatchTracker()
val fieldRegister = state.dfaRegistersPool.getFromPool("parseRemainder")
fieldRegister.reset(state, input, delimIter)
var stillSearching: Boolean = true
var foundBlockEnd: Boolean = false
var beforeDelimiter: DataInputStream.MarkPos = DataInputStream.MarkPos.NoMarkPos
while (stillSearching) {
Assert.invariant(beforeDelimiter =#= DataInputStream.MarkPos.NoMarkPos)
fieldEsc.run(fieldRegister)
val dfaStatus = fieldRegister.status
beforeDelimiter =
input.markPos // at this point the input is one past the end of the field.
fieldRegister.actionNum = 0
dfaStatus match {
case StateKind.EndOfData => stillSearching = false
case StateKind.Failed => stillSearching = false
case StateKind.Paused => {
// Pick up where field left off, we are looking for the blockEnd.
val endBlockRegister = state.dfaRegistersPool.getFromPool("parseRemainder2")
endBlockRegister.reset(state, input, delimIter)
endBlock.run(endBlockRegister)
val endBlockStatus = endBlockRegister.status
state.dfaRegistersPool.returnToPool(endBlockRegister)
endBlockStatus match {
case StateKind.Succeeded => {
// Found the unescaped block end, now we need to
// find any padding.
this.removeRightPadding(state, input, delimIter)
beforeDelimiter = input.markPos
delimIter.reset()
while (delimIter.hasNext()) {
// Finally, we can look for the delimiter.
val d = delimIter.next() // Pick up where end of block/padding left off
val delimRegister = state.dfaRegistersPool.getFromPool("parseRemainder3")
input.resetPos(beforeDelimiter)
beforeDelimiter = input.markPos
delimRegister.reset(state, input, delimIter)
d.run(delimRegister)
if (delimRegister.status == StateKind.Succeeded) {
lmt.successfulMatch(
delimRegister.matchStartPos,
delimRegister.delimString,
d,
delimIter.currentIndex
)
}
state.dfaRegistersPool.returnToPool(delimRegister)
}
foundBlockEnd = true
stillSearching = false
}
case _ => {
//
// In this case we already found
// a block start, (because we're in parseRemainder)
// and we halted scanning because we found the start of a block end
// However, it turns out not to be an entire block end.
//
// So we keep going. But we have to accumulate the
// characters we were scrutinizing as the possible block end
// into the field.
//
input.resetPos(beforeDelimiter)
beforeDelimiter = DataInputStream.MarkPos.NoMarkPos
fieldRegister.resetChars(state)
// resume field parse
//
// This resumes the field dfa by moving it onto the next rule
// This assumes that the field dfa will resume properly using
// it's existing state, so long as the input is repositioned properly.
//
fieldRegister.actionNum = fieldRegister.actionNum + 1 // goto next rule
}
}
}
}
} // End While
Assert.invariant(beforeDelimiter !=#= DataInputStream.MarkPos.NoMarkPos)
input.resetPos(beforeDelimiter)
val result = {
if (lmt.longestMatches.isEmpty) {
//
// No delimiter found
// that may or may not be ok
//
if (foundBlockEnd && isDelimRequired) Nope
else if (!foundBlockEnd) Nope
else {
//
// In this case we found a block end, and no delimiter is required
// so we have enough to be done with the field
//
val fieldValue: Maybe[String] = {
One(fieldRegister.resultString.toString)
}
One(new ParseResult(fieldValue, Nope, lmt.longestMatches))
}
} else {
//
// A delimiter was found
//
val fieldValue: Maybe[String] = {
One(fieldRegister.resultString.toString)
}
val delim: Maybe[String] = {
One(lmt.longestMatchedString)
}
One(new ParseResult(fieldValue, delim, lmt.longestMatches))
}
}
state.dfaRegistersPool.returnToPool(fieldRegister)
result
}