my class X::Encoding::Unknown { ... } my class X::Encoding::AlreadyRegistered { ... } my class Encoding::Registry { my $lock := Lock.new; my %lookup; # access for registering builtins at compile time my $lookup := nqp::getattr(%lookup,Map,'$!storage'); # access for runtime BEGIN { my $lookup := nqp::bindattr(%lookup,Map,'$!storage',nqp::hash); ### If updating encodings, also update src/core.c/Rakudo/Internals.rakumod my $encodings := nqp::list( nqp::list('utf8', 'utf-8'), nqp::list('utf8-c8', 'utf8c8', 'utf-8-c8'), nqp::list('utf16', 'utf-16'), nqp::list('utf16le', 'utf-16le', 'utf16-le', 'utf-16-le'), nqp::list('utf16be', 'utf-16be', 'utf16-be', 'utf-16-be'), #?if !moar nqp::list('utf32', 'utf-32'), #?endif nqp::list('ascii'), nqp::list('iso-8859-1','iso_8859-1:1987','iso_8859-1','iso-ir-100', 'latin1','latin-1','csisolatin1','l1','ibm819','cp819'), nqp::list('windows-1251', 'windows1251'), nqp::list('windows-1252', 'windows1252'), nqp::list('windows-932', 'windows932'), nqp::list('gb2312', 'gb2312'), nqp::list('gb18030', 'gb18030'), ); my int $i = -1; my int $elems = nqp::elems($encodings); while nqp::islt_i(++$i,$elems) { my $names := nqp::atpos($encodings,$i); my $builtin := nqp::create(Encoding::Builtin).SET-SELF( nqp::shift($names),nqp::clone($names)); nqp::bindkey($lookup,$builtin.name,$builtin); while nqp::elems($names) { nqp::bindkey($lookup,nqp::shift($names),$builtin); } } } method register(Encoding $enc --> Nil) { $lock.protect: { nqp::existskey($lookup,(my str $key = $enc.name.fc)) ?? X::Encoding::AlreadyRegistered.new(name => $enc.name).throw !! nqp::bindkey($lookup,$key,$enc); my $names := nqp::getattr($enc.alternative-names,List,'$!reified'); my int $elems = nqp::elems($names); my int $i = -1; nqp::while( nqp::islt_i(++$i,$elems), nqp::if( nqp::existskey($lookup,($key = nqp::atpos($names,$i).fc)), X::Encoding::AlreadyRegistered.new( name => nqp::atpos($names,$i)).throw, nqp::bindkey($lookup,$key,$enc) ) ); } } method find(Str() $name) { $lock.protect: { nqp::ifnull( nqp::atkey($lookup,$name.fc), X::Encoding::Unknown.new(:$name).throw ) } } } # vim: expandtab shiftwidth=4