Skip to content

Commit 533b50e

Browse files
committed
[Java]: Added support for fields to Java OTF decoder.
1 parent fcf23f1 commit 533b50e

File tree

9 files changed

+497
-50
lines changed

9 files changed

+497
-50
lines changed

build.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,10 @@
251251
<javac srcdir="${dir.examples.src}" destdir="${dir.examples.build}" includeAntRuntime="false" debug="true">
252252
<classpath refid="examples.classpath"/>
253253
</javac>
254-
<java classname="uk.co.real_logic.sbe.examples.GeneratedStubExample">
254+
<java classname="uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub">
255255
<classpath refid="examples.classpath"/>
256256
</java>
257-
<java classname="uk.co.real_logic.sbe.examples.GeneratedStubExtensionExample">
257+
<java classname="uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStubExtension">
258258
<classpath refid="examples.classpath"/>
259259
</java>
260260
</target>
@@ -316,7 +316,7 @@
316316
<sysproperty key="sbe.ir.filename" value="Car.sbeir"/>
317317
<arg value="${dir.examples.resources}/TestSchema.xml"/>
318318
</java>
319-
<java classname="uk.co.real_logic.sbe.examples.GeneratedStubExample">
319+
<java classname="uk.co.real_logic.sbe.examples.ExampleUsingGeneratedStub">
320320
<classpath refid="examples.classpath"/>
321321
<sysproperty key="sbe.encoding.filename" value="${dir.gen.cpp98}/Car.data"/>
322322
</java>

examples/java/uk/co/real_logic/sbe/examples/ExampleTokenListener.java

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,262 @@
1515
*/
1616
package uk.co.real_logic.sbe.examples;
1717

18+
import uk.co.real_logic.sbe.PrimitiveValue;
19+
import uk.co.real_logic.sbe.codec.java.CodecUtil;
20+
import uk.co.real_logic.sbe.codec.java.DirectBuffer;
21+
import uk.co.real_logic.sbe.ir.Encoding;
22+
import uk.co.real_logic.sbe.ir.Token;
1823
import uk.co.real_logic.sbe.otf.TokenListener;
1924

25+
import java.io.PrintWriter;
26+
import java.util.ArrayDeque;
27+
import java.util.Deque;
28+
import java.util.Iterator;
29+
import java.util.List;
30+
2031
public class ExampleTokenListener implements TokenListener
2132
{
33+
final PrintWriter out;
34+
final Deque<String> namedScope = new ArrayDeque<>();
35+
36+
public ExampleTokenListener(final PrintWriter out)
37+
{
38+
this.out = out;
39+
}
40+
41+
public void onBeginMessage(final Token token)
42+
{
43+
namedScope.push(token.name() + ".");
44+
}
45+
46+
public void onEndMessage(final Token token)
47+
{
48+
namedScope.pop();
49+
}
50+
51+
public void onEncoding(final Token fieldToken,
52+
final DirectBuffer buffer,
53+
final int index,
54+
final Token typeToken,
55+
final int actingVersion)
56+
{
57+
final CharSequence value = readEncodingAsString(buffer, index, typeToken, actingVersion);
58+
59+
printScope();
60+
out.append(fieldToken.name())
61+
.append('=')
62+
.append(value)
63+
.println();
64+
}
65+
66+
public void onEnum(final Token fieldToken,
67+
final DirectBuffer buffer, final int bufferIndex,
68+
final List<Token> tokens, final int beginIndex, final int endIndex,
69+
final int actingVersion,
70+
final TokenListener listener)
71+
{
72+
final Token typeToken = tokens.get(beginIndex + 1);
73+
final long encodedValue = readEncodingAsLong(buffer, bufferIndex, typeToken, actingVersion);
74+
75+
String value = null;
76+
for (int i = beginIndex + 1; i < endIndex; i++)
77+
{
78+
if (encodedValue == tokens.get(i).encoding().constVal().longValue())
79+
{
80+
value = tokens.get(i).name();
81+
break;
82+
}
83+
}
84+
85+
printScope();
86+
out.append(fieldToken.name())
87+
.append('=')
88+
.append(value)
89+
.println();
90+
}
91+
92+
public void onBitSet(final Token fieldToken,
93+
final DirectBuffer buffer, final int bufferIndex,
94+
final List<Token> tokens, final int beginIndex, final int endIndex,
95+
final int actingVersion,
96+
final TokenListener listener)
97+
{
98+
final Token typeToken = tokens.get(beginIndex + 1);
99+
final long encodedValue = readEncodingAsLong(buffer, bufferIndex, typeToken, actingVersion);
100+
101+
printScope();
102+
out.append(fieldToken.name()).append(':');
103+
104+
for (int i = beginIndex + 1; i < endIndex; i++)
105+
{
106+
out.append(' ').append(tokens.get(i).name()).append('=');
107+
108+
final long bitPosition = tokens.get(i).encoding().constVal().longValue();
109+
final boolean flag = (encodedValue & (1L << bitPosition)) != 0;
110+
111+
out.append(Boolean.toString(flag));
112+
}
113+
114+
out.println();
115+
}
116+
117+
public void onBeginComposite(final Token fieldToken, final List<Token> tokens, final int fromIndex, final int toIndex)
118+
{
119+
namedScope.push(fieldToken.name() + ".");
120+
}
121+
122+
public void onEndComposite(final Token fieldToken, final List<Token> tokens, final int fromIndex, final int toIndex)
123+
{
124+
namedScope.pop();
125+
}
126+
127+
private static CharSequence readEncodingAsString(final DirectBuffer buffer,
128+
final int index,
129+
final Token typeToken,
130+
final int actingVersion)
131+
{
132+
final PrimitiveValue constOrNotPresentValue = constOrNotPresentValue(typeToken, actingVersion);
133+
if (null != constOrNotPresentValue)
134+
{
135+
return constOrNotPresentValue.toString();
136+
}
137+
138+
final StringBuilder sb = new StringBuilder();
139+
final Encoding encoding = typeToken.encoding();
140+
final int elementSize = encoding.primitiveType().size();
141+
142+
for (int i = 0, size = typeToken.arrayLength(); i < size; i++)
143+
{
144+
mapEncodingToString(sb, buffer, index + (i * elementSize), encoding);
145+
sb.append(", ");
146+
}
147+
148+
sb.setLength(sb.length() - 2);
149+
150+
return sb;
151+
}
152+
153+
private long readEncodingAsLong(final DirectBuffer buffer, final int bufferIndex, final Token typeToken, final int actingVersion)
154+
{
155+
final PrimitiveValue constOrNotPresentValue = constOrNotPresentValue(typeToken, actingVersion);
156+
if (null != constOrNotPresentValue)
157+
{
158+
return constOrNotPresentValue.longValue();
159+
}
160+
161+
return readAsLong(buffer, bufferIndex, typeToken.encoding());
162+
}
163+
164+
private static PrimitiveValue constOrNotPresentValue(final Token token, final int actingVersion)
165+
{
166+
final Encoding encoding = token.encoding();
167+
if (Encoding.Presence.CONSTANT == encoding.presence())
168+
{
169+
return encoding.constVal();
170+
}
171+
else if (Encoding.Presence.OPTIONAL == encoding.presence())
172+
{
173+
if (token.version() < actingVersion)
174+
{
175+
return encoding.applicableNullVal();
176+
}
177+
}
178+
179+
return null;
180+
}
181+
182+
private static void mapEncodingToString(final StringBuilder sb, final DirectBuffer buffer, final int index, final Encoding encoding)
183+
{
184+
switch (encoding.primitiveType())
185+
{
186+
case CHAR:
187+
sb.append('\'').append((char)CodecUtil.charGet(buffer, index)).append('\'');
188+
break;
189+
190+
case INT8:
191+
sb.append(CodecUtil.int8Get(buffer, index));
192+
break;
193+
194+
case INT16:
195+
sb.append(CodecUtil.int16Get(buffer, index, encoding.byteOrder()));
196+
break;
197+
198+
case INT32:
199+
sb.append(CodecUtil.int32Get(buffer, index, encoding.byteOrder()));
200+
break;
201+
202+
case INT64:
203+
sb.append(CodecUtil.int64Get(buffer, index, encoding.byteOrder()));
204+
break;
205+
206+
case UINT8:
207+
sb.append(CodecUtil.uint8Get(buffer, index));
208+
break;
209+
210+
case UINT16:
211+
sb.append(CodecUtil.uint16Get(buffer, index, encoding.byteOrder()));
212+
break;
213+
214+
case UINT32:
215+
sb.append(CodecUtil.uint32Get(buffer, index, encoding.byteOrder()));
216+
break;
217+
218+
case UINT64:
219+
sb.append(CodecUtil.uint64Get(buffer, index, encoding.byteOrder()));
220+
break;
221+
222+
case FLOAT:
223+
sb.append(CodecUtil.floatGet(buffer, index, encoding.byteOrder()));
224+
break;
225+
226+
case DOUBLE:
227+
sb.append(CodecUtil.doubleGet(buffer, index, encoding.byteOrder()));
228+
break;
229+
}
230+
}
231+
232+
private static long readAsLong(final DirectBuffer buffer, final int index, final Encoding encoding)
233+
{
234+
switch (encoding.primitiveType())
235+
{
236+
case CHAR:
237+
return CodecUtil.charGet(buffer, index);
238+
239+
case INT8:
240+
return CodecUtil.int8Get(buffer, index);
241+
242+
case INT16:
243+
return CodecUtil.int16Get(buffer, index, encoding.byteOrder());
244+
245+
case INT32:
246+
return CodecUtil.int32Get(buffer, index, encoding.byteOrder());
247+
248+
case INT64:
249+
return CodecUtil.int64Get(buffer, index, encoding.byteOrder());
250+
251+
case UINT8:
252+
return CodecUtil.uint8Get(buffer, index);
253+
254+
case UINT16:
255+
return CodecUtil.uint16Get(buffer, index, encoding.byteOrder());
256+
257+
case UINT32:
258+
return CodecUtil.uint32Get(buffer, index, encoding.byteOrder());
259+
260+
case UINT64:
261+
return CodecUtil.uint64Get(buffer, index, encoding.byteOrder());
262+
263+
default:
264+
throw new IllegalArgumentException("Unsupported type for long: " + encoding.primitiveType());
265+
}
266+
}
267+
268+
private void printScope()
269+
{
270+
final Iterator<String> iter = namedScope.descendingIterator();
271+
while (iter.hasNext())
272+
{
273+
out.print(iter.next());
274+
}
275+
}
22276
}

examples/java/uk/co/real_logic/sbe/examples/GeneratedStubExample.java renamed to examples/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStub.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import java.nio.ByteBuffer;
2424
import java.nio.channels.FileChannel;
2525

26-
public class GeneratedStubExample
26+
public class ExampleUsingGeneratedStub
2727
{
2828
private static final String ENCODING_FILENAME = "sbe.encoding.filename";
2929
private static final byte[] VEHICLE_CODE;

examples/java/uk/co/real_logic/sbe/examples/GeneratedStubExtensionExample.java renamed to examples/java/uk/co/real_logic/sbe/examples/ExampleUsingGeneratedStubExtension.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import java.nio.ByteBuffer;
2424
import java.nio.channels.FileChannel;
2525

26-
public class GeneratedStubExtensionExample
26+
public class ExampleUsingGeneratedStubExtension
2727
{
2828
private static final String ENCODING_FILENAME = "sbe.encoding.filename";
2929
private static final byte[] VEHICLE_CODE;

examples/java/uk/co/real_logic/sbe/examples/OtfExample.java

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,24 @@
33
import baseline.Car;
44
import baseline.MessageHeader;
55
import uk.co.real_logic.sbe.codec.java.DirectBuffer;
6-
import uk.co.real_logic.sbe.ir.Decoder;
7-
import uk.co.real_logic.sbe.ir.Encoder;
8-
import uk.co.real_logic.sbe.ir.HeaderStructure;
9-
import uk.co.real_logic.sbe.ir.IntermediateRepresentation;
6+
import uk.co.real_logic.sbe.ir.*;
7+
import uk.co.real_logic.sbe.otf.OtfDecoder;
108
import uk.co.real_logic.sbe.otf.OtfHeaderDecoder;
119
import uk.co.real_logic.sbe.xml.IrGenerator;
1210
import uk.co.real_logic.sbe.xml.MessageSchema;
1311
import uk.co.real_logic.sbe.xml.XmlSchemaParser;
1412

15-
import java.io.FileInputStream;
13+
import java.io.*;
1614

17-
import java.io.IOException;
18-
import java.io.InputStream;
1915
import java.nio.ByteBuffer;
16+
import java.util.List;
2017

2118
public class OtfExample
2219
{
2320
private static final MessageHeader MESSAGE_HEADER = new MessageHeader();
2421
private static final Car CAR = new Car();
2522
private static final int ACTING_VERSION = 0;
26-
private static final int MSG_BUFFER_CAPACITY = 16 * 1024;
23+
private static final int MSG_BUFFER_CAPACITY = 4 * 1024;
2724
private static final int SCHEMA_BUFFER_CAPACITY = 16 * 1024;
2825

2926
public static void main(final String[] args) throws Exception
@@ -35,12 +32,11 @@ public static void main(final String[] args) throws Exception
3532
final ByteBuffer encodedMsgBuffer = ByteBuffer.allocateDirect(MSG_BUFFER_CAPACITY);
3633
encodeTestMessage(encodedMsgBuffer);
3734

38-
3935
// Now lets decode the schema IR so we have IR objects.
4036
encodedSchemaBuffer.flip();
4137
final IntermediateRepresentation ir = decodeIr(encodedSchemaBuffer);
4238

43-
// Now we have IR we can read the message headerStructure
39+
// Now we have IR we can read the message header
4440
int bufferOffset = 0;
4541
final DirectBuffer buffer = new DirectBuffer(encodedMsgBuffer);
4642
final OtfHeaderDecoder otfHeaderDecoder = new OtfHeaderDecoder(ir.headerStructure());
@@ -49,7 +45,22 @@ public static void main(final String[] args) throws Exception
4945
final int actingVersion = otfHeaderDecoder.getTemplateVersion(buffer, bufferOffset);
5046
final int blockLength = otfHeaderDecoder.getBlockLength(buffer, bufferOffset);
5147

52-
// Given the headerStructure we can select the appropriate message to decode.
48+
bufferOffset += otfHeaderDecoder.size();
49+
50+
// Given the header information we can select the appropriate message template to do the decode.
51+
final List<Token> msgTokens = ir.getMessage(templateId);
52+
final OtfDecoder oftDecoder = new OtfDecoder();
53+
bufferOffset = oftDecoder.decode(buffer,
54+
bufferOffset,
55+
actingVersion,
56+
blockLength,
57+
msgTokens,
58+
new ExampleTokenListener(new PrintWriter(System.out, true)));
59+
60+
if (bufferOffset != encodedMsgBuffer.position())
61+
{
62+
// throw new IllegalStateException("Message not fully decoded");
63+
}
5364
}
5465

5566
private static void encodeSchema(final ByteBuffer buffer)
@@ -75,7 +86,9 @@ private static void encodeTestMessage(final ByteBuffer buffer)
7586

7687
bufferOffset += MESSAGE_HEADER.size();
7788

78-
GeneratedStubExample.encode(CAR, directBuffer, bufferOffset);
89+
bufferOffset += ExampleUsingGeneratedStub.encode(CAR, directBuffer, bufferOffset);
90+
91+
buffer.position(bufferOffset);
7992
}
8093

8194
private static IntermediateRepresentation decodeIr(final ByteBuffer buffer)

0 commit comments

Comments
 (0)