pure subroutine encode_bits(bits, padd, code)
!< Encode a bits stream (must be multiple of 24 bits) into base64 charcaters code (of length multiple of 4).
!<
!< The bits stream are encoded in chunks of 24 bits as the following example (in little endian order)
!<```
!< +--first octet--+-second octet--+--third octet--+
!< |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
!< +-----------+---+-------+-------+---+-----------+
!< |5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|
!< +--1.index--+--2.index--+--3.index--+--4.index--+
!<```
!< @note The 4 indexes are stored into 4 elements 8 bits array, thus 2 bits of each array element are not used.
!<
!< @note The number of paddings must be computed outside this procedure, into the calling scope.
!<
!< @warning This procedure is the backend of encoding, thus it must be never called outside the module.
integer(I1P), intent(in) :: bits(1:) !< Bits to be encoded.
integer(I4P), intent(in) :: padd !< Number of padding characters ('=').
character(*), intent(out) :: code !< Characters code.
integer(I1P) :: sixb(1:4) !< 6 bits slices (stored into 8 bits integer) of 24 bits input.
integer(I8P) :: c !< Counter.
integer(I8P) :: e !< Counter.
integer(I8P) :: Nb !< Length of bits array.
Nb=size(bits,dim=1,kind=I8P)
c = 1_I8P
do e=1_I8P,Nb,3_I8P ! loop over array elements: 3 bytes (24 bits) scanning
sixb = 0_I1P
call mvbits(bits(e ),2,6,sixb(1),0)
call mvbits(bits(e ),0,2,sixb(2),4)
if (e+1<=Nb) then
call mvbits(bits(e+1),4,4,sixb(2),0)
call mvbits(bits(e+1),0,4,sixb(3),2)
endif
if (e+2<=Nb) then
call mvbits(bits(e+2),6,2,sixb(3),0)
call mvbits(bits(e+2),0,6,sixb(4),0)
endif
sixb = sixb + 1_I1P
code(c :c ) = base64(sixb(1):sixb(1))
code(c+1:c+1) = base64(sixb(2):sixb(2))
code(c+2:c+2) = base64(sixb(3):sixb(3))
code(c+3:c+3) = base64(sixb(4):sixb(4))
c = c + 4_I8P
enddo
if (padd>0) code(len(code)-padd+1:)=repeat('=',padd)
endsubroutine encode_bits