blob: dcddb8940857490e3214aa4ece9897da8a33dfc6 [file] [log] [blame]
package edu.illinois.ncsa.daffodil.processors.unparsers
import edu.illinois.ncsa.daffodil.processors.TermRuntimeData
import edu.illinois.ncsa.daffodil.processors.PrimUnparser
import edu.illinois.ncsa.daffodil.processors.parsers.DelimiterTextType
import edu.illinois.ncsa.daffodil.util.Maybe._
import edu.illinois.ncsa.daffodil.util.LogLevel
import java.nio.charset.MalformedInputException
import edu.illinois.ncsa.daffodil.util.Misc
import edu.illinois.ncsa.daffodil.exceptions.Assert
import edu.illinois.ncsa.daffodil.dsom.CompiledExpression
class DelimiterTextUnparser(erd: TermRuntimeData, delimExpr: CompiledExpression,
delimiterType: DelimiterTextType.Type)
extends PrimUnparser(erd) with TextUnparserRuntimeMixin {
override lazy val nom = {
if (delimiterType == DelimiterTextType.Initiator) "InitiatorUnparser"
else if (delimiterType == DelimiterTextType.Separator) "SeparatorUnparser"
else "TerminatorUnparser"
}
override def toBriefXML(depthLimit: Int = -1): String = {
if (depthLimit == 0) "..."
else "<" + nom + ">" + delimExpr + "</" + nom + ">"
}
def unparse(state: UState): Unit = {
setupEncoding(state, erd)
log(LogLevel.Debug, "Unparsing starting at bit position: %s", state.bitPos1b)
val localDelimNode = state.localDelimiters
val (delimDFAOpt, _ /* location */ ) = {
if (delimiterType == DelimiterTextType.Initiator) (localDelimNode.initiator, localDelimNode.initiatorLoc)
else if (delimiterType == DelimiterTextType.Separator) (localDelimNode.separator, localDelimNode.separatorLoc)
else (localDelimNode.terminator, localDelimNode.terminatorLoc)
}
if (!delimDFAOpt.isDefined) Assert.invariantFailed("Expected a delimiter of type " + delimiterType + " on the stack, but was not found.")
val delimDFA = delimDFAOpt.get
try {
val valueString = delimDFA.unparseValue
val outStream = state.dataOutputStream
val nCharsWritten = outStream.putString(valueString)
if (nCharsWritten != valueString.length)
UE(state, "%s - Too many bits in delimiter: IndexOutOfBounds. Insufficient space to write delimiter '%s'.",
nom, Misc.remapStringToVisibleGlyphs(valueString))
} catch {
// Characters in infoset element cannot be encoded without error.
//
// This won't actually be thrown until encodingErrorPolicy='error' is
// implemented.
//
case m: MalformedInputException => { UnparseError(One(erd.schemaFileLocation), One(state.currentLocation), "%s - MalformedInputException: \n%s", nom, m.getMessage()) }
}
}
}