1616final class EmptyCollectionHelper {
1717
1818 /**
19- * This function determine the new offset in signature for empty collections.
19+ * This function determine the new offset in signature for empty Dictionary/Map collections.
2020 * Normally the element inside a collection determines the new offset,
2121 * however in case of empty collections there is no element to determine the sub signature of the list
2222 * so this function determines which part of the signature to skip
2323 * @param sigb the total signature
2424 * @param currentOffset the current offset within the signature
2525 * @return the index of the last element of the collection (subtype)
2626 */
27- static int determineSignatureOffset (byte [] sigb , int currentOffset ) {
28- byte [] restSigbytes = Arrays .copyOfRange (sigb , currentOffset , sigb .length );
29- String sigSubString = new String (restSigbytes );
27+ static int determineSignatureOffsetDict (byte [] sigb , int currentOffset ) {
28+ return determineEndOfBracketStructure (sigb , currentOffset , '{' , '}' );
29+ }
30+
31+ /**
32+ * This function determine the new offset in signature for empty Array/List collections.
33+ * Normally the element inside a collection determines the new offset,
34+ * however in case of empty collections there is no element to determine the sub signature of the list
35+ * so this function determines which part of the signature to skip
36+ * @param sigb the total signature
37+ * @param currentOffset the current offset within the signature
38+ * @return the index of the last element of the collection (subtype)
39+ */
40+ static int determineSignatureOffsetArray (byte [] sigb , int currentOffset ) {
41+ String sigSubString = determineSubSignature (sigb , currentOffset );
3042
3143 // End of string so can't have any more offset
3244 if (sigSubString .isEmpty ()) {
3345 return currentOffset ;
3446 }
3547
36- // find end of structure
37- // meaning the end of the sub structure
48+ ECollectionSubType newtype = determineCollectionSubType ((char )sigb [currentOffset ]);
49+ switch (newtype ) {
50+ case ARRAY :
51+ // array in array so look at the next type
52+ return determineSignatureOffsetArray (sigb , currentOffset + 1 );
53+ case DICT :
54+ return determineSignatureOffsetDict (sigb , currentOffset );
55+ case STRUCT :
56+ return determineSignatureOffsetStruct (sigb , currentOffset );
57+ case PRIMITIVE :
58+ //primitive is always one element so no need to skip more
59+ return currentOffset ;
60+ default :
61+ break ;
62+
63+ }
64+ throw new IllegalStateException ("Unable to parse signature for empty collection" );
65+ }
66+
67+ private static int determineSignatureOffsetStruct (byte [] sigb , int currentOffset ) {
68+ return determineEndOfBracketStructure (sigb , currentOffset , '(' , ')' );
69+ }
70+
71+ /**
72+ * This is a generic function to determine the end of a structure that has opening and closing characters.
73+ * Currently used for Struct () and Dict {}
74+ *
75+ */
76+ private static int determineEndOfBracketStructure (byte [] sigb , int currentOffset , char openChar , char closeChar ) {
77+ String sigSubString = determineSubSignature (sigb , currentOffset );
78+
79+ // End of string so can't have any more offset
80+ if (sigSubString .isEmpty ()) {
81+ return currentOffset ;
82+ }
3883 int i = 0 ;
39- int structsDepth = 0 ;
40- int dictDepth = 0 ;
84+ int depth = 0 ;
4185
42- ECollectionSubType subTypeCategory = determineCollectionSubType ((char )sigb [currentOffset ]);
4386 for (char chr : sigSubString .toCharArray ()) {
4487 //book keeping of depth of nested structures to solve opening closing bracket problem
45- switch (chr ) {
46- case '(' :
47- structsDepth ++;
48- break ;
49- case ')' :
50- structsDepth --;
51- break ;
52- case '{' :
53- dictDepth ++;
54- break ;
55- case '}' :
56- dictDepth --;
57- break ;
58- default :
59- break ;
88+ if (chr == openChar ) {
89+ depth ++;
90+ } else if (chr == closeChar ) {
91+ depth --;
6092 }
61-
62- // determine the case on when to return since subtype is complete
63- switch (subTypeCategory ) {
64- case STRUCT :
65- if (structsDepth == 0 ) {
66- return currentOffset + i ;
67- }
68- break ;
69- case DICT :
70- if (dictDepth == 0 ) {
71- return currentOffset + i ;
72- }
73- break ;
74- case ARRAY :
75- // array is a strange type it has on starting/ending character. It just uses the next full type.
76- // For example aa(ii) means an array of arrays of struct with two Integer.
77- return determineSignatureOffset (sigb , currentOffset + i + 1 );
78- case PRIMITIVE :
79- default :
80- return currentOffset + i ;
93+ if (depth == 0 ) {
94+ return currentOffset + i ;
8195 }
8296 i ++;
8397 }
8498 throw new IllegalStateException ("Unable to parse signature for empty collection" );
8599 }
86-
87100
101+ private static String determineSubSignature (byte [] sigb , int currentOffset ) {
102+ byte [] restSigbytes = Arrays .copyOfRange (sigb , currentOffset , sigb .length );
103+ return new String (restSigbytes );
104+ }
105+
88106 /**
89107 * The starting type determines of a collection determines when it ends
90108 * @param sig the signature letter of the type
@@ -103,14 +121,13 @@ private static ECollectionSubType determineCollectionSubType(char sig) {
103121 }
104122 }
105123
106-
107124 /**
108125 * Internal Enumeration used to group the types of element
109126 */
110- private enum ECollectionSubType {
127+ enum ECollectionSubType {
111128 STRUCT ,
112129 DICT ,
113130 ARRAY ,
114131 PRIMITIVE
115132 }
116- }
133+ }
0 commit comments