Core base64 decoder
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | input | |||
| integer(kind=int8), | intent(out), | allocatable | :: | bytes(:) | ||
| integer, | intent(out) | :: | nbytes |
subroutine base64_decode_bytes(input, bytes, nbytes) !! Core base64 decoder use iso_fortran_env, only: int8 implicit none character(*), intent(in) :: input integer(int8), allocatable, intent(out) :: bytes(:) integer, intent(out) :: nbytes character(64), parameter :: b64 = & 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' integer :: i, j, in_len, ngroups, pad integer :: v0, v1, v2, v3 in_len = len_trim(input) if(in_len .eq. 0)then allocate(bytes(0)) nbytes = 0 return end if ! Count padding pad = 0 if(input(in_len:in_len) .eq. '=') pad = pad + 1 if(in_len .ge. 2 .and. input(in_len-1:in_len-1) .eq. '=') pad = pad + 1 ngroups = in_len / 4 nbytes = ngroups * 3 - pad allocate(bytes(nbytes)) j = 1 do i = 1, in_len, 4 v0 = index(b64, input(i:i)) - 1 v1 = index(b64, input(i+1:i+1)) - 1 if(input(i+2:i+2) .ne. '=')then v2 = index(b64, input(i+2:i+2)) - 1 else v2 = 0 end if if(input(i+3:i+3) .ne. '=')then v3 = index(b64, input(i+3:i+3)) - 1 else v3 = 0 end if if(j .le. nbytes) & bytes(j) = int(ior(ishft(v0, 2), ishft(v1, -4)), int8) if(j + 1 .le. nbytes) & bytes(j+1) = int(ior(ishft(iand(v1, 15), 4), ishft(v2, -2)), int8) if(j + 2 .le. nbytes) & bytes(j+2) = int(ior(ishft(iand(v2, 3), 6), v3), int8) j = j + 3 end do end subroutine base64_decode_bytes