Skip to content

Commit a25aa1e

Browse files
committed
Replace ArrayBuffer[State] with Array[State]
- currently in 2.13 we are getting a "ReflectiveOperationException durins deserialzation" error on account of states being a pass by name parameter leading to lambda serialization, removing that resulted in a ClassCastException where it was complaining about not being able to cast DefaultSerializationProxy to ArrayBuffer, which was weird because in a separate example class we were able to deserialize ArrayBuffer[SomeSerializableClass] just fine. So we set about converting ArrayBuffer to Array to see if it fixed the error, which it did...we also changed recursive buildTransitions function to an iterative function to support using an Array for allstates instead of an ArrayBuffer DAFFODIL-2152
1 parent 8928303 commit a25aa1e

File tree

4 files changed

+76
-81
lines changed

4 files changed

+76
-81
lines changed

daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/dfa/CreateDelimiterDFA.scala

+31-24
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
package org.apache.daffodil.runtime1.processors.dfa
1919

20-
import scala.collection.mutable.ArrayBuffer
20+
import scala.collection.compat.immutable.ArraySeq
2121

2222
import org.apache.daffodil.runtime1.dsom.DPathCompileInfo
2323
import org.apache.daffodil.runtime1.processors.CharDelim
@@ -44,14 +44,14 @@ object CreateDelimiterDFA {
4444
outputNewLine: String
4545
): DFADelimiter = {
4646

47-
val allStates: ArrayBuffer[State] = ArrayBuffer.empty
47+
val allStates: Array[State] = new Array[State](delimiter.length)
4848

4949
buildTransitions(delimiter, allStates, false)
5050

5151
val unparseValue = delimiter.map { _.unparseValue(outputNewLine) }.mkString
5252
new DFADelimiterImplUnparse(
5353
delimType,
54-
allStates.reverse.toArray,
54+
allStates.reverse,
5555
delimiterStr,
5656
unparseValue,
5757
ci.schemaFileLocation
@@ -70,13 +70,13 @@ object CreateDelimiterDFA {
7070
ignoreCase: Boolean
7171
): DFADelimiter = {
7272

73-
val allStates: ArrayBuffer[State] = ArrayBuffer.empty
73+
val allStates: Array[State] = new Array[State](delimiter.length)
7474

7575
buildTransitions(delimiter, allStates, ignoreCase)
7676

7777
new DFADelimiterImpl(
7878
delimType,
79-
allStates.reverse.toArray,
79+
allStates.reverse,
8080
delimiterStr,
8181
ci.schemaFileLocation
8282
)
@@ -95,7 +95,7 @@ object CreateDelimiterDFA {
9595
val d = new Delimiter()
9696
d.compileDelimiter(delimiterStr, ignoreCase)
9797
val db = d.delimBuf
98-
apply(delimType, ci, db, delimiterStr, ignoreCase)
98+
apply(delimType, ci, ArraySeq.unsafeWrapArray(db), delimiterStr, ignoreCase)
9999
}
100100

101101
/**
@@ -111,7 +111,7 @@ object CreateDelimiterDFA {
111111
val d = new Delimiter()
112112
d.compileDelimiter(delimiterStr, false)
113113
val db = d.delimBuf
114-
apply(delimType, ci, db, delimiterStr, outputNewLine)
114+
apply(delimType, ci, ArraySeq.unsafeWrapArray(db), delimiterStr, outputNewLine)
115115
}
116116

117117
/**
@@ -147,7 +147,7 @@ object CreateDelimiterDFA {
147147
d: DelimBase,
148148
nextState: Int,
149149
stateNum: Int,
150-
allStates: ArrayBuffer[State],
150+
allStates: Array[State],
151151
ignoreCase: Boolean
152152
): DelimStateBase = {
153153

@@ -176,7 +176,7 @@ object CreateDelimiterDFA {
176176

177177
private def buildTransitions(
178178
delim: Seq[DelimBase],
179-
allStates: ArrayBuffer[State],
179+
allStates: Array[State],
180180
ignoreCase: Boolean
181181
): State = {
182182
assert(!delim.isEmpty)
@@ -186,26 +186,33 @@ object CreateDelimiterDFA {
186186
private def buildTransitions(
187187
nextState: DelimStateBase,
188188
delim: Seq[DelimBase],
189-
allStates: ArrayBuffer[State],
189+
allStates: Array[State],
190190
ignoreCase: Boolean
191191
): State = {
192192

193-
if (delim.isEmpty && nextState != null) {
194-
// We are initial state
195-
nextState.stateName = "StartState" // "PTERM0"
196-
return nextState
193+
var i = 0
194+
var remainingDelim = delim
195+
var currentNextState = nextState
196+
197+
while (remainingDelim.nonEmpty) {
198+
val currentState = getState(
199+
remainingDelim.head,
200+
if (currentNextState == null) DFA.FinalState else currentNextState.stateNum,
201+
remainingDelim.length - 1,
202+
allStates,
203+
ignoreCase
204+
)
205+
remainingDelim = remainingDelim.tail
206+
allStates(i) = currentState
207+
currentNextState = currentState
208+
i += 1
197209
}
198210

199-
val currentState = getState(
200-
delim(0),
201-
if (nextState == null) DFA.FinalState else nextState.stateNum,
202-
delim.length - 1,
203-
allStates,
204-
ignoreCase
205-
)
206-
val rest = delim.tail
211+
if (currentNextState != null) {
212+
// We are initial state
213+
currentNextState.stateName = "StartState" // "PTERM0"
214+
}
207215

208-
allStates += currentState
209-
return buildTransitions(currentState, rest, allStates, ignoreCase)
216+
currentNextState
210217
}
211218
}

daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/dfa/CreateFieldDFA.scala

+12-14
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717

1818
package org.apache.daffodil.runtime1.processors.dfa
1919

20-
import scala.collection.mutable.ArrayBuffer
21-
2220
import org.apache.daffodil.lib.util.MaybeChar
2321

2422
/**
@@ -43,47 +41,47 @@ object CreateFieldDFA {
4341
*/
4442
def apply(): DFAField = {
4543

46-
val allStates: ArrayBuffer[State] = ArrayBuffer.empty
44+
val allStates: Array[State] = new Array[State](1)
4745

4846
val startState = new StartState(allStates, 0)
4947

50-
allStates.insert(0, startState)
48+
allStates(0) = startState
5149

52-
new DFAFieldImpl(allStates.toArray)
50+
new DFAFieldImpl(allStates)
5351
}
5452

5553
/**
5654
* Constructs a DFAField object with EscapeSchemeKind.Character
5755
*/
5856
def apply(EC: Char, EEC: MaybeChar): DFAField = {
5957

60-
val allStates: ArrayBuffer[State] = ArrayBuffer.empty
58+
val allStates: Array[State] = new Array(3)
6159

6260
val ecState = new ECState(allStates, EC, 1)
6361
val eecState = new EECState(allStates, EEC, EC, 2)
6462
val startState = new StartStateEscapeChar(allStates, EEC, EC, 0)
6563

66-
allStates.insert(0, eecState)
67-
allStates.insert(0, ecState)
68-
allStates.insert(0, startState)
64+
allStates(2) = eecState
65+
allStates(1) = ecState
66+
allStates(0) = startState
6967

70-
new DFAFieldImpl(allStates.toArray)
68+
new DFAFieldImpl(allStates)
7169
}
7270

7371
/**
7472
* Constructs a DFAField object with EscpaeSchemeKind.Block
7573
*/
7674
def apply(blockEnd: DFADelimiter, EEC: MaybeChar): DFAField = {
7775

78-
val allStates: ArrayBuffer[State] = ArrayBuffer.empty
76+
val allStates: Array[State] = new Array[State](2)
7977

8078
val eecState = new EECStateBlock(allStates, blockEnd, EEC, 1)
8179
val startState = new StartStateEscapeBlock(allStates, blockEnd, EEC, 0)
8280

83-
allStates.insert(0, eecState)
84-
allStates.insert(0, startState)
81+
allStates(1) = eecState
82+
allStates(0) = startState
8583

86-
new DFAFieldImpl(allStates.toArray)
84+
new DFAFieldImpl(allStates)
8785
}
8886

8987
}

daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/dfa/CreatePaddingDFA.scala

+6-8
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717

1818
package org.apache.daffodil.runtime1.processors.dfa
1919

20-
import scala.collection.mutable.ArrayBuffer
21-
2220
import org.apache.daffodil.runtime1.processors.Delimiter
2321
import org.apache.daffodil.runtime1.processors.TermRuntimeData
2422
import org.apache.daffodil.runtime1.processors.parsers.DelimiterTextType
@@ -33,15 +31,15 @@ object CreatePaddingDFA {
3331
// TODO: In the future we will need to change this because the padChar isn't necessarily a char.
3432
// One can use it to specify a numeric byte to be used to pad as well.
3533

36-
val allStates: ArrayBuffer[State] = ArrayBuffer.empty
34+
val allStates: Array[State] = new Array[State](1)
3735

3836
val startState = new StartStatePadding(allStates, padChar)
3937

40-
allStates.insert(0, startState)
38+
allStates(0) = startState
4139

4240
new DFADelimiterImpl(
4341
DelimiterTextType.Other,
44-
allStates.toArray,
42+
allStates,
4543
padChar.toString(),
4644
rd.schemaFileLocation
4745
)
@@ -55,11 +53,11 @@ object CreatePaddingDFA {
5553
// TODO: In the future we will need to change this because the padChar isn't necessarily a char.
5654
// One can use it to specify a numeric byte to be used to pad as well.
5755

58-
val allStates: ArrayBuffer[State] = ArrayBuffer.empty
56+
val allStates: Array[State] = new Array[State](1)
5957

6058
val startState = new StartStatePadding(allStates, padChar)
6159

62-
allStates.insert(0, startState)
60+
allStates(0) = startState
6361

6462
val d = new Delimiter()
6563
d.compileDelimiter(padChar.toString, false)
@@ -68,7 +66,7 @@ object CreatePaddingDFA {
6866

6967
new DFADelimiterImplUnparse(
7068
DelimiterTextType.Other,
71-
allStates.toArray,
69+
allStates,
7270
padChar.toString(),
7371
unparseValue,
7472
rd.schemaFileLocation

0 commit comments

Comments
 (0)