Skip to content

Commit 079999d

Browse files
authored
C/C++ sbe rewind (aeron-io#863)
* [C++] Partial test for rewind. * [C++] Implement SBE rewind for C++ codecs. * [C] Implement SBE rewind for C codecs. * [C] Use template params correctly in C code generator.
1 parent f99b6b5 commit 079999d

File tree

5 files changed

+381
-1
lines changed

5 files changed

+381
-1
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ file(GLOB_RECURSE SBE_SOURCES
153153
)
154154

155155
add_custom_command(OUTPUT ${SBE_JAR}
156-
COMMAND ./gradlew assemble -x javadoc
156+
COMMAND ./gradlew assemble -x javadoc --console=plain
157157
DEPENDS ${SBE_SOURCES}
158158
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
159159
COMMENT "Generating SBE jar"

sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/c/CGenerator.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,6 +1868,7 @@ private CharSequence generateMessageFlyweightStruct(final String structName)
18681868
" uint64_t buffer_length;\n" +
18691869
" uint64_t offset;\n" +
18701870
" uint64_t position;\n" +
1871+
" uint64_t acting_block_length;\n" +
18711872
" uint64_t acting_version;\n" +
18721873
"};\n",
18731874
structName);
@@ -1920,6 +1921,7 @@ private CharSequence generateMessageFlyweightFunctions(
19201921
" codec->buffer = buffer;\n" +
19211922
" codec->offset = offset;\n" +
19221923
" codec->buffer_length = buffer_length;\n" +
1924+
" codec->acting_block_length = acting_block_length;\n" +
19231925
" codec->acting_version = acting_version;\n" +
19241926
" if (!%10$s_set_sbe_position(codec, offset + acting_block_length))\n" +
19251927
" {\n" +
@@ -1935,6 +1937,7 @@ private CharSequence generateMessageFlyweightFunctions(
19351937
" codec->buffer = other->buffer;\n" +
19361938
" codec->offset = other->offset;\n" +
19371939
" codec->buffer_length = other->buffer_length;\n" +
1940+
" codec->acting_block_length = other->acting_block_length;\n" +
19381941
" codec->acting_version = other->acting_version;\n" +
19391942
" codec->position = other->position;\n\n" +
19401943
" return codec;\n" +
@@ -2028,6 +2031,18 @@ private CharSequence generateMessageFlyweightFunctions(
20282031
" acting_version);\n" +
20292032
"}\n\n" +
20302033

2034+
"SBE_ONE_DEF struct %10$s *%10$s_sbe_rewind(\n" +
2035+
" struct %10$s *const codec)\n" +
2036+
"{\n" +
2037+
" return %10$s_wrap_for_decode(\n" +
2038+
" codec,\n" +
2039+
" codec->buffer,\n" +
2040+
" codec->offset,\n" +
2041+
" codec->acting_block_length,\n" +
2042+
" codec->acting_version,\n" +
2043+
" codec->buffer_length);\n" +
2044+
"}\n\n" +
2045+
20312046
"SBE_ONE_DEF uint64_t %10$s_encoded_length(\n" +
20322047
" const struct %10$s *const codec)\n" +
20332048
"{\n" +

sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,6 +2050,12 @@ private CharSequence generateMessageFlyweightCode(final String className, final
20502050
" return *this = %10$s(buffer, offset, bufferLength, actingBlockLength, actingVersion);\n" +
20512051
" }\n\n" +
20522052

2053+
" %10$s &sbeRewind()\n" +
2054+
" {\n" +
2055+
" return wrapForDecode(" +
2056+
"m_buffer, m_offset, m_actingBlockLength, m_actingVersion, m_bufferLength);\n" +
2057+
" }\n\n" +
2058+
20532059
" SBE_NODISCARD std::uint64_t sbePosition() const SBE_NOEXCEPT\n" +
20542060
" {\n" +
20552061
" return m_position;\n" +

sbe-tool/src/test/c/CodeGenTest.cpp

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,178 @@ class CodeGenTest : public testing::Test
220220
return CGT(car_encoded_length)(&car);
221221
}
222222

223+
static std::string walkCar(CGT(car)& car)
224+
{
225+
std::stringstream output;
226+
227+
output <<
228+
CGT(car_serialNumber)(&car) << ';' <<
229+
CGT(car_modelYear) << ';' <<
230+
CGT(car_available) << ';' <<
231+
CGT(car_code) << ';';
232+
233+
for (std::uint64_t i = 0; i < CGT(car_someNumbers_length()); i++)
234+
{
235+
output << (int)CGT(car_someNumbers_buffer(&car))[i] << ';';
236+
}
237+
238+
output << std::string(CGT(car_vehicleCode_buffer(&car)), CGT(car_vehicleCode_length())) << ';';
239+
240+
CGT(optionalExtras) extras = {};
241+
if (!CGT(car_extras)(&car, &extras))
242+
{
243+
output <<
244+
CGT(optionalExtras_sunRoof)(&extras) << ';' <<
245+
CGT(optionalExtras_sportsPack)(&extras) << ';' <<
246+
CGT(optionalExtras_cruiseControl)(&extras) << ';';
247+
}
248+
249+
char code_buf[4];
250+
CGT(engine) engine = {};
251+
if (CGT(car_engine)(&car, &engine))
252+
{
253+
output <<
254+
CGT(engine_capacity(&engine)) << ';' <<
255+
(int)CGT(engine_numCylinders(&engine)) << ';' <<
256+
CGT(engine_maxRpm()) << ';' <<
257+
CGT(engine_get_manufacturerCode(&engine, code_buf, 3)) << ';' <<
258+
std::string(CGT(engine_fuel()), CGT(engine_fuel_length())) << ';';
259+
}
260+
261+
CGT(car_fuelFigures) fuelFigures = {};
262+
if (CGT(car_get_fuelFigures)(&car, &fuelFigures))
263+
{
264+
while (CGT(car_fuelFigures_has_next)(&fuelFigures))
265+
{
266+
CGT(car_fuelFigures_next)(&fuelFigures);
267+
output <<
268+
CGT(car_fuelFigures_speed(&fuelFigures)) << ';' <<
269+
CGT(car_fuelFigures_mpg(&fuelFigures)) << ';' <<
270+
std::string(
271+
CGT(car_fuelFigures_usageDescription(&fuelFigures)),
272+
CGT(car_fuelFigures_usageDescription_length(&fuelFigures))) << ';';
273+
}
274+
}
275+
276+
CGT(car_performanceFigures) perfFigures = {};
277+
if (CGT(car_get_performanceFigures(&car, &perfFigures)))
278+
{
279+
output << CGT(car_performanceFigures_count)(&perfFigures) << ';';
280+
281+
while (CGT(car_performanceFigures_has_next)(&perfFigures))
282+
{
283+
CGT(car_performanceFigures_next(&perfFigures));
284+
output << CGT(car_performanceFigures_octaneRating(&perfFigures)) << ';';
285+
286+
CGT(car_performanceFigures_acceleration) acceleration = {};
287+
if (CGT(car_performanceFigures_get_acceleration(&perfFigures, &acceleration)))
288+
{
289+
while (CGT(car_performanceFigures_acceleration_has_next)(&acceleration))
290+
{
291+
CGT(car_performanceFigures_acceleration_next(&acceleration));
292+
output <<
293+
CGT(car_performanceFigures_acceleration_mph(&acceleration)) << ';' <<
294+
CGT(car_performanceFigures_acceleration_seconds(&acceleration)) << ';';
295+
}
296+
}
297+
}
298+
}
299+
300+
CGT(car_string_view) manufacturer = CGT(car_get_manufacturer_as_string_view(&car));
301+
if (nullptr != manufacturer.data)
302+
{
303+
output << std::string(manufacturer.data, manufacturer.length) << ';';
304+
}
305+
CGT(car_string_view) model = CGT(car_get_model_as_string_view(&car));
306+
if (nullptr != model.data)
307+
{
308+
output << std::string(model.data, model.length) << ';';
309+
}
310+
311+
return output.str();
312+
}
313+
314+
static std::string partialWalkCar(CGT(car)& car)
315+
{
316+
std::stringstream output;
317+
318+
output <<
319+
CGT(car_serialNumber)(&car) << ';' <<
320+
CGT(car_modelYear) << ';' <<
321+
CGT(car_available) << ';' <<
322+
CGT(car_code) << ';';
323+
324+
for (std::uint64_t i = 0; i < CGT(car_someNumbers_length()); i++)
325+
{
326+
output << (int)CGT(car_someNumbers_buffer(&car))[i] << ';';
327+
}
328+
329+
output << std::string(CGT(car_vehicleCode_buffer(&car)), CGT(car_vehicleCode_length())) << ';';
330+
331+
CGT(optionalExtras) extras = {};
332+
if (!CGT(car_extras)(&car, &extras))
333+
{
334+
output <<
335+
CGT(optionalExtras_sunRoof)(&extras) << ';' <<
336+
CGT(optionalExtras_sportsPack)(&extras) << ';' <<
337+
CGT(optionalExtras_cruiseControl)(&extras) << ';';
338+
}
339+
340+
char code_buf[4];
341+
CGT(engine) engine = {};
342+
if (CGT(car_engine)(&car, &engine))
343+
{
344+
output <<
345+
CGT(engine_capacity(&engine)) << ';' <<
346+
(int)CGT(engine_numCylinders(&engine)) << ';' <<
347+
CGT(engine_maxRpm()) << ';' <<
348+
CGT(engine_get_manufacturerCode(&engine, code_buf, 3)) << ';' <<
349+
std::string(CGT(engine_fuel()), CGT(engine_fuel_length())) << ';';
350+
}
351+
352+
CGT(car_fuelFigures) fuelFigures = {};
353+
if (CGT(car_get_fuelFigures)(&car, &fuelFigures))
354+
{
355+
while (CGT(car_fuelFigures_has_next)(&fuelFigures))
356+
{
357+
CGT(car_fuelFigures_next)(&fuelFigures);
358+
output <<
359+
CGT(car_fuelFigures_speed(&fuelFigures)) << ';' <<
360+
CGT(car_fuelFigures_mpg(&fuelFigures)) << ';' <<
361+
std::string(
362+
CGT(car_fuelFigures_usageDescription(&fuelFigures)),
363+
CGT(car_fuelFigures_usageDescription_length(&fuelFigures))) << ';';
364+
}
365+
}
366+
367+
CGT(car_performanceFigures) perfFigures = {};
368+
if (CGT(car_get_performanceFigures(&car, &perfFigures)))
369+
{
370+
output << CGT(car_performanceFigures_count)(&perfFigures) << ';';
371+
372+
if (CGT(car_performanceFigures_has_next)(&perfFigures))
373+
{
374+
CGT(car_performanceFigures_next(&perfFigures));
375+
output << CGT(car_performanceFigures_octaneRating(&perfFigures)) << ';';
376+
377+
CGT(car_performanceFigures_acceleration) acceleration = {};
378+
if (CGT(car_performanceFigures_get_acceleration(&perfFigures, &acceleration)))
379+
{
380+
if (CGT(car_performanceFigures_acceleration_has_next)(&acceleration))
381+
{
382+
CGT(car_performanceFigures_acceleration_next(&acceleration));
383+
output <<
384+
CGT(car_performanceFigures_acceleration_mph(&acceleration)) << ';' <<
385+
CGT(car_performanceFigures_acceleration_seconds(&acceleration)) << ';';
386+
}
387+
}
388+
}
389+
}
390+
391+
return output.str();
392+
}
393+
394+
223395
std::uint64_t encodeHdr(char *buffer, std::uint64_t offset, std::uint64_t bufferLength)
224396
{
225397
if (!CGT(messageHeader_wrap)(&m_hdr, buffer, offset, 0, bufferLength))
@@ -1009,3 +1181,43 @@ TEST_F(CodeGenTest, shouldBeAbleToUseStdStringMethodsForDecode)
10091181

10101182
EXPECT_EQ(CGT(car_encoded_length)(&carDecoder), expectedCarEncodedLength);
10111183
}
1184+
1185+
TEST_F(CodeGenTest, shouldAllowForMultipleIterations2)
1186+
{
1187+
char buffer[2048] = {};
1188+
1189+
std::uint64_t hdrSz = encodeHdr(buffer, 0, sizeof(buffer));
1190+
std::uint64_t carEncodedLength = encodeCar(
1191+
buffer, CGT(messageHeader_encoded_length)(), sizeof(buffer) - CGT(messageHeader_encoded_length)());
1192+
1193+
if (!CGT(messageHeader_wrap)(&m_hdrDecoder, buffer, 0, 0, hdrSz))
1194+
{
1195+
throw std::runtime_error(sbe_strerror(errno));
1196+
}
1197+
1198+
if (!CGT(car_wrap_for_decode)(
1199+
&m_carDecoder,
1200+
buffer,
1201+
CGT(messageHeader_encoded_length)(),
1202+
CGT(car_sbe_block_length)(),
1203+
CGT(car_sbe_schema_version)(),
1204+
hdrSz + carEncodedLength))
1205+
{
1206+
throw std::runtime_error(sbe_strerror(errno));
1207+
}
1208+
1209+
std::string passOne = walkCar(m_carDecoder);
1210+
CGT(car_sbe_rewind(&m_carDecoder));
1211+
std::string passTwo = walkCar(m_carDecoder);
1212+
EXPECT_EQ(passOne, passTwo);
1213+
1214+
CGT(car_sbe_rewind(&m_carDecoder));
1215+
std::string passThree = partialWalkCar(m_carDecoder);
1216+
CGT(car_sbe_rewind(&m_carDecoder));
1217+
std::string passFour = partialWalkCar(m_carDecoder);
1218+
EXPECT_EQ(passThree, passFour);
1219+
1220+
CGT(car_sbe_rewind(&m_carDecoder));
1221+
std::string passFive = walkCar(m_carDecoder);
1222+
EXPECT_EQ(passOne, passFive);
1223+
}

0 commit comments

Comments
 (0)