stevedlawrence commented on code in PR #1187: URL: https://github.com/apache/daffodil/pull/1187#discussion_r1532414511
########## daffodil-runtime1-layers/src/main/scala/org/apache/daffodil/layers/runtime1/BoundaryMarkLayer.scala: ########## @@ -0,0 +1,99 @@ +/* + * 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.layers.runtime1 + +import java.io.InputStream +import java.io.OutputStream +import java.nio.charset.Charset + +import org.apache.daffodil.io.BoundaryMarkInsertingJavaOutputStream +import org.apache.daffodil.io.BoundaryMarkLimitingInputStream +import org.apache.daffodil.runtime1.layers.api.Layer + +/** + * A layer which isolates text data by way of a boundary mark string. + * This is like a terminating delimiter of a DFDL element or sequence/choice group, + * except that there is no escaping mechanism, so the data cannot in any way + * contain the boundary mark string, and elements within the layer can have + * any dfdl:lengthKind, but this does not affect the search for the boundary mark. + * + * For example, when using an element with dfdl:lengthKind="delimited" and a dfdl:terminator="END", + * if that element contains a child element with dfdl:lengthKind="explicit", then the + * search for the "END" terminator is suspended for the length of the child element, and + * that search resumes after the child element's length has been parsed. + * + * In contrast to this, if a boundary mark layer is used with the boundaryMark variable + * bound to "END", then the data stream is decoded as characters in the charset encoding + * given by the layerEncoding variable, and the layer continues until the "END" is found. + * The dfdl:lengthKind of any child element enclosed within the layer, or even the lengths + * of other layers found within the scope of this boundary mark layer are not considered and do not + * disrupt the search for the boundary mark string. + * + * This layer does not populate any DFDL variables with results. + * + * This layer defines two DFDL variables which provide required parameters. + */ +final class BoundaryMarkLayer + extends Layer("boundaryMark", "urn:org.apache.daffodil.layers.boundaryMark") { + + private var boundaryMark: String = _ + private var layerEncoding: String = _ + + private val maxBoundaryMarkLength: Int = Short.MaxValue + + /** + * @param boundaryMark a string which is the boundary marker. Searching for this string is + * done without any notion of escaping. When parsing the data in the + * layer is up to but not including that of the boundary mark string, + * which is removed from the data-stream on parsing, and inserted into + * the data stream on unparsing. + * @param layerEncoding a string which is the name of the character set encoding used to + * decode characters during the search for the boundary mark, and used + * to encode characters when inserting the boundary mark when unparsing. + */ + private[layers] def setLayerVariableParameters( + boundaryMark: String, + layerEncoding: String, + ): Unit = { + this.boundaryMark = boundaryMark + if (boundaryMark.isEmpty) + processingError("The boundaryMark variable value may not be empty string.") + if (boundaryMark.length > maxBoundaryMarkLength) + processingError( + s"The boundaryMark string length may not be greater than the limit: $maxBoundaryMarkLength", + ) Review Comment: That's fair. Just thinking about possible counterpoints, the spec says an initiator expression cannot evaluate to the empty string, or it's an SDE. I could imagine a case where a variable is set to the empty string because of speculative parsing, that variable is used as the value of the dfdl:initiator, and Daffodil would treat it as an SDE. That feels very similar to the `boundaryMark.isEmpty` test, but which we we treat as a PE. There's other cases, for example it's an SDE if a separator contains the string "%ES;". So it's not just about being empty, but about being an invalid value for the property. So I could see an argument that invalid "properties" for a layer would be treated as SDE's. Layers are a different beast though, I'm not sure how much we can really compare layers with DFDL properties. And ultimately it's up to the layer author, and I guess PE is more flexible. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
