@@ -1008,7 +1008,13 @@ bool canardTableDecodeMessage(const CanardCodingTable* table,
10081008 uint32_t bit_ofs = 0 ;
10091009 const CanardCodingTableEntry * entry = & table -> entries [0 ];
10101010 const CanardCodingTableEntry * entry_last = & table -> entries [table -> entries_max ];
1011- if (tableDecodeCore (entry , entry_last , transfer , & bit_ofs , msg )) {
1011+ if (tableDecodeCore (entry , entry_last , transfer , & bit_ofs , msg ,
1012+ #if CANARD_ENABLE_TAO_OPTION
1013+ transfer -> tao
1014+ #else
1015+ true
1016+ #endif
1017+ )) {
10121018 return true; // decode failure
10131019 }
10141020
@@ -1038,7 +1044,13 @@ uint32_t canardTableEncodeMessage(const CanardCodingTable* table,
10381044 uint32_t bit_ofs = 0 ;
10391045 const CanardCodingTableEntry * entry = & table -> entries [0 ];
10401046 const CanardCodingTableEntry * entry_last = & table -> entries [table -> entries_max ];
1041- tableEncodeCore (entry , entry_last , buffer , & bit_ofs , msg );
1047+ tableEncodeCore (entry , entry_last , buffer , & bit_ofs , msg ,
1048+ #if CANARD_ENABLE_TAO_OPTION
1049+ tao
1050+ #else
1051+ true
1052+ #endif
1053+ );
10421054
10431055 return ((bit_ofs + 7 )/8 );
10441056}
@@ -1897,7 +1909,8 @@ CANARD_INTERNAL bool tableDecodeCore(const CanardCodingTableEntry* entry,
18971909 const CanardCodingTableEntry * entry_last ,
18981910 const CanardRxTransfer * transfer ,
18991911 uint32_t * bit_ofs ,
1900- void * msg )
1912+ void * msg ,
1913+ bool tao )
19011914{
19021915 do {
19031916 void * p = (char * )msg + entry -> offset ;
@@ -1931,7 +1944,7 @@ CANARD_INTERNAL bool tableDecodeCore(const CanardCodingTableEntry* entry,
19311944
19321945 uint16_t elems = aux -> type | ((uint16_t )aux -> bitlen << 8 );
19331946 while (elems -- ) {
1934- if (tableDecodeCore (array_entry , array_entry_last , transfer , bit_ofs , p )) {
1947+ if (tableDecodeCore (array_entry , array_entry_last , transfer , bit_ofs , p , ! elems && tao )) {
19351948 return true;
19361949 }
19371950 p = (char * )p + aux -> offset ;
@@ -1940,6 +1953,60 @@ CANARD_INTERNAL bool tableDecodeCore(const CanardCodingTableEntry* entry,
19401953 break ;
19411954 }
19421955
1956+ case CANARD_TABLE_CODING_ARRAY_DYNAMIC :
1957+ case CANARD_TABLE_CODING_ARRAY_DYNAMIC_TAO : {
1958+ const CanardCodingTableEntry * aux = ++ entry ;
1959+ const CanardCodingTableEntry * aux2 = ++ entry ;
1960+ const CanardCodingTableEntry * array_entry = ++ entry ;
1961+ const CanardCodingTableEntry * array_entry_last = array_entry + bitlen ;
1962+ entry = array_entry_last ; // point entry to last for ++entry at end of loop
1963+
1964+ uint16_t max_len = aux -> type | ((uint16_t )aux -> bitlen << 8 );
1965+ void * len_p = ((char * )msg + aux2 -> offset );
1966+ uint8_t len_bitlen = aux2 -> bitlen ;
1967+ if (type != CANARD_TABLE_CODING_ARRAY_DYNAMIC_TAO || !tao ) {
1968+ // not using TAO
1969+ canardDecodeScalar (transfer , * bit_ofs , len_bitlen , false, len_p );
1970+ * bit_ofs += len_bitlen ;
1971+
1972+ uint16_t elems ;
1973+ if (len_bitlen <= 8 ) {
1974+ elems = * (uint8_t * )len_p ;
1975+ } else { // 16 bits is max supported len
1976+ elems = * (uint16_t * )len_p ;
1977+ }
1978+ if (elems > max_len ) {
1979+ return true; // invalid value
1980+ }
1981+
1982+ while (elems -- ) {
1983+ if (tableDecodeCore (array_entry , array_entry_last , transfer , bit_ofs , p , !elems && tao )) {
1984+ return true;
1985+ }
1986+ p = (char * )p + aux -> offset ;
1987+ }
1988+ } else {
1989+ // TAO optimization in play
1990+ uint16_t elems = 0 ;
1991+ // TAO requires the element size to be at least 8 bits so if we have less we know we are done
1992+ uint32_t max_bits = (transfer -> payload_len * 8 )- 7 ;
1993+ while (max_bits > * bit_ofs ) {
1994+ if (!max_len -- || tableDecodeCore (array_entry , array_entry_last , transfer , bit_ofs , p , false)) {
1995+ return true;
1996+ }
1997+ p = (char * )p + aux -> offset ;
1998+ elems ++ ;
1999+ }
2000+ if (len_bitlen <= 8 ) {
2001+ * (uint8_t * )len_p = (uint8_t )elems ;
2002+ } else { // 16 bits is max supported len
2003+ * (uint16_t * )len_p = elems ;
2004+ }
2005+ }
2006+
2007+ break ;
2008+ }
2009+
19432010 default :
19442011 return true; // invalid type
19452012 }
@@ -1954,7 +2021,8 @@ CANARD_INTERNAL void tableEncodeCore(const CanardCodingTableEntry* entry,
19542021 const CanardCodingTableEntry * entry_last ,
19552022 uint8_t * buffer ,
19562023 uint32_t * bit_ofs ,
1957- const void * msg )
2024+ const void * msg ,
2025+ bool tao )
19582026{
19592027 do {
19602028 const void * p = (const char * )msg + entry -> offset ;
@@ -1989,7 +2057,51 @@ CANARD_INTERNAL void tableEncodeCore(const CanardCodingTableEntry* entry,
19892057
19902058 uint16_t elems = aux -> type | ((uint16_t )aux -> bitlen << 8 );
19912059 while (elems -- ) {
1992- tableEncodeCore (array_entry , array_entry_last , buffer , bit_ofs , p );
2060+ tableEncodeCore (array_entry , array_entry_last , buffer , bit_ofs , p , !elems && tao );
2061+ p = (const char * )p + aux -> offset ;
2062+ }
2063+
2064+ break ;
2065+ }
2066+
2067+ case CANARD_TABLE_CODING_ARRAY_DYNAMIC :
2068+ case CANARD_TABLE_CODING_ARRAY_DYNAMIC_TAO : {
2069+ const CanardCodingTableEntry * aux = ++ entry ;
2070+ const CanardCodingTableEntry * aux2 = ++ entry ;
2071+ const CanardCodingTableEntry * array_entry = ++ entry ;
2072+ const CanardCodingTableEntry * array_entry_last = array_entry + bitlen ;
2073+ entry = array_entry_last ; // point entry to last for ++entry at end of loop
2074+
2075+ uint16_t max_len = aux -> type | ((uint16_t )aux -> bitlen << 8 );
2076+ const void * len_p = (const char * )msg + aux2 -> offset ;
2077+ uint8_t len_bitlen = aux2 -> bitlen ;
2078+
2079+ uint16_t elems ;
2080+ if (len_bitlen <= 8 ) {
2081+ elems = * (const uint8_t * )len_p ;
2082+ } else { // 16 bits is max supported len
2083+ elems = * (const uint16_t * )len_p ;
2084+ }
2085+ if (elems > max_len ) {
2086+ elems = max_len ;
2087+ }
2088+
2089+ if (type != CANARD_TABLE_CODING_ARRAY_DYNAMIC_TAO || !tao ) {
2090+ // encode the length value we have clamped to the maximum
2091+ uint8_t elems_8 ;
2092+ if (len_bitlen <= 8 ) {
2093+ elems_8 = (uint8_t )elems ;
2094+ len_p = & elems_8 ;
2095+ } else { // 16 bits is max supported len
2096+ len_p = & elems ;
2097+ }
2098+ canardEncodeScalar (buffer , * bit_ofs , len_bitlen , len_p );
2099+ * bit_ofs += len_bitlen ;
2100+ }
2101+
2102+ int element_tao = type != CANARD_TABLE_CODING_ARRAY_DYNAMIC_TAO && tao ;
2103+ while (elems -- ) {
2104+ tableEncodeCore (array_entry , array_entry_last , buffer , bit_ofs , p , !elems && element_tao );
19932105 p = (const char * )p + aux -> offset ;
19942106 }
19952107
0 commit comments