540 likes | 802 Views
Urnik. –. –. Evolucija. Win16: D1 Win32: D2, D3, D4, D5, D6, D7, D2005, D2006, D2007 Win32: D2009, D2010, XE, XE2 …. 2002. UNICODE. ANSI. 2008. Win64, OS X, ( iOS ). Unicode – kaj in zakaj. ANSI. American National Standards Institute En znak = en bajt
E N D
Urnik – –
Evolucija • Win16: D1 • Win32: D2, D3, D4, D5, D6, D7, D2005, D2006, D2007 • Win32: D2009, D2010, XE, XE2 … 2002 UNICODE ANSI 2008 Win64, OS X, (iOS)
ANSI • American National Standards Institute • En znak = en bajt • »Primož«= $50 $72 $69 $6D $6F $9E • Na svetu je več kot 256 znakov! • Kodne strani • 128 ASCII + 128
CP 1250 - Primož CP 1251 - Primoђ vir: Microsoft
Problemi • Lokalizacija/internacionalizacija • Vnos in shranjevanje geografsko razpršenih podatkov • Pisave s 100+ znaki
Rešitev • CJK DBCS: OEM/ANSI 932, 936, 949, 950 • Unicode
Unicode • Zapis vseh svetovnih pisav • Črke, številke, ločila, matematični znaki, šahovski simboli, mahjongg, domino, emotikoni, alkemija/astrologija … • 6.1: 100 pisav, > 110.000 znakov • Prostora za 1,114.112 znakov • Prvih 256 = ISO 8859-1
Problemi • Pomanjkanje »popolnih« tipografij • Arial Unicode MS, Calibri • Velika poraba prostora • 4 bajti na znak
Ravni • Kodne točke: 0 - $10FFFF • Ravni: $00 - $10 • Vsaka raven: $0000 - $FFFF • Prva raven (raven 0): osnovna večjezična raven (BMP) • Najpomembnejših 65536 znakov • Raven 1: dodatni znaki • Raven 2: dodatni ideografski znaki • Raven 14: dodatni znaki za posebne namene • Ravni 15, 16: privatno področje (PUA)
Zapis • BMP: U+hhhh • »A« = $41 = U+0041 • Druge ravni: U+hhhhh ali U+hhhhhh • » « = U+10080 • »𝒪« = U+1D4AA
Kompozicija • Sestavljena oblika • »ö« = U+00F6 • Komponentna oblika • »ö«= U+006F, U+0308 • Komponente (diakritična znamenja) lahko nizamo vir: StackOverflow
Kodiranja • UCS-4 • UTF-32 • UCS-2 • UTF-16 • UTF-8
UTF-32 • 4 bajti za znak • Littleendian (LE) in big endian(BE) • UTF-32LE:$50 $00 $00 $00 $72 $00 $00 $00 $69 $00 $00 $00$6D $00 $00 $00 $6F $00 $00 $00$7E $01 $00 $00 [–] Ogromnaporabaprostora [+] Enostavnamanipulacija
UTF-16 • 2 ali 4 bajti za znak • BMP: 2 bajta • Drugo: 4 bajti; U+1D4AA = U+D835, U+DCAA • UTF-16LE: $50 $00 $72 $00 $69 $00 $6D $00 $6F $00 $7E $01 • UTF-16BE: $00 $50 $00 $72 $00 $69 $00 $6D $00 $6F$01 $7E [–] Otežkočeno delo z znaki, ki niso v BMP [+] Dober kompromis
UTF-8 • Od 1 do 3 bajti za znak • ASCII: 1 bajt • Evropski znaki (in drugo): 2 bajta • Preostanek: 3 bajti • Ne obstajata LE in BE • UTF-8: $50 $72 $69 $6D $6F $C5 $BE [–] Otežkočena manipulacija [+] Majhna poraba prostora
I. Unicode okna • CreateWindowsW • Sporočila prenašajo nize Unicode UTF-16LE • D2007: TNT Unicode Controls
II.»Wide« API • VCL in RTL kličeta »W« različice funkcij • function GetModuleFileName(hModule: HINST; lpFilename: PWideChar; nSize: DWORD): DWORD; stdcall; • function GetModuleFileNameA(hModule: HINST; lpFilename: PAnsiChar; nSize: DWORD): DWORD; stdcall; • function GetModuleFileNameW(hModule: HINST; lpFilename: PWideChar; nSize: DWORD): DWORD; stdcall; • VCL in RTL interno uporabljata Unicode • D2007: LoadLibrary
III. Privzeta oblika nizov • String = UnicodeString = UTF-16LE • WideString, AnsiString • D2007: String = AnsiString; WideString
Spremembe • I. Unicode okna • II. »Wide« API • III. Unicode nizi • Privzetoobnašanje je sedaj Unicodno, za delo z osembitnimi znaki se moramo posebej potruditi!
Nizi na sto načinov • String[] • var ime: string[40]; • AnsiString • RawByteString • UTF8String • UnicodeString • WideString • UCS4String
AnsiString • Osembitni znaki • Nov metapodatek: kodna stran • var s: AnsiString; • type CyrillicString = type AnsiString(1251); • var s: CyrillicString • Samodejno pretvarjanje kodnih strani
RawByteString • type RawByteString = type AnsiString($FFFF); • Prirejanje brez pretvarjanja
UTF8String • type UTF8String = type AnsiString(65001); • Samodejna pretvorba v UTF8 in iz njega pri prirejanju
UnicodeString • UTF-16LE • Štetje referenc • Delphijev dodeljevalnik pomnilnika • Length('#$D835#$DCAA' {𝒪}) = 2 • ElementToCharLen('#$D835#$DCAA') = 1 • NextCharIndex, StrNextChar
WideString • UTF-16LE • Brez štetja referenc • COM dodeljevalnik pomnilnika • Nespremenjen glede na D2007
UCS4String • type UCS4String = arrayof UCS4Char; • Slaba podpora: ConvertFromUTF32, ConvertToUTF32
TEncoding • Memo1.Lines.LoadFromFile('tekst.txt', TEncoding.Ansi) • Memo1.Lines.SaveToStream(str, TEncoding.UTF8) • classproperty ANSI: TEncoding • classproperty ASCII: TEncoding • classproperty BigEndianUnicode: TEncoding • classproperty Default: TEncoding • classproperty Unicode: TEncoding • classproperty UTF7: TEncoding • classproperty UTF8: TEncoding
TEncoding kot pretvornik var ime16be: string; ime16be:= TEncoding.BigEndianUnicode.GetString(TEncoding.Unicode.GetBytes(FIme));
Character • Lastnosti znakov • GetUnicodeCategory, IsLower, IsSeparator, IsWhiteSpace … • Lastnosti nizov • IsLower, IsNumber, IsLetter … • Spreminjanje • ToLower, ToUpper, ConvertToUtf32, ConvertFromUtf32
CharInSet var ch: char; if ch in ['A'..'Z'] then … ⇒ if CharInSet(ch, ['A'..'Z']) then … ⇒ if IsLetter(ch) then …
Baze • TField.AsWideString • TField.AsString ostaja nespremenjen (Ansi) • Podatki shranjeni v UTF8 - spremenljiva dolžina niza
Kako čez prepad? ogromno dela, še misliti si ne morete, koliko težavnost prehoda trivialno
Tuje knjižnice in komponente • Predelujte le v skrajni sili • Raje poiščite nadomestek • Turbo Power je sedaj na SourceForgu
Opozorila prevajalnika W1050WideCharreduced to bytechar in set expressions. Considerusing 'CharInSet' function in 'SysUtils' unit. W1058Implicitstringcastwithpotentialdatalossfrom 'string' to 'AnsiString' W1057Implicitstringcastfrom 'AnsiString' to 'string' W1059Explicitstringcast W1060Explicitstringcastwithpotentialdataloss W1062Narrowinggivenwide/Unicode stringconstantlostinformation W1063WideninggivenAnsiCharconstant to WideCharlostinformation W1064WideninggivenAnsiStringconstantlostinformation
Problem I: SizeOf(char) = 1 varbuffer: array[0..255] ofchar; FillChar(Buffer, Length(Buffer), 0); ⇒ varbuffer: array[0..255] ofchar; FillChar(Buffer, Length(Buffer) *SizeOf(buffer[0]), 0);
Problem II: Nizikotnosilcipodatkov function ReadFromStream(s: TStream): string;var len: integer;begin s.Read(len, 4); SetLength(Result, len); s.Read(Result[1], len);end; • Rezultat: »㨰崶㼠㼿㼿 «
Rešitev II: Nizi kot nosilci podatkov function ReadFromStream(s: TStream):RawByteString;var len: integer;begin s.Read(len, 4); SetLength(Result, len); s.Read(Result[1], len);end;
Problem III: Čarovnije s kazalci function CountSpaces(const s: string): integer;var i : integer; pc: PChar;begin Result := 0;if s <> '' thenbegin pc := @(s[1]);for i := 1 to Length(s) dobeginif pc^ = ' ' then Inc(Result); pc := pointer(integer(pc)+1);end;end;end;
Rešitev III: Čarovnije s kazalci function CountSpaces(const s: string): integer;var i : integer; pc: PChar;begin Result := 0;if s <> '' thenbegin pc := @(s[1]);for i := 1 to Length(s) dobeginif IsWhiteSpace(pc^) then Inc(Result); Inc(pc); //pc := pointer(integer(pc)+1); end;end;end;
Pogosti viri težav • Move, FillChar, NewStr, DisposeStr, AllocMem, GetMem, StrAlloc, Read, ReadBuffer, Write, WriteBuffer • PChar, PString • MultiByteToWideChar, WideCharToMultiByte • LoadFromFile, LoadFromStream, SaveToFile, SaveToStream • »array of const« - vtUnicodeString
Uppercase : AnsiUppercase • Uppercase('aâăá') = 'Aâăá' • AnsiUppercase('aâăá') = 'AÂĂÁ' • UpperCase, LowerCase, CompareStr, CompareText, SameStr …
Nasveti • char ⇒ AnsiChar, PChar ⇒ PAnsiChar, string ⇒ AnsiString, PString ⇒ PAnsiString • AnsiStrings • TWideStrings ?⇒ TStrings, TWideStringList ?⇒ TStringList • CreateProcessW • PAnsiChar(AnsiString(s))
PopolnapodporaUnicoda • Kompozicija • Nadomestni pari • Desno-levi jeziki znotraj katerih se pojavljajo levo-desni deli • Delna podpora Unicoda (samo levo-desni jeziki, samo BMP) je enostavna