Skip to content

Commit 35d974f

Browse files
author
thk123
committed
Add method for finding the matching ; corresponding to a reference L
1 parent e1621a3 commit 35d974f

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

src/java_bytecode/java_types.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,39 @@ build_class_name(const std::string src, const std::string &class_name_prefix)
320320
return java_reference_type(symbol_type);
321321
}
322322

323+
/// Finds the closing semi-colon ending a ClassTypeSignature that starts at
324+
/// \p starting_point.
325+
/// \param src: The input string to work on.
326+
/// \param starting_point: The string position where the opening 'L' we want to
327+
/// find the closing ';' for.
328+
/// \return The string position corresponding to the matching ';'. For example:
329+
/// LA;, we would return 2. For LA<TT;>; we would return 7.
330+
/// See unit/java_bytecode/java_util_tests.cpp for more examples.
331+
size_t find_closing_semi_colon_for_reference_type(
332+
const std::string src,
333+
size_t starting_point = 0)
334+
{
335+
PRECONDITION(src[starting_point] == 'L');
336+
size_t next_semi_colon = src.find(';', starting_point);
337+
INVARIANT(
338+
next_semi_colon != std::string::npos,
339+
"There must be a semi-colon somewhere in the input");
340+
size_t next_angle_bracket = src.find('<', starting_point);
341+
342+
while(next_angle_bracket < next_semi_colon)
343+
{
344+
size_t end_bracket =
345+
find_closing_delimiter(src, next_angle_bracket, '<', '>');
346+
INVARIANT(
347+
end_bracket != std::string::npos, "Must find matching angle bracket");
348+
349+
next_semi_colon = src.find(';', end_bracket + 1);
350+
next_angle_bracket = src.find('<', end_bracket + 1);
351+
}
352+
353+
return next_semi_colon;
354+
}
355+
323356
/// Transforms a string representation of a Java type into an internal type
324357
/// representation thereof.
325358
///

unit/java_bytecode/java_utils_test.cpp

+85
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,88 @@ SCENARIO("gather_full_class_name")
221221
}
222222
}
223223
}
224+
225+
SCENARIO("find_closing_semi_colon_for_reference_type", "[core][java_util_test]")
226+
{
227+
GIVEN("A simple reference type")
228+
{
229+
std::string descriptor = "LA;";
230+
// |
231+
// 012
232+
REQUIRE(find_closing_semi_colon_for_reference_type(descriptor, 0) == 2);
233+
}
234+
GIVEN("A generic reference type")
235+
{
236+
std::string descriptor = "LA<TT;>;";
237+
// |
238+
// 01234567
239+
REQUIRE(find_closing_semi_colon_for_reference_type(descriptor, 0) == 7);
240+
}
241+
GIVEN("A generic reference type with multiple generic params")
242+
{
243+
std::string descriptor = "LA<TT;TU;>;";
244+
// |
245+
// 01234567890
246+
REQUIRE(find_closing_semi_colon_for_reference_type(descriptor, 0) == 10);
247+
}
248+
GIVEN("A descriptor with multiple reference type")
249+
{
250+
std::string descriptor = "LA;LB;";
251+
// |
252+
// 012
253+
REQUIRE(find_closing_semi_colon_for_reference_type(descriptor, 0) == 2);
254+
}
255+
GIVEN("A descriptor with multiple reference types parsing the second")
256+
{
257+
std::string descriptor = "LA;LB;";
258+
// | |
259+
// 012345
260+
REQUIRE(find_closing_semi_colon_for_reference_type(descriptor, 3) == 5);
261+
}
262+
GIVEN("A descriptor inner class")
263+
{
264+
std::string descriptor = "LA$B;";
265+
// |
266+
// 01234
267+
REQUIRE(find_closing_semi_colon_for_reference_type(descriptor, 0) == 4);
268+
}
269+
GIVEN("A signature inner class")
270+
{
271+
std::string descriptor = "LA.B;";
272+
// |
273+
// 01234
274+
REQUIRE(find_closing_semi_colon_for_reference_type(descriptor, 0) == 4);
275+
}
276+
GIVEN("A inner class of a generic class")
277+
{
278+
std::string descriptor = "LA<TT;>.B;";
279+
// |
280+
// 0123456789
281+
REQUIRE(find_closing_semi_colon_for_reference_type(descriptor, 0) == 9);
282+
}
283+
GIVEN("A inner class of a instantiated generic class")
284+
{
285+
std::string descriptor = "LA<LFoo;>.B;";
286+
// |
287+
// 012345678901
288+
REQUIRE(find_closing_semi_colon_for_reference_type(descriptor, 0) == 11);
289+
}
290+
GIVEN(
291+
"A signature with multiple references and an inner class of a generic "
292+
"class")
293+
{
294+
std::string descriptor = "LA<TT;>.B;LA<TT;>.B;";
295+
// |
296+
// 0123456789
297+
REQUIRE(find_closing_semi_colon_for_reference_type(descriptor, 0) == 9);
298+
}
299+
GIVEN(
300+
"A signature with multiple references and an inner class of a generic "
301+
"class")
302+
{
303+
std::string descriptor = "LA<TT;>.B;LA<TT;>.B;";
304+
// | |
305+
// 01234567890123456789
306+
REQUIRE(find_closing_semi_colon_for_reference_type(descriptor, 10) == 19);
307+
}
308+
}

0 commit comments

Comments
 (0)