As described in UTF-8 and in Wikipedia, UTF-8 is a popular encoding of (multi-byte) Unicode code-points into eight-bit octets.

The goal of this task is to write a encoder that takes a unicode code-point (an integer representing a unicode character) and returns a sequence of 1-4 bytes representing that character in the UTF-8 encoding.

Then you have to write the corresponding decoder that takes a sequence of 1-4 UTF-8 encoded bytes and return the corresponding unicode character.

Demonstrate the functionality of your encoder and decoder on the following five characters:

Character   Name                                  Unicode    UTF-8 encoding (hex)
---------------------------------------------------------------------------------
A           LATIN CAPITAL LETTER A                U+0041     41
ö           LATIN SMALL LETTER O WITH DIAERESIS   U+00F6     C3 B6
Ж           CYRILLIC CAPITAL LETTER ZHE           U+0416     D0 96
€           EURO SIGN                             U+20AC     E2 82 AC
𝄞           MUSICAL SYMBOL G CLEF                 U+1D11E    F0 9D 84 9E

Provided below is a reference implementation in Common Lisp.

import java.nio.charset.StandardCharsets
 
class UTF8EncodeDecode {
    static byte[] utf8encode(int codePoint) {
        char[] characters = [codePoint]
        new String(characters, 0, 1).getBytes StandardCharsets.UTF_8
    }
 
    static int utf8decode(byte[] bytes) {
        new String(bytes, StandardCharsets.UTF_8).codePointAt(0)
    }
 
    static void main(String[] args) {
        printf "%-7s %-43s %7s\t%s\t%7s%n", "Char", "Name", "Unicode", "UTF-8 encoded", "Decoded"
 
        ([0x0041, 0x00F6, 0x0416, 0x20AC, 0x1D11E]).each { int codePoint ->
            byte[] encoded = utf8encode codePoint
            Formatter formatter = new Formatter()
            encoded.each { byte b ->
                formatter.format "%02X ", b
            }
            String encodedHex = formatter.toString()
            int decoded = utf8decode encoded
            printf "%-7c %-43s U+%04X\t%-12s\tU+%04X%n", codePoint, Character.getName(codePoint), codePoint, encodedHex, decoded
        }
    }
}