Difference between revisions of "FPC Unicode support/es"

From Lazarus wiki
Jump to navigationJump to search
m (Fixed syntax highlighting)
 
(11 intermediate revisions by 2 users not shown)
Line 46: Line 46:
 
* '''Valor inicial''':
 
* '''Valor inicial''':
 
** Windows: UTF-8, porque el RTL utiliza llamadas a la API del sistema operativo UTF-16 (por lo que no se pierden datos en operaciones intermedias).
 
** Windows: UTF-8, porque el RTL utiliza llamadas a la API del sistema operativo UTF-16 (por lo que no se pierden datos en operaciones intermedias).
** OS X e iOS: DefaultSystemCodePage si no hay ningún [http://www.freepascal.org/docs-html/rtl/system/setwidestringmanager.html widestring manager] instalado, de lo contrario UTF-8 (según lo definido por Apple).
+
** macOS e iOS: DefaultSystemCodePage si no hay ningún [http://www.freepascal.org/docs-html/rtl/system/setwidestringmanager.html widestring manager] instalado, de lo contrario UTF-8 (según lo definido por Apple).
** Unix (excluyendo OS X e iOS): DefaultSystemCodePage, porque la codificación de nombres de archivo es indefinida en plataformas Unix (es una matriz sin tipo de bytes que se puede interpretar de cualquier manera; no se garantiza que sea válida UTF-8).
+
** Unix (excluyendo macOS e iOS): DefaultSystemCodePage, porque la codificación de nombres de archivo es indefinida en plataformas Unix (es una matriz sin tipo de bytes que se puede interpretar de cualquier manera; no se garantiza que sea válida UTF-8).
 
** DefaultSystemCodePage, porque OS/2 no proporciona ninguna posibilidad de especificar una página de códigos diferente para las operaciones de E/S de archivo que no sea la página de códigos de todo el proceso actual.
 
** DefaultSystemCodePage, porque OS/2 no proporciona ninguna posibilidad de especificar una página de códigos diferente para las operaciones de E/S de archivo que no sea la página de códigos de todo el proceso actual.
 
** Otras plataformas: igual que DefaultSystemCodePage.
 
** Otras plataformas: igual que DefaultSystemCodePage.
 
* '''Modificaciones''': puede modificar este valor llamando a SetMultiByteFileSystemCodePage(CodePage: TSystemCodePage); tenga en cuenta que en OS/2 esta variable se está sincronizando con la página de códigos de proceso actual (establecida, por ejemplo, por DosSetProcessCP) durante todas las operaciones de E/S de archivos con el fin de evitar transformaciones no válidas.
 
* '''Modificaciones''': puede modificar este valor llamando a SetMultiByteFileSystemCodePage(CodePage: TSystemCodePage); tenga en cuenta que en OS/2 esta variable se está sincronizando con la página de códigos de proceso actual (establecida, por ejemplo, por DosSetProcessCP) durante todas las operaciones de E/S de archivos con el fin de evitar transformaciones no válidas.
* '''Notas''': la configuración de Unix/OS X/iOS solo se aplica en caso de que se instale el administrador de cadenas anchas cwstring, de lo contrario DefaultFileSystemCodePage tendrá el mismo valor que DefaultSystemCodePage después del inicio del programa.
+
* '''Notas''': la configuración de Unix/macOS/iOS solo se aplica en caso de que se instale el administrador de cadenas anchas cwstring, de lo contrario DefaultFileSystemCodePage tendrá el mismo valor que DefaultSystemCodePage después del inicio del programa.
  
 
=== DefaultRTLFileSystemCodePage ===
 
=== DefaultRTLFileSystemCodePage ===
Line 57: Line 57:
 
* '''Valor inicial'''
 
* '''Valor inicial'''
 
** Windows: DefaultSystemCodePage, para retrocompatibilidad.
 
** Windows: DefaultSystemCodePage, para retrocompatibilidad.
** OS X and iOS: DefaultSystemCodePage si no hay un [http://www.freepascal.org/docs-html/rtl/system/setwidestringmanager.html widestring manager] instalado, caso contrario UTF-8 para retrocompatibilidad (era siempre UTF-8 en el pasado, ya que eso es lo que devuelven las API de archivos del sistema operativo y no convertimos estos datos).
+
** macOS and iOS: DefaultSystemCodePage si no hay un [http://www.freepascal.org/docs-html/rtl/system/setwidestringmanager.html widestring manager] instalado, caso contrario UTF-8 para retrocompatibilidad (era siempre UTF-8 en el pasado, ya que eso es lo que devuelven las API de archivos del sistema operativo y no convertimos estos datos).
** Unix (excluding OS X and iOS): DefaultSystemCodePage, por la misma razón que con DefaultFileSystemCodePage. Establecer esto en un valir diferente a DefaultFileSystemCodePage es una mala idea en estas plataformas, debido a que cualquier conversión de página de códigos puede dañar estas cadenas, ya que se desconoce su codificación inicial.
+
** Unix (excluding macOS and iOS): DefaultSystemCodePage, por la misma razón que con DefaultFileSystemCodePage. Establecer esto en un valir diferente a DefaultFileSystemCodePage es una mala idea en estas plataformas, debido a que cualquier conversión de página de códigos puede dañar estas cadenas, ya que se desconoce su codificación inicial.
 
** OS/2: igual a DefaultSystemCodePage (por compatibilidad con versiones anteriores y también porque es la opción más natural a menos que necesite jugar con diferentes páginas de códigos)
 
** OS/2: igual a DefaultSystemCodePage (por compatibilidad con versiones anteriores y también porque es la opción más natural a menos que necesite jugar con diferentes páginas de códigos)
 
** Other platforms: igual a DefaultSystemCodePage
 
** Other platforms: igual a DefaultSystemCodePage
Line 95: Line 95:
  
 
=== Ansistring ===
 
=== Ansistring ===
AnsiStrings are reference-counted types with a maximum length of high(SizeInt) bytes. Additionally, they now also have code page information associated with them.
+
AnsiStrings son tipos de conteo de referencia con una longitud máxima de bytes High(SizeInt). Además, ahora también tienen información del código de página asociado con ellos.
  
The most important thing to understand about the new AnsiString type is that it both has a declared/static/preferred/default code page (called ''declared code page'' from now on), and a dynamic code page. The declared code page tells the compiler that when assigning something to that AnsiString, it should first convert the data to that declared code page (except if it is CP_NONE, see [[#RawByteString|RawByteString]] below). The dynamic code page is a property of the AnsiString which, similar to the length and the reference count, defines the actual code page of the data currently held by that AnsiString.
+
Lo más importante que debe comprender sobre el nuevo tipo AnsiString es que tiene una página de códigos declarada/estática/preferida/predeterminada (denominada página de códigos declarada a partir de ahora) y una página de códigos dinámica. La página de códigos declarada indica al compilador que al asignar algo a ese AnsiString, primero debe convertir los datos a esa página de códigos declarada (excepto si es CP_NONE, vea [[#RawByteString|RawByteString]] a continuación). La página de códigos dinámicos es una propiedad de la AnsiString que, similar a la longitud y el recuento de referencias, define la página de códigos real de los datos que actualmente tiene ese AnsiString.  
  
==== Declared code page ====
+
==== Códigos de página declarados ====
The declared code page of an AnsiString can only be defined by declaring a new type as follows:
+
El código de páginas declarado de un AnsiString sólo se puede definir declarando un nuevo tipo (type) de la siguiente manera:
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
type
 
type
   CP866String = type AnsiString(866); // note the extra "type"
+
   CP866String = type AnsiString(866);  
 
</syntaxhighlight>
 
</syntaxhighlight>
  
The declared code page of a variable declared as plain ''AnsiString'' is CP_ACP. In effect, the AnsiString type is now semantically defined in the System unit as
+
El código de página declarado de una variable declarada como AnsiString sin formato es CP_ACP. En efecto, el tipo AnsiString ahora se define semánticamente en la unidad System como:
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
type
 
type
 
   AnsiString = type AnsiString(CP_ACP);
 
   AnsiString = type AnsiString(CP_ACP);
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Another predefined AnsiString(X) type in the System unit is UTF8String:
+
Otro tipo AnsiString(X) predefinido en la unidad System es UTF8String:
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
type
 
type
 
   UTF8String = type AnsiString(CP_UTF8);
 
   UTF8String = type AnsiString(CP_UTF8);
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Once you have defined such a custom AnsiString(X) type, you can use it to declare variables, parameters, fields etc as usual.
+
Una vez que haya definido un tipo AnsiString(X) personalizado, puede usarlo para declarar variables, parámetros, campos, etc. como de costumbre.  
  
Note that CP_UTF16 and CP_UTF16BE are not valid as code pages for AnsiStrings. The result of defining an AnsiString with such a code page is undefined.
+
Tenga en cuenta que CP_UTF16 y CP_UTF16BE no son válidos como páginas de códigos para AnsiStrings. El resultado de definir un AnsiString con una página de códigos es indefinido.
  
==== Dynamic code page ====
+
==== Código de páginas dinámico ====
 +
Si un string con un código de página declarado SOURCE_CP se asigna a un string con el código de página declarado DEST_CP, entonces:
 
If a string with a declared code page SOURCE_CP is assigned to a string with declared code page DEST_CP , then
 
If a string with a declared code page SOURCE_CP is assigned to a string with declared code page DEST_CP , then
* if (SOURCE_CP = CP_NONE) or (DEST_CP = CP_NONE), see [[#RawByteString|RawByteString]], otherwise
+
* if (SOURCE_CP = CP_NONE) or (DEST_CP = CP_NONE), ver [[#RawByteString|RawByteString]], de lo contrario
* if (source file codepage <> CP_ACP), then if (DEST_CP = CP_ACP) and (SOURCE_CP = source file codepage) or vice versa, no conversion will occur (even if at run time ''DefaultSystemCodePage'' has a different value from the source file code page). The reason for the "(source file codepage <> CP_ACP)" condition is backward compatibility with previous FPC versions (while they did not support AnsiStrings with arbitrary code pages, they did always reinterpret AnsiStrings according to the current value of the system code page). Otherwise,
+
* if (source file codepage <> CP_ACP), then if (DEST_CP = CP_ACP) and (SOURCE_CP = source file codepage) or vice versa, no se producirá ninguna conversión (inclusive si en tiempo de ejecución ''DefaultSystemCodePage'' tiene un valor distinto del código de página del archivo fuente). La razón para la condición "(source file codepage <> CP_ACP)" condition es la compatibilidad con versiones anteriores de FPC (aunque no admitían AnsiStrings con páginas de códigos arbitrarias, siempre se interpretaban AnsiStrings según el valor actual de la página de códigos del sistema). de o contrario,
* if (SOURCE_CP <> DEST_CP), the string data will be converted from codepage X1 to codepage X2 before assignment, whereby CP_ACP will be interpreted as the current value of ''DefaultSystemCodePage''. Otherwise,
+
* if (SOURCE_CP <> DEST_CP), el string se convertirá desde codepage X1 a codepage X2 antes de la asignación, donde CP_ACP será interpretado como el valor actual de ''Defaultsysticacodepage''. de lo contrario,
* if (SOURCE_CP = DEST_CP), no codepage conversion will be performed.
+
* if (SOURCE_CP = DEST_CP), no se realizará ninguna conversión.
  
These rules mean that it is perfectly possible for an AnsiString variable to get a dynamic code page that differs from its declared code page. E.g. in the third case SOURCE_CP could be CP_ACP, while after the assignment it may have a dynamic code page equal to ''DefaultSystemCodePage''.
+
Estas reglas significan que es perfectamente posible para una variable AnsiString obtener una página de códigos dinámica que difiere de su página de códigos declarada. Por ejemplo, en el tercer caso SOURCE_CP podría ser CP_ACP, mientras que después de la asignación puede tener una página de códigos dinámica igual a ''DefaultSystemCodePage''.  
  
Note: as mentioned above, whether or not a potential code page conversion happens only depends on the ''declared code pages'' of the involved strings. This means that if you assign one AnsiString(X) to another AnsiString(X) and the former's dynamic code was different from X, the string data will ''not'' be converted to code page X by the assignment.
+
Nota: como se mencionó anteriormente, si se produce o no una posible conversión de página de códigos depende únicamente de las páginas de códigos declaradas de las cadenas implicadas. Esto significa que si asigna un AnsiString(X) a otro AnsiString(X) y el código dinámico del primero era diferente de X, los datos de cadena no se convertirán en la página de códigos X por la asignación.
  
 
==== RawByteString ====
 
==== RawByteString ====
The RawByteString type is defined as
+
El tipo (type) RawByteString se define como:
<syntaxhighlight>
+
<syntaxhighlight lang=pascal>
 
type
 
type
 
   RawByteString = type AnsiString(CP_NONE);
 
   RawByteString = type AnsiString(CP_NONE);
 
</syntaxhighlight>
 
</syntaxhighlight>
  
As mentioned earlier, the results of operations on strings with the CP_NONE code page are undefined. As it does not make sense to define a type in the RTL whose behaviour is undefined, the behaviour of RawByteString is somewhat different than that of other AnsiString(X) types.
+
Como se mencionó anteriormente, los resultados de las operaciones en cadenas con la página de códigos CP_NONE son indefinidos. Como no tiene sentido definir un tipo en el RTL cuyo comportamiento es indefinido, el comportamiento de RawByteString es algo diferente al de otros tipos AnsiString(X).  
  
As a first approximation, ''RawByteString'' can be thought of as an "untyped AnsiString": assigning an AnsiString(X) to a RawByteString has exactly the same behaviour as assigning that AnsiString(X) to another AnsiString(X) variable with the same value of X: no code page conversion or copying occurs, just the reference count is increased.
+
Como una primera aproximación, RawByteString se puede considerar como un "AnsiString sin tipo": asignar un AnsiString(X) a un RawByteString tiene exactamente el mismo comportamiento que asignar ese AnsiString(X) a otra variable AnsiString(X) con el mismo valor de X: ningún código la conversión o copia de páginas se produce, solo se aumenta el recuento de referencias.  
  
Less intuitive is probably that when a RawByteString is assigned to an AnsiString(X), the same happens: no code page conversion or copying, just the reference count is increased. Note that this means that results from functions returning a RawByteString will never be converted to the destination's declared code page. This is another way in which the dynamic code page of an AnsiString(X) can become different from its declared code page.
+
Menos intuitivo es probablemente que cuando un RawByteString se asigna a un AnsiString(X), lo mismo sucede: no hay conversión de página de códigos o copia, sólo se aumenta el recuento de referencias. Tenga en cuenta que esto significa que los resultados de las funciones que devuelven un RawByteString nunca se convertirán a la página de códigos declarada del destino. Esta es otra forma en la que la página de códigos dinámicos de un AnsiString(X) puede ser diferente de su página de códigos declarada.  
  
This type is mainly used to declare ''const'', ''constref'' and value parameters that accept any AnsiString(X) value without converting it to a predefined declared code page. Note that if you do this, the routine accepting those parameters should be able to handle strings with any possible dynamic code page.
+
Este tipo se utiliza principalmente para declarar ''const'', ''constref'' y parámetros de valor que aceptan cualquier valor AnsiString(X) sin convertirlo en una página de códigos declarada predefinida. Tenga en cuenta que si lo hace, la rutina que acepta esos parámetros debe ser capaz de controlar cadenas con cualquier página de códigos dinámico posible.  
  
''var'' and ''out'' parameters can also be declared as ''RawByteString'', but in this case the compiler will give an error if an AnsiString(X) whose declared code page is different from CP_NONE is passed in. This is consistent with ''var'' and ''out'' parameters in general: they require an exactly matching type to be passed in. You can add an explicit RawByteString() typecast around an argument to remove this error, but then you must be prepared to deal with the fact that the returned string can have any dynamic code page.
+
Los parámetros ''var'' y ''out'' también se pueden declarar como RawByteString, pero en este caso el compilador dará un error si un AnsiString(X) cuya página de códigos declarada es diferente de CP_NONE se pasa. Esto es coherente con los parámetros var y out en general: requieren que se pase un tipo exactamente coincidente. Puede agregar una conversión de tipo RawByteString() explícita alrededor de un argumento para eliminar este error, pero debe estar preparado para tratar el hecho de que la cadena devuelta puede tener cualquier página de códigos dinámicos.
  
== String concatenations ==
+
== Concatenaciones de cadenas (strings) ==
Normally, in Pascal the result type of an expression is independent of how its result is used afterwards. E.g. multiplying two longints on a 32 bit platform and assigning the result to an int64 will still perform the multiplication using 32 bit arithmetic, and only afterwards the result is converted to 64 bit.
+
Normalmente, en Pascal el tipo de resultado de una expresión es independiente de cómo se utiliza su resultado después. Por ejemplo, multiplicar dos longints en una plataforma de 32 bits y asignar el resultado a un int64 seguirá realizando la multiplicación usando la aritmética de 32 bits, y sólo después el resultado se convierte a 64 bits.  
  
Code page-aware strings are the only exception to this rule: concatenating two or more strings always occurs without data loss, although afterwards the resulting string will of course still be converted to the declared code page of the destination (which may result in data loss).
+
Las cadenas compatibles con la página de códigos son la única excepción a esta regla: la concatenación de dos o más cadenas siempre se produce sin pérdida de datos, aunque después la cadena resultante, por supuesto, se seguirá convirtiendo en la página de códigos declarada del destino (lo que puede resultar pérdida de datos).  
  
Assigning the result of a concatenation to a RawByteString is again special:
+
Asignar el resultado de una concatenación a un RawByteString es de nuevo especial:  
* if all concatenated strings have the same dynamic code page, the result will have this code page too
+
* si todas las cadenas concatenadas tienen la misma página de códigos dinámicos, el resultado también tendrá esta página de códigos;
* in other cases the result will be converted to CP_ACP (we may add an option in the future to change this RawByteString behaviour, as it is not very practical).
+
* en otros casos el resultado se convertirá a CP_ACP (podemos agregar una opción en el futuro para cambiar este comportamiento RawByteString, ya que no es muy práctico).
  
 
== String constants ==
 
== String constants ==
The compiler has to know the code page according to which it should interpret string constants, as it may have to convert them at compile time. Normally, a string constant is interpreted according to the [[#Source file codepage|source file codepage]]. If the source file codepage is CP_ACP, a default is used instead: in that case, during conversions the constant strings are assumed to have code page 28591 (''ISO 8859-1 Latin 1; Western European'').
+
El compilador tiene que conocer la página de códigos según la cual debe interpretar las constantes de cadena (string constants), ya que puede tener que convertirlas en tiempo de compilación. Normalmente, una constante de cadena se interpreta según [[#Source file codepage|la página de códigos del archivo fuente]]. Si la página de códigos del archivo fuente es CP_ACP, se utiliza un valor predeterminado en su lugar: en ese caso, durante las conversiones se supone que las cadenas constantes tienen la página de códigos 28591 (ISO 8859-1 Latin 1; Europa Occidental).  
  
When a string constant is assigned to an AnsiString(X) either in code or as part of a typed constant or variable initialisation, then
+
Cuando se asigna una constante de cadena a un AnsiString(X) en el código o como parte de una constante con tipo o una inicialización variable, entonces:
* if X = CP_NONE (i.e., the target is a RawByteString), the result is the same as if the constant string were assigned to an AnsiString(CP_ACP)
+
* if X = CP_NONE (p.e., el destino es un RawByteString), el resultado es el mismo que si la cadena constante se asignara a un AnsiString(CP_ACP).
* if X = CP_ACP and the code page of the string constant is different from CP_ACP, then the string constant is converted, at compile time, to the source file code page. If the source file code page is also CP_ACP, it will be stored in the program unaltered with a code page of CP_ACP and hence its meaning/interpretation will depend on the actual value of ''DefaultSystemCodePage'' at run time. This ensures compatibility with older versions of FPC when assigning string constants to AnsiString variables without using a ''{$codepage xxx}'' directive or UTF-8 BOM.
+
* if X = CP_ACP y la página de códigos de la constante de cadena es diferente de CP_ACP, entonces la constante de cadena se convierte, en tiempo de compilación, en la página de códigos del archivo fuente. Si la página de códigos del archivo fuente también es CP_ACP, se almacenará en el programa sin cambios con una página de códigos de CP_ACP y, por lo tanto, su significado/interpretación dependerá del valor real de ''DefaultSystemCodePage'' en tiempo de ejecución. Esto garantiza la compatibilidad con versiones anteriores de FPC al asignar constantes de cadena a variables AnsiString sin usar una directiva d''{$codepage xxx}'' o UTF-8 BOM.
* for other values of X, the string constant is converted, at compile time, to code page X
+
* para otros valores de X, la constante de cadena se convierte, en tiempo de compilación, en la página de códigos X.
  
Similarly, if a string constant is assigned to a UnicodeString, the string constant is converted, at compile time, from the source file code page to UTF-16.
+
De forma similar, si se asigna una constante de cadena a un UnicodeString, la constante de cadena se convierte, en tiempo de compilación, de la página de códigos del archivo fuente a UTF-16.  
  
For ShortString and PChar, the same rule as for AnsiString(CP_ACP) is followed.
+
Para ShortString y PChar, se sigue la misma regla que para AnsiString(CP_ACP).  
  
Note that symbolic string constants will be converted at compile time to the appropriate string type and code page whenever they are used. This means that there is no speed overhead when using a single string constant in multiple code page and string type contexts, only some data size overhead.
+
Tenga en cuenta que las constantes de cadena simbólicas se convertirán en tiempo de compilación en el tipo de cadena y la página de códigos adecuados siempre que se usen. Esto significa que no hay ninguna sobrecarga de velocidad cuando se usa una sola constante de cadena en varios contextos de tipo de cadena y página de códigos, solo alguna sobrecarga de tamaño de datos.  
  
From the above it follows that to ensure predictable interpretation of string constants in your source code, it is best to either include an explicit ''{$codepage xxx}'' directive (or use the equivalent ''-Fc'' command line option), or to save the source code in UTF-8 with a BOM.
+
De lo anterior se deduce que para garantizar una interpretación predecible de las constantes de cadena en el código fuente, es mejor incluir una directiva explícita de ''{$codepage xxx}'' (o usar la opción de línea de comandos equivalente ''-Fc''), o guardar el código fuente en UTF-8 con un BOM.
  
== String indexing ==
+
== Indexado de cadenas (strings) ==
Nothing changes to string indexing. Every string element of a UnicodeString/WideString is two bytes and every string element of all other strings is one byte. The string indexing mechanism completely ignores code pages and composite code points.
+
Nada cambia en la indexación de cadenas. Cada elemento de cadena de un UnicodeString/WideString es de dos bytes y cada elemento de cadena de todas las demás cadenas es de un byte. El mecanismo de indexación de cadenas omite completamente los códigos de páginas y los puntos de código compuestos.
  
= RTL changes =
+
= Cambios en la RTL =
  
In order to fully guarantee data integrity in the presence of  codepage-aware strings, all routines in the RTL and packages that accept ''AnsiString'' parameters must be adapted. The reason is that if their parameters remain plain ''AnsiString'', then any string with a different declared code page will be converted to ''DefaultSystemCodePage'' when it is passed in. This can result in data loss.
+
Para garantizar completamente la integridad de los datos en presencia de cadenas compatibles con la página de códigos, se deben adaptar todas las rutinas de la RTL y los paquetes que aceptan parámetros AnsiString. La razón es que si sus parámetros siguen siendo simples AnsiString, cualquier cadena con una página de códigos declarada diferente se convertirá en DefaultSystemCodePage cuando se pasa. Esto puede provocar la pérdida de datos.  
 
+
Hasta ahora, las rutinas que se ocupan principalmente del acceso al sistema de archivos se han actualizado para conservar todos los datos de caracteres. A continuación se muestra una lista exhaustiva de todas las rutinas que conservan la codificación de cadenas en FPC 3.0. A menos que se indique explícitamente lo contrario, todas estas rutinas también tienen sobrecargas que aceptan parámetros unicodeString.  
Until now, primarily routines dealing with file system access have been updated to preserve all character data. Below is an exhaustive list of all routines that preserve the string encoding in FPC 3.0. Unless where explicitly noted otherwise, these routines also all have overloads that accept ''UnicodeString'' parameters.
 
 
* '''System''': FExpand, LowerCase, UpperCase, GetDir, MKDir, ChDir, RMDir, Assign, Erase, Rename, standard I/O (Read/Write/Readln/Writeln/Readstr/Writestr), Insert, Copy, Delete, SetString
 
* '''System''': FExpand, LowerCase, UpperCase, GetDir, MKDir, ChDir, RMDir, Assign, Erase, Rename, standard I/O (Read/Write/Readln/Writeln/Readstr/Writestr), Insert, Copy, Delete, SetString
* '''ObjPas''' (used automatically in Delphi and ObjFPC modes): AssignFile
+
* '''ObjPas''' (usado automaticamente en los modos (modes) Delphi y ObjFPC): AssignFile
 
* '''SysUtils''': FileCreate, FileOpen, FileExists, DirectoryExists, FileSetDate, FileGetAttr, FileSetAttr, DeleteFile, RenameFile, FileSearch, ExeSearch, FindFirst, FindNext, FindClose, FileIsReadOnly, GetCurrentDir, SetCurrentDir, ChangeFileExt, ExtractFilePath, ExtractFileDrive, ExtractFileName, ExtractFileExt, ExtractFileDir, ExtractShortPathName, ExpandFileName, ExpandFileNameCase, ExpandUNCFileName, ExtractRelativepath, IncludeTrailingPathDelimiter, IncludeTrailingBackslash, ExcludeTrailingBackslash, ExcludeTrailingPathDelimiter, IncludeLeadingPathDelimiter, ExcludeLeadingPathDelimiter, IsPathDelimiter, DoDirSeparators, SetDirSeparators, GetDirs, ConcatPaths, GetEnvironmentVariable
 
* '''SysUtils''': FileCreate, FileOpen, FileExists, DirectoryExists, FileSetDate, FileGetAttr, FileSetAttr, DeleteFile, RenameFile, FileSearch, ExeSearch, FindFirst, FindNext, FindClose, FileIsReadOnly, GetCurrentDir, SetCurrentDir, ChangeFileExt, ExtractFilePath, ExtractFileDrive, ExtractFileName, ExtractFileExt, ExtractFileDir, ExtractShortPathName, ExpandFileName, ExpandFileNameCase, ExpandUNCFileName, ExtractRelativepath, IncludeTrailingPathDelimiter, IncludeTrailingBackslash, ExcludeTrailingBackslash, ExcludeTrailingPathDelimiter, IncludeLeadingPathDelimiter, ExcludeLeadingPathDelimiter, IsPathDelimiter, DoDirSeparators, SetDirSeparators, GetDirs, ConcatPaths, GetEnvironmentVariable
* '''Unix''': fp*() routines related to file system operations (no ''UnicodeString'' overloads), POpen
+
* '''Unix''': fp*() rutinas relacionadas con las operaciones del sistema de archivos (sin sobrecargas UnicodeString), POpen.
* '''DynLibs''': all routines
+
* '''DynLibs''': todas las rutinas.
  
= RTL todos =
+
= RTL ToDo =
As the above list is exhaustive, no other RTL routines support arbitrary code pages yet. This section contains a list of gotchas that some people have identified and, if possible, workarounds. Note that routines not mentioned here nor above are equally unsafe as the ones that are explicitly mentioned.
+
Como la lista anterior es exhaustiva, no existen otras rutinas RTL que soporten páginas de código arbitrarias. Esta sección contiene una lista de los errores que algunas personas han identificado y, si es posible, soluciones. Tenga en cuenta que las rutinas no mencionadas aquí ni arriba son igualmente inseguras como las que se mencionan explícitamente.
  
==TFormatSettings and DefaultFormatSettings==
+
==TFormatSettings y DefaultFormatSettings==
The type of ''ThousandSeparator'' and ''DecimalSeparator'' is AnsiChar type. This means that if ''DefaultSystemCodePage'' is UTF-8 and the locale's separator is more than one byte long in that encoding, these fields are not large enough. Examples are the French and Russian non-breaking white space character used to represent the ''ThousandSeparator''.
+
El tipo de ''ThousandSeparator'' y ''DecimalSeparator'' es del tipo AnsiChar. Esto significa que si DefaultSystemCodePage es UTF-8 y el separador de la configuración regional tiene más de un byte de largo en esa codificación, estos campos no son lo suficientemente grandes. Algunos ejemplos son el carácter de espacio en blanco "non-breaking" del francés y ruso que se utiliza para representar el  ''ThousandSeparator''.
  
= Old/obsolete sections=
+
= Secciones antiguas u obsoletas =
{{Warning|These sections are kept for historical reference - please update the sections above with this information if it is still applicable. Since FPC 2.7 (development version before the release of 3.0.0), extensive Unicode support has been implemented.}}
+
{{Warning| Estas secciones se mantienen para referencia histórica - por favor actualice las secciones anteriores con esta información si todavía es aplicable. Desde FPC 2.7 (versión de desarrollo antes del lanzamiento de 3.0.0), se ha implementado un amplio soporte Unicode.}}
  
  
==User visible changes==
+
==Cambios visibles para el usuario==
  
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.
+
La compatibilidad completa con cadenas compatibles con la página de códigos no es posible sin romper algún código existente. La siguiente lista intenta resumir los cambios visibles al usuario más importantes.  
* The string header has two new fields: encoding and element size. On 32 Bit platforms this increases the header size by 4 and on 64 bit platforms by 8 bytes.
+
* El encabezado de cadena (string header)tiene dos campos nuevos: codificación y tamaño del elemento. En las plataformas de 32 bits esto aumenta el tamaño del encabezado por 4 y en las plataformas de 64 bits por 8 bytes..
* WideCharLenToString, UnicodeCharLenToString, WideCharToString, UnicodeCharToString and OleStrToString return an UnicodeString instead of an Ansistring before.
+
* WideCharLenToString, UnicodeCharLenToString, WideCharToString, UnicodeCharToString and OleStrToString devuelven un UnicodeString en lugar de un Ansistring de antes.
* the type of the dest parameter of WideCharLenToString and UnicodeCharLenToString has been changed from Ansistring to Unicodestring
+
* el tipo del parámetro "dest" de WideCharLenToString y UnicodeCharLenToString se ha cambiado de Ansistring a Unicodestring.
* UTF8ToAnsi and AnsiToUTF8 take a RawByteString now
+
* UTF8ToAnsi y AnsiToUTF8 ahora toman un RawByteString.
  
= See Also =
+
= Ver también =
  
* [[Character and string types]]
+
* [[Character and string types/es]]
 
* [[unicode use cases]]
 
* [[unicode use cases]]
 
* [[LCL Unicode Support]]
 
* [[LCL Unicode Support]]
* Suggestion: [[not Delphi compatible enhancement for Unicode Support]]
+
* Sugerencia: [[not Delphi compatible enhancement for Unicode Support]]
  
 
[[Category:Español]]
 
[[Category:Español]]
 
[[Category:Unicode/es]]
 
[[Category:Unicode/es]]
 
[[Category:FPC/es]]
 
[[Category:FPC/es]]

Latest revision as of 04:06, 16 February 2020

English (en) español (es) français (fr) русский (ru)

Introducción

Hasta FPC 2.6.x, incluido FPC 2.6.x, el RTL se basaba en los de Turbo Pascal y Delphi 7. Esto significa que se basaba principalmente en los tipos shortstring, ansistring y pchar. Ninguno de estos tipos tenía ninguna información de codificación asociada a ellos, pero se supone implícitamente que está codificado en la "codificación predeterminada del sistema" y se transmitió a las llamadas a la API del S.O. sin ninguna conversión.

En Delphi 2009, Embarcadero cambió toda la RTL al tipo UnicodeString, que representa cadenas mediante UTF-16. Además, también hicieron que el tipo AnsiString "code page-aware" (reconocimiento de página de códigos). Esto significa que AnsiStrings a partir de entonces contienen la página de códigos según la cual se deben interpretar sus datos.

La compatibilidad de nivel de lenguaje de FPC para estos tipos de cadena ya está disponible en las versiones estables actuales del compilador (FPC 3.0.0 y versiones superiores). El soporte de nivel RTL aún no está completo. Esta página ofrece una visión general del comportamiento relacionado con la página de códigos de estos tipos de cadena, el nivel actual de compatibilidad en el RTL y las posibles formas futuras de cómo se puede mejorar esta compatibilidad.

Retrocompatibilidad

Si tiene código existente que funciona de forma definida (*) con una versión anterior de FPC y no realiza ningún cambio en él, debe seguir funcionando sin modificar con la nueva versión de FPC. Garantizar esto es el propósito principal de la multitud de variables default*CodePage y sus valores predeterminados como se describe a continuación.

(*) esto significa principalmente: no se almacenan datos en una ansistring que se ha codificado con algo más que la página de códigos predeterminada del sistema y, posteriormente, se pasa esta cadena tal cual a una rutina FPC RTL. Por ejemplo, el código Lazarus actual es generalmente fino, ya que se supone que debe llamar a UTF8ToAnsi() antes de pasar sus cadenas a las rutinas FPC RTL.

Si su código existente usó ansistrings de una manera no soportada, es decir, almacenando datos en él que no están codificados en la página de código predeterminado del sistema y no teniendo cuidado al interactuar con otro código (como las rutinas RTL), todavía puede ser capaz de trabajar en la mayoría de los problemas si estos datos siempre utilizan la misma codificación. En ese caso, puede llamar a SetMultiByteConversionCodePage() al iniciar su programa, y como argumento, la página de códigos de los datos que contienen las ansistrings. Tenga en cuenta que esto también afectará a la interpretación de todos los datos ShortString, AnsiChar y PAnsiChar.

Código de páginas

Un código de páginas define cómo se deben interpretar los bytes individuales de una cadena (string), es decir, qué letra, símbolo u otro carácter gráfico corresponde a cada byte o secuencia de bytes.

Identificadores de códigos de página

Un identificador de código de página siempre se almacena como un TSystemCodePage, que es un alias para Word. El valor representa el código correspondiente según lo definido por Microsoft Windows. Además, hay 3 valores de códigos de página especiales:

  • CP_ACP: este valor representa el código de página del sistema establecido actualmente "código de página predeterminado del sistema". Consulte #Code page settings para obtener más información.
  • CP_OEM: este valor representa el código de página OEM. En plataformas Windows, esto corresponde al código de página utilizado por consola (por ejemplo, ventanas cmd.exe). En otras plataformas este valor se interpreta igual que CP_ACP.
  • CP_NONE: este valor indica que no se ha asociado ninguna información de código de página con los datos de cadena. El resultado de cualquier operación en una cadena que tiene este código de páginas dinámico es indefinido. Lo mismo se mantiene para cualquier otro código de página que no esté en la lista anterior, pero a diferencia de los otros valores de códigos de página no válidos, CP_NONE tiene un significado especial en caso de que se utilice como código de página declarado.

Nota: los identificadores de códigos de página son diferentes de los nombres de códigos de página que se utilizan en las directivas {$codepage xxx} (que ya está disponible en la versión estable de FPC actual). Los nombres de códigos de páginas son los nombres de unidades de códigos de página individuales expuestos por la unidad charset, que tienen nombres como cp866, cp1251 y utf8.

Configuración del código de página

La unidad del sistema contiene varias variables globales que indican el código de página predeterminado utilizado para determinadas operaciones.

DefaultSystemCodePage

  • Propósito: determina cómo se interpreta CP_ACP.
  • Valor inicial:
    • El resultado de la llamada al sistema operativo GetACP, que devuelve el código de página ANSI de Windows.
    • iOS: CP_ACP si no hay ningún widestring manager instalado, de lo contrario UTF-8.
    • Unix (excluyendo iOS): CP_ACP si no hay ningún widestring manager instalado, de lo contrario se basa en las variables de entorno LANG o LC_CTYPE actualmente establecidas. Esto suele ser UTF-8, pero no se garantiza que sea el caso.
    • OS/2: página de códigos actual proporcionada en el primer valor devuelto por DosQueryCP y luego traducido al número de página de códigos utilizado para el mismo juego de caracteres en MS Windows (porque eso es lo que se ha utilizado en Delphi originalmente y la implementación de FPC intenta ser compatible con Delphi); es posible aplicar siempre utilizando números de página de códigos nativos oS/2 en FPC RTL cambiando la variable booleana RTLUsesWinCP a false (el valor predeterminado es true). Tenga en cuenta que los números de página de códigos son en gran medida idénticos para OS/2 y MS Windows con páginas de códigos permitidas para la página de códigos de proceso actual en OS/2 (los números de página de códigos son diferentes para las llamadas páginas de códigos ANSI, páginas de códigos ISO-8859-x y páginas de códigos de Mac OS y páginas de códigos de Mac OS , pero ninguno de estos puede utilizarse como página de códigos de proceso actual en OS/2).
    • Otras plataformas: CP_ACP (estas plataformas actualmente no admiten varias páginas de códigos y están codificadas de forma rígida para usar su página de códigos específica del sistema operativo en todos los casos).
  • Modificaciones: se puede modificar este valor con un llamando a SetMultiByteConversionCodePage (CodePage: TSystemCodePage).
  • Notas: Dado que el valor de esta variable se puede cambiar, no es una buena idea utilizar su valor para determinar el código de página real predeterminado del sistema operativo (a menos que lo haga al inicio del programa y esté seguro de que ninguna otra unidad lo ha cambiado en su código de inicialización).

DefaultFileSystemCodePage

  • Propósito: define la página de códigos a la que se traducen los nombres de archivo/ruta antes de que se pasen a las llamadas a la API del SO, si la RTL utiliza una API de SO de un solo byte para este propósito en la plataforma actual. Esta página de códigos también se utiliza para operaciones intermedias en rutas de acceso de archivo dentro de la RTL antes de realizar llamadas a la API del SO. Esta variable no existe en Delphi y se ha introducido en FPC para que sea posible cambiar el valor de DefaultSystemCodePage sin interrumpir las interfaces RTL con las llamadas a la API del sistema de archivos del sistema operativo.
  • Valor inicial:
    • Windows: UTF-8, porque el RTL utiliza llamadas a la API del sistema operativo UTF-16 (por lo que no se pierden datos en operaciones intermedias).
    • macOS e iOS: DefaultSystemCodePage si no hay ningún widestring manager instalado, de lo contrario UTF-8 (según lo definido por Apple).
    • Unix (excluyendo macOS e iOS): DefaultSystemCodePage, porque la codificación de nombres de archivo es indefinida en plataformas Unix (es una matriz sin tipo de bytes que se puede interpretar de cualquier manera; no se garantiza que sea válida UTF-8).
    • DefaultSystemCodePage, porque OS/2 no proporciona ninguna posibilidad de especificar una página de códigos diferente para las operaciones de E/S de archivo que no sea la página de códigos de todo el proceso actual.
    • Otras plataformas: igual que DefaultSystemCodePage.
  • Modificaciones: puede modificar este valor llamando a SetMultiByteFileSystemCodePage(CodePage: TSystemCodePage); tenga en cuenta que en OS/2 esta variable se está sincronizando con la página de códigos de proceso actual (establecida, por ejemplo, por DosSetProcessCP) durante todas las operaciones de E/S de archivos con el fin de evitar transformaciones no válidas.
  • Notas: la configuración de Unix/macOS/iOS solo se aplica en caso de que se instale el administrador de cadenas anchas cwstring, de lo contrario DefaultFileSystemCodePage tendrá el mismo valor que DefaultSystemCodePage después del inicio del programa.

DefaultRTLFileSystemCodePage

  • Propósito: define la página de códigos a la que se traducen los nombres de archivo/ruta de acceso antes de que se devuelvan desde las rutinas RTL de ruta/archivo RawByteString. Entre los ejemplos se incluyen los nombres de archivo/ruta de acceso devueltos por las versiones RawbyteString de SysUtils.FindFirst y System.GetDir. La razón principal de su existencia es permitir que el RTL proporcione compatibilidad con versiones anteriores de FPC, ya que estas siempre devolvían cadenas codificadas en cualquier API de un solo byte del sistema operativo utilizada (que normalmente era lo que ahora se conoce como DefaultSystemCodePage).
  • Valor inicial
    • Windows: DefaultSystemCodePage, para retrocompatibilidad.
    • macOS and iOS: DefaultSystemCodePage si no hay un widestring manager instalado, caso contrario UTF-8 para retrocompatibilidad (era siempre UTF-8 en el pasado, ya que eso es lo que devuelven las API de archivos del sistema operativo y no convertimos estos datos).
    • Unix (excluding macOS and iOS): DefaultSystemCodePage, por la misma razón que con DefaultFileSystemCodePage. Establecer esto en un valir diferente a DefaultFileSystemCodePage es una mala idea en estas plataformas, debido a que cualquier conversión de página de códigos puede dañar estas cadenas, ya que se desconoce su codificación inicial.
    • OS/2: igual a DefaultSystemCodePage (por compatibilidad con versiones anteriores y también porque es la opción más natural a menos que necesite jugar con diferentes páginas de códigos)
    • Other platforms: igual a DefaultSystemCodePage
  • Modificaciones: se puede modificar este valor llamando aSetMultiByteRTLFileSystemCodePage(CodePage: TSystemCodePage); se puede usar esta posibilidad para leer y/o escribir archivos con un código de página arbitrario.
  • Notas: igual que para DefaultFileSystemCodePage.

Código de página del archivo fuente

El código de página del archivo fuente determina cómo se interpretan las constantes de cadena, y donde el compilador insertará operaciones de conversión del código de página al asignar un tipo de cadena a otro.

Los códigos de página del archivo fuente se determinan de la siguiente manera:

  • si un archivo contiene la directiva {$codepage xxx} (p.e. {$codepage UTF8}), entonces el código de página del archivo fuente es ése, de otra forma
  • si el archivo comienza con un UTF-8 BOM, entonces el código de página del archivo fuente es UTF-8, caso contrario
  • si la directiva {$modeswitch systemcodepage} está activa, entonces el código de página del archivo fuente es el DefaultSystemCodePage de la computadora en que el compilador mismo está actualmente ejecutándose (p.e. ompilar el código fuente en un sistema diferente puede dar lugar a un programa que se comporta de manera diferente; este conmutador está disponible para la compatibilidad con Delphi y está habilitado de forma predeterminada en la opción {$mode delphiunicode}), de otra forma
  • el código de página del archivo fuente se establece en CP_ACP (para la compatibilidad con versiones anteriores de FPC).

Strings

String/character types

Shortstring

El código de página de un shortstring es implícitamente CP_ACP y por lo tanto siempre será igual al valor actual de Defaultsysticacodepage.

PAnsiChar/AnsiChar

Estos tipos son los mismos que los tipos PChar/Char antiguos. En todos los modos del compilador, excepto en el {$mode delphiunicode}, PChar/Char también son alias para PAnsiChar/AnsiChar. Su código de páginas es implícitamente CP_ACP y, por lo tanto, siempre será igual al valor actual de DefaultSystemCodePage.

PWideChar/PUnicodeChar y WideChar/UnicodeChar

Estos tipos permanecen sin cambios. WideChar/UnicodeChar puede contener una sola unidad de código UTF-16, mientras que PWideChar/PUnicodeChar apunta a una sola matriz o a una matriz de unidades de código UTF-16.

En {$mode delphiunicode}, PChar se convierte en un alias para PWideChar/PUnicodeChar y Char se convierte en un alias para WideChar/UnicodeChar.

UnicodeString/WideString

Estos tipos se comportan igual que en versiones anteriores:

  • Widestring es lo mismo que un "COM BSTR" en Windows, y un alias para UnicodeString en las demás plataformas. Sus datos de cadena (string) se codifican en mediante UTF-16.
  • UnicodeString es una cadena (string) con recuento de referencias con una longitud máxima de unidades de código UTF-16 high(SizeInt).

Ansistring

AnsiStrings son tipos de conteo de referencia con una longitud máxima de bytes High(SizeInt). Además, ahora también tienen información del código de página asociado con ellos.

Lo más importante que debe comprender sobre el nuevo tipo AnsiString es que tiene una página de códigos declarada/estática/preferida/predeterminada (denominada página de códigos declarada a partir de ahora) y una página de códigos dinámica. La página de códigos declarada indica al compilador que al asignar algo a ese AnsiString, primero debe convertir los datos a esa página de códigos declarada (excepto si es CP_NONE, vea RawByteString a continuación). La página de códigos dinámicos es una propiedad de la AnsiString que, similar a la longitud y el recuento de referencias, define la página de códigos real de los datos que actualmente tiene ese AnsiString.

Códigos de página declarados

El código de páginas declarado de un AnsiString sólo se puede definir declarando un nuevo tipo (type) de la siguiente manera:

type
  CP866String = type AnsiString(866);

El código de página declarado de una variable declarada como AnsiString sin formato es CP_ACP. En efecto, el tipo AnsiString ahora se define semánticamente en la unidad System como:

type
  AnsiString = type AnsiString(CP_ACP);

Otro tipo AnsiString(X) predefinido en la unidad System es UTF8String:

type
  UTF8String = type AnsiString(CP_UTF8);

Una vez que haya definido un tipo AnsiString(X) personalizado, puede usarlo para declarar variables, parámetros, campos, etc. como de costumbre.

Tenga en cuenta que CP_UTF16 y CP_UTF16BE no son válidos como páginas de códigos para AnsiStrings. El resultado de definir un AnsiString con una página de códigos es indefinido.

Código de páginas dinámico

Si un string con un código de página declarado SOURCE_CP se asigna a un string con el código de página declarado DEST_CP, entonces: If a string with a declared code page SOURCE_CP is assigned to a string with declared code page DEST_CP , then

  • if (SOURCE_CP = CP_NONE) or (DEST_CP = CP_NONE), ver RawByteString, de lo contrario
  • if (source file codepage <> CP_ACP), then if (DEST_CP = CP_ACP) and (SOURCE_CP = source file codepage) or vice versa, no se producirá ninguna conversión (inclusive si en tiempo de ejecución DefaultSystemCodePage tiene un valor distinto del código de página del archivo fuente). La razón para la condición "(source file codepage <> CP_ACP)" condition es la compatibilidad con versiones anteriores de FPC (aunque no admitían AnsiStrings con páginas de códigos arbitrarias, siempre se interpretaban AnsiStrings según el valor actual de la página de códigos del sistema). de o contrario,
  • if (SOURCE_CP <> DEST_CP), el string se convertirá desde codepage X1 a codepage X2 antes de la asignación, donde CP_ACP será interpretado como el valor actual de Defaultsysticacodepage. de lo contrario,
  • if (SOURCE_CP = DEST_CP), no se realizará ninguna conversión.

Estas reglas significan que es perfectamente posible para una variable AnsiString obtener una página de códigos dinámica que difiere de su página de códigos declarada. Por ejemplo, en el tercer caso SOURCE_CP podría ser CP_ACP, mientras que después de la asignación puede tener una página de códigos dinámica igual a DefaultSystemCodePage.

Nota: como se mencionó anteriormente, si se produce o no una posible conversión de página de códigos depende únicamente de las páginas de códigos declaradas de las cadenas implicadas. Esto significa que si asigna un AnsiString(X) a otro AnsiString(X) y el código dinámico del primero era diferente de X, los datos de cadena no se convertirán en la página de códigos X por la asignación.

RawByteString

El tipo (type) RawByteString se define como:

type
  RawByteString = type AnsiString(CP_NONE);

Como se mencionó anteriormente, los resultados de las operaciones en cadenas con la página de códigos CP_NONE son indefinidos. Como no tiene sentido definir un tipo en el RTL cuyo comportamiento es indefinido, el comportamiento de RawByteString es algo diferente al de otros tipos AnsiString(X).

Como una primera aproximación, RawByteString se puede considerar como un "AnsiString sin tipo": asignar un AnsiString(X) a un RawByteString tiene exactamente el mismo comportamiento que asignar ese AnsiString(X) a otra variable AnsiString(X) con el mismo valor de X: ningún código la conversión o copia de páginas se produce, solo se aumenta el recuento de referencias.

Menos intuitivo es probablemente que cuando un RawByteString se asigna a un AnsiString(X), lo mismo sucede: no hay conversión de página de códigos o copia, sólo se aumenta el recuento de referencias. Tenga en cuenta que esto significa que los resultados de las funciones que devuelven un RawByteString nunca se convertirán a la página de códigos declarada del destino. Esta es otra forma en la que la página de códigos dinámicos de un AnsiString(X) puede ser diferente de su página de códigos declarada.

Este tipo se utiliza principalmente para declarar const, constref y parámetros de valor que aceptan cualquier valor AnsiString(X) sin convertirlo en una página de códigos declarada predefinida. Tenga en cuenta que si lo hace, la rutina que acepta esos parámetros debe ser capaz de controlar cadenas con cualquier página de códigos dinámico posible.

Los parámetros var y out también se pueden declarar como RawByteString, pero en este caso el compilador dará un error si un AnsiString(X) cuya página de códigos declarada es diferente de CP_NONE se pasa. Esto es coherente con los parámetros var y out en general: requieren que se pase un tipo exactamente coincidente. Puede agregar una conversión de tipo RawByteString() explícita alrededor de un argumento para eliminar este error, pero debe estar preparado para tratar el hecho de que la cadena devuelta puede tener cualquier página de códigos dinámicos.

Concatenaciones de cadenas (strings)

Normalmente, en Pascal el tipo de resultado de una expresión es independiente de cómo se utiliza su resultado después. Por ejemplo, multiplicar dos longints en una plataforma de 32 bits y asignar el resultado a un int64 seguirá realizando la multiplicación usando la aritmética de 32 bits, y sólo después el resultado se convierte a 64 bits.

Las cadenas compatibles con la página de códigos son la única excepción a esta regla: la concatenación de dos o más cadenas siempre se produce sin pérdida de datos, aunque después la cadena resultante, por supuesto, se seguirá convirtiendo en la página de códigos declarada del destino (lo que puede resultar pérdida de datos).

Asignar el resultado de una concatenación a un RawByteString es de nuevo especial:

  • si todas las cadenas concatenadas tienen la misma página de códigos dinámicos, el resultado también tendrá esta página de códigos;
  • en otros casos el resultado se convertirá a CP_ACP (podemos agregar una opción en el futuro para cambiar este comportamiento RawByteString, ya que no es muy práctico).

String constants

El compilador tiene que conocer la página de códigos según la cual debe interpretar las constantes de cadena (string constants), ya que puede tener que convertirlas en tiempo de compilación. Normalmente, una constante de cadena se interpreta según la página de códigos del archivo fuente. Si la página de códigos del archivo fuente es CP_ACP, se utiliza un valor predeterminado en su lugar: en ese caso, durante las conversiones se supone que las cadenas constantes tienen la página de códigos 28591 (ISO 8859-1 Latin 1; Europa Occidental).

Cuando se asigna una constante de cadena a un AnsiString(X) en el código o como parte de una constante con tipo o una inicialización variable, entonces:

  • if X = CP_NONE (p.e., el destino es un RawByteString), el resultado es el mismo que si la cadena constante se asignara a un AnsiString(CP_ACP).
  • if X = CP_ACP y la página de códigos de la constante de cadena es diferente de CP_ACP, entonces la constante de cadena se convierte, en tiempo de compilación, en la página de códigos del archivo fuente. Si la página de códigos del archivo fuente también es CP_ACP, se almacenará en el programa sin cambios con una página de códigos de CP_ACP y, por lo tanto, su significado/interpretación dependerá del valor real de DefaultSystemCodePage en tiempo de ejecución. Esto garantiza la compatibilidad con versiones anteriores de FPC al asignar constantes de cadena a variables AnsiString sin usar una directiva d{$codepage xxx} o UTF-8 BOM.
  • para otros valores de X, la constante de cadena se convierte, en tiempo de compilación, en la página de códigos X.

De forma similar, si se asigna una constante de cadena a un UnicodeString, la constante de cadena se convierte, en tiempo de compilación, de la página de códigos del archivo fuente a UTF-16.

Para ShortString y PChar, se sigue la misma regla que para AnsiString(CP_ACP).

Tenga en cuenta que las constantes de cadena simbólicas se convertirán en tiempo de compilación en el tipo de cadena y la página de códigos adecuados siempre que se usen. Esto significa que no hay ninguna sobrecarga de velocidad cuando se usa una sola constante de cadena en varios contextos de tipo de cadena y página de códigos, solo alguna sobrecarga de tamaño de datos.

De lo anterior se deduce que para garantizar una interpretación predecible de las constantes de cadena en el código fuente, es mejor incluir una directiva explícita de {$codepage xxx} (o usar la opción de línea de comandos equivalente -Fc), o guardar el código fuente en UTF-8 con un BOM.

Indexado de cadenas (strings)

Nada cambia en la indexación de cadenas. Cada elemento de cadena de un UnicodeString/WideString es de dos bytes y cada elemento de cadena de todas las demás cadenas es de un byte. El mecanismo de indexación de cadenas omite completamente los códigos de páginas y los puntos de código compuestos.

Cambios en la RTL

Para garantizar completamente la integridad de los datos en presencia de cadenas compatibles con la página de códigos, se deben adaptar todas las rutinas de la RTL y los paquetes que aceptan parámetros AnsiString. La razón es que si sus parámetros siguen siendo simples AnsiString, cualquier cadena con una página de códigos declarada diferente se convertirá en DefaultSystemCodePage cuando se pasa. Esto puede provocar la pérdida de datos. Hasta ahora, las rutinas que se ocupan principalmente del acceso al sistema de archivos se han actualizado para conservar todos los datos de caracteres. A continuación se muestra una lista exhaustiva de todas las rutinas que conservan la codificación de cadenas en FPC 3.0. A menos que se indique explícitamente lo contrario, todas estas rutinas también tienen sobrecargas que aceptan parámetros unicodeString.

  • System: FExpand, LowerCase, UpperCase, GetDir, MKDir, ChDir, RMDir, Assign, Erase, Rename, standard I/O (Read/Write/Readln/Writeln/Readstr/Writestr), Insert, Copy, Delete, SetString
  • ObjPas (usado automaticamente en los modos (modes) Delphi y ObjFPC): AssignFile
  • SysUtils: FileCreate, FileOpen, FileExists, DirectoryExists, FileSetDate, FileGetAttr, FileSetAttr, DeleteFile, RenameFile, FileSearch, ExeSearch, FindFirst, FindNext, FindClose, FileIsReadOnly, GetCurrentDir, SetCurrentDir, ChangeFileExt, ExtractFilePath, ExtractFileDrive, ExtractFileName, ExtractFileExt, ExtractFileDir, ExtractShortPathName, ExpandFileName, ExpandFileNameCase, ExpandUNCFileName, ExtractRelativepath, IncludeTrailingPathDelimiter, IncludeTrailingBackslash, ExcludeTrailingBackslash, ExcludeTrailingPathDelimiter, IncludeLeadingPathDelimiter, ExcludeLeadingPathDelimiter, IsPathDelimiter, DoDirSeparators, SetDirSeparators, GetDirs, ConcatPaths, GetEnvironmentVariable
  • Unix: fp*() rutinas relacionadas con las operaciones del sistema de archivos (sin sobrecargas UnicodeString), POpen.
  • DynLibs: todas las rutinas.

RTL ToDo

Como la lista anterior es exhaustiva, no existen otras rutinas RTL que soporten páginas de código arbitrarias. Esta sección contiene una lista de los errores que algunas personas han identificado y, si es posible, soluciones. Tenga en cuenta que las rutinas no mencionadas aquí ni arriba son igualmente inseguras como las que se mencionan explícitamente.

TFormatSettings y DefaultFormatSettings

El tipo de ThousandSeparator y DecimalSeparator es del tipo AnsiChar. Esto significa que si DefaultSystemCodePage es UTF-8 y el separador de la configuración regional tiene más de un byte de largo en esa codificación, estos campos no son lo suficientemente grandes. Algunos ejemplos son el carácter de espacio en blanco "non-breaking" del francés y ruso que se utiliza para representar el ThousandSeparator.

Secciones antiguas u obsoletas

Warning-icon.png

Warning: Estas secciones se mantienen para referencia histórica - por favor actualice las secciones anteriores con esta información si todavía es aplicable. Desde FPC 2.7 (versión de desarrollo antes del lanzamiento de 3.0.0), se ha implementado un amplio soporte Unicode.


Cambios visibles para el usuario

La compatibilidad completa con cadenas compatibles con la página de códigos no es posible sin romper algún código existente. La siguiente lista intenta resumir los cambios visibles al usuario más importantes.

  • El encabezado de cadena (string header)tiene dos campos nuevos: codificación y tamaño del elemento. En las plataformas de 32 bits esto aumenta el tamaño del encabezado por 4 y en las plataformas de 64 bits por 8 bytes..
  • WideCharLenToString, UnicodeCharLenToString, WideCharToString, UnicodeCharToString and OleStrToString devuelven un UnicodeString en lugar de un Ansistring de antes.
  • el tipo del parámetro "dest" de WideCharLenToString y UnicodeCharLenToString se ha cambiado de Ansistring a Unicodestring.
  • UTF8ToAnsi y AnsiToUTF8 ahora toman un RawByteString.

Ver también