Sign in Join
Wiki copytemporary

FPC Unicode support/fr

English · Español · Français · Русский

Introduction

Jusqu'à la version 2.6.x inclus, la RTL est basée sur ceux de Turbo Pascal et Delphi 7. Cela signifie qu'elle était au départ basé sur les types shortstring, ansistring et pchar. Aucun de ces types n'avait d'information d'encodage associé avec eux, mais ils étaient supposés être implicitement encodés dans l'"encodage système par défaut" et étaient passés aux API système sans aucune conversion.

Dans Delphi 2009, Embarcadero a basculé l'ensemble de la RTL vers le type UnicodeString, qui représente des chaînes utilisant UTF-16. En plus, ils sont rendu le type AnsiString "sensible (aware) à la page de code". Cela signifie que les AnsiStrings dès lors contiennent la page de code selon lequel les données doivent être interprétées.

Le support au niveau du langage de FPC est déjà disponible dans les versions en cours de développement du compilateur (FPC 2.7.1/trunk). Le support au niveau RTL n'est pas encore complet. Cette page donne une vue d'ensemble des comportements relatifs à la page de code pour ces types de chaînes, le niveau actuel du support par la RTL et des possibles voies d'amélioration futures pour ce support.

Compatibilité ascendante

Si vous avez du code existant qui marche d'une façon connue (*) avec une version antérieure de FPC et que vous ne faites aucun changement, il devrait continuer à fonctionner non modifié avec la nouvelle verison de FPC. Garantir tel est le but principal de la multitude de variables de page de code et leurs valeurs par défaut, comme décrit ci-dessous.

(*) cela veut dire this principalement : vous ne stockez pas de donnée dans une AnsiString qui a été encodée par autre chose que la page de code par défaut du système et par la suite passe cette chaîne tel quelle à une routine RTL de FPC. Par exemple, le code actuel de Lazarus est bien en général, comme vous êtes censés appeler UTF8ToAnsi() avant de passer ses chaînes aux routines RTL de FPC.

Code pages

Une page de code définit comment les octets individuels d'une chaînes sont interprétés i.e. quelle lettre, quel symbole ou autre caractère graphique correspond à chaque octet ou séquence d'octets.

Identificateurs de page de code

Un identificateur de page de code est toujours enregistré comme un TSystemCodePage, qui est un alias pour Word. La valeur représente la page de code correspondante telle que définie par [http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx Microsoft Windows]. En plus, il y a 3 valeurs spéciales de code de page :

Note: les identificateurs de page de code sont différent des noms de page de code tels qu'ils sont utilisés dans la directive {$codepage xxx} (qui est déjà disponible dans la version stable de FPC). Les noms de page de code sont des noms d'unités individuelles de page de code exposés dans l'unité de jeu de caractères, qui ont des noms tels que cp866 et cp1251 et utf8.

Réglage de la page de code

L'unité system contient plusieurs variables globales qui indiquent la page de code par défaut utilisée par certaines opérations.

DefaultSystemCodePage

DefaultFileSystemCodePage

DefaultRTLFileSystemCodePage

Page de code du fichier source

La page de code du fichier sourcedétermine comment les constantes de chaîne sont interprétées et où le compilateur insèrera l'opération de conversion de la page de code à l'affectation d'un type de chaîne vers un autre.

La page de code du fichier source est déterminée de la façon suivante:

Strings

String/character types

Shortstring

La page de code d'une shortstring est implicitement CP_ACP d'où elle sera toujours égale à la valeur courante de DefaultSystemCodePage.

PAnsiChar/AnsiChar

Ces types sont les mêmes que les anciens types PChar/Char. Dans tous les modes du compilateur sauf pour {$mode delphiunicode}, PChar/Char sont aussi encore des alias pour PAnsiChar/AnsiChar. Leur page de code est implicitement CP_ACP et donc toujours égale à la valeur courante de DefaultSystemCodePage.

PWideChar/PUnicodeChar et WideChar/UnicodeChar

Ces types demeurent inchangés. WideChar/UnicodeChar peuvent contenir une simple unité de code UTF-16, alors que PWideChar/PUnicodeChar pointe sur une simple unité de code ou un tableau d'unités de code en UTF-16.

En {$mode delphiunicode}, PChar devient un alias de PWideChar/PUnicodeChar et Char devient un alias de WideChar/UnicodeChar.

UnicodeString/WideString

Ces types se comporte comme dans les versions précédentes:

Ansistring

Les AnsiStrings sont des chaînes à comptage de références avec une longueur maximal de high(SizeInt) octets. En plus, une information de code de page peut maintenant leur être associée.

La chose la plus importante à comprendre sur le nouveau type AnsiString est qu'il a à la fois une page de code déclarée/statique/préférée/par défaut (appelée page de code declarée à partir de maintenant), et une page de code dynamique. La page de code declarée dit au compilateur que lorsqu'on affecte quelque chose à cet AnsiString, il devrait d'abord convertir cette donnée vers cette page de code (sauf si c'est CP_NONE, voir RawByteString plus bas). La page de code dynamique est une propriété de l'AnsiString qui, tels la longueur et le compteur de référence, définit la page de code en cours des données actuellement tenues par cette AnsiString.

Page de code declarée

La page de code declarée d'une AnsiString peut seulement être définie en déclarant un nouveau type comme suit:

pascal
type
  CP866String = type AnsiString(866); // note the extra "type"

La page de code declarée d'une variable déclarée comme pure AnsiString est CP_ACP. En effet, le type AnsiString est maintenant sémantiquement défini dans l'unité System comme:

pascal
type
  AnsiString = type AnsiString(CP_ACP);

Un autre type AnsiString(X) prédéfini dans l'unité System est UTF8String:

pascal
type
  UTF8String = type AnsiString(CP_UTF8);

Une fois que vous avez défini tel type AnsiString(X), vous pouvez l'utiliser pour déclarer des variables, des paramètres, champs etc comme d'habitude.

Notez que CP_UTF16 et CP_UTF16BE ne sont pas valides comme page de code pour les AnsiStrings. Ce qui peut résulter d'une telle définition est indéfini.

Page de code dynamique

Si une chaîne d'une page de code declarée X1 est affectée par une chaîne d'une pafe de code X2, alors:

Ces règles signifient qu'il est parfaitement possible pour une variable AnsiString d'avoir une page de code dynamique qui diffère de sa page de code declarée. P.ex. dans le troisième cas, X1 pourrait être CP_ACP, alors qu'après affectation, il pourrait avoir un page de code dynamique égale à DefaultSystemCodePage.

Note: comme mentionné au-dessus, qu'une conversion potentielle de page de code survienne ou pas dépend seulement de la page de code declarée des chaînes impliquées. Cela signifie que si vous affectez une AnsiString(X) à une autre AnsiString(X) et que l'ancienne page de code dynamique était différente de X, la chaîne ne sera pas convertie vers la page de code X par l'affectation.

RawByteString

Le type RawByteString est défini comme

pascal
type
  RawByteString = type AnsiString(CP_NONE);

Comme mentionné avant, les résultats de conversions de/vers la page de code CP_NONE sont indéfinis. Comme cela n'a pas de sens de définir un type dans la RTL dont le comportement est indéfini, le comportement de RawByteString est quelque peu différent des autres types AnsiString(X).

Comme première approximation, RawByteString paut être considéré comme un "AnsiString non typé": affecter une AnsiString(X) vers une RawByteString a exactement le même comportement que d'affecter cet AnsiString(X) vers une autre variable AnsiString(X) avec la même valeur de X: aucune conversion de page de code ou copie ne se passe, seul le compteur de référence est incrémenté.

Moins intuitif est probablement le fait que lorsqu'une RawByteString est affectée vers une AnsiString(X), la meêm chose se produit: pas de conversion de page de code ni de copie, seulment une incrémentation du compteur. Notez que cela signifie que les résultats de fonctions retourant une RawByteString ne seront jamais converties vers la page de code de destination. C'est une autre manière par laquelle la page de code dynamique d'une AnsiString(X) peut devenir différente de sa page de code declarée.

Ce type est principalement utilisé pour déclarer des const, constref et des paramètres par valeur qui acceptent toute valeur AnsiString(X) sans la convertir vers une page de code prédéfinie. Notez que si vous faites cela, la routine acceptant ces paramètres devrait être capable de manipuler des chaînes avec n'importe quelle page de code dynamique.

Les paramètres var et out peuvent être aussi déclarés comme RawByteString, mais dans ce cas, le compilateur donnera une erreur si une AnsiString(X) dont le page de code declarée est différente de CP_NONE est passé dedans. C'est consistant avec les paramètres var et out en général: ils nécessitent une exacte correspondance de type à passer dedans. Vous pouvez ajouter une conversion explicite de type vers RawByteString() pour supprimer l'erreur, mais vous devez être préparé à traiter le fait que la chaîne retournée peut avoir aucune page de code dynamique.

Concaténation de chaîne

Normalement, en Pascal le type du résultat d'une expression est indépendant de comment son résultat est utilisé après. P.ex. multiplier 2 longints sur une plate-forme 32-bit et affecter le résultat vers un Int64 réalisera encore la multiplication en utilisant l'artithmétique 32-bit, et seulement après le résultat is converti en 64 bit.

Les chaînes sensibles à la page de code sont la seule exception à la règle: concaténer deux chaînes ou plus se produit toujours sans perte de données, bien qu'après la chaîne résultante sera bien sûr convertie vers la page de code declarée de la destination (une perte de donnée peut alors en résulter).

Affecter le résultat d'une concaténation vers une RawByteString est aussi particulier:

String constants

Le compilateur doit connaître la page de code selon laquelle il devra interprété les constantes de chaîne car il peut avoir à les convertir au moment de la compilation. Normalement, une constante de chaîne est interprétée selon la page de code du fichier source. Si la page de code du fichier source est ACP_CP, une valeur par défaut est utilisée à la place: dans ce cas, pendant les conversions, la constante de chaîne est supposée avoir la page de code 28591 (ISO 8859-1 Latin 1; Western European).

Quand une constante de chaîne est affectée dans une AnsiString(X) soit par code ou comme partie d'une constante typée ou d'une initialisation de variable alors :

Similairement, si une constante String est affectée dans une UnicodeString, la constante String est convertie, à la compilation, de la page de code du fichier source vers UTF-16.

Pour les ShortString et PChar, la même règle que pour AnsiString(CP_ACP) est suivie.

Notez que les constantes String symboliques seront converties à la compilation vers le type String et la page de code appropriés chaque fois qu'ils sont utilisés. Cela signifie qu'il n'y a pas de charge sur la vitesse en utilisant une constante simple chaîne dans des contextes de pages de code et types de chaîne multiples, seulement quelque charge sur la taille de donnée.

Il s'ensuit de tout ceci que pour garantir une interprétation prédictible des constantes String dans votre code source, il est mieux soit inclure une directive explicite {$codepage xxx} (ou d'utiliser l'option en ligne de commande -Fc), ou enregistrer le code source en UTF-8 avec un BOM.

Indexation de chaîne

Rien ne change dans l'indexation de chaînes. Chaque élément d'une chaîne UnicodeString/WideString est à 2 octets et chaque élément de tout autre type de chaîne est à 1 octet. Le mécanisme d'indexation de chaîne ignore totalement les pages de code et les points de code composites.

Changements dans la RTL

En vue de garantir pleinement l'intégrité de donnée en présence de chaîne sensible à la page de code, toutes les routines dans la RTL et les paquets qui acceptent des paramètres AnsiString doivent être adaptées. La raison en est que si leurs paramètres restent des purs AnsiString alors toute chaîne avec un code de page statique sera convertie vers DefaultSystemCodePage quand elle sera passée dedans. Il en résultera une perte de donnée.

Jusqu'à maintenant, les routines traitant de l'accès au système de fichier ont été mise à jour pour préserver toute la donnée caractère. Ci se trouve une liste exhaustive de toutes les routines qui préservent l'encodage des chaînes dans FPC 2.7.1 et postérieur. Sauf mention explicitement contraire, ces routines ont également toutes des surcharges qui acceptent des paramètres UnicodeString.

A faire dans la RTL

Comme la liste ci-dessus est exhaustive, aucune autre routine RTL ne supporte encore des pages de code arbitraire. Cette section contient une liste des pièges que certaines personnes ont identifiés et, si possible, des solutions de contournement. Notez que les routines non mentionnés ici ni ci-dessus sont aussi peu sûres que celles qui sont explicitement mentionnées.

TFormatSettings et DefaultFormatSettings

Le type de ThousandSeparatoretDecimalSeparatorest AnsiChar. Cela veut dire que siDefaultSystemCodePage'' vaut UTF-8 et que le séparateur de locale fait plus d'un caractère de longueur dans cet encodage, ces champs ne seront pas assez grands. Des exemples sont le blancs insécables français et russes utilisés pour représenter le séparateur des milliers.

Sections anciennes/obsolètes

Warning: Ces sections sont conservées à titre historique - SVP, mettez à jour les sections du dessus avec cette information si elle est toujours applicable. Depuis FPC 2.7, (version en cours de développement), le support intensif d'Unicode a été implémenté.

Changements visibles par l'utilisateur

(*** non traduit car obsolète ***)

Full support of code page aware strings is not possible without breaking some existing code. The following list tries to summarize the most important user visible changes.

Voir aussi


From the Free Pascal wiki, page "FPC Unicode support/fr", as it stood on 2020-02-16 after a change by GAN, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 1, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.