You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by ja...@apache.org on 2018/07/09 16:04:10 UTC
[incubator-daffodil] 01/01: Implemented Zoned Decimal formats
This is an automated email from the ASF dual-hosted git repository.
jadams pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-daffodil.git
commit 098b3d54e6bc6d60ffbb612e912ee2daec83dcca
Author: Josh Adams <ja...@tresys.com>
AuthorDate: Thu Apr 5 08:36:50 2018 -0400
Implemented Zoned Decimal formats
This commit implements parsers and unparsers for the following Zoned
Decimal formats:
- asciiStandard
- asciiTranslatedEBCDIC
- asciiCARealiaModified
- asciiTandemModified
The one caveat to this support is that due to the DecimalFormat library
we use P/V symbols, which are used to indicate decimal point position in
dfdl:textNumberPattern, are not supported and therefore we currently
cannot support Zoned Decimal numbers that have a decimal point.
DAFFODIL-1738
---
.../daffodil/grammar/ElementBaseGrammarMixin.scala | 56 ++-
.../grammar/primitives/PrimitivesTextNumber.scala | 4 +-
.../grammar/primitives/PrimitivesZoned.scala | 197 +++++++-
.../org/apache/daffodil/util/DecimalUtils.scala | 154 +++++-
.../apache/daffodil/util/TestDecimalUtils.scala | 515 ++++++++++++++++++++-
.../apache/daffodil/xsd/DFDL_part1_simpletypes.xsd | 1 +
.../unparsers/ConvertZonedNumberUnparser.scala | 72 +++
.../processors/parsers/PrimitivesTextNumber1.scala | 34 +-
.../processors/parsers/ZonedTextParsers.scala | 92 +++-
.../org/apache/daffodil/section13/zoned/zoned.tdml | 427 +++++++++++++++++
.../daffodil/section13/zoned/TestZoned.scala | 69 +++
11 files changed, 1578 insertions(+), 43 deletions(-)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala
index 76c4be2..e83e40a 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala
@@ -67,6 +67,18 @@ import org.apache.daffodil.grammar.primitives.ConvertTextUnsignedBytePrim
import org.apache.daffodil.grammar.primitives.ConvertTextUnsignedIntPrim
import org.apache.daffodil.grammar.primitives.ConvertTextUnsignedLongPrim
import org.apache.daffodil.grammar.primitives.ConvertTextUnsignedShortPrim
+import org.apache.daffodil.grammar.primitives.ConvertZonedBytePrim
+import org.apache.daffodil.grammar.primitives.ConvertZonedCombinator
+import org.apache.daffodil.grammar.primitives.ConvertZonedDecimalPrim
+import org.apache.daffodil.grammar.primitives.ConvertZonedIntPrim
+import org.apache.daffodil.grammar.primitives.ConvertZonedIntegerPrim
+import org.apache.daffodil.grammar.primitives.ConvertZonedLongPrim
+import org.apache.daffodil.grammar.primitives.ConvertZonedNonNegativeIntegerPrim
+import org.apache.daffodil.grammar.primitives.ConvertZonedShortPrim
+import org.apache.daffodil.grammar.primitives.ConvertZonedUnsignedBytePrim
+import org.apache.daffodil.grammar.primitives.ConvertZonedUnsignedIntPrim
+import org.apache.daffodil.grammar.primitives.ConvertZonedUnsignedLongPrim
+import org.apache.daffodil.grammar.primitives.ConvertZonedUnsignedShortPrim
import org.apache.daffodil.grammar.primitives.DelimiterStackCombinatorElement
import org.apache.daffodil.grammar.primitives.DynamicEscapeSchemeCombinatorElement
import org.apache.daffodil.grammar.primitives.ElementCombinator
@@ -112,7 +124,6 @@ import org.apache.daffodil.grammar.primitives.StringDelimitedEndOfData
import org.apache.daffodil.grammar.primitives.StringOfSpecifiedLength
import org.apache.daffodil.grammar.primitives.Terminator
import org.apache.daffodil.grammar.primitives.TrailingSkipRegion
-import org.apache.daffodil.grammar.primitives.ZonedTextIntPrim
import org.apache.daffodil.processors.TextJustificationType
import org.apache.daffodil.schema.annotation.props.Found
import org.apache.daffodil.schema.annotation.props.NotFound
@@ -552,43 +563,43 @@ trait ElementBaseGrammarMixin
}
private lazy val textByte = prod("textByte", impliedRepresentation == Representation.Text) {
- standardTextByte || zonedTextInt
+ standardTextByte || zonedTextByte
}
private lazy val textShort = prod("textShort", impliedRepresentation == Representation.Text) {
- standardTextShort || zonedTextInt
+ standardTextShort || zonedTextShort
}
private lazy val textLong = prod("textLong", impliedRepresentation == Representation.Text) {
- standardTextLong || zonedTextInt
+ standardTextLong || zonedTextLong
}
private lazy val textInteger = prod("textInteger", impliedRepresentation == Representation.Text) {
- standardTextInteger || zonedTextInt
+ standardTextInteger || zonedTextInteger
}
private lazy val textDecimal = prod("textDecimal", impliedRepresentation == Representation.Text) {
- standardTextDecimal || zonedTextInt
+ standardTextDecimal || zonedTextDecimal
}
private lazy val textNonNegativeInteger = prod("textNonNegativeInteger", impliedRepresentation == Representation.Text) {
- standardTextNonNegativeInteger || zonedTextInt
+ standardTextNonNegativeInteger || zonedTextNonNegativeInteger
}
private lazy val textUnsignedInt = prod("textUnsignedInt", impliedRepresentation == Representation.Text) {
- standardTextUnsignedInt || zonedTextInt
+ standardTextUnsignedInt || zonedTextUnsignedInt
}
private lazy val textUnsignedByte = prod("textUnsignedByte", impliedRepresentation == Representation.Text) {
- standardTextUnsignedByte || zonedTextInt
+ standardTextUnsignedByte || zonedTextUnsignedByte
}
private lazy val textUnsignedShort = prod("textUnsignedShort", impliedRepresentation == Representation.Text) {
- standardTextUnsignedShort || zonedTextInt
+ standardTextUnsignedShort || zonedTextUnsignedShort
}
private lazy val textUnsignedLong = prod("textUnsignedLong", impliedRepresentation == Representation.Text) {
- standardTextUnsignedLong || zonedTextInt
+ standardTextUnsignedLong || zonedTextUnsignedLong
}
//
@@ -617,8 +628,29 @@ trait ElementBaseGrammarMixin
textNumberRep == TextNumberRep.Standard) { ConvertTextCombinator(this, stringValue, ConvertTextUnsignedShortPrim(this)) }
private lazy val standardTextUnsignedByte = prod("standardTextUnsignedByte",
textNumberRep == TextNumberRep.Standard) { ConvertTextCombinator(this, stringValue, ConvertTextUnsignedBytePrim(this)) }
+
+ private lazy val zonedTextInteger = prod("zonedTextInteger",
+ textNumberRep == TextNumberRep.Zoned) { ConvertZonedCombinator(this, stringValue, ConvertZonedIntegerPrim(this)) }
+ private lazy val zonedTextDecimal = prod("zonedTextDecimal",
+ textNumberRep == TextNumberRep.Zoned) { ConvertZonedCombinator(this, stringValue, ConvertZonedDecimalPrim(this)) }
+ private lazy val zonedTextNonNegativeInteger = prod("zonedTextNonNegativeInteger",
+ textNumberRep == TextNumberRep.Zoned) { ConvertZonedCombinator(this, stringValue, ConvertZonedNonNegativeIntegerPrim(this)) }
+ private lazy val zonedTextLong = prod("zonedTextLong",
+ textNumberRep == TextNumberRep.Zoned) { ConvertZonedCombinator(this, stringValue, ConvertZonedLongPrim(this)) }
private lazy val zonedTextInt = prod("zonedTextInt",
- textNumberRep == TextNumberRep.Zoned) { ZonedTextIntPrim(this) }
+ textNumberRep == TextNumberRep.Zoned) { ConvertZonedCombinator(this, stringValue, ConvertZonedIntPrim(this)) }
+ private lazy val zonedTextShort = prod("zonedTextShort",
+ textNumberRep == TextNumberRep.Zoned) { ConvertZonedCombinator(this, stringValue, ConvertZonedShortPrim(this)) }
+ private lazy val zonedTextByte = prod("zonedTextByte",
+ textNumberRep == TextNumberRep.Zoned) { ConvertZonedCombinator(this, stringValue, ConvertZonedBytePrim(this)) }
+ private lazy val zonedTextUnsignedLong = prod("zonedTextUnsignedLong",
+ textNumberRep == TextNumberRep.Zoned) { ConvertZonedCombinator(this, stringValue, ConvertZonedUnsignedLongPrim(this)) }
+ private lazy val zonedTextUnsignedInt = prod("zonedTextUnsignedInt",
+ textNumberRep == TextNumberRep.Zoned) { ConvertZonedCombinator(this, stringValue, ConvertZonedUnsignedIntPrim(this)) }
+ private lazy val zonedTextUnsignedShort = prod("zonedTextUnsignedShort",
+ textNumberRep == TextNumberRep.Zoned) { ConvertZonedCombinator(this, stringValue, ConvertZonedUnsignedShortPrim(this)) }
+ private lazy val zonedTextUnsignedByte = prod("zonedTextUnsignedByte",
+ textNumberRep == TextNumberRep.Zoned) { ConvertZonedCombinator(this, stringValue, ConvertZonedUnsignedBytePrim(this)) }
private lazy val textDouble = prod("textDouble", impliedRepresentation == Representation.Text) {
standardTextDouble || zonedTextDouble
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesTextNumber.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesTextNumber.scala
index 7907797..84a9f1c 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesTextNumber.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesTextNumber.scala
@@ -132,7 +132,7 @@ abstract class ConvertTextNumberPrim[S](e: ElementBase)
new NumberFormatFactoryStatic[S](e.termRuntimeData, h,
decSep,
groupSep,
- e.textStandardExponentRepEv,
+ One(e.textStandardExponentRepEv),
infRep,
nanRep,
e.textNumberCheckPolicy,
@@ -144,7 +144,7 @@ abstract class ConvertTextNumberPrim[S](e: ElementBase)
new NumberFormatFactoryDynamic[S](e.termRuntimeData, h,
decSep,
groupSep,
- e.textStandardExponentRepEv,
+ One(e.textStandardExponentRepEv),
infRep,
nanRep,
e.textNumberCheckPolicy,
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesZoned.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesZoned.scala
index ecad042..6a8e684 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesZoned.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesZoned.scala
@@ -17,13 +17,196 @@
package org.apache.daffodil.grammar.primitives
-import org.apache.daffodil.dsom.ElementBase
+import org.apache.daffodil.dsom._
+import org.apache.daffodil.dpath.NodeInfo.PrimType
+import org.apache.daffodil.grammar.Gram
+import org.apache.daffodil.grammar.Terminal
+import com.ibm.icu.text.DecimalFormat
+import org.apache.daffodil.processors.unparsers.Unparser
+import org.apache.daffodil.processors.unparsers.ConvertZonedNumberUnparser
+import org.apache.daffodil.processors.unparsers.ConvertZonedCombinatorUnparser
+import org.apache.daffodil.processors.parsers.Parser
+import org.apache.daffodil.processors.parsers.ConvertZonedNumberParser
+import org.apache.daffodil.processors.parsers.ConvertZonedCombinatorParser
+import org.apache.daffodil.processors.parsers.ConvertTextByteParserUnparserHelper
+import org.apache.daffodil.processors.parsers.ConvertTextDecimalParserUnparserHelper
+import org.apache.daffodil.processors.parsers.ConvertTextIntParserUnparserHelper
+import org.apache.daffodil.processors.parsers.ConvertTextIntegerParserUnparserHelper
+import org.apache.daffodil.processors.parsers.ConvertTextLongParserUnparserHelper
+import org.apache.daffodil.processors.parsers.ConvertTextNonNegativeIntegerParserUnparserHelper
+import org.apache.daffodil.processors.parsers.ConvertTextNumberParserUnparserHelperBase
+import org.apache.daffodil.processors.parsers.ConvertTextShortParserUnparserHelper
+import org.apache.daffodil.processors.parsers.ConvertTextUnsignedByteParserUnparserHelper
+import org.apache.daffodil.processors.parsers.ConvertTextUnsignedLongParserUnparserHelper
+import org.apache.daffodil.processors.parsers.ConvertTextUnsignedShortParserUnparserHelper
+import org.apache.daffodil.processors.parsers.ConvertTextUnsignedIntParserUnparserHelper
+import org.apache.daffodil.processors.parsers.NumberFormatFactoryBase
+import org.apache.daffodil.processors.parsers.NumberFormatFactoryStatic
+import org.apache.daffodil.schema.annotation.props.gen.TextNumberCheckPolicy
+import org.apache.daffodil.schema.annotation.props.gen.TextNumberRounding
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.util.Maybe._
+import org.apache.daffodil.util.MaybeDouble
+import org.apache.daffodil.util.DecimalUtils.OverpunchLocation
-abstract class ZonedTextNumberPrim(e: ElementBase, guard: Boolean) extends UnimplementedPrimitive(e, guard) {
- // lazy val parser: DaffodilParser = new ZonedTextNumberParser(e.elementRuntimeData)
+import java.math.{ BigDecimal => JBigDecimal }
+import java.math.{ BigInteger => JBigInt }
+
+case class ConvertZonedCombinator(e: ElementBase, value: Gram, converter: Gram)
+ extends Terminal(e, !(value.isEmpty || converter.isEmpty)) {
+
+ override lazy val parser = new ConvertZonedCombinatorParser(e.termRuntimeData, value.parser, converter.parser)
+
+ override lazy val unparser = new ConvertZonedCombinatorUnparser(e.termRuntimeData, value.unparser, converter.unparser)
}
-case class ZonedTextBytePrim(el: ElementBase) extends ZonedTextNumberPrim(el, false)
-case class ZonedTextShortPrim(el: ElementBase) extends ZonedTextNumberPrim(el, false)
-case class ZonedTextIntPrim(el: ElementBase) extends ZonedTextNumberPrim(el, false)
-case class ZonedTextLongPrim(el: ElementBase) extends ZonedTextNumberPrim(el, false)
+abstract class ConvertZonedNumberPrim[S](e: ElementBase)
+ extends Terminal(e, true) {
+
+ def helper: ConvertTextNumberParserUnparserHelperBase[S]
+
+ def numFormatFactory: NumberFormatFactoryBase[S] = {
+ val h = helper
+
+ val pattern = {
+ val p = e.textNumberPattern
+
+ val noEscapedTicksRegex = """''""".r
+ val patternNoEscapedTicks = noEscapedTicksRegex.replaceAllIn(p, "")
+ val noQuotedRegex = """'[^']+'""".r
+ val patternNoQuoted = noQuotedRegex.replaceAllIn(patternNoEscapedTicks, "")
+ val zonedPatternRegex = "\\+?#*[0-9]+\\+?".r
+
+ if (patternNoQuoted.contains("V")) {
+ e.notYetImplemented("textNumberPattern with V symbol")
+ }
+
+ if (patternNoQuoted.contains("P")) {
+ e.notYetImplemented("textNumberPattern with P symbol")
+ }
+
+ if (patternNoQuoted.contains("@")) {
+ e.SDE("The '@' symbol may not be used in textNumberPattern for textNumberRep='zoned'")
+ }
+
+ if (patternNoQuoted.contains(";")) {
+ e.SDE("Negative patterns may not be used in textNumberPattern for textNumberRep='zoned'")
+ }
+
+ e.primType match {
+ case PrimType.Double | PrimType.Float => e.SDE("textZonedFormat='zoned' does not support Doubles/Floats")
+ case PrimType.UnsignedLong | PrimType.UnsignedInt | PrimType.UnsignedShort | PrimType.UnsignedByte => {
+ if (e.textNumberCheckPolicy == TextNumberCheckPolicy.Lax) {
+ if ((patternNoQuoted(0) != '+') && (patternNoQuoted(patternNoQuoted.length - 1) != '+'))
+ e.SDE("textNumberPattern must have '+' at the beginning or the end of the pattern when textZonedFormat='zoned' and textNumberPolicy='lax' for unsigned numbers")
+ }
+ }
+ case _ => {
+ if ((patternNoQuoted(0) != '+') && (patternNoQuoted(patternNoQuoted.length - 1) != '+'))
+ e.SDE("textNumberPattern must have '+' at the beginning or the end of the pattern when textZonedFormat='zoned' for signed numbers")
+ }
+ }
+
+ if ((patternNoQuoted(0) == '+') && (patternNoQuoted(patternNoQuoted.length - 1) == '+'))
+ e.SDE("The textNumberPattern may either begin or end with a '+', not both.")
+
+ if (!zonedPatternRegex.pattern.matcher(patternNoQuoted).matches)
+ e.SDE("Invalid characters used in textNubmerPattern for zoned number. Only the following characters may be used with zoned numbers: '+', 'V', 'P', '0-9', and '#'")
+
+ // Load the pattern to make sure it is valid
+ try {
+ new DecimalFormat(p.replace("+", ""))
+ } catch {
+ case ex: IllegalArgumentException => e.SDE("Invalid textNumberPattern: " + ex.getMessage())
+ }
+
+ p
+ }
+
+ /* Need to remove the '+' from the number pattern as '+' is only
+ * used to indicate which digit of the number is overpunched when
+ * dealing with zoned decimal formats. If the '+' is not removed
+ * DecimalFormat will attempt to use it as an indicator for exponent
+ * numbers, which will most likely not match the zoned number being
+ * parsed */
+ val zonedPattern = pattern.replace("+", "")
+
+ val (roundingIncrement, roundingMode) =
+ e.textNumberRounding match {
+ case TextNumberRounding.Explicit => (MaybeDouble(e.textNumberRoundingIncrement), One(e.textNumberRoundingMode))
+ case TextNumberRounding.Pattern => (MaybeDouble.Nope, Nope)
+ }
+
+ val nff = new NumberFormatFactoryStatic[S](
+ e.termRuntimeData, h,
+ Maybe.Nope,
+ Maybe.Nope,
+ Maybe.Nope,
+ Maybe.Nope,
+ Maybe.Nope,
+ e.textNumberCheckPolicy,
+ zonedPattern,
+ e.textNumberRounding,
+ roundingMode,
+ roundingIncrement)
+ nff
+ }
+
+ val opindex = e.textNumberPattern.indexOf('+')
+ val opl = {
+ if (opindex == 0)
+ OverpunchLocation.Start
+ else if (opindex == e.textNumberPattern.length - 1)
+ OverpunchLocation.End
+ else
+ OverpunchLocation.None
+ }
+
+ lazy val parser: Parser = new ConvertZonedNumberParser[S](helper, opl, numFormatFactory, e.textZonedSignStyle, e.elementRuntimeData)
+
+ override lazy val unparser: Unparser = new ConvertZonedNumberUnparser[S](helper, opl, e.textZonedSignStyle, e.elementRuntimeData)
+}
+
+case class ConvertZonedIntegerPrim(e: ElementBase) extends ConvertZonedNumberPrim[JBigInt](e) {
+ val helper = new ConvertTextIntegerParserUnparserHelper[JBigInt](List(), false)
+}
+
+case class ConvertZonedDecimalPrim(e: ElementBase) extends ConvertZonedNumberPrim[JBigDecimal](e) {
+ val helper = new ConvertTextDecimalParserUnparserHelper[JBigDecimal](List(), false)
+}
+
+case class ConvertZonedNonNegativeIntegerPrim(e: ElementBase) extends ConvertZonedNumberPrim[JBigInt](e) {
+ val helper = new ConvertTextNonNegativeIntegerParserUnparserHelper[JBigDecimal](List(), false)
+}
+
+case class ConvertZonedLongPrim(e: ElementBase) extends ConvertZonedNumberPrim[Long](e) {
+ val helper = new ConvertTextLongParserUnparserHelper[Long](List(), false)
+}
+
+case class ConvertZonedIntPrim(e: ElementBase) extends ConvertZonedNumberPrim[Int](e) {
+ val helper = new ConvertTextIntParserUnparserHelper[Int](List(), false)
+}
+
+case class ConvertZonedShortPrim(e: ElementBase) extends ConvertZonedNumberPrim[Short](e) {
+ val helper = new ConvertTextShortParserUnparserHelper[Short](List(), false)
+}
+
+case class ConvertZonedBytePrim(e: ElementBase) extends ConvertZonedNumberPrim[Byte](e) {
+ val helper = new ConvertTextByteParserUnparserHelper[Byte](List(), false)
+}
+
+case class ConvertZonedUnsignedLongPrim(e: ElementBase) extends ConvertZonedNumberPrim[JBigInt](e) {
+ val helper = new ConvertTextUnsignedLongParserUnparserHelper[JBigInt](List(), false)
+}
+
+case class ConvertZonedUnsignedIntPrim(e: ElementBase) extends ConvertZonedNumberPrim[Long](e) {
+ val helper = ConvertTextUnsignedIntParserUnparserHelper[Long](List(), false)
+}
+
+case class ConvertZonedUnsignedShortPrim(e: ElementBase) extends ConvertZonedNumberPrim[Int](e) {
+ val helper = new ConvertTextUnsignedShortParserUnparserHelper[Int](List(), false)
+}
+
+case class ConvertZonedUnsignedBytePrim(e: ElementBase) extends ConvertZonedNumberPrim[Short](e) {
+ val helper = new ConvertTextUnsignedByteParserUnparserHelper[Short](List(), false)
+}
diff --git a/daffodil-lib/src/main/scala/org/apache/daffodil/util/DecimalUtils.scala b/daffodil-lib/src/main/scala/org/apache/daffodil/util/DecimalUtils.scala
index a6e452c..9acbac6 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/util/DecimalUtils.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/util/DecimalUtils.scala
@@ -19,6 +19,7 @@ package org.apache.daffodil.util
import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.schema.annotation.props.gen.BinaryNumberCheckPolicy
+import org.apache.daffodil.schema.annotation.props.gen.TextZonedSignStyle
import java.math.{ BigInteger => JBigInteger, BigDecimal => JBigDecimal }
@@ -111,7 +112,7 @@ object DecimalUtils {
}
def packedToBigDecimal(num: Array[Byte], scale: Int, signCodes: PackedSignCodes): JBigDecimal = {
- return new JBigDecimal(packedToBigInteger(num, signCodes), scale)
+ new JBigDecimal(packedToBigInteger(num, signCodes), scale)
}
def packedFromBigInteger(bigInt: JBigInteger, minLengthInBits: Int, signCodes: PackedSignCodes): Array[Byte] = {
@@ -335,4 +336,155 @@ object DecimalUtils {
outArray
}
+ def convertFromAsciiStandard(digit: Char): (Int, Boolean) = {
+ if ((digit >= '0') && (digit <= '9')) // positive 0-9
+ (digit - 48, false)
+ else if ((digit >= 'p') && (digit <= 'y')) // negative 0-9
+ (digit - 112, true)
+ else
+ throw new NumberFormatException("Invalid zoned digit: " + digit)
+ }
+
+ def convertToAsciiStandard(digit: Char, positive: Boolean): Char = {
+ if (positive)
+ digit
+ else
+ (digit + 64).asInstanceOf[Char]
+ }
+
+ def convertFromAsciiTranslatedEBCDIC(digit: Char): (Int, Boolean) = {
+ if (digit == '{')
+ (0, false)
+ else if (digit == '}')
+ (0, true)
+ else if ((digit >= 'A') && (digit <= 'I')) // positive 1-9
+ (digit - 64, false)
+ else if ((digit >= 'J') && (digit <= 'R')) // negative 1-9
+ (digit - 73, true)
+ else if ((digit >= '0') && (digit <= '9'))
+ (digit - 48, false) // non-overpunched digit
+ else
+ throw new NumberFormatException("Invalid zoned digit: " + digit)
+ }
+
+ def convertToAsciiTranslatedEBCDIC(digit: Char, positive: Boolean): Char = {
+ if (positive) {
+ if (digit == '0')
+ '{'
+ else
+ (digit + 16).asInstanceOf[Char]
+ } else {
+ if (digit == '0')
+ '}'
+ else
+ (digit + 25).asInstanceOf[Char]
+ }
+ }
+
+ def convertFromAsciiCARealiaModified(digit: Char): (Int, Boolean) = {
+ if ((digit >= '0') && (digit <= '9')) // positive 0-9
+ (digit - 48, false)
+ else if ((digit >= ' ') && (digit <= ')')) // negative 0-9
+ (digit - 32, true)
+ else
+ throw new NumberFormatException("Invalid zoned digit: " + digit)
+ }
+
+ def convertToAsciiCARealiaModified(digit: Char, positive: Boolean): Char = {
+ if (positive)
+ digit
+ else
+ (digit - 16).asInstanceOf[Char]
+ }
+
+ def convertFromAsciiTandemModified(digit: Char): (Int, Boolean) = {
+ if ((digit >= '0') && (digit <= '9')) // positive 0-9
+ (digit - 48, false)
+ else if ((digit >= 128) && (digit <= 137)) // negative 0-9
+ (digit - 128, true)
+ else
+ throw new NumberFormatException("Invalid zoned digit: " + digit)
+ }
+
+ def convertToAsciiTandemModified(digit: Char, positive: Boolean): Char = {
+ if (positive)
+ digit
+ else
+ (digit + 80).asInstanceOf[Char]
+ }
+
+ object OverpunchLocation extends Enumeration {
+ type OverpunchLocation = Value
+ val Start, End, None = Value
+ }
+
+ def zonedToNumber(num: String, zonedStyle: TextZonedSignStyle, opl: OverpunchLocation.Value): String = {
+ val opindex = opl match {
+ case OverpunchLocation.Start => 0
+ case OverpunchLocation.End => num.length - 1
+ case _ => -1
+ }
+
+ val decodedValue = {
+ if (opl == OverpunchLocation.None) {
+ num
+ } else {
+ val (digit, opneg) = zonedStyle match {
+ case TextZonedSignStyle.AsciiStandard => convertFromAsciiStandard(num(opindex))
+ case TextZonedSignStyle.AsciiTranslatedEBCDIC => convertFromAsciiTranslatedEBCDIC(num(opindex))
+ case TextZonedSignStyle.AsciiCARealiaModified => convertFromAsciiCARealiaModified(num(opindex))
+ case TextZonedSignStyle.AsciiTandemModified => convertFromAsciiTandemModified(num(opindex))
+ }
+
+ val convertedNum = (opneg, opl) match {
+ case (true, OverpunchLocation.Start) => "-" + digit + num.substring(1)
+ case (false, OverpunchLocation.Start) => digit + num.substring(1)
+ case (true, OverpunchLocation.End) => "-" + num.substring(0, opindex) + digit
+ case (false, OverpunchLocation.End) => num.substring(0, opindex) + digit
+ case _ => Assert.impossible()
+ }
+
+ convertedNum
+ }
+ }
+
+ decodedValue
+ }
+
+ def zonedFromNumber(num: String, zonedStyle: TextZonedSignStyle, opl: OverpunchLocation.Value): String = {
+ val positive = (num.charAt(0) != '-')
+ val inStr = positive match {
+ case true => num
+ case false => num.substring(1)
+ }
+ val opindex = opl match {
+ case OverpunchLocation.Start => 0
+ case OverpunchLocation.End => inStr.length - 1
+ case _ => -1
+ }
+
+ val encodedValue = {
+ if (opl == OverpunchLocation.None) {
+ if (!positive) Assert.impossible()
+ inStr
+ } else {
+ val digit = zonedStyle match {
+ case TextZonedSignStyle.AsciiStandard => convertToAsciiStandard(inStr(opindex), positive)
+ case TextZonedSignStyle.AsciiTranslatedEBCDIC => convertToAsciiTranslatedEBCDIC(inStr(opindex), positive)
+ case TextZonedSignStyle.AsciiCARealiaModified => convertToAsciiCARealiaModified(inStr(opindex), positive)
+ case TextZonedSignStyle.AsciiTandemModified => convertToAsciiTandemModified(inStr(opindex), positive)
+ }
+
+ val convertedNum = opl match {
+ case OverpunchLocation.Start => digit + inStr.substring(1)
+ case OverpunchLocation.End => inStr.substring(0, opindex) + digit
+ case _ => Assert.impossible()
+ }
+
+ convertedNum
+ }
+ }
+
+ encodedValue
+ }
}
diff --git a/daffodil-lib/src/test/scala/org/apache/daffodil/util/TestDecimalUtils.scala b/daffodil-lib/src/test/scala/org/apache/daffodil/util/TestDecimalUtils.scala
index 74cb96e..2f8b94b 100644
--- a/daffodil-lib/src/test/scala/org/apache/daffodil/util/TestDecimalUtils.scala
+++ b/daffodil-lib/src/test/scala/org/apache/daffodil/util/TestDecimalUtils.scala
@@ -18,7 +18,7 @@
package org.apache.daffodil.util
import org.apache.daffodil.util.DecimalUtils._
-import org.apache.daffodil.schema.annotation.props.gen.BinaryNumberCheckPolicy
+import org.apache.daffodil.schema.annotation.props.gen.{ BinaryNumberCheckPolicy, TextZonedSignStyle }
import java.math.{ BigInteger => JBigInteger, BigDecimal => JBigDecimal }
import org.junit.Test
@@ -1249,4 +1249,517 @@ class TestDecimalUtils {
case nfe: NumberFormatException => assertTrue(nfe.getMessage().contains("Invalid low nibble"))
}
}
+
+ @Test def zonedIntAsciiStandardPos1() {
+ val num = "1"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start)
+ assertEquals(result, "1")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiStandardPos2() {
+ val num = "12"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard, OverpunchLocation.End)
+ System.out.println("Result: " + result)
+ assertEquals(result, "12")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiStandardPos3() {
+ val num = "123"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard, OverpunchLocation.None)
+ assertEquals(result, "123")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.None), num)
+ }
+
+ @Test def zonedIntAsciiStandardPos4() {
+ val num = "1234567890"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start)
+ assertEquals(result, "1234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiStandardPos5() {
+ val num = "000000000001234567890"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start)
+ assertEquals(result, "000000000001234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "000000000001234567890")
+ }
+
+ @Test def zonedIntAsciiStandardNeg1() {
+ val num = "q"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start)
+ assertEquals(result, "-1")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiStandardNeg2() {
+ val num = "1r"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard, OverpunchLocation.End)
+ assertEquals(result, "-12")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiStandardNeg3() {
+ val num = "q23"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start)
+ assertEquals(result, "-123")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiStandardNeg4() {
+ val num = "123456789p"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard, OverpunchLocation.End)
+ assertEquals(result, "-1234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiStandardNeg5() {
+ val num = "p00000000001234567890"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start)
+ assertEquals(result, "-000000000001234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiStandardInvalidDigit() {
+ val num = "z123"
+ try {
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start)
+ assertEquals(result, "-0123")
+ } catch {
+ case nfe: NumberFormatException => assertTrue(nfe.getMessage().contains("Invalid zoned digit"))
+ }
+ }
+
+ @Test def zonedIntAsciiTranslatedEBCDICPos1() {
+ val num = "A"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start)
+ assertEquals(result, "1")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiTranslatedEBCDICPos2() {
+ val num = "1B"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End)
+ assertEquals(result, "12")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiTranslatedEBCDICPos3() {
+ val num = "123"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None)
+ assertEquals(result, "123")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), num)
+ }
+
+ @Test def zonedIntAsciiTranslatedEBCDICPos4() {
+ val num = "A234567890"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start)
+ assertEquals(result, "1234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiTranslatedEBCDICPos5() {
+ val num = "00000000000123456789{"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End)
+ assertEquals(result, "000000000001234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiTranslatedEBCDICNeg1() {
+ val num = "J"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start)
+ assertEquals(result, "-1")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiTranslatedEBCDICNeg2() {
+ val num = "1K"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End)
+ assertEquals(result, "-12")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiTranslatedEBCDICNeg3() {
+ val num = "J23"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start)
+ assertEquals(result, "-123")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiTranslatedEBCDICNeg4() {
+ val num = "123456789}"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End)
+ assertEquals(result, "-1234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiTranslatedEBCDICNeg5() {
+ val num = "}00000000001234567890"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start)
+ assertEquals(result, "-000000000001234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiTranslatedEBCDICInvalidDigit() {
+ val num = "z123"
+ try {
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start)
+ assertEquals(result, "-0123")
+ } catch {
+ case nfe: NumberFormatException => assertTrue(nfe.getMessage().contains("Invalid zoned digit"))
+ }
+ }
+
+ @Test def zonedIntAsciiCARealiaModifiedPos1() {
+ val num = "1"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start)
+ assertEquals(result, "1")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiCARealiaModifiedPos2() {
+ val num = "12"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End)
+ assertEquals(result, "12")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiCARealiaModifiedPos3() {
+ val num = "123"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.None)
+ assertEquals(result, "123")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.None), num)
+ }
+
+ @Test def zonedIntAsciiCARealiaModifiedPos4() {
+ val num = "1234567890"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start)
+ assertEquals(result, "1234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiCARealiaModifiedPos5() {
+ val num = "000000000001234567890"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End)
+ assertEquals(result, "000000000001234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiCARealiaModifiedNeg1() {
+ val num = "!"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start)
+ assertEquals(result, "-1")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiCARealiaModifiedNeg2() {
+ val num = "1\""
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End)
+ assertEquals(result, "-12")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiCARealiaModifiedNeg3() {
+ val num = "!23"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start)
+ assertEquals(result, "-123")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiCARealiaModifiedNeg4() {
+ val num = "123456789 "
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End)
+ assertEquals(result, "-1234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiCARealiaModifiedNeg5() {
+ val num = " 00000000001234567890"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start)
+ assertEquals(result, "-000000000001234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiCARealiaModifiedInvalidDigit() {
+ val num = "z123"
+ try {
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start)
+ assertEquals(result, "-0123")
+ } catch {
+ case nfe: NumberFormatException => assertTrue(nfe.getMessage().contains("Invalid zoned digit"))
+ }
+ }
+
+ @Test def zonedIntAsciiTandemModifiedPos1() {
+ val num = "1"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start)
+ assertEquals(result, "1")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiTandemModifiedPos2() {
+ val num = "12"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End)
+ assertEquals(result, "12")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiTandemModifiedPos3() {
+ val num = "123"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.None)
+ assertEquals(result, "123")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.None), num)
+ }
+
+ @Test def zonedIntAsciiTandemModifiedPos4() {
+ val num = "1234567890"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start)
+ assertEquals(result, "1234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiTandemModifiedPos5() {
+ val num = "000000000001234567890"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End)
+ assertEquals(result, "000000000001234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiTandemModifiedNeg1() {
+ val num = ""
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start)
+ assertEquals(result, "-1")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiTandemModifiedNeg2() {
+ val num = "1"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End)
+ assertEquals(result, "-12")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiTandemModifiedNeg3() {
+ val num = "23"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start)
+ assertEquals(result, "-123")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiTandemModifiedNeg4() {
+ val num = "123456789"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End)
+ assertEquals(result, "-1234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End), num)
+ }
+
+ @Test def zonedIntAsciiTandemModifiedNeg5() {
+ val num = "00000000001234567890"
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start)
+ assertEquals(result, "-000000000001234567890")
+ assertEquals(zonedFromNumber(result, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), num)
+ }
+
+ @Test def zonedIntAsciiTandemModifiedInvalidDigit() {
+ val num = "z123"
+ try {
+ val result = zonedToNumber(num, TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start)
+ assertEquals(result, "-0123")
+ } catch {
+ case nfe: NumberFormatException => assertTrue(nfe.getMessage().contains("Invalid zoned digit"))
+ }
+ }
+
+ @Test def zonedIntAsciiStandardAllDigits() {
+ assertEquals(zonedToNumber("0", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "0")
+ assertEquals(zonedFromNumber("0", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "0")
+ assertEquals(zonedToNumber("1", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "1")
+ assertEquals(zonedFromNumber("1", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "1")
+ assertEquals(zonedToNumber("2", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "2")
+ assertEquals(zonedFromNumber("2", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "2")
+ assertEquals(zonedToNumber("3", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "3")
+ assertEquals(zonedFromNumber("3", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "3")
+ assertEquals(zonedToNumber("4", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "4")
+ assertEquals(zonedFromNumber("4", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "4")
+ assertEquals(zonedToNumber("5", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "5")
+ assertEquals(zonedFromNumber("5", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "5")
+ assertEquals(zonedToNumber("6", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "6")
+ assertEquals(zonedFromNumber("6", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "6")
+ assertEquals(zonedToNumber("7", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "7")
+ assertEquals(zonedFromNumber("7", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "7")
+ assertEquals(zonedToNumber("8", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "8")
+ assertEquals(zonedFromNumber("8", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "8")
+ assertEquals(zonedToNumber("9", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "9")
+ assertEquals(zonedFromNumber("9", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "9")
+ assertEquals(zonedToNumber("1p", TextZonedSignStyle.AsciiStandard, OverpunchLocation.End), "-10")
+ assertEquals(zonedFromNumber("-10", TextZonedSignStyle.AsciiStandard, OverpunchLocation.End), "1p")
+ assertEquals(zonedToNumber("q", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "-1")
+ assertEquals(zonedFromNumber("-1", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "q")
+ assertEquals(zonedToNumber("r", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "-2")
+ assertEquals(zonedFromNumber("-2", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "r")
+ assertEquals(zonedToNumber("s", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "-3")
+ assertEquals(zonedFromNumber("-3", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "s")
+ assertEquals(zonedToNumber("t", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "-4")
+ assertEquals(zonedFromNumber("-4", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "t")
+ assertEquals(zonedToNumber("u", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "-5")
+ assertEquals(zonedFromNumber("-5", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "u")
+ assertEquals(zonedToNumber("v", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "-6")
+ assertEquals(zonedFromNumber("-6", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "v")
+ assertEquals(zonedToNumber("w", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "-7")
+ assertEquals(zonedFromNumber("-7", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "w")
+ assertEquals(zonedToNumber("x", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "-8")
+ assertEquals(zonedFromNumber("-8", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "x")
+ assertEquals(zonedToNumber("y", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "-9")
+ assertEquals(zonedFromNumber("-9", TextZonedSignStyle.AsciiStandard, OverpunchLocation.Start), "y")
+ }
+
+ @Test def zonedIntAsciiTranslatedEBCDICAllDigits() {
+ assertEquals(zonedToNumber("0", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "0")
+ assertEquals(zonedFromNumber("0", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "0")
+ assertEquals(zonedToNumber("1", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "1")
+ assertEquals(zonedFromNumber("1", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "1")
+ assertEquals(zonedToNumber("2", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "2")
+ assertEquals(zonedFromNumber("2", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "2")
+ assertEquals(zonedToNumber("3", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "3")
+ assertEquals(zonedFromNumber("3", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "3")
+ assertEquals(zonedToNumber("4", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "4")
+ assertEquals(zonedFromNumber("4", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "4")
+ assertEquals(zonedToNumber("5", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "5")
+ assertEquals(zonedFromNumber("5", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "5")
+ assertEquals(zonedToNumber("6", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "6")
+ assertEquals(zonedFromNumber("6", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "6")
+ assertEquals(zonedToNumber("7", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "7")
+ assertEquals(zonedFromNumber("7", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "7")
+ assertEquals(zonedToNumber("8", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "8")
+ assertEquals(zonedFromNumber("8", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "8")
+ assertEquals(zonedToNumber("9", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "9")
+ assertEquals(zonedFromNumber("9", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.None), "9")
+ assertEquals(zonedToNumber("{", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "0")
+ assertEquals(zonedFromNumber("0", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "{")
+ assertEquals(zonedToNumber("A", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "1")
+ assertEquals(zonedFromNumber("1", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "A")
+ assertEquals(zonedToNumber("B", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "2")
+ assertEquals(zonedFromNumber("2", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "B")
+ assertEquals(zonedToNumber("C", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "3")
+ assertEquals(zonedFromNumber("3", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "C")
+ assertEquals(zonedToNumber("D", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "4")
+ assertEquals(zonedFromNumber("4", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "D")
+ assertEquals(zonedToNumber("E", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "5")
+ assertEquals(zonedFromNumber("5", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "E")
+ assertEquals(zonedToNumber("F", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "6")
+ assertEquals(zonedFromNumber("6", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "F")
+ assertEquals(zonedToNumber("G", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "7")
+ assertEquals(zonedFromNumber("7", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "G")
+ assertEquals(zonedToNumber("H", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "8")
+ assertEquals(zonedFromNumber("8", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "H")
+ assertEquals(zonedToNumber("I", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "9")
+ assertEquals(zonedFromNumber("9", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "I")
+ assertEquals(zonedToNumber("1}", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End), "-10")
+ assertEquals(zonedFromNumber("-10", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.End), "1}")
+ assertEquals(zonedToNumber("J", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "-1")
+ assertEquals(zonedFromNumber("-1", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "J")
+ assertEquals(zonedToNumber("K", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "-2")
+ assertEquals(zonedFromNumber("-2", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "K")
+ assertEquals(zonedToNumber("L", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "-3")
+ assertEquals(zonedFromNumber("-3", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "L")
+ assertEquals(zonedToNumber("M", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "-4")
+ assertEquals(zonedFromNumber("-4", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "M")
+ assertEquals(zonedToNumber("N", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "-5")
+ assertEquals(zonedFromNumber("-5", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "N")
+ assertEquals(zonedToNumber("O", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "-6")
+ assertEquals(zonedFromNumber("-6", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "O")
+ assertEquals(zonedToNumber("P", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "-7")
+ assertEquals(zonedFromNumber("-7", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "P")
+ assertEquals(zonedToNumber("Q", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "-8")
+ assertEquals(zonedFromNumber("-8", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "Q")
+ assertEquals(zonedToNumber("R", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "-9")
+ assertEquals(zonedFromNumber("-9", TextZonedSignStyle.AsciiTranslatedEBCDIC, OverpunchLocation.Start), "R")
+ }
+
+ @Test def zonedIntAsciiCARealiaModifiedAllDigits() {
+ assertEquals(zonedToNumber("0", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "0")
+ assertEquals(zonedFromNumber("0", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "0")
+ assertEquals(zonedToNumber("1", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "1")
+ assertEquals(zonedFromNumber("1", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "1")
+ assertEquals(zonedToNumber("2", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "2")
+ assertEquals(zonedFromNumber("2", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "2")
+ assertEquals(zonedToNumber("3", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "3")
+ assertEquals(zonedFromNumber("3", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "3")
+ assertEquals(zonedToNumber("4", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "4")
+ assertEquals(zonedFromNumber("4", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "4")
+ assertEquals(zonedToNumber("5", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "5")
+ assertEquals(zonedFromNumber("5", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "5")
+ assertEquals(zonedToNumber("6", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "6")
+ assertEquals(zonedFromNumber("6", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "6")
+ assertEquals(zonedToNumber("7", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "7")
+ assertEquals(zonedFromNumber("7", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "7")
+ assertEquals(zonedToNumber("8", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "8")
+ assertEquals(zonedFromNumber("8", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "8")
+ assertEquals(zonedToNumber("9", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "9")
+ assertEquals(zonedFromNumber("9", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "9")
+ assertEquals(zonedToNumber("1 ", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End), "-10")
+ assertEquals(zonedFromNumber("-10", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.End), "1 ")
+ assertEquals(zonedToNumber("!", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "-1")
+ assertEquals(zonedFromNumber("-1", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "!")
+ assertEquals(zonedToNumber("\"", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "-2")
+ assertEquals(zonedFromNumber("-2", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "\"")
+ assertEquals(zonedToNumber("#", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "-3")
+ assertEquals(zonedFromNumber("-3", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "#")
+ assertEquals(zonedToNumber("$", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "-4")
+ assertEquals(zonedFromNumber("-4", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "$")
+ assertEquals(zonedToNumber("%", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "-5")
+ assertEquals(zonedFromNumber("-5", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "%")
+ assertEquals(zonedToNumber("&", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "-6")
+ assertEquals(zonedFromNumber("-6", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "&")
+ assertEquals(zonedToNumber("'", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "-7")
+ assertEquals(zonedFromNumber("-7", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "'")
+ assertEquals(zonedToNumber("(", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "-8")
+ assertEquals(zonedFromNumber("-8", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "(")
+ assertEquals(zonedToNumber(")", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), "-9")
+ assertEquals(zonedFromNumber("-9", TextZonedSignStyle.AsciiCARealiaModified, OverpunchLocation.Start), ")")
+ }
+
+ @Test def zonedIntAsciiTandemModifiedAllDigits() {
+ assertEquals(zonedToNumber("0", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "0")
+ assertEquals(zonedFromNumber("0", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "0")
+ assertEquals(zonedToNumber("1", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "1")
+ assertEquals(zonedFromNumber("1", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "1")
+ assertEquals(zonedToNumber("2", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "2")
+ assertEquals(zonedFromNumber("2", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "2")
+ assertEquals(zonedToNumber("3", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "3")
+ assertEquals(zonedFromNumber("3", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "3")
+ assertEquals(zonedToNumber("4", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "4")
+ assertEquals(zonedFromNumber("4", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "4")
+ assertEquals(zonedToNumber("5", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "5")
+ assertEquals(zonedFromNumber("5", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "5")
+ assertEquals(zonedToNumber("6", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "6")
+ assertEquals(zonedFromNumber("6", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "6")
+ assertEquals(zonedToNumber("7", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "7")
+ assertEquals(zonedFromNumber("7", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "7")
+ assertEquals(zonedToNumber("8", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "8")
+ assertEquals(zonedFromNumber("8", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "8")
+ assertEquals(zonedToNumber("9", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "9")
+ assertEquals(zonedFromNumber("9", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "9")
+ assertEquals(zonedToNumber("1", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End), "-10")
+ assertEquals(zonedFromNumber("-10", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.End), "1")
+ assertEquals(zonedToNumber("", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "-1")
+ assertEquals(zonedFromNumber("-1", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "")
+ assertEquals(zonedToNumber("", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "-2")
+ assertEquals(zonedFromNumber("-2", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "")
+ assertEquals(zonedToNumber("", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "-3")
+ assertEquals(zonedFromNumber("-3", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "")
+ assertEquals(zonedToNumber("", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "-4")
+ assertEquals(zonedFromNumber("-4", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "")
+ assertEquals(zonedToNumber("
", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "-5")
+ assertEquals(zonedFromNumber("-5", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "
")
+ assertEquals(zonedToNumber("", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "-6")
+ assertEquals(zonedFromNumber("-6", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "")
+ assertEquals(zonedToNumber("", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "-7")
+ assertEquals(zonedFromNumber("-7", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "")
+ assertEquals(zonedToNumber("", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "-8")
+ assertEquals(zonedFromNumber("-8", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "")
+ assertEquals(zonedToNumber("", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "-9")
+ assertEquals(zonedFromNumber("-9", TextZonedSignStyle.AsciiTandemModified, OverpunchLocation.Start), "")
+ }
}
diff --git a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/DFDL_part1_simpletypes.xsd b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/DFDL_part1_simpletypes.xsd
index 1d1635c..280c367 100644
--- a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/DFDL_part1_simpletypes.xsd
+++ b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/DFDL_part1_simpletypes.xsd
@@ -314,6 +314,7 @@
<xsd:enumeration value="asciiStandard" />
<xsd:enumeration value="asciiTranslatedEBCDIC" />
<xsd:enumeration value="asciiCARealiaModified" />
+ <xsd:enumeration value="asciiTandemModified" />
</xsd:restriction>
</xsd:simpleType>
diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertZonedNumberUnparser.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertZonedNumberUnparser.scala
new file mode 100644
index 0000000..9bdf0c7
--- /dev/null
+++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ConvertZonedNumberUnparser.scala
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.processors.unparsers
+
+import org.apache.daffodil.schema.annotation.props.gen.TextZonedSignStyle
+import org.apache.daffodil.processors._
+import org.apache.daffodil.util.DecimalUtils
+import org.apache.daffodil.util.DecimalUtils.OverpunchLocation
+import org.apache.daffodil.processors.parsers.ConvertTextNumberParserUnparserHelperBase
+
+case class ConvertZonedCombinatorUnparser(
+ rd: TermRuntimeData,
+ valueUnparser: Unparser,
+ converterUnparser: Unparser)
+ extends CombinatorUnparser(rd) {
+
+ override lazy val runtimeDependencies = Nil
+
+ override lazy val childProcessors = Seq(converterUnparser, valueUnparser)
+
+ override def unparse(state: UState): Unit = {
+ converterUnparser.unparse1(state)
+
+ if (state.processorStatus eq Success) {
+ valueUnparser.unparse1(state)
+ }
+ }
+}
+
+case class ConvertZonedNumberUnparser[S](
+ helper: ConvertTextNumberParserUnparserHelperBase[S],
+ opl: OverpunchLocation.Value,
+ zonedSignStyle: TextZonedSignStyle,
+ override val context: ElementRuntimeData)
+ extends PrimUnparser
+ with ToBriefXMLImpl {
+
+ override lazy val runtimeDependencies = Nil
+
+ override def toString = "to(xs:" + helper.xsdType + ")"
+ override lazy val childProcessors = Nil
+
+ override def unparse(state: UState): Unit = {
+
+ val node = state.currentInfosetNode.asSimple
+ val value = node.dataValueAsString
+
+ // The type of value should have the type of S, but type erasure makes this
+ // difficult to assert. Could probably check this with TypeTags or Manifest
+ // if we find this is not the case. Want something akin to:
+ // Assert.invariant(value.isInstanceOf[S])
+
+ val strRep = DecimalUtils.zonedFromNumber(value, zonedSignStyle, opl)
+
+ node.overwriteDataValue(strRep)
+ }
+}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PrimitivesTextNumber1.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PrimitivesTextNumber1.scala
index d9d6614..a2b933d 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PrimitivesTextNumber1.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PrimitivesTextNumber1.scala
@@ -442,7 +442,7 @@ abstract class NumberFormatFactoryBase[S](parserHelper: ConvertTextNumberParserU
protected def generateNumFormat(decimalSepList: Maybe[List[Character]],
groupingSep: Maybe[Character],
- exponentRep: String,
+ exponentRep: Maybe[String],
infRep: Maybe[String],
nanRep: Maybe[String],
checkPolicy: TextNumberCheckPolicy,
@@ -463,7 +463,9 @@ abstract class NumberFormatFactoryBase[S](parserHelper: ConvertTextNumberParserU
}
// TODO: this is allowed to be case insenstive, ICU doesn't support that
- dfs.setExponentSeparator(exponentRep)
+ if (exponentRep.isDefined) {
+ dfs.setExponentSeparator(exponentRep.get)
+ }
if (infRep.isDefined) {
// TODO: this is allowed to be case insensitive, ICU doesn't support that
@@ -557,7 +559,7 @@ class NumberFormatFactoryStatic[S](context: ThrowsSDE,
parserHelper: ConvertTextNumberParserUnparserHelperBase[S],
decimalSepExpEv: Maybe[Evaluatable[List[String]]],
groupingSepExpEv: Maybe[Evaluatable[String]],
- exponentRepExpEv: Evaluatable[String],
+ exponentRepExpEv: Maybe[Evaluatable[String]],
infRep: Maybe[String],
nanRep: Maybe[String],
checkPolicy: TextNumberCheckPolicy,
@@ -566,9 +568,6 @@ class NumberFormatFactoryStatic[S](context: ThrowsSDE,
roundingMode: Maybe[TextNumberRoundingMode],
roundingIncrement: MaybeDouble)
extends NumberFormatFactoryBase[S](parserHelper) {
- Assert.invariant((!decimalSepExpEv.isDefined || decimalSepExpEv.get.isConstant) &&
- (!groupingSepExpEv.isDefined || groupingSepExpEv.get.isConstant) &&
- exponentRepExpEv.isConstant)
val decSep =
if (decimalSepExpEv.isEmpty) Nope else One {
@@ -582,17 +581,18 @@ class NumberFormatFactoryStatic[S](context: ThrowsSDE,
getGroupingSep(gse, context)
}
- val expRep = {
- Assert.invariant(exponentRepExpEv.isConstant)
- getExponentRep(exponentRepExpEv.maybeConstant.get, context)
- }
+ val expRep =
+ if (exponentRepExpEv.isEmpty) Nope else One {
+ Assert.invariant(exponentRepExpEv.get.isConstant)
+ getExponentRep(exponentRepExpEv.get.maybeConstant.get, context)
+ }
val roundingInc: MaybeDouble = if (roundingIncrement.isEmpty) MaybeDouble.Nope else MaybeDouble { getRoundingIncrement(roundingIncrement.value, context) }
checkUnique(
decSep,
groupSep,
- One(expRep),
+ expRep,
infRep,
nanRep,
parserHelper.zeroRepListRaw,
@@ -623,7 +623,7 @@ class NumberFormatFactoryDynamic[S](staticContext: ThrowsSDE,
parserHelper: ConvertTextNumberParserUnparserHelperBase[S],
decimalSepExpEv: Maybe[Evaluatable[List[String]]],
groupingSepExpEv: Maybe[Evaluatable[String]],
- exponentRepExpEv: Evaluatable[String],
+ exponentRepExpEv: Maybe[Evaluatable[String]],
infRep: Maybe[String],
nanRep: Maybe[String],
checkPolicy: TextNumberCheckPolicy,
@@ -644,14 +644,14 @@ class NumberFormatFactoryDynamic[S](staticContext: ThrowsSDE,
(a: String) => getGroupingSep(a, staticContext)
}
- val exponentRepCached: CachedDynamic[String, String] =
- cacheConstantExpression(exponentRepExpEv) {
+ val exponentRepCached: Maybe[CachedDynamic[String, String]] =
+ cacheConstantExpressionMaybe(exponentRepExpEv) {
(a: String) => getExponentRep(a, staticContext)
}
checkUnique(getStaticMaybe(decimalSepListCached),
getStaticMaybe(groupingSepCached),
- getStatic(exponentRepCached),
+ getStaticMaybe(exponentRepCached),
infRep,
nanRep,
parserHelper.zeroRepListRaw,
@@ -675,7 +675,7 @@ class NumberFormatFactoryDynamic[S](staticContext: ThrowsSDE,
}
}
- val exponentRep = evalWithConversion(state, exponentRepCached) {
+ val exponentRep = evalWithConversionMaybe(state, exponentRepCached) {
(s: ParseOrUnparseState, c: String) =>
{
getExponentRep(c, s)
@@ -685,7 +685,7 @@ class NumberFormatFactoryDynamic[S](staticContext: ThrowsSDE,
checkUnique(
decimalSepList,
groupingSep,
- One(exponentRep),
+ exponentRep,
infRep,
nanRep,
parserHelper.zeroRepListRaw,
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ZonedTextParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ZonedTextParsers.scala
index d300cd8..3419351 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ZonedTextParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ZonedTextParsers.scala
@@ -17,14 +17,100 @@
package org.apache.daffodil.processors.parsers
+import org.apache.daffodil.schema.annotation.props.gen.TextZonedSignStyle
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.exceptions.UnsuppressableException
+import org.apache.daffodil.util.DecimalUtils
+import org.apache.daffodil.util.DecimalUtils.OverpunchLocation
+import java.text.ParsePosition
+import java.lang.{ Number => JNumber }
+import org.apache.daffodil.infoset.DISimple
import org.apache.daffodil.processors.ElementRuntimeData
+import org.apache.daffodil.processors.Success
+import org.apache.daffodil.processors.TermRuntimeData
-class ZonedTextNumberParser(override val context: ElementRuntimeData)
- extends TextPrimParser {
+case class ConvertZonedCombinatorParser(
+ rd: TermRuntimeData,
+ valueParser: Parser,
+ converterParser: Parser)
+ extends CombinatorParser(rd) {
override lazy val runtimeDependencies = Nil
+ override lazy val childProcessors = Seq(valueParser, converterParser)
+
+ def parse(start: PState): Unit = {
+ valueParser.parse1(start)
+ if (start.processorStatus eq Success) {
+ converterParser.parse1(start)
+ }
+ }
+}
+
+case class ConvertZonedNumberParser[S](
+ helper: ConvertTextNumberParserUnparserHelperBase[S],
+ opl: OverpunchLocation.Value,
+ nff: NumberFormatFactoryBase[S],
+ zonedSignStyle: TextZonedSignStyle,
+ override val context: ElementRuntimeData) extends TextPrimParser {
+ override lazy val runtimeDependencies = Nil
+
+ override def toString = "to(xs:" + helper.xsdType + ")"
+
def parse(start: PState): Unit = {
- context.notYetImplemented("Zoned Numbers")
+ val node: DISimple = start.simpleElement
+ val str = node.dataValueAsString
+
+ Assert.invariant(str != null) // worst case it should be empty string. But not null.
+ if (str == "") {
+ PE(start, "Convert to %s (for xs:%s): Cannot parse number from empty string", helper.prettyType, helper.xsdType)
+ return
+ }
+
+ var checkLength = str.length
+ val numValue = {
+ val df = nff.getNumFormat(start)
+ val pos = new ParsePosition(0)
+ val num = try {
+ val decodedNum = DecimalUtils.zonedToNumber(str, zonedSignStyle, opl)
+ if (decodedNum(0) == '-')
+ checkLength = checkLength + 1
+ df.get.parse(decodedNum, pos)
+ } catch {
+ case s: scala.util.control.ControlThrowable => throw s
+ case u: UnsuppressableException => throw u
+ case e: Exception => {
+ PE(start, "Convert to %s (for xs:%s): Parse of '%s' threw exception %s",
+ helper.prettyType, helper.xsdType, str, e)
+ return
+ }
+ }
+
+ // Verify that what was parsed was what was passed exactly in byte count.
+ // Use pos to verify all characters consumed & check for errors!
+ if (num == null || pos.getIndex != checkLength) {
+ PE(start, "Convert to %s (for xs:%s): Unable to parse '%s' (using up all characters).",
+ helper.prettyType, helper.xsdType, str)
+ return
+ }
+
+ val numValue = {
+ if (helper.isInvalidRange(num)) {
+ PE(start, "Convert to %s (for xs:%s): Out of Range: '%s' converted to %s, is not in range for the type.",
+ helper.prettyType, helper.xsdType, str, num)
+ return
+ }
+
+ // convert to proper type
+ val asNumber = helper.getNum(num)
+ Assert.invariant(!asNumber.isInstanceOf[String])
+
+ asNumber
+ }
+ numValue
+ }
+
+ node.overwriteDataValue(numValue.asInstanceOf[JNumber])
+
}
}
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section13/zoned/zoned.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section13/zoned/zoned.tdml
new file mode 100644
index 0000000..7a79dea
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section13/zoned/zoned.tdml
@@ -0,0 +1,427 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<tdml:testSuite suiteName="zoned"
+ description="Zoned Number Properties" xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ct="http://w3.ibm.com/xmlns/dfdl/ctInfoset"
+ xmlns:ex="http://example.com" xmlns="http://example.com" xmlns:tns="http://example.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ defaultRoundTrip="true">
+
+ <tdml:defineSchema name="s1">
+ <dfdl:format ref="ex:GeneralFormat" lengthKind="explicit" encoding="ISO-8859-1" occursCountKind="implicit"
+ textNumberCheckPolicy="strict" textNumberPadCharacter="0" textNumberJustification="right" textNumberRep="zoned"
+ textZonedSignStyle="asciiStandard"
+ lengthUnits="characters"/>
+
+ <xs:element name="int01" type="xs:int" dfdl:length="4" dfdl:textNumberPattern="+00@00" />
+ <xs:element name="int02" type="xs:int" dfdl:length="4" dfdl:textNumberPattern="0000" />
+ <xs:element name="int03" type="xs:int" dfdl:length="4" dfdl:textNumberPattern="+00E00" />
+ <xs:element name="uint01" type="xs:unsignedInt" dfdl:length="4" dfdl:textNumberPattern="0000" dfdl:textNumberCheckPolicy="lax"/>
+ <xs:element name="int04" type="xs:int" dfdl:length="4" dfdl:textNumberPattern="+00;00" />
+ <xs:element name="int05" type="xs:int" dfdl:length="4" dfdl:textNumberPattern="+0000+" />
+ <xs:element name="float01" type="xs:float" dfdl:length="4" dfdl:textNumberPattern="+00;00" />
+ <xs:element name="double01" type="xs:double" dfdl:length="4" dfdl:textNumberPattern="+00;00" />
+
+
+ <xs:element name="standard01" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="+0000000000" />
+ <xs:element name="standard02" type="xs:unsignedInt" dfdl:length="10" dfdl:textNumberPattern="0000000000" />
+ <xs:element name="standard03" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="0000000000+" />
+
+ <xs:element name="trans01" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="+0000000000" dfdl:textZonedSignStyle="asciiTranslatedEBCDIC" />
+ <xs:element name="trans02" type="xs:unsignedInt" dfdl:length="10" dfdl:textNumberPattern="0000000000" dfdl:textZonedSignStyle="asciiTranslatedEBCDIC" />
+ <xs:element name="trans03" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="0000000000+" dfdl:textZonedSignStyle="asciiTranslatedEBCDIC" />
+<xs:element name="mod01" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="+0000000000" dfdl:textZonedSignStyle="asciiCARealiaModified" />
+ <xs:element name="mod02" type="xs:unsignedInt" dfdl:length="10" dfdl:textNumberPattern="0000000000" dfdl:textZonedSignStyle="asciiCARealiaModified" />
+ <xs:element name="mod03" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="0000000000+" dfdl:textZonedSignStyle="asciiCARealiaModified" />
+
+ <xs:element name="tmod01" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="+0000000000" dfdl:textZonedSignStyle="asciiTandemModified" />
+ <xs:element name="tmod02" type="xs:unsignedInt" dfdl:length="10" dfdl:textNumberPattern="0000000000" dfdl:textZonedSignStyle="asciiTandemModified" />
+ <xs:element name="tmod03" type="xs:int" dfdl:length="10" dfdl:textNumberPattern="0000000000+" dfdl:textZonedSignStyle="asciiTandemModified" />
+ </tdml:defineSchema>
+
+ <tdml:parserTestCase name="zoned_textNumberPattern_fail01" root="int01" model="s1"
+ description="This test should fail because '@' is not allowed to appear in the textNumberPattern for zoned numbers">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1988</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>The '@' symbol may not be used</tdml:error>
+ </tdml:errors>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="zoned_textNumberPattern_fail02" root="int02" model="s1"
+ description="This test should fail because '+' must be the first or last character in the textNumberPattern when using zoned numbers with signed types">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1988</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>textNumberPattern must have '+' at the beginning</tdml:error>
+ <tdml:error>for signed numbers</tdml:error>
+ </tdml:errors>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="zoned_textNumberPattern_fail03" root="uint01" model="s1"
+ description="This test should fail because '+' must be the first or last character in the textNumberPattern when using zoned numbers and textNumberCheckPolicy=strict">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1988</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>textNumberPattern must have '+' at the beginning</tdml:error>
+ <tdml:error>for unsigned numbers</tdml:error>
+ </tdml:errors>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="zoned_textNumberPattern_fail04" root="int04" model="s1"
+ description="This test should fail because negative number patterns may not be used with zoned numbers">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1988</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>Negative patterns may not be used</tdml:error>
+ </tdml:errors>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="zoned_textNumberPattern_fail05" root="int03" model="s1"
+ description="This test should fail because 'E' is not an allowed character in the textNumberPattern for zoned numbers">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1988</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>Invalid characters used in textNubmerPattern for zoned number</tdml:error>
+ </tdml:errors>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="zoned_textNumberPattern_fail06" root="int05" model="s1"
+ description="This test should fail because '+' is not allowed to be at both the start and end of the textNumberPattern">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1988</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>The textNumberPattern may either begin or end with a '+', not both</tdml:error>
+ </tdml:errors>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="zoned_float_fail01" root="float01" model="s1"
+ description="This test should fail because floats are not supported with zoned decimal">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1988</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>Zoned not supported for float and double</tdml:error>
+ </tdml:errors>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="zoned_double_fail01" root="double01" model="s1"
+ description="This test should fail because doubles are not supported with zoned decimal">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1988</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>Zoned not supported for float and double</tdml:error>
+ </tdml:errors>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedStandard01" root="standard01" model="s1"
+ description="Test of a positive number with zonedSignStyle=asciiStandard">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <standard01>1234567890</standard01>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedStandard02" root="standard01" model="s1"
+ description="Test of a negative number with zonedSignStyle=asciiStandard with overpunch on first char">
+
+ <tdml:document>
+ <tdml:documentPart type="text">q234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <standard01>-1234567890</standard01>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedStandard03" root="standard01" model="s1"
+ description="This test should fail as 'z' is not a valid digit in zoned AsciiStandard">
+
+ <tdml:document>
+ <tdml:documentPart type="text">z234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>NumberFormatException: Invalid zoned digit</tdml:error>
+ </tdml:errors>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedStandard04" root="standard02" model="s1"
+ description="Test of a positive number with zonedSignStyle=asciiStandard with no overpunch char">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <standard02>1234567890</standard02>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedStandard05" root="standard03" model="s1"
+ description="Test of a negative number with zonedSignStyle=asciiStandard with overpunch on last char">
+
+ <tdml:document>
+ <tdml:documentPart type="text">123456789p</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <standard03>-1234567890</standard03>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedTranslatedEBCDIC01" root="trans01" model="s1"
+ description="Test of a positive number with zonedSignStyle=asciiTranslatedEBCDIC">
+
+ <tdml:document>
+ <tdml:documentPart type="text">A234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <trans01>1234567890</trans01>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedTranslatedEBCDIC02" root="trans01" model="s1"
+ description="Test of a negative number with zonedSignStyle=asciiTranslatedEBCDIC with overpunch on first char">
+
+ <tdml:document>
+ <tdml:documentPart type="text">J234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <trans01>-1234567890</trans01>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedTranslatedEBCDIC03" root="trans01" model="s1"
+ description="This test should fail as 'z' is not a valid digit in zoned AsciiTranslatedEBCDIC">
+
+ <tdml:document>
+ <tdml:documentPart type="text">z234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>NumberFormatException: Invalid zoned digit</tdml:error>
+ </tdml:errors>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedTranslatedEBCDIC04" root="trans02" model="s1"
+ description="Test of a positive number with zonedSignStyle=asciiTranslatedEBCDIC with no overpunch char">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <trans02>1234567890</trans02>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedTranslatedEBCDIC05" root="trans03" model="s1"
+ description="Test of a negative number with zonedSignStyle=asciiTranslatedEBCDIC with overpunch on last char">
+
+ <tdml:document>
+ <tdml:documentPart type="text">123456789}</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <trans03>-1234567890</trans03>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedCARealiaModified01" root="mod01" model="s1"
+ description="Test of a positive number with zonedSignStyle=asciiCARealiaModified">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <mod01>1234567890</mod01>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedCARealiaModified02" root="mod01" model="s1"
+ description="Test of a negative number with zonedSignStyle=asciiCARealiaModified with overpunch on first char">
+
+ <tdml:document>
+ <tdml:documentPart type="text">!234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <mod01>-1234567890</mod01>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedCARealiaModified03" root="mod01" model="s1"
+ description="This test should fail as 'z' is not a valid digit in zoned AsciiCARealiaModified">
+
+ <tdml:document>
+ <tdml:documentPart type="text">z234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>NumberFormatException: Invalid zoned digit</tdml:error>
+ </tdml:errors>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedCARealiaModified04" root="mod02" model="s1"
+ description="Test of a positive number with zonedSignStyle=asciiCARealiaModified with no overpunch char">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <mod02>1234567890</mod02>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedCARealiaModified05" root="mod03" model="s1"
+ description="Test of a negative number with zonedSignStyle=asciiCARealiaModified with overpunch on last char">
+
+ <tdml:document>
+ <tdml:documentPart type="text">123456789 </tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <mod03>-1234567890</mod03>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedTandemModified01" root="tmod01" model="s1"
+ description="Test of a positive number with zonedSignStyle=asciiTandemModified">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <tmod01>1234567890</tmod01>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedTandemModified02" root="tmod01" model="s1"
+ description="Test of a negative number with zonedSignStyle=asciiTandemModified with overpunch on first char">
+
+ <tdml:document>
+ <tdml:documentPart type="text" encoding="ISO-8859-1">234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <tmod01>-1234567890</tmod01>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedTandemModified03" root="tmod01" model="s1"
+ description="This test should fail as 'z' is not a valid digit in zoned AsciiTandemModified">
+
+ <tdml:document>
+ <tdml:documentPart type="text">z234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:errors>
+ <tdml:error>NumberFormatException: Invalid zoned digit</tdml:error>
+ </tdml:errors>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedTandemModified04" root="tmod02" model="s1"
+ description="Test of a positive number with zonedSignStyle=asciiTandemModified with no overpunch char">
+
+ <tdml:document>
+ <tdml:documentPart type="text">1234567890</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <tmod02>1234567890</tmod02>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="ZonedTandemModified05" root="tmod03" model="s1"
+ description="Test of a negative number with zonedSignStyle=asciiTandemModified with overpunch on last char">
+
+ <tdml:document>
+ <tdml:documentPart type="text" encoding="ISO-8859-1">123456789€</tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <tmod03>-1234567890</tmod03>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
+</tdml:testSuite>
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section13/zoned/TestZoned.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section13/zoned/TestZoned.scala
new file mode 100644
index 0000000..73f9ace
--- /dev/null
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section13/zoned/TestZoned.scala
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.section13.zoned
+
+import org.apache.daffodil.tdml.Runner
+import org.junit.AfterClass
+import org.junit.Test
+
+object TestZoned {
+ val testDir = "/org/apache/daffodil/section13/zoned/"
+ lazy val runner = Runner(testDir, "zoned.tdml")
+
+ @AfterClass def shutdown(): Unit = {
+ runner.reset
+ }
+
+}
+
+class TestZoned {
+ import TestZoned._
+
+ @Test def testZonedPatternFail01(): Unit = { runner.runOneTest("zoned_textNumberPattern_fail01") }
+ @Test def testZonedPatternFail02(): Unit = { runner.runOneTest("zoned_textNumberPattern_fail02") }
+ @Test def testZonedPatternFail03(): Unit = { runner.runOneTest("zoned_textNumberPattern_fail03") }
+ @Test def testZonedPatternFail04(): Unit = { runner.runOneTest("zoned_textNumberPattern_fail04") }
+ @Test def testZonedPatternFail05(): Unit = { runner.runOneTest("zoned_textNumberPattern_fail05") }
+ @Test def testZonedPatternFail06(): Unit = { runner.runOneTest("zoned_textNumberPattern_fail06") }
+ @Test def testZonedFloatFail01(): Unit = { runner.runOneTest("zoned_float_fail01") }
+ @Test def testZonedDoubleFail01(): Unit = { runner.runOneTest("zoned_double_fail01") }
+
+ @Test def testZonedStandard01(): Unit = { runner.runOneTest("ZonedStandard01") }
+ @Test def testZonedStandard02(): Unit = { runner.runOneTest("ZonedStandard02") }
+ @Test def testZonedStandard03(): Unit = { runner.runOneTest("ZonedStandard03") }
+ @Test def testZonedStandard04(): Unit = { runner.runOneTest("ZonedStandard04") }
+ @Test def testZonedStandard05(): Unit = { runner.runOneTest("ZonedStandard05") }
+
+ @Test def testZonedTranslatedEBCDIC01(): Unit = { runner.runOneTest("ZonedTranslatedEBCDIC01") }
+ @Test def testZonedTranslatedEBCDIC02(): Unit = { runner.runOneTest("ZonedTranslatedEBCDIC02") }
+ @Test def testZonedTranslatedEBCDIC03(): Unit = { runner.runOneTest("ZonedTranslatedEBCDIC03") }
+ @Test def testZonedTranslatedEBCDIC04(): Unit = { runner.runOneTest("ZonedTranslatedEBCDIC04") }
+ @Test def testZonedTranslatedEBCDIC05(): Unit = { runner.runOneTest("ZonedTranslatedEBCDIC05") }
+
+ @Test def testZonedCARealiaModified01(): Unit = { runner.runOneTest("ZonedCARealiaModified01") }
+ @Test def testZonedCARealiaModified02(): Unit = { runner.runOneTest("ZonedCARealiaModified02") }
+ @Test def testZonedCARealiaModified03(): Unit = { runner.runOneTest("ZonedCARealiaModified03") }
+ @Test def testZonedCARealiaModified04(): Unit = { runner.runOneTest("ZonedCARealiaModified04") }
+ @Test def testZonedCARealiaModified05(): Unit = { runner.runOneTest("ZonedCARealiaModified05") }
+
+ @Test def testZonedTandemModified01(): Unit = { runner.runOneTest("ZonedTandemModified01") }
+ @Test def testZonedTandemModified02(): Unit = { runner.runOneTest("ZonedTandemModified02") }
+ @Test def testZonedTandemModified03(): Unit = { runner.runOneTest("ZonedTandemModified03") }
+ @Test def testZonedTandemModified04(): Unit = { runner.runOneTest("ZonedTandemModified04") }
+ @Test def testZonedTandemModified05(): Unit = { runner.runOneTest("ZonedTandemModified05") }
+}