2.2.1a2 Codificaciones UCS/Unicode
§1 Introducción
Respecto al problema ya esbozado en el capítulo anterior ( 2.2.1a), de representar los caracteres de lenguas distintas del inglés americano, se habían utilizado múltiples soluciones parciales, pero a finales de los 80 se hicieron intentos para definir un sistema de codificación verdaderamente universal. De un lado el denominado UCS ("Universal Character Set"), preconizado por la organización internacional de estandarización ISO; de otro el denominado Unicode, desarrollado por la iniciativa privada (Microsoft principalmente). Esta compañía había incorporado en sus sistemas Windows 9x un juego de caracteres bastante adaptado a la mayoría de alfabetos occidentales. Posteriormente implementó Unicode en sus sistemas NT y sucesores.
Tanto UCS como Unicode pretendían eliminar el problema de una vez por todas, estableciendo un sistema de codificación que permitiese la incorporación los caracteres (grafos) de todas las lenguas escritas del mundo, tanto actuales como pasadas, así como los símbolos utilizados en matemáticas, tipografía (por ejemplo los utilizados en TeX) y otros, como el juego de caracteres fonéticos IPA ("International Phonetic Alphabet"); tipos usados frecuentemente para reconocimiento óptico de caracteres (OCR), etc. El sistema debería ser además extensible, de forma que pudieran añadirse nuevos tipos en el futuro.
Aunque el desarrollo inicial de ambos sistemas fue independiente, los respectivos comités se dieron cuenta enseguida que este camino seguiría manteniendo el cisma que tanto daño había causado a la informática desde los primeros intentos de extender el US-ASCII, de forma que pronto convergieron, y el sistema Unicode se convirtió en un subset del sistema UCS más general.
§2 UCS
El sistema universal de caracteres UCS se concreta en el estándar ISO-10646 y se define como un juego de caracteres de 31 bits. Por supuesto sus 231 posibilidades garantizan que pueda soportar con creces las amplísimas expectativas señaladas en el párrafo anterior. Sin embargo, como no es necesario utilizar un potencial tan desmesurado, se han definido subconjuntos. En realidad todos los espacios utilizados por el momento se agrupan en los 16 primeros bits. Este subconjunto es conocido como BMP ("Basic Multilingual Plane") o Plano 0, y sus 216 (65.536) posibilidades son suficientes para los caracteres de todas las lenguas conocidas.
Nota: en realidad, lo que se hizo fue copiar el conocidísimo juego de caracteres US-ACII en las 128 primeras posiciones. A continuación, en las 128 siguientes, hasta completar 256, se colocaron los caracteres de la extensión ANSI/ISO 8859-1 (una variación de los caracteres mostrados en la tabla §3.2a del capítulo anterior). Sucesivamente se fueron reservando zonas para diversos alfabetos, por ejemplo, para el Griego; el Cirílico (utilizado en la Federación Rusa y otros países limítrofes); Armenio; Hebreo y los ideogramas Kanji (Japoneses), Hangeul (Coreanos) y del alfabeto Chino.
Los espacios situados fuera de este "Plano" están reservados para
los caracteres utilizados en aplicaciones muy especiales. Por ejemplo, los
estudiosos de culturas antiguas o la notación científica. El estándar
ISO-10646-1 fue establecido en 1993, y le siguió una versión ISO-10646-2 en
el 2001. La teoría es que pueden añadirse nuevos caracteres según las
necesidades, pero los ya establecidos no se alterarán nunca más, de forma
que se pretende una plataforma estable. Además se supone que no
existirán nunca caracteres de más de 21 bits, ya que mil trillones de
caracteres (221) serán suficientes.
§3 Unicode
Técnicamente Unicode es el ISO 10646-1. Así pues cada carácter ocupa 16 bits, lo que significa que puede estar representado por un carácter ancho (wchar_t 2.2.1a1) de cualquier compilador C++.
El inconveniente es que evidentemente, los almacenamientos ocupan el doble de espacio que con los caracteres estándar. La ventaja es que no existe necesidad de ninguna conversión ni ambigüedad. Cada carácter, representado por un número, tiene una significación inequívoca. Como ejemplo se incluye un trozo de código tomado del fichero winnt.h, donde puede verse como la definición de los typedef ( 3.2.1a) TCHAR y PTCHAR se realiza de forma distinta según se esté utilizando un juego de caracteres normales o Unicode.
#ifdef UNICODE
typedef WCHAR TCHAR, *PTCHAR;
#else
typedef char TCHAR, *PTCHAR;
#endif
Los programas Windows identifican la lengua mediante una constante manifiesta ( 1.4.1a) que es traducida por el preprocesador a una constante hexadecimal ( 3.2.3b). A su vez, las variaciones o dialectos locales ("sublenguajes" en la terminología de estos compiladores) se identifican mediante otras constantes que son también traducidas a números.
Para dar idea de las lenguas soportadas, a continuación se relacionan las constantes implementadas en el compilador MS VC++ 6.0
Lengua | Variedad |
#define LANG_NEUTRAL 0x00 #define LANG_AFRIKAANS 0x36 #define LANG_ALBANIAN 0x1c #define LANG_ARABIC 0x01 #define LANG_ARMENIAN 0x2b #define LANG_ASSAMESE 0x4d #define LANG_AZERI 0x2c #define LANG_BASQUE 0x2d #define LANG_BELARUSIAN 0x23 #define LANG_BENGALI 0x45 #define LANG_BULGARIAN 0x02 #define LANG_CATALAN 0x03 #define LANG_CHINESE 0x04 #define LANG_CROATIAN 0x1a #define LANG_CZECH 0x05 #define LANG_DANISH 0x06 #define LANG_DUTCH 0x13 #define LANG_ENGLISH 0x09 #define LANG_ESTONIAN 0x25 #define LANG_FAEROESE 0x38 #define LANG_FARSI 0x29 #define LANG_FINNISH 0x0b #define LANG_FRENCH 0x0c #define LANG_GEORGIAN 0x37 #define LANG_GERMAN 0x07 #define LANG_GREEK 0x08 #define LANG_GUJARATI 0x47 #define LANG_HEBREW 0x0d #define LANG_HINDI 0x39 #define LANG_HUNGARIAN 0x0e #define LANG_ICELANDIC 0x0f #define LANG_INDONESIAN 0x21 #define LANG_ITALIAN 0x10 #define LANG_JAPANESE 0x11 #define LANG_KANNADA 0x4b #define LANG_KASHMIRI 0x60 #define LANG_KAZAK 0x3f #define LANG_KONKANI 0x57 #define LANG_KOREAN 0x12 #define LANG_LATVIAN 0x26 #define LANG_LITHUANIAN 0x27 #define LANG_MACEDONIAN 0x2f #define LANG_MALAY 0x3e #define LANG_MALAYALAM 0x4c #define LANG_MANIPURI 0x58 #define LANG_MARATHI 0x4e #define LANG_NEPALI 0x61 #define LANG_NORWEGIAN 0x14 #define LANG_ORIYA 0x48 #define LANG_POLISH 0x15 #define LANG_PORTUGUESE 0x16 #define LANG_PUNJABI 0x46 #define LANG_ROMANIAN 0x18 #define LANG_RUSSIAN 0x19 #define LANG_SANSKRIT 0x4f #define LANG_SERBIAN 0x1a #define LANG_SINDHI 0x59 #define LANG_SLOVAK 0x1b #define LANG_SLOVENIAN 0x24 #define LANG_SPANISH 0x0a #define LANG_SWAHILI 0x41 #define LANG_SWEDISH 0x1d #define LANG_TAMIL 0x49 #define LANG_TATAR 0x44 #define LANG_TELUGU 0x4a #define LANG_THAI 0x1e #define LANG_TURKISH 0x1f #define LANG_UKRAINIAN 0x22 #define LANG_URDU 0x20 #define LANG_UZBEK 0x43 #define LANG_VIETNAMESE 0x2a |
#define SUBLANG_NEUTRAL 0x00 // language neutral #define SUBLANG_DEFAULT 0x01 // user default #define SUBLANG_SYS_DEFAULT 0x02 // system default #define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 // Arabic (Saudi Arabia) #define SUBLANG_ARABIC_IRAQ 0x02 // Arabic (Iraq) #define SUBLANG_ARABIC_EGYPT 0x03 // Arabic (Egypt) #define SUBLANG_ARABIC_LIBYA 0x04 // Arabic (Libya) #define SUBLANG_ARABIC_ALGERIA 0x05 // Arabic (Algeria) #define SUBLANG_ARABIC_MOROCCO 0x06 // Arabic (Morocco) #define SUBLANG_ARABIC_TUNISIA 0x07 // Arabic (Tunisia) #define SUBLANG_ARABIC_OMAN 0x08 // Arabic (Oman) #define SUBLANG_ARABIC_YEMEN 0x09 // Arabic (Yemen) #define SUBLANG_ARABIC_SYRIA 0x0a // Arabic (Syria) #define SUBLANG_ARABIC_JORDAN 0x0b // Arabic (Jordan) #define SUBLANG_ARABIC_LEBANON 0x0c // Arabic (Lebanon) #define SUBLANG_ARABIC_KUWAIT 0x0d // Arabic (Kuwait) #define SUBLANG_ARABIC_UAE 0x0e // Arabic (U.A.E) #define SUBLANG_ARABIC_BAHRAIN 0x0f // Arabic (Bahrain) #define SUBLANG_ARABIC_QATAR 0x10 // Arabic (Qatar) #define SUBLANG_AZERI_LATIN 0x01 // Azeri (Latin) #define SUBLANG_AZERI_CYRILLIC 0x02 // Azeri (Cyrillic) #define SUBLANG_CHINESE_TRADITIONAL 0x01 // Chinese (Taiwan) #define SUBLANG_CHINESE_SIMPLIFIED 0x02 // Chinese (PR China) #define SUBLANG_CHINESE_HONGKONG 0x03 // Chinese (Hong Kong) #define SUBLANG_CHINESE_SINGAPORE 0x04 // Chinese (Singapore) #define SUBLANG_CHINESE_MACAU 0x05 // Chinese (Macau) #define SUBLANG_DUTCH 0x01 // Dutch #define SUBLANG_DUTCH_BELGIAN 0x02 // Dutch (Belgian) #define SUBLANG_ENGLISH_US 0x01 // English (USA) #define SUBLANG_ENGLISH_UK 0x02 // English (UK) #define SUBLANG_ENGLISH_AUS 0x03 // English (Australian) #define SUBLANG_ENGLISH_CAN 0x04 // English (Canadian) #define SUBLANG_ENGLISH_NZ 0x05 // English (New Zealand) #define SUBLANG_ENGLISH_EIRE 0x06 // English (Irish) #define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07 // English (South Africa) #define SUBLANG_ENGLISH_JAMAICA 0x08 // English (Jamaica) #define SUBLANG_ENGLISH_CARIBBEAN 0x09 // English (Caribbean) #define SUBLANG_ENGLISH_BELIZE 0x0a // English (Belize) #define SUBLANG_ENGLISH_TRINIDAD 0x0b // English (Trinidad) #define SUBLANG_ENGLISH_ZIMBABWE 0x0c // English (Zimbabwe) #define SUBLANG_ENGLISH_PHILIPPINES 0x0d // English (Philippines) #define SUBLANG_FRENCH 0x01 // French #define SUBLANG_FRENCH_BELGIAN 0x02 // French (Belgian) #define SUBLANG_FRENCH_CANADIAN 0x03 // French (Canadian) #define SUBLANG_FRENCH_SWISS 0x04 // French (Swiss) #define SUBLANG_FRENCH_LUXEMBOURG 0x05 // French (Luxembourg) #define SUBLANG_FRENCH_MONACO 0x06 // French (Monaco) #define SUBLANG_GERMAN 0x01 // German #define SUBLANG_GERMAN_SWISS 0x02 // German (Swiss) #define SUBLANG_GERMAN_AUSTRIAN 0x03 // German (Austrian) #define SUBLANG_GERMAN_LUXEMBOURG 0x04 // German (Luxembourg) #define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 // German (Liechtenstein) #define SUBLANG_ITALIAN 0x01 // Italian #define SUBLANG_ITALIAN_SWISS 0x02 // Italian (Swiss) #define SUBLANG_KASHMIRI_INDIA 0x02 // Kashmiri (India) #define SUBLANG_KOREAN 0x01 // Korean (Extended Wansung) #define SUBLANG_LITHUANIAN 0x01 // Lithuanian #define SUBLANG_LITHUANIAN_CLASSIC 0x02 // Lithuanian (Classic) #define SUBLANG_MALAY_MALAYSIA 0x01 // Malay (Malaysia) #define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 // Malay (Brunei Darussalam) #define SUBLANG_NEPALI_INDIA 0x02 // Nepali (India) #define SUBLANG_NORWEGIAN_BOKMAL 0x01 // Norwegian (Bokmal) #define SUBLANG_NORWEGIAN_NYNORSK 0x02 // Norwegian (Nynorsk) #define SUBLANG_PORTUGUESE 0x02 // Portuguese #define SUBLANG_PORTUGUESE_BRAZILIAN 0x01 // Portuguese (Brazilian) #define SUBLANG_SERBIAN_LATIN 0x02 // Serbian (Latin) #define SUBLANG_SERBIAN_CYRILLIC 0x03 // Serbian (Cyrillic) #define SUBLANG_SPANISH 0x01 // Spanish (Castilian) #define SUBLANG_SPANISH_MEXICAN 0x02 // Spanish (Mexican) #define SUBLANG_SPANISH_MODERN 0x03 // Spanish (Modern) #define SUBLANG_SPANISH_GUATEMALA 0x04 // Spanish (Guatemala) #define SUBLANG_SPANISH_COSTA_RICA 0x05 // Spanish (Costa Rica) #define SUBLANG_SPANISH_PANAMA 0x06 // Spanish (Panama) #define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 // Spanish (Dominican Republic) #define SUBLANG_SPANISH_VENEZUELA 0x08 // Spanish (Venezuela) #define SUBLANG_SPANISH_COLOMBIA 0x09 // Spanish (Colombia) #define SUBLANG_SPANISH_PERU 0x0a // Spanish (Peru) #define SUBLANG_SPANISH_ARGENTINA 0x0b // Spanish (Argentina) #define SUBLANG_SPANISH_ECUADOR 0x0c // Spanish (Ecuador) #define SUBLANG_SPANISH_CHILE 0x0d // Spanish (Chile) #define SUBLANG_SPANISH_URUGUAY 0x0e // Spanish (Uruguay) #define SUBLANG_SPANISH_PARAGUAY 0x0f // Spanish (Paraguay) #define SUBLANG_SPANISH_BOLIVIA 0x10 // Spanish (Bolivia) #define SUBLANG_SPANISH_EL_SALVADOR 0x11 // Spanish (El Salvador) #define SUBLANG_SPANISH_HONDURAS 0x12 // Spanish (Honduras) #define SUBLANG_SPANISH_NICARAGUA 0x13 // Spanish (Nicaragua) #define SUBLANG_SPANISH_PUERTO_RICO 0x14 // Spanish (Puerto Rico) #define SUBLANG_SWEDISH 0x01 // Swedish #define SUBLANG_SWEDISH_FINLAND 0x02 // Swedish (Finland) #define SUBLANG_URDU_PAKISTAN 0x01 // Urdu (Pakistan) #define SUBLANG_URDU_INDIA 0x02 // Urdu (India) #define SUBLANG_UZBEK_LATIN 0x01 // Uzbek (Latin) #define SUBLANG_UZBEK_CYRILLIC 0x02 // Uzbek (Cyrillic) |
§3 Webografía
- UTF-8 and Unicode FAQ for Unix/Linux www.cl.cam.ac.uk
A pesar de su título, esta página de Markus Kuhn es una excelente guía acerca de los sistemas de codificación en general.
- Unicode.org www.unicode.org/unicode/
Sin duda el sitio oficial es la mejor fuente de información. En la página "Code charts" pueden obtenerse las tablas de caracteres, ideogramas y signos de todas las lenguas del mundo.