๐Ÿช Perl Unicode Essentials

Growing explosively over the last decade, most text today is now in Unicode, with some corpora reaching 100% Unicode. This tutorial shows Perl programmers how to write scripts to handle Unicode data reliably.

Tom Christiansen
<tchrist@perl.com>

๐Ÿ˜ˆ ยกฦจdlษ™ษฅ ฦจแด‰ษฅส‡ ษ™doษฅ puษ สปฮปษp ษ™ษ”แด‰u ษ ษ™สŒษษฅ สปสžษ”nl pooโ… ๐Ÿ˜ˆ

What is this?

Welcome to Unicode!

The Bad News

Surprise!

The Good News ๐Ÿ˜ป

Included ๐Ÿช Unicode Tools

  • Iโ€™ve included a directory full of ๐Ÿช scripts which I ๏ฌnd useful in Appendix 2: Tools:
  • ๐Ÿช Unicode Tools: Setup

    ๐Ÿช Unicode Tools: ๐”ˆ๐”ต๐”ข๐”ช๐”ญ๐”ฉ๐”ฆย ๐”Š๐”ฏ๐”ž๐”ฑ๐”ฆ๐”žย 

    Here are simple examples to play with:

     % pc 'say "\N{long s} \N{ae} \N{Omega} \N{omega}" \N{UPWARDS ARROW}'
    
     % echo exempli gratia | tc | unifont 
    
     % tcgrep -n '\P{ASCII}' pue.pod | uniquote -x | less
     % tcgrep -n '\P{ASCII}' pue.pod | uniquote -v | less
    
     % echo you are not expected to read this | leo
    
     % echo these are small caps | tc | unicaps
     % echo supers                    | unisupers
     % echo 123a                      | unisubs 

    ๐Ÿช Unicode Tools: ๐”ˆ๐”ต๐”ข๐”ช๐”ญ๐”ฉ๐”ฆย ๐”Š๐”ฏ๐”ž๐”ฑ๐”ฆ๐”žย  (contยนโ€ฆ)

    Here are more interesting examples to play with:

     % uninames latin ligat
     % uninames SIGN -arabic
     % uninames arrow -combining
    
     % uniprops 'MICRO SIGN'
     % uniprops -a 2010
    
     % unichars '\pL' '\p{Greek}'
     % unichars '\pL' '\p{Greek}' | um
     % unichars '\p{Age=6.0}'     | um
     % unichars -gasn NUM
    
     % unilook glob
     % unilook /glob
     % unilook -v '\pM'
     % unilook -v '\N{acute}'
     % unilook -v whom
     % unilook -vpn run 

    Basic Recommendations

    Basic Recommendations (contยนโ€ฆ)

    Basic Recommendations (contยฒโ€ฆ)

    Unicode Template

    Unicode Template: Pragmas

    Donโ€™t take my #! here too seriously; it has Issues.

     #!/usr/bin/env perl
    
     use v5.14;
     use utf8;
    
     use strict;
     use autodie;
     use warnings; 
    
     use warnings    qw< FATAL utf8 >;
     use open        qw< :std :encoding(UTF-8) >;
     use charnames   qw< :full >;
     use feature     qw< unicode_strings >; 

    Unicode Template: Modules

    The ๏ฌrst of these is almost always needed; the rest, not so much.

     use Unicode::Normalize  qw< NFD NFC >;
     use Encode              qw< encode decode >;
    
     use Carp                qw< carp croak confess cluck >;
     use File::Basename      qw< basename >;
    
     $0 = basename($0);  # shorter messages 

    Unicode Template: DATA, @ARGV

    Donโ€™t make $| hot if you have a lot of output on STDOUT.

     binmode(DATA, ":encoding(UTF-8)");
     
     # This works like perl -CA: note that it
     # assumes your terminal is set to use UTF-8
     if (grep /\P{ASCII}/ => @ARGV) { 
        @ARGV = map { decode("UTF-8", $_) } @ARGV;
     }
     
     $| = 1;   # comment out for performance
    
     END { close STDOUT } 

    Unicode Template: Set Traps

    This avoids compileโ€time ๐Ÿœ โ€œbugsโ€ in the pragma:

     # XXX: use warnings FATAL => "all";
     
     local $SIG{__DIE__} = sub {
         confess "Uncaught exception: @_" unless $^S;
     };
     
     local $SIG{__WARN__} = sub {
         if ($^S) { cluck   "Trapped warning: @_" } 
         else     { confess "Deadly warning: @_"  }
     }; 

    Unicode Template: Filters

    I use this on normal CLI ๏ฌlters:

     if (@ARGV == 0 && -t STDIN && -t STDERR) {
        print STDERR "$0: reading input from tty, type ^D for EOF...\n";
     }
    
     while (<>)  {
         chomp;
         $_ = NFD($_);
         ...
     } continue {
         say NFC($_);
     }
     
     __END__
     ๐–๐–Ž๐–ˆ ๐–๐–†๐–ˆ๐–Š๐–“๐–™ย ๐–‰๐–†๐–™๐–† ๐–š๐–“๐–Ž๐–ˆ๐–”๐–‰๐–Ž๐–ˆ๐–† 

    ๐Ÿช Runtime Environment

    ๐Ÿช Unicode Laundry List

    ๐Ÿœ Ixnay on the Ugbay Already! ๐Ÿœ

    Core Pragmas

    Program Literals

    Specify Unicode literals any of these ways:

    1. As literal UTFโ€8 under the recommended utf8 pragma, allowing you to write "ร  contre-cล“ur", "ร…ngstrรถm", or "๐Ÿ‘ช ๐Ÿ’— ๐Ÿช" directly.

    2. As wicked โ€œmagic numbersโ€ like chr(0x1F4A9), "\x{2639}", or "\N{U+A0}".

    3. Using the charnames pragma and the \N{CHARNAME} construct, strings like "\N{LATIN SMALL LETTER A WITH GRAVE} contre-c\N{LATIN SMALL LIGATURE OE}ur", "A\N{COMBINING RING ABOVE}ngstro\N{COMBINING DIAERESIS}m", and "\N{FAMILY} \N{GROWING HEART} \N{DROMEDARY CAMEL}".

    The charnames Pragma

    Basic charnames Examples

    Custom charnames Examples

    Core Modules

    Key core modules for Unicode are:

    The Encode module

  • The Encode module is most often used implicitly: itโ€™s loaded automatically whenever you pass an :encoding(ENC) argument to binmode or to open.
     binmode(STDIN,       ":encoding(cp1252)")
                   || die "can't binmode STDIN: $!";
    
     open(OUTPUT, "> :raw :encoding(UTF-16LE) :crlf", $filename) 
                   || die "can't open $filename: $!";
    
     print OUTPUT while <STDIN>;
    
     close(OUTPUT) || die "couldn't close $filename: $!";
     close(STDIN)  || die "couldn't close STDIN: $!"; 
  • The Encode module (contยนโ€ฆ)

    The Encode module (contยฒโ€ฆ)

    The MacRoman encoding is a bit weird:

     use charnames qw< :full >;
     use Encode (
         "decode",   # $unicode = decode("scheme", $bytes);
         "encode",   # $bytes   = encode("scheme", $unicode);
     );
    
     my $permil = "\N{PER MILLE SIGN}";
     printf "A permille %s is U+%vX in Unicode", $permil, $permil;
    
     my $bytes = encode("macroman", $permil);
     printf " but is 0x%vX in Macroman\n", $bytes;
    
        # A permille โ€ฐ is U+2030 in Unicode but is 0xE4 in Macroman 

    The Encode module (contยณโ€ฆ)

    The MacRoman encoding is still a bit weird:

     use charnames qw< :full >;
     use Encode (
         "decode",   # $unicode = decode("scheme", $bytes);
         "encode",   # $bytes   = encode("scheme", $unicode);
     );
    
     my $byte = chr(0x8E);
     my $char = decode("macroman", $byte);
    
     printf "An %vX in MacRoman is %vX in Unicode\n", $byte, $char;
     printf "Which is really a %s\n", charnames::viacode(ord $char);
    
        # An 8E in MacRoman is E9 in Unicode
        # Which is really a LATIN SMALL LETTER E WITH ACUTE 

    The Unicode::Normalize module

    Canonical Conundra

    Just as one example, consider all these variants of a Latin small letter o with tilde:

    N Glyph NFC? NFD? ๐Ÿช๐Ÿช๐Ÿช๐Ÿช๐Ÿช Code Points
    1 รต โœ“ โ”€ "\x{F5}" LATIN SMALL LETTER O WITH TILDE
    2 oฬƒ โ”€ โœ“ "o\x{303}" LATIN SMALL LETTER O, COMBINING TILDE
    3 ศญ โœ“ โ”€ "\x{22D}" LATIN SMALL LETTER O WITH TILDE AND MACRON
    4 รตฬ„ โ”€ โ”€ "\x{F5}\x{304}" LATIN SMALL LETTER O WITH TILDE, COMBINING MACRON
    5 oฬƒฬ„ โ”€ โœ“ "o\x{303}\x{304}" LATIN SMALL LETTER O, COMBINING TILDE, COMBINING MACRON
    6 ลฬƒ โ”€ โœ“ "o\x{304}\x{303}" LATIN SMALL LETTER O, COMBINING MACRON, COMBINING TILDE
    7 ลฬƒ โœ“ โ”€ "\x{14D}\x{303}" LATIN SMALL LETTER O WITH MACRON, COMBINING TILDE

    Oh shucks...

    ... and more shucks!

    In a regex, all 7 of those will be completely matched by \X, an extended grapheme cluster. Yes, but now what? ๐Ÿ˜ญ Iโ€™m afraid this is where it stops being easy. NFD is assumed and required for the following to work:

    ๐Ÿ‘ฝ Filesystems Hate You

    The Unicode::Collate module

    Replacing sort

    Replacing eq

    Program Options to ucsort

    These are its literal Getopt:::Long arguments:

      # collator constructor options
        --backwards-levels=i
        --collation-level|level|l=i
        --katakana-before-hiragana
        --normalization|n=s
        --override-CJK=s
        --override-Hangul=s
        --preprocess|P=s
        --upper-before-lower|u
        --variable=s
    
      # program specific options
        --case-insensitive|insensitive|i
        --input-encoding|e=s
        --locale|L=s
        --paragraph|p
        --reverse-fields|last
        --reverse-output|r
        --right-to-left|reverse-input 

    CPAN Modules

    CPAN modules for handling Unicode include:

    No POSIX Locales, por favor

    Unicode Locales

    Unicode Regex Gotchas

    Unicode Regex Gotchas (contยนโ€ฆ)

    Unicode Regex Gotchas (contยฒโ€ฆ)

    Unicode Antipatterns ๐Ÿ’ฉ

    People make millions of broken assumptions about Unicode. Until they understand these things, their ๐Ÿช code will be broken. Look for these Unicode antipatterns:

    Antipatterns (contยนโ€ฆ)

    Antipatterns (contยฒโ€ฆ)

    Antipatterns (contยณโ€ฆ)

    Antipatterns (contโดโ€ฆ)

    Antipatterns (contโตโ€ฆ)

    Antipatterns (contโถโ€ฆ)

    Antipatterns (contโทโ€ฆ)

    Antipatterns (contโธโ€ฆ)

    Antipatterns (contโนโ€ฆ)

    Antipatterns (contยนโฐ...)

    Antipatterns (contยนยน...)

    Appendix 1: Font suggestions

    Appendix 2: Tools

    Contact Information

    YANETUT

    ๆ–‡ๅญ—ๅŒ–ใ‘ ๐€ฌ ๐€ณ ๐€ต ๐€ท ๐€บ ๐ ๐ฉ ๐ญ ๐ฒ ๐„ ๐„ƒ ๐„ˆ ๐„ ๐„ ๐„’ ๐„” ๐„— ๐„™ ๐„ฌ ๐„ฏ ๐„ฑ ๐„ต ๐„น ๐„ป ๐…€ ๐…ค ๐…ซ ๐†„ ๐†’ ๐†• ๐†— ๐†š ๐†ถ ๐†ป ๐‡€ ๐Ÿ€€ ๐Ÿ€„ ๐Ÿ€ˆ ๐Ÿ€‹ ๐Ÿ€ ๐Ÿ€ ๐Ÿ€’ ๐Ÿ€• ๐Ÿ€š ๐Ÿ€ž ๐Ÿ€  ๐Ÿ€ฃ ๐Ÿ€ฆ ๐Ÿ€จ ๐Ÿ€ซ ๐Ÿ‚ฉ ๐Ÿ‚ฌ ๐Ÿ‚ฎ ๐Ÿ‚ฑ ๐Ÿ‚ต ๐Ÿ‚บ ๐Ÿ‚ผ ๐Ÿƒ ๐Ÿƒƒ ๐Ÿƒ† ๐Ÿƒˆ ๐Ÿƒ ๐Ÿƒ“ ๐Ÿƒ• ๐Ÿƒ˜ ๐Ÿƒš ๐Ÿƒ ๐ŸƒŸ ๐ŸŒ€ ๐ŸŒ ๐ŸŒ‚ ๐ŸŒƒ ๐ŸŒ„ ๐ŸŒ… ๐ŸŒ† ๐ŸŒ‡ ๐ŸŒˆ ๐ŸŒ‰ ๐ŸŒŠ ๐ŸŒ‹ ๐ŸŒŒ ๐ŸŒ ๐ŸŒŽ ๐ŸŒ ๐ŸŒ ๐ŸŒ‘ ๐ŸŒ’ ๐ŸŒ“ ๐ŸŒ” ๐ŸŒ• ๐ŸŒ– ๐ŸŒ— ๐ŸŒ˜ ๐ŸŒ™ ๐ŸŒš ๐ŸŒ› ๐ŸŒœ ๐ŸŒ ๐ŸŒž ๐ŸŒŸ ๐ŸŒ  ๐ŸŒฐ ๐ŸŒฑ ๐ŸŒฒ ๐ŸŒณ ๐ŸŒด ๐ŸŒต ๐ŸŒท ๐ŸŒธ ๐ŸŒน ๐ŸŒบ ๐ŸŒป ๐ŸŒผ ๐ŸŒฝ ๐ŸŒพ ๐ŸŒฟ ๐Ÿ€ ๐Ÿ ๐Ÿ‚ ๐Ÿƒ ๐Ÿ„ ๐Ÿ… ๐Ÿ† ๐Ÿ‡ ๐Ÿˆ ๐Ÿ‰ ๐ŸŠ ๐Ÿ‹ ๐ŸŒ ๐Ÿ ๐ŸŽ ๐Ÿ ๐Ÿ ๐Ÿ‘ ๐Ÿ’ ๐Ÿ“ ๐Ÿ” ๐Ÿ• ๐Ÿ– ๐Ÿ— ๐Ÿ˜ ๐Ÿ™ ๐Ÿš ๐Ÿ› ๐Ÿœ ๐Ÿ ๐Ÿž ๐ŸŸ ๐Ÿ  ๐Ÿก ๐Ÿข ๐Ÿฃ ๐Ÿค ๐Ÿฅ ๐Ÿฆ ๐Ÿง ๐Ÿจ ๐Ÿฉ ๐Ÿช ๐Ÿซ ๐Ÿฌ ๐Ÿญ ๐Ÿฎ ๐Ÿฏ ๐Ÿฐ ๐Ÿฑ ๐Ÿฒ ๐Ÿณ ๐Ÿด ๐Ÿต ๐Ÿถ ๐Ÿท ๐Ÿธ ๐Ÿน ๐Ÿบ ๐Ÿป ๐Ÿผ ๐ŸŽ€ ๐ŸŽ ๐ŸŽ‚ ๐ŸŽƒ ๐ŸŽ„ ๐ŸŽ… ๐ŸŽ† ๐ŸŽ‡ ๐ŸŽˆ ๐ŸŽ‰ ๐ŸŽŠ ๐ŸŽ‹ ๐ŸŽŒ ๐ŸŽ ๐ŸŽŽ ๐ŸŽ ๐ŸŽ ๐ŸŽ‘ ๐ŸŽ’ ๐ŸŽ“ ๐ŸŽ  ๐ŸŽก ๐ŸŽข ๐ŸŽฃ ๐ŸŽค ๐ŸŽฅ ๐ŸŽฆ ๐ŸŽง ๐ŸŽจ ๐ŸŽฉ ๐ŸŽช ๐ŸŽซ ๐ŸŽฌ ๐ŸŽญ ๐ŸŽฎ ๐ŸŽฏ ๐ŸŽฐ ๐ŸŽฑ ๐ŸŽฒ ๐ŸŽณ ๐ŸŽด ๐ŸŽต ๐ŸŽถ ๐ŸŽท ๐ŸŽธ ๐ŸŽน ๐ŸŽบ ๐ŸŽป ๐ŸŽผ ๐ŸŽฝ ๐ŸŽพ ๐ŸŽฟ ๐Ÿ€ ๐Ÿ ๐Ÿ‚ ๐Ÿƒ ๐Ÿ„ ๐Ÿ† ๐Ÿ‡ ๐Ÿˆ ๐Ÿ‰ ๐ŸŠ ๐Ÿ  ๐Ÿก ๐Ÿข ๐Ÿฃ ๐Ÿค ๐Ÿฅ ๐Ÿฆ ๐Ÿง ๐Ÿจ ๐Ÿฉ ๐Ÿช ๐Ÿซ ๐Ÿฌ ๐Ÿญ ๐Ÿฎ ๐Ÿฏ ๐Ÿฐ ๐Ÿ€ ๐Ÿ ๐Ÿ‚ ๐Ÿƒ ๐Ÿ„ ๐Ÿ… ๐Ÿ† ๐Ÿ‡ ๐Ÿˆ ๐Ÿ‰ ๐ŸŠ ๐Ÿ‹ ๐ŸŒ ๐Ÿ ๐ŸŽ ๐Ÿ ๐Ÿ ๐Ÿ‘ ๐Ÿ’ ๐Ÿ“ ๐Ÿ” ๐Ÿ• ๐Ÿ– ๐Ÿ— ๐Ÿ˜ ๐Ÿ™ ๐Ÿš ๐Ÿ› ๐Ÿœ ๐Ÿ ๐Ÿž ๐ŸŸ ๐Ÿ  ๐Ÿก ๐Ÿข ๐Ÿฃ ๐Ÿค ๐Ÿฅ ๐Ÿฆ ๐Ÿง ๐Ÿจ ๐Ÿฉ ๐Ÿช ๐Ÿซ ๐Ÿฌ ๐Ÿญ ๐Ÿฎ ๐Ÿฏ ๐Ÿฐ ๐Ÿฑ ๐Ÿฒ ๐Ÿณ ๐Ÿด ๐Ÿต ๐Ÿถ ๐Ÿท ๐Ÿธ ๐Ÿน ๐Ÿบ ๐Ÿป ๐Ÿผ ๐Ÿฝ ๐Ÿพ ๐Ÿ‘€ ๐Ÿ‘‚ ๐Ÿ‘ƒ ๐Ÿ‘„ ๐Ÿ‘… ๐Ÿ‘† ๐Ÿ‘‡ ๐Ÿ‘ˆ ๐Ÿ‘‰ ๐Ÿ‘Š ๐Ÿ‘‹ ๐Ÿ‘Œ ๐Ÿ‘ ๐Ÿ‘Ž ๐Ÿ‘ ๐Ÿ‘ ๐Ÿ‘‘ ๐Ÿ‘’ ๐Ÿ‘“ ๐Ÿ‘” ๐Ÿ‘• ๐Ÿ‘– ๐Ÿ‘— ๐Ÿ‘˜ ๐Ÿ‘™ ๐Ÿ‘š ๐Ÿ‘› ๐Ÿ‘œ ๐Ÿ‘ ๐Ÿ‘ž ๐Ÿ‘Ÿ ๐Ÿ‘  ๐Ÿ‘ก ๐Ÿ‘ข ๐Ÿ‘ฃ ๐Ÿ‘ค ๐Ÿ‘ฅ ๐Ÿ‘ฆ ๐Ÿ‘ง ๐Ÿ‘จ ๐Ÿ‘ฉ ๐Ÿ‘ช ๐Ÿ‘ซ ๐Ÿ‘ฌ ๐Ÿ‘ญ ๐Ÿ‘ฎ ๐Ÿ‘ฏ ๐Ÿ‘ฐ ๐Ÿ‘ฑ ๐Ÿ‘ฒ ๐Ÿ‘ณ ๐Ÿ‘ด ๐Ÿ‘ต ๐Ÿ‘ถ ๐Ÿ‘ท ๐Ÿ‘ธ ๐Ÿ‘น ๐Ÿ‘บ ๐Ÿ‘ป ๐Ÿ‘ผ ๐Ÿ‘ฝ ๐Ÿ‘พ ๐Ÿ‘ฟ ๐Ÿ’€ ๐Ÿ’ ๐Ÿ’‚ ๐Ÿ’ƒ ๐Ÿ’„ ๐Ÿ’… ๐Ÿ’† ๐Ÿ’‡ ๐Ÿ’ˆ ๐Ÿ’‰ ๐Ÿ’Š ๐Ÿ’‹ ๐Ÿ’Œ ๐Ÿ’ ๐Ÿ’Ž ๐Ÿ’ ๐Ÿ’ ๐Ÿ’‘ ๐Ÿ’’ ๐Ÿ’“ ๐Ÿ’” ๐Ÿ’• ๐Ÿ’– ๐Ÿ’— ๐Ÿ’˜ ๐Ÿ’™ ๐Ÿ’š ๐Ÿ’› ๐Ÿ’œ ๐Ÿ’ ๐Ÿ’ž ๐Ÿ’Ÿ ๐Ÿ’  ๐Ÿ’ก ๐Ÿ’ข ๐Ÿ’ฃ ๐Ÿ’ค ๐Ÿ’ฅ ๐Ÿ’ฆ ๐Ÿ’ง ๐Ÿ’จ ๐Ÿ’ฉ ๐Ÿ’ช ๐Ÿ’ซ ๐Ÿ’ฌ ๐Ÿ’ญ ๐Ÿ’ฎ ๐Ÿ’ฏ ๐Ÿ’ฐ ๐Ÿ’ฑ ๐Ÿ’ฒ ๐Ÿ’ณ ๐Ÿ’ด ๐Ÿ’ต ๐Ÿ’ถ ๐Ÿ’ท ๐Ÿ’ธ ๐Ÿ’น ๐Ÿ’บ ๐Ÿ’ป ๐Ÿ’ผ ๐Ÿ’ฝ ๐Ÿ’พ ๐Ÿ’ฟ ๐Ÿ“€ ๐Ÿ“ ๐Ÿ“‚ ๐Ÿ“ƒ ๐Ÿ“„ ๐Ÿ“… ๐Ÿ“† ๐Ÿ“‡ ๐Ÿ“ˆ ๐Ÿ“‰ ๐Ÿ“Š ๐Ÿ“‹ ๐Ÿ“Œ ๐Ÿ“ ๐Ÿ“Ž ๐Ÿ“ ๐Ÿ“ ๐Ÿ“‘ ๐Ÿ“’ ๐Ÿ““ ๐Ÿ“” ๐Ÿ“• ๐Ÿ“– ๐Ÿ“— ๐Ÿ“˜ ๐Ÿ“™ ๐Ÿ“š ๐Ÿ“› ๐Ÿ“œ ๐Ÿ“ ๐Ÿ“ž ๐Ÿ“Ÿ ๐Ÿ“  ๐Ÿ“ก ๐Ÿ“ข ๐Ÿ“ฃ ๐Ÿ“ค ๐Ÿ“ฅ ๐Ÿ“ฆ ๐Ÿ“ง ๐Ÿ“จ ๐Ÿ“ฉ ๐Ÿ“ช ๐Ÿ“ซ ๐Ÿ“ฌ ๐Ÿ“ญ ๐Ÿ“ฎ ๐Ÿ“ฏ ๐Ÿ“ฐ ๐Ÿ“ฑ ๐Ÿ“ฒ ๐Ÿ“ณ ๐Ÿ“ด ๐Ÿ“ต ๐Ÿ“ถ ๐Ÿ“ท ๐Ÿ“น ๐Ÿ“บ ๐Ÿ“ป ๐Ÿ“ผ ๐Ÿ”€ ๐Ÿ” ๐Ÿ”‚ ๐Ÿ”ƒ ๐Ÿ”„ ๐Ÿ”… ๐Ÿ”† ๐Ÿ”‡ ๐Ÿ”ˆ ๐Ÿ”‰ ๐Ÿ”Š ๐Ÿ”‹ ๐Ÿ”Œ ๐Ÿ” ๐Ÿ”Ž ๐Ÿ” ๐Ÿ” ๐Ÿ”‘ ๐Ÿ”’ ๐Ÿ”“ ๐Ÿ”” ๐Ÿ”• ๐Ÿ”– ๐Ÿ”— ๐Ÿ”˜ ๐Ÿ”™ ๐Ÿ”š ๐Ÿ”› ๐Ÿ”œ ๐Ÿ” ๐Ÿ”ž ๐Ÿ”Ÿ ๐Ÿ”  ๐Ÿ”ก ๐Ÿ”ข ๐Ÿ”ฃ ๐Ÿ”ค ๐Ÿ”ฅ ๐Ÿ”ฆ ๐Ÿ”ง ๐Ÿ”จ ๐Ÿ”ฉ ๐Ÿ”ช ๐Ÿ”ซ ๐Ÿ”ฌ ๐Ÿ”ญ ๐Ÿ”ฎ ๐Ÿ”ฏ ๐Ÿ”ฐ ๐Ÿ”ฑ ๐Ÿ”ฒ ๐Ÿ”ณ ๐Ÿ”ด ๐Ÿ”ต ๐Ÿ”ถ ๐Ÿ”ท ๐Ÿ”ธ ๐Ÿ”น ๐Ÿ”บ ๐Ÿ”ป ๐Ÿ”ผ ๐Ÿ”ฝ ๐Ÿ• ๐Ÿ•‘ ๐Ÿ•’ ๐Ÿ•“ ๐Ÿ•” ๐Ÿ•• ๐Ÿ•– ๐Ÿ•— ๐Ÿ•˜ ๐Ÿ•™ ๐Ÿ•š ๐Ÿ•› ๐Ÿ•œ ๐Ÿ• ๐Ÿ•ž ๐Ÿ•Ÿ ๐Ÿ•  ๐Ÿ•ก ๐Ÿ•ข ๐Ÿ•ฃ ๐Ÿ•ค ๐Ÿ•ฅ ๐Ÿ•ฆ ๐Ÿ•ง ๐Ÿ—ป ๐Ÿ—ผ ๐Ÿ—ฝ ๐Ÿ—พ ๐Ÿ—ฟ ๐Ÿ˜ ๐Ÿ˜‚ ๐Ÿ˜ƒ ๐Ÿ˜„ ๐Ÿ˜… ๐Ÿ˜† ๐Ÿ˜‡ ๐Ÿ˜ˆ ๐Ÿ˜‰ ๐Ÿ˜Š ๐Ÿ˜‹ ๐Ÿ˜Œ ๐Ÿ˜ ๐Ÿ˜Ž ๐Ÿ˜ ๐Ÿ˜ ๐Ÿ˜’ ๐Ÿ˜“ ๐Ÿ˜” ๐Ÿ˜– ๐Ÿ˜˜ ๐Ÿ˜š ๐Ÿ˜œ ๐Ÿ˜ ๐Ÿ˜ž ๐Ÿ˜  ๐Ÿ˜ก ๐Ÿ˜ข ๐Ÿ˜ฃ ๐Ÿ˜ค ๐Ÿ˜ฅ ๐Ÿ˜จ ๐Ÿ˜ฉ ๐Ÿ˜ช ๐Ÿ˜ซ ๐Ÿ˜ญ ๐Ÿ˜ฐ ๐Ÿ˜ฑ ๐Ÿ˜ฒ ๐Ÿ˜ณ ๐Ÿ˜ต ๐Ÿ˜ถ ๐Ÿ˜ท ๐Ÿ˜ธ ๐Ÿ˜น ๐Ÿ˜บ ๐Ÿ˜ป ๐Ÿ˜ผ ๐Ÿ˜ฝ ๐Ÿ˜พ ๐Ÿ˜ฟ ๐Ÿ™€ ๐Ÿ™… ๐Ÿ™† ๐Ÿ™Š ๐Ÿ™ ๐Ÿ™ ๐Ÿš ๐Ÿšƒ ๐Ÿš‡ ๐Ÿšˆ ๐ŸšŒ ๐Ÿš ๐Ÿš‘ ๐Ÿš” ๐Ÿš– ๐Ÿš™ ๐Ÿšž ๐Ÿšข ๐Ÿšค ๐Ÿšง ๐Ÿšช ๐Ÿšฌ ๐Ÿšฏ ๐Ÿšณ ๐Ÿšธ ๐Ÿœ‚ ๐Ÿœƒ ๐Ÿœ‡ ๐Ÿœˆ ๐Ÿœ ๐Ÿœ“ ๐Ÿœ• ๐Ÿœ˜ ๐Ÿœ ๐Ÿœก ๐Ÿœค ๐Ÿœฆ ๐Ÿœฉ ๐Ÿœซ ๐Ÿœฎ ๐Ÿœฒ ๐Ÿœณ ๐Ÿœท ๐Ÿœบ ๐Ÿœผ ๐Ÿœฟ ๐Ÿ ๐Ÿˆ ๐ŸŒ ๐Ÿ ๐Ÿ ๐Ÿ’ ๐Ÿ— ๐ŸŸ ๐Ÿข ๐Ÿฉ ๐Ÿฎ ๐Ÿฐ ๐Ÿณ ใ€  ๊ฃ ๐Œด ๐Œถ ๐Œน ๐Œป ๐Œพ ๐ƒ ๐„ ๐ˆ ๐Š ๐’‚Š ๐’‚ญ ๐’‚ฑ ๐’ƒ” ๐’‡‰ ๐’‹ง ๐’‹ผ ๐’Œฃ