Skip to content
1 change: 1 addition & 0 deletions doc/specs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This is an index/directory of the specifications (specs) for each new module/fea
- [ansi](./stdlib_ansi.html) - Terminal color and style escape sequences
- [array](./stdlib_array.html) - Procedures for index manipulation and array handling
- [ascii](./stdlib_ascii.html) - Procedures for handling ASCII characters
- [base64](./stdlib_base64.html) - Base64 encoding and decoding routines
- [constants](./stdlib_constants.html) - Constants
- [bitsets](./stdlib_bitsets.html) - Bitset data types and procedures
- [error](./stdlib_error.html) - Catching and handling errors
Expand Down
179 changes: 179 additions & 0 deletions doc/specs/stdlib_base64.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
---
title: base64
---

# The `stdlib_base64` module

[TOC]

## Introduction

The `stdlib_base64` module provides procedures to encode and decode intrinsic
Fortran data using the Base64 encoding scheme defined by RFC 4648.

## Specification of the `stdlib_base64` procedures

### `base64_encode`

#### Status

Experimental

#### Description

Encodes intrinsic arrays into Base64 text.

This is the ergonomic API for encoding. It allocates and returns the output
string automatically.

#### Syntax

`res =` [[stdlib_base64(module):base64_encode(interface)]] `(data)`

#### Class

Function.

#### Argument

`data`: shall be a contiguous array of an intrinsic type (`real`, `integer`,
`complex`, `logical`, or `integer(int8)`). It is an `intent(in)` argument.

#### Result value

The result `res` is an allocatable character string (`character(len=:)`)
containing the Base64 representation of the input `data`.

#### Example

```fortran
Comment thread
RatanKokal marked this conversation as resolved.
{!example/strings/example_base64_encode.f90!}
```

### `base64_encode_into`

#### Status

Experimental

#### Description

Encodes bytes into a caller-provided output buffer.

This is the preallocated API for throughput-sensitive workflows. It does not
allocate and reports status through `err_state`. On success,
`err_state%ok()` is `.true.` and `encoded_len` is the number of meaningful
characters written to `str`.

#### Syntax

`call` [[stdlib_base64(module):base64_encode_into(subroutine)]] &
`(bytes, str, encoded_len, err_state)`

#### Class

Pure module subroutine.

#### Arguments

`bytes`: shall be a contiguous array of type `integer(int8)`. It is an
`intent(in)` argument.

`str`: shall be an intrinsic character type. It is an `intent(out)` argument.

`encoded_len`: shall be an `integer`. It is an `intent(out)` argument
representing the number of encoded characters written.

`err_state`: shall be a `type(state_type)` from `stdlib_error`. It is an
`intent(out)` argument used to report success or errors.

#### Example

```fortran
{!example/strings/example_base64_encode_into.f90!}
```

### `base64_decode`

#### Status

Experimental

#### Description

Decodes Base64 text and returns an allocated byte string.

This is the ergonomic API for decoding. It allocates and returns the result
automatically. On error, an empty result is returned. If `err_state` is
present, error details are reported there.

#### Syntax

`res =` [[stdlib_base64(module):base64_decode(function)]] `(str [, err_state])`

#### Class

Function.

#### Arguments

`str`: shall be an intrinsic character type. It is an `intent(in)` argument.

`err_state` (optional): shall be a `type(state_type)` from `stdlib_error`.
It is an `intent(out)` argument used to report invalid Base64 sequences.

#### Result value

The result `res` is an allocatable character string (`character(len=:)`)
containing the decoded bytes.

#### Example

```fortran
{!example/strings/example_base64_decode.f90!}
```

### `base64_decode_into`

#### Status

Experimental

#### Description

Decodes Base64 text into a caller-provided output buffer.

This is the preallocated API for throughput-sensitive workflows. It does not
allocate and reports status through `err_state`. The optional `skip_despace`
argument can be used when the input is already whitespace-free to bypass the
despacing step.

#### Syntax

`call` [[stdlib_base64(module):base64_decode_into(subroutine)]] &
`(str, res, decoded_len, err_state [, skip_despace])`

#### Class

Pure module subroutine.

#### Arguments

`str`: shall be an intrinsic character type. It is an `intent(in)` argument.

`res`: shall be an intrinsic character type. It is an `intent(out)` argument.

`decoded_len`: shall be an `integer`. It is an `intent(out)` argument
representing the number of decoded bytes written.

`err_state`: shall be a `type(state_type)` from `stdlib_error`. It is an
`intent(out)` argument used to report success or errors.

`skip_despace` (optional): shall be a `logical`. It is an `intent(in)`
argument. If `.true.`, the routine assumes the input contains no whitespace.

#### Example

```fortran
{!example/strings/example_base64_decode_into.f90!}
```
4 changes: 4 additions & 0 deletions example/strings/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
ADD_EXAMPLE(chomp)
ADD_EXAMPLE(base64_encode)
ADD_EXAMPLE(base64_encode_into)
ADD_EXAMPLE(base64_decode)
ADD_EXAMPLE(base64_decode_into)
ADD_EXAMPLE(count)
ADD_EXAMPLE(ends_with)
ADD_EXAMPLE(find)
Expand Down
10 changes: 10 additions & 0 deletions example/strings/example_base64_decode.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
program example_base64_decode
use stdlib_base64, only: base64_decode
implicit none

character(len=:), allocatable :: decoded

decoded = base64_decode("TWFu")

print '(a)', decoded
end program example_base64_decode
18 changes: 18 additions & 0 deletions example/strings/example_base64_decode_into.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
program example_base64_decode_into
use stdlib_base64, only: base64_decode_into
use stdlib_error, only: state_type
implicit none

character(len=4) :: str = "TWFu"
character(len=3) :: res
integer :: decoded_len
type(state_type) :: err_state

call base64_decode_into(str, res, decoded_len, err_state)

if (err_state%ok()) then
print '(a)', res
else
print '(a)', "Decoding failed"
end if
end program example_base64_decode_into
13 changes: 13 additions & 0 deletions example/strings/example_base64_encode.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
program example_base64_encode
use stdlib_base64, only: base64_encode
use stdlib_kinds, only: int8
implicit none

character(len=:), allocatable :: encoded
integer(int8) :: bytes(3)

bytes = [77_int8, 97_int8, 110_int8]
encoded = base64_encode(bytes)

print '(a)', encoded
end program example_base64_encode
20 changes: 20 additions & 0 deletions example/strings/example_base64_encode_into.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
program example_base64_encode_into
use stdlib_base64, only: base64_encode_into
use stdlib_kinds, only: int8
use stdlib_error, only: state_type
implicit none

integer(int8) :: bytes(3)
character(len=4) :: str
integer :: encoded_len
type(state_type) :: err_state

bytes = [77_int8, 97_int8, 110_int8]
call base64_encode_into(bytes, str, encoded_len, err_state)

if (err_state%ok()) then
print '(a)', str
else
print '(a)', "Encoding failed"
end if
end program example_base64_encode_into
1 change: 1 addition & 0 deletions src/core/stdlib_ascii.fypp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ module stdlib_ascii
character(len=*), public, parameter :: letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" !! A .. Za .. z
character(len=*), public, parameter :: uppercase = letters(1:26) !! A .. Z
character(len=*), public, parameter :: lowercase = letters(27:) !! a .. z
character(len=*), public, parameter :: base64_alphabet = letters//digits//"+/" !! RFC 4648 Base64 alphabet
character(len=*), public, parameter :: whitespace = " "//TAB//VT//CR//LF//FF !! ASCII _whitespace


Expand Down
3 changes: 3 additions & 0 deletions src/strings/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
set(strings_fppFiles
stdlib_base64_encode.fypp
stdlib_base64_decode.fypp
stdlib_base64.fypp
stdlib_string_type.fypp
stdlib_string_type_constructor.fypp
stdlib_str2num.fypp
Expand Down
Loading