@@ -33,3 +33,32 @@ void memfault_base64_encode(const void *buf, size_t buf_len, void *base64_out) {
33
33
out_bufp [curr_idx ++ ] = ((bin_idx + 2 ) < buf_len ) ? prv_get_char_from_word (triple , 0 ) : '=' ;
34
34
}
35
35
}
36
+
37
+ void memfault_base64_encode_inplace (void * buf , size_t bin_len ) {
38
+ // When encoding with base64, every 3 bytes is represented as 4 characters. If the input binary
39
+ // blob is not a multiple of 3, we will need to use the "=" padding character. Here we determine
40
+ // what index to start encoding at that will end on a multiple of 3 boundary
41
+ const size_t remainder = bin_len % 3 ;
42
+ const size_t start_idx = (remainder == 0 ) ? bin_len - 3 : bin_len - remainder ;
43
+
44
+ // The index to write the base64 character conversion into starting with the last location
45
+ const size_t encoded_len = MEMFAULT_BASE64_ENCODE_LEN (bin_len );
46
+ int curr_idx = (int )encoded_len - 1 ;
47
+
48
+ const uint8_t * bin_inp = (const uint8_t * )buf ;
49
+ char * out_bufp = (char * )buf ;
50
+
51
+ // NB: By encoding from last set of 3 bytes to first set, we can edit the buffer inplace
52
+ // without clobbering the input data we need to determine the encoding
53
+ for (int bin_idx = (int )start_idx ; bin_idx >= 0 ; bin_idx -= 3 ) {
54
+ const uint32_t byte0 = bin_inp [bin_idx ];
55
+ const uint32_t byte1 = ((bin_idx + 1 ) < (int )bin_len ) ? bin_inp [bin_idx + 1 ] : 0 ;
56
+ const uint32_t byte2 = ((bin_idx + 2 ) < (int )bin_len ) ? bin_inp [bin_idx + 2 ] : 0 ;
57
+ const uint32_t triple = (byte0 << 16 ) + (byte1 << 8 ) + byte2 ;
58
+
59
+ out_bufp [curr_idx -- ] = ((bin_idx + 2 ) < (int )bin_len ) ? prv_get_char_from_word (triple , 0 ) : '=' ;
60
+ out_bufp [curr_idx -- ] = ((bin_idx + 1 ) < (int )bin_len ) ? prv_get_char_from_word (triple , 1 ) : '=' ;
61
+ out_bufp [curr_idx -- ] = prv_get_char_from_word (triple , 2 );
62
+ out_bufp [curr_idx -- ] = prv_get_char_from_word (triple , 3 );
63
+ }
64
+ }
0 commit comments