TDoG-Skin/vendor/hoa/ustring/Documentation/Fr/Index.xyl
2024-08-17 19:13:54 +08:00

634 lines
28 KiB
XML
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="utf-8"?>
<overlay xmlns="http://hoa-project.net/xyl/xylophone">
<yield id="chapter">
<p>Les chaînes de caractères peuvent parfois être <strong>complexes</strong>,
particulièrement lorsqu'elles utilisent l'encodage <strong>Unicode</strong>.
La bibliothèque <code>Hoa\Ustring</code> propose plusieurs opérations sur des
chaînes de caractères UTF-8.</p>
<h2 id="Table_of_contents">Table des matières</h2>
<tableofcontents id="main-toc" />
<h2 id="Introduction" for="main-toc">Introduction</h2>
<p>Lorsque nous manipulons des chaînes de caractères, le format
<a href="http://unicode.org/">Unicode</a> s'impose par sa
<strong>compatibilité</strong> avec les formats de base historiques (comme
ASCII) et par sa grande capacité à comprendre une très <strong>large</strong>
plage de caractères et de symboles, pour toutes les cultures et toutes les
régions de notre monde. PHP propose plusieurs outils pour manipuler de telles
chaînes, comme les extensions
<a href="http://php.net/mbstring"><code>mbstring</code></a>,
<a href="http://php.net/iconv"><code>iconv</code></a> ou encore l'excellente
<a href="http://php.net/intl"><code>intl</code></a> qui se base sur
<a href="http://icu-project.org/">ICU</a>, l'implémentation de référence
d'Unicode. Malheureusement, il faut parfois mélanger ces extensions pour
arriver à nos fins et au prix d'une certaine <strong>complexité</strong> et
d'une <strong>verbosité</strong> regrettable.</p>
<p>La bibliothèque <code>Hoa\Ustring</code> répond à ces problématiques en
proposant une façon <strong>simple</strong> de manipuler des chaînes de
caractères, de manière <strong>performante</strong> et
<strong>efficace</strong>. Elle propose également des algorithmes évolués pour
des opérations de <strong>recherche</strong> sur des chaînes de
caractères.</p>
<h2 id="Unicode_strings" for="main-toc">Chaîne de caractères Unicode</h2>
<p>La classe <code>Hoa\Ustring\Ustring</code> représente une chaîne de
caractères Unicode <strong>UTF-8</strong> et permet de la manipuler
facilement. Elle implémente les interfaces
<a href="http://php.net/arrayaccess"><code>ArrayAccess</code></a>,
<a href="http://php.net/countable"><code>Countable</code></a> et
<a href="http://php.net/iteratoraggregate"><code>IteratorAggregate</code></a>.
Nous allons utiliser trois exemples dans trois langues différentes : français,
arabe et japonais. Ainsi :</p>
<pre><code class="language-php">$french = new Hoa\Ustring\Ustring('Je t\'aime');
$arabic = new Hoa\Ustring\Ustring('أحبك');
$japanese = new Hoa\Ustring\Ustring('私はあなたを愛して');</code></pre>
<p>Maintenant, voyons les opérations possibles sur ces trois chaînes.</p>
<h3 id="String_manipulation" for="main-toc">Manipulation de la chaîne</h3>
<p>Commençons par les opérations <strong>élémentaires</strong>. Si nous
voulons <strong>compter</strong> le nombre de caractères (et non pas
d'octets), nous allons utiliser <a href="http://php.net/count">la fonction
<code>count</code></a> de PHP. Ainsi :</p>
<pre><code class="language-php">var_dump(
count($french),
count($arabic),
count($japanese)
);
/**
* Will output:
* int(9)
* int(4)
* int(9)
*/</code></pre>
<p>Quand nous parlons de position sur un texte, il n'est pas adéquat de parler
de droite ou de gauche, mais plutôt de <strong>début</strong> ou de
<strong>fin</strong>, et cela à partir de la <strong>direction</strong> (sens
d'écriture) du texte. Nous pouvons connaître cette direction grâce à la
méthode <code>Hoa\Ustring\Ustring::getDirection</code>. Elle retourne la
valeur d'une des constantes suivantes :</p>
<ul>
<li><code>Hoa\Ustring\Ustring::LTR</code>, pour
<em lang="en">left-to-right</em>, si le texte s'écrit de gauche à
droite ;</li>
<li><code>Hoa\Ustring\Ustring::RTL</code>, pour
<em lang="en">right-to-left</em>, si le texte s'écrit de droite à
gauche.</li>
</ul>
<p>Observons le résultat sur nos exemples :</p>
<pre><code class="language-php">var_dump(
$french->getDirection() === Hoa\Ustring\Ustring::LTR, // is left-to-right?
$arabic->getDirection() === Hoa\Ustring\Ustring::RTL, // is right-to-left?
$japanese->getDirection() === Hoa\Ustring\Ustring::LTR // is left-to-right?
);
/**
* Will output:
* bool(true)
* bool(true)
* bool(true)
*/</code></pre>
<p>Le résultat de cette méthode est calculé grâce à la méthode statique
<code>Hoa\Ustring\Ustring::getCharDirection</code> qui calcule la direction
d'un seul caractère.</p>
<p>Si nous voulons <strong>concaténer</strong> une autre chaîne à la fin ou au
début, nous utiliserons respectivement les méthodes
<code>Hoa\Ustring\Ustring::append</code> et
<code>Hoa\Ustring\Ustring::prepend</code>. Ces méthodes, comme la plupart de
celles qui modifient la chaîne, retournent l'objet lui-même, ce afin de
chaîner les appels. Par exemple :</p>
<pre><code class="language-php">echo $french->append('… et toi, m\'aimes-tu ?')->prepend('Mam\'zelle ! ');
/**
* Will output:
* Mam'zelle ! Je t'aime… et toi, m'aimes-tu ?
*/</code></pre>
<p>Nous avons également les méthodes
<code>Hoa\Ustring\Ustring::toLowerCase</code> et
<code>Hoa\Ustring\Ustring::toUpperCase</code> pour, respectivement, mettre la
chaîne en <strong>minuscules</strong> ou en <strong>majuscules</strong>. Par
exemple :</p>
<pre><code class="language-php">echo $french->toUpperCase();
/**
* Will output:
* MAM'ZELLE ! JE T'AIME… ET TOI, M'AIMES-TU ?
*/</code></pre>
<p>Nous pouvons aussi ajouter des caractères en début ou en fin de chaîne pour
atteindre une taille <strong>minimum</strong>. Cette opération est plus
couramment appelée le <em lang="en">padding</em> (pour des raisons historiques
remontant aux machines à écrire). C'est pourquoi nous trouvons la méthode
<code>Hoa\Ustring\Ustring::pad</code> qui prend trois arguments : la taille
minimum, les caractères à ajouter et une constante indiquant si nous devons
ajouter en fin ou en début de chaîne (respectivement
<code>Hoa\Ustring\Ustring::END</code>, par défaut, et
<code>Hoa\Ustring\Ustring::BEGINNING</code>).</p>
<pre><code class="language-php">echo $arabic->pad(20, ' ');
/**
* Will output:
* أحبك
*/</code></pre>
<p>Une opération similairement inverse permet de supprimer, par défaut, les
<strong>espaces</strong> en début et en fin de chaîne grâce à la méthode
<code>Hoa\Ustring\Ustring::trim</code>. Par exemple, pour revenir à notre
chaîne arabe originale :</p>
<pre><code class="language-php">echo $arabic->trim();
/**
* Will output:
* أحبك
*/</code></pre>
<p>Si nous voulons supprimer d'autres caractères, nous pouvons utiliser son
premier argument qui doit être une expression régulière. Enfin, son second
argument permet de préciser de quel côté nous voulons supprimer les
caractères : en début, en fin ou les deux, toujours en utilisant les
constantes <code>Hoa\Ustring\Ustring::BEGINNING</code> et
<code>Hoa\Ustring\Ustring::END</code>. Nous pouvons combiner ces constantes
pour exprimer « les deux côtés », ce qui est la valeur par défaut :
<code class="language-php">Hoa\Ustring\Ustring::BEGINNING |
Hoa\Ustring\Ustring::END</code>. Par exemple, pour supprimer tous les nombres
et les espaces uniquement à la fin, nous écrirons :</p>
<pre><code class="language-php">$arabic->trim('\s|\d', Hoa\Ustring\Ustring::END);</code></pre>
<p>Nous pouvons également <strong>réduire</strong> la chaîne à une
<strong>sous-chaîne</strong> en précisant la position du premier caractère
puis la taille de la sous-chaîne à la méthode
<code>Hoa\Ustring\Ustring::reduce</code> :</p>
<pre><code class="language-php">echo $french->reduce(3, 6)->reduce(2, 4);
/**
* Will output:
* aime
*/</code></pre>
<p>Si nous voulons obtenir un caractère en particulier, nous pouvons exploiter
l'interface <code>ArrayAccess</code>. Par exemple, pour obtenir le premier
caractère de chacun de nos exemples (en les reprenant depuis le début) :</p>
<pre><code class="language-php">var_dump(
$french[0],
$arabic[0],
$japanese[0]
);
/**
* Will output:
* string(1) "J"
* string(2) "أ"
* string(3) "私"
*/</code></pre>
<p>Si nous voulons le dernier caractère, nous utiliserons l'index -1. L'index
n'est pas borné à la taille de la chaîne. Si jamais l'index dépasse cette
taille, alors un <em>modulo</em> sera appliqué.</p>
<p>Nous pouvons aussi modifier ou supprimer un caractère précis avec cette
méthode. Par exemple :</p>
<pre><code class="language-php">$french->append(' ?');
$french[-1] = '!';
echo $french;
/**
* Will output:
* Je t'aime !
*/</code></pre>
<p>Une autre méthode fort utile est la transformation en
<strong>ASCII</strong>. Attention, ce n'est pas toujours possible, selon votre
installation. Par exemple :</p>
<pre><code class="language-php">$title = new Hoa\Ustring\Ustring('Un été brûlant sur la côte');
echo $title->toAscii();
/**
* Will output:
* Un ete brulant sur la cote
*/</code></pre>
<p>Nous pouvons aussi transformer de l'arabe ou du japonais vers de l'ASCII.
Les symboles, comme les symboles Mathématiques ou les emojis, sont aussi
transformés :</p>
<pre><code class="language-php">$emoji = new Hoa\Ustring\Ustring('I ❤ Unicode');
$maths = new Hoa\Ustring\Ustring('∀ i ∈ ');
echo
$arabic->toAscii(), "\n",
$japanese->toAscii(), "\n",
$emoji->toAscii(), "\n",
$maths->toAscii(), "\n";
/**
* Will output:
* ahbk
* sihaanatawo aishite
* I (heavy black heart) Unicode
* (for all) i (element of) N
*/</code></pre>
<p>Pour que cette méthode fonctionne correctement, il faut que l'extension
<a href="http://php.net/intl"><code>intl</code></a> soit présente, pour que la
classe <a href="http://php.net/transliterator"><code>Transliterator</code></a>
existe. Si elle n'existe pas, la classe
<a href="http://php.net/normalizer"><code>Normalizer</code></a> doit exister.
Si cette classe n'existe pas non plus, la méthode
<code>Hoa\Ustring\Ustring::toAscii</code> peut quand même essayer une
transformation mais moins efficace. Pour cela, il faut passer
<code>true</code> en seul argument. Ce tour de force est déconseillé dans la
plupart des cas.</p>
<p>Nous trouvons également la méthode <code>getTransliterator</code> qui
retourne un objet <code>Transliterator</code>, ou <code>null</code> si cette
classe n'existe pas. Cette méthode prend en argument un identifiant de
translitération. Nous conseillons de
<a href="http://userguide.icu-project.org/transforms/general">lire la
documentation sur le translitérateur d'ICU</a> pour comprendre cet
identifiant. La méthode <code>transliterate</code> permet de translitérer la
chaîne courante à partir d'un identifiant et d'un index de début et de
fin. Elle fonctionne de la même façon que la méthode
<a href="http://php.net/transliterator.transliterate"><code>Transliterator::transliterate</code></a>.</p>
<p>Plus généralement, pour des changements d'<strong>encodage</strong> brut,
nous pouvons utiliser la méthode statique
<code>Hoa\Ustring\Ustring::transcode</code>, avec en premier argument une chaîne
de caractères, en deuxième argument l'encodage d'origine et en dernier
argument l'encodage final souhaité (par défaut UTF-8). Pour la liste des
encodages, il faut se reporter à l'extension
<a href="http://php.net/iconv"><code>iconv</code></a> ou entrer la commande
suivante dans un terminal :</p>
<pre><code class="language-php">$ iconv --list</code></pre>
<p>Pour savoir si une chaîne est encodée en UTF-8, nous pouvons utiliser la
méthode statique <code>Hoa\Ustring\Ustring::isUtf8</code> ; par exemple :</p>
<pre><code class="language-php">var_dump(
Hoa\Ustring\Ustring::isUtf8('a'),
Hoa\Ustring\Ustring::isUtf8(Hoa\Ustring\Ustring::transcode('a', 'UTF-8', 'UTF-16'))
);
/**
* Will output:
* bool(true)
* bool(false)
*/</code></pre>
<p>Nous pouvons <strong>éclater</strong> la chaîne en plusieurs sous-chaînes
en utilisant la méthode <code>Hoa\Ustring\Ustring::split</code>. En premier
argument, nous avons une expression régulière (type
<a href="http://pcre.org/">PCRE</a>), puis un entier représentant le nombre
maximum d'éléments à retourner et enfin une combinaison de constantes. Ces
constantes sont les mêmes que celles de
<a href="http://php.net/preg_split"><code>preg_split</code></a>.</p>
<p>Par défaut, le deuxième argument vaut -1, qui symbolise l'infini, et le
dernier argument vaut <code>PREG_SPLIT_NO_EMPTY</code>. Ainsi, si nous
voulons obtenir tous les mots d'une chaîne, nous écrirons :</p>
<pre><code class="language-php">print_r($title->split('#\b|\s#'));
/**
* Will output:
* Array
* (
* [0] => Un
* [1] => ete
* [2] => brulant
* [3] => sur
* [4] => la
* [5] => cote
* )
*/</code></pre>
<p>Si nous voulons <strong>itérer</strong> sur tous les
<strong>caractères</strong>, il est préférable d'exploiter l'interface
<code>IteratorAggregate</code>, soit la méthode
<code>Hoa\Ustring\Ustring::getIterator</code>. Voyons plutôt sur l'exemple en
arabe :</p>
<pre><code class="language-php">foreach ($arabic as $letter) {
echo $letter, "\n";
}
/**
* Will output:
* أ
* ح
* ب
* ك
*/</code></pre>
<p>Nous remarquons que l'itération se fait suivant la direction du texte,
c'est à dire que le premier élément de l'itération est la première lettre de
la chaîne en partant du début.</p>
<p>Bien sûr, si nous voulons obtenir un tableau des caractères, nous pouvons
utiliser la fonction
<a href="http://php.net/iterator_to_array"><code>iterator_to_array</code></a>
de PHP :</p>
<pre><code class="language-php">print_r(iterator_to_array($arabic));
/**
* Will output:
* Array
* (
* [0] => أ
* [1] => ح
* [2] => ب
* [3] => ك
* )
*/</code></pre>
<h3 id="Comparison_and_search" for="main-toc">Comparaison et recherche</h3>
<p>Les chaînes peuvent également être <strong>comparées</strong> entre elles
grâce à la méthode <code>Hoa\Ustring\Ustring::compare</code> :</p>
<pre><code class="language-php">$string = new Hoa\Ustring\Ustring('abc');
var_dump(
$string->compare('wxyz')
);
/**
* Will output:
* string(-1)
*/</code></pre>
<p>Cette méthode retourne -1 si la chaîne initiale vient avant (par ordre
alphabétique), 0 si elle est identique et 1 si elle vient après. Si nous
voulons utiliser la pleine
puissance du mécanisme sous-jacent, nous pouvons appeler la méthode statique
<code>Hoa\Ustring\Ustring::getCollator</code> (si la classe
<a href="http://php.net/Collator"><code>Collator</code></a> existe, sinon
<code>Hoa\Ustring\Ustring::compare</code> utilisera une comparaison simple
octet par octets sans tenir compte d'autres paramètres). Ainsi, si nous
voulons trier un tableau de chaînes, nous écrirons plutôt :</p>
<pre><code class="language-php">$strings = array('c', 'Σ', 'd', 'x', 'α', 'a');
Hoa\Ustring\Ustring::getCollator()->sort($strings);
print_r($strings);
/**
* Could output:
* Array
* (
* [0] => a
* [1] => c
* [2] => d
* [3] => x
* [4] => α
* [5] => Σ
* )
*/</code></pre>
<p>La comparaison entre deux chaînes dépend de la <strong>locale</strong>,
c'est à dire de la régionalisation du système, comme la langue, le pays, la
région etc. Nous pouvons utiliser <a href="@hack:chapter=Locale">la
bibliothèque <code>Hoa\Locale</code></a> pour modifier ces données, mais ce
n'est pas une dépendance de <code>Hoa\Ustring</code> pour autant.</p>
<p>Nous pouvons également savoir si une chaîne <strong>correspond</strong> à
un certain motif, toujours exprimé avec une expression régulière. Pour cela,
nous allons utiliser la méthode <code>Hoa\Ustring\Ustring::match</code>. Cette
méthode repose sur les fonctions
<a href="http://php.net/preg_match"><code>preg_match</code></a> et
<a href="http://php.net/preg_match_all"><code>preg_match_all</code></a> de
PHP, mais en modifiant les options du motif afin qu'il supporte Unicode. Nous
avons les paramètres suivants : le motif, une variable par référence pour
récupérer les captures, les <em lang="en">flags</em>, la position de début de
recherche (<em lang="en">offset</em>) et enfin un booléen indiquant si la
recherche est globale ou non (respectivement si nous devons utiliser
<code>preg_match_all</code> ou <code>preg_match</code>). Par défaut, la
recherche n'est pas globale.</p>
<p>Ainsi, nous allons vérifier que notre exemple en français contient bien
<code>aime</code> avec son complément d'objet direct :</p>
<pre><code class="language-php">$french->match('#(?:(?&amp;lt;direct_object>\w)[\'\b])aime#', $matches);
var_dump($matches['direct_object']);
/**
* Will output:
* string(1) "t"
*/</code></pre>
<p>Cette méthode retourne <code>false</code> si une erreur est survenue (par
exemple si le motif n'est pas correct), 0 si aucune correspondance n'a été
trouvée, le nombre de correspondances trouvées sinon.</p>
<p>Similairement, nous pouvons <strong>chercher</strong> et
<strong>remplacer</strong> des sous-chaînes par d'autres sous-chaînes suivant
un motif, toujours exprimé avec une expression régulière. Pour cela, nous
allons utiliser la méthode <code>Hoa\Ustring\Ustring::replace</code>. Cette
méthode repose sur les fonctions
<a href="http://php.net/preg_replace"><code>preg_replace</code></a> et
<a href="http://php.net/preg_replace_callback"><code>preg_replace_callback</code></a>
de PHP, mais toujours en modifiant les options du motif afin qu'il supporte
Unicode. En premier argument, nous trouvons le ou les motifs, en deuxième
argument, le ou les remplacements et en dernier argument la limite de
remplacements à faire. Si le remplacement est un <em lang="en">callable</em>,
alors la fonction <code>preg_replace_callback</code> sera utilisée.</p>
<p>Ainsi, nous allons modifier notre exemple français pour qu'il soit plus
poli :</p>
<pre><code class="language-php">$french->replace('#(?:\w[\'\b])(?&amp;lt;verb>aime)#', function ($matches) {
return 'vous ' . $matches['verb'];
});
echo $french;
/**
* Will output:
* Je vous aime
*/</code></pre>
<p>La classe <code>Hoa\Ustring\Ustring</code> propose des constantes qui sont
des aliases de constantes PHP et qui permettent une meilleure lecture du
code:</p>
<ul>
<li><code>Hoa\Ustring\Ustring::WITHOUT_EMPTY</code>, alias de
<code>PREG_SPLIT_NO_EMPTY</code> ;</li>
<li><code>Hoa\Ustring\Ustring::WITH_DELIMITERS</code>, alias de
<code>PREG_SPLIT_DELIM_CAPTURE</code> ;</li>
<li><code>Hoa\Ustring\Ustring::WITH_OFFSET</code>, alias de
<code>PREG_OFFSET_CAPTURE</code> et
<code>PREG_SPLIT_OFFSET_CAPTURE</code> ;</li>
<li><code>Hoa\Ustring\Ustring::GROUP_BY_PATTERN</code>, alias de
<code>PREG_PATTERN_ORDER</code> ;</li>
<li><code>Hoa\Ustring\Ustring::GROUP_BY_TUPLE</code>, alias de
<code>PREG_SET_ORDER</code>.</li>
</ul>
<p>Comme ce sont des aliases stricts, nous pouvons écrire :</p>
<pre><code class="language-php">$string = new Hoa\Ustring\Ustring('abc1 defg2 hikl3 xyz4');
$string->match(
'#(\w+)(\d)#',
$matches,
Hoa\Ustring\Ustring::WITH_OFFSET
| Hoa\Ustring\Ustring::GROUP_BY_TUPLE,
0,
true
);</code></pre>
<h3 id="Characters" for="main-toc">Caractères</h3>
<p>La classe <code>Hoa\Ustring\Ustring</code> offre des méthodes statiques
travaillant sur un seul caractère Unicode. Nous avons déjà évoqué la méthode
<code>getCharDirection</code> qui permet de connaître la
<strong>direction</strong> d'un caractère. Nous trouvons aussi
<code>getCharWidth</code> qui calcule le <strong>nombre de colonnes</strong>
nécessaires pour l'affichage d'un seul caractère. Ainsi :</p>
<pre><code class="language-php">var_dump(
Hoa\Ustring\Ustring::getCharWidth(Hoa\Ustring\Ustring::fromCode(0x7f)),
Hoa\Ustring\Ustring::getCharWidth('a'),
Hoa\Ustring\Ustring::getCharWidth('㽠')
);
/**
* Will output:
* int(-1)
* int(1)
* int(2)
*/</code></pre>
<p>Cette méthode retourne -1 ou 0 si le caractère n'est pas
<strong>imprimable</strong> (par exemple si c'est un caractère de contrôle,
comme <code>0x7f</code> qui correspond à <code>DELETE</code>), 1 ou plus si
c'est un caractère qui peut être imprimé. Dans notre exemple, <code></code>
s'imprime sur 2 colonnes.</p>
<p>Pour plus de sémantique, nous avons accès à la méthode
<code>Hoa\Ustring\Ustring::isCharPrintable</code> qui permet de savoir si un
caractère est imprimable ou pas.</p>
<p>Si nous voulons calculer le nombre de colonnes pour tout une chaîne, il
faut utiliser la méthode <code>Hoa\Ustring\Ustring::getWidth</code>.
Ainsi :</p>
<pre><code class="language-php">var_dump(
$french->getWidth(),
$arabic->getWidth(),
$japanese->getWidth()
);
/**
* Will output:
* int(9)
* int(4)
* int(18)
*/</code></pre>
<p>Essayez dans un terminal avec une police <strong>mono-espacée</strong>.
Vous verrez que le japonais demande 18 colonnes pour s'afficher. Cette mesure
est très utile si nous voulons connaître la largeur d'une chaîne pour la
positionner correctement.</p>
<p>La méthode <code>getCharWidth</code> est différente de
<code>getWidth</code> car elle prend en compte des caractères de contrôles.
Elle est destinée à être utilisée, par exemple, avec des terminaux (voir
<a href="@hack:chapter=Console">la bibliothèque
<code>Hoa\Console</code></a>).</p>
<p>Enfin, si cette fois nous ne nous intéressons pas aux caractères Unicode
mais aux caractères <strong>machines</strong> <code>char</code> (soit 1
octet), nous avons une opération supplémentaire. La méthode
<code>Hoa\Ustring\Ustring::getBytesLength</code> va compter la
<strong>taille</strong> de la chaîne en octets :</p>
<pre><code class="language-php">var_dump(
$arabic->getBytesLength(),
$japanese->getBytesLength()
);
/**
* Will output:
* int(8)
* int(27)
*/</code></pre>
<p>Si nous comparons ces résultats avec ceux de la méthode
<code>Hoa\Ustring\Ustring::count</code>, nous comprenons que les caractères
arabes sont encodés sur 2 octets alors que les caractères japonais sont
encodés sur 3 octets. Nous pouvons également obtenir un octet précis à l'aide
de la méthode <code>Hoa\Ustring\Ustring::getByteAt</code>. Encore une fois,
l'index n'est pas borné.</p>
<h3 id="Code-point" for="main-toc">Code-point</h3>
<p>Chaque caractère est représenté en machine par un entier, appelé
<strong>code-point</strong>. Pour obtenir le code-point d'un caractère, nous
pouvons utiliser la méthode statique <code>Hoa\Ustring\Ustring::toCode</code>,
et pour obtenir un caractère à partir d'un code, nous pouvons utiliser la
méthode statique <code>Hoa\Ustring\Ustring::fromCode</code>. Nous avons aussi
la méthode statique <code>Hoa\Ustring\Ustring::toBinaryCode</code> qui
retourne la représentation sous forme binaire d'un caractère. Prenons un
exemple :</p>
<pre><code class="language-php">var_dump(
Hoa\Ustring\Ustring::toCode('Σ'),
Hoa\Ustring\Ustring::toBinaryCode('Σ'),
Hoa\Ustring\Ustring::fromCode(0x1a9)
);
/**
* Will output:
* int(931)
* string(32) "1100111010100011"
* string(2) "Σ"
*/</code></pre>
<h2 id="Search_algorithms" for="main-toc">Algorithmes de recherche</h2>
<p>La bibliothèque <code>Hoa\Ustring</code> propose des algorithmes de
<strong>recherches</strong> sophistiquées sur les chaînes de caractères à
travers la classe <code>Hoa\Ustring\Search</code>.</p>
<p>Nous allons étudier l'algorithme
<code>Hoa\Ustring\Search::approximated</code> qui fait une recherche d'une
sous-chaîne dans une chaîne avec au maximum <strong><em>k</em>
différences</strong> (une différence étant une insertion, une délétion ou une
modification). Prenons un exemple classique avec une représentation
ADN : nous allons chercher toutes les sous-chaînes s'approchant de
<code>GATAA</code> à 1 différence près (au maximum) dans
<code>CAGATAAGAGAA</code>. Pour cela, nous allons donc écrire :</p>
<pre><code class="language-php">$x = 'GATAA';
$y = 'CAGATAAGAGAA';
$k = 1;
$search = Hoa\Ustring\Search::approximated($y, $x, $k);
$n = count($search);
echo 'Try to match ', $x, ' in ', $y, ' with at most ', $k, ' difference(s):', "\n";
echo $n, ' match(es) found:', "\n";
foreach ($search as $position) {
echo ' • ', substr($y, $position['i'], $position['l'), "\n";
}
/**
* Will output:
* Try to match GATAA in CAGATAAGAGAA with at most 1 difference(s):
* 4 match(es) found:
* • AGATA
* • GATAA
* • ATAAG
* • GAGAA
*/</code></pre>
<p>Cette méthode retourne un tableau de tableaux. Chaque sous-tableau
représente un résultat et contient trois indexes : <code>i</code> pour la
position du premier caractère (octet) du résultat, <code>j</code> pour la
position du dernier caractère et <code>l</code> pour la taille du résultat
(tout simplement <code>j</code> - <code>i</code>).
Ainsi, nous pouvons calculer les résultats en utilisant notre chaîne initiale
(ici <code class="language-php">$y</code>) et ces indexes.</p>
<p>Avec notre exemple, nous avons quatre résultats. Le premier est
<code>AGATA</code>, soit <code>GATA<em>A</em></code> avec un caractère
déplacé, et <code>AGATA</code> existe bien dans
<code>C<em>AGATA</em>AGAGAA</code>. Le deuxième résultat est
<code>GATAA</code>, notre sous-chaîne, qui existe bel et bien dans
<code>CA<em>GATAA</em>GAGAA</code>. Le troisième résultat est
<code>ATAAG</code>, soit <code><em>G</em>ATAA</code> avec un caractère
déplacé, et <code>ATAAG</code> existe bien dans
<code>CAG<em>ATAAG</em>AGAA</code>. Enfin, le dernier résultat est
<code>GAGAA</code>, soit <code>GA<em>T</em>AA</code> avec un caractère
modifié, et <code>GAGAA</code> existe bien dans
<code>CAGATAA<em>GAGAA</em></code>.</p>
<p>Prenons un autre exemple, plus concret cette fois-ci. Nous allons
considérer la chaîne <code>--testIt --foobar --testThat --testAt</code> (qui
représente les options possibles d'une ligne de commande), et nous allons
chercher <code>--testot</code>, une option qu'aurait pu donner
l'utilisateur. Cette option n'existe pas telle quelle. Nous allons donc
utiliser notre algorithme de recherche avec 1 différence au maximum. Voyons
plutôt :</p>
<pre><code class="language-php">$x = 'testot';
$y = '--testIt --foobar --testThat --testAt';
$k = 1;
$search = Hoa\Ustring\Search::approximated($y, $x, $k);
$n = count($search);
// …
/**
* Will output:
* Try to match testot in --testIt --foobar --testThat --testAt with at most 1 difference(s)
* 2 match(es) found:
* • testIt
* • testAt
*/</code></pre>
<p>Les résultats <code>testIt</code> et <code>testAt</code> sont des vraies
options, donc nous pouvons les proposer à l'utilisateur. C'est un mécanisme
utilisé par <code>Hoa\Console</code> pour proposer des corrections à
l'utilisateur s'il se trompe.</p>
<h2 id="Conclusion" for="main-toc">Conclusion</h2>
<p>La bibliothèque <code>Hoa\Ustring</code> propose des facilités pour
manipuler des chaînes encodées au format Unicode, mais aussi pour effectuer
des recherches sophistiquées sur des chaînes.</p>
</yield>
</overlay>