Hezké shrnutí. Ještě dneska si pamatuju na to pozdvižení, když RedHat zvolil do své distribuce UTF-8 jako výchozí kódování. Dneska je cokoliv jiného sebevražda :-)
Ten první příklad bude spíš klasické x86, nikoliv x86_64. I když za předpokladu, že adresa řetězce bude ve spodních 32 bitech (což asi bude), by mohl spíše náhodou fungovat i na x86_64. Nejsem si jistý, jestli je podporováno int $0x80 místo sysenter... Řetězec by běžně umístil překladač do sekce ".text".
Myšlenka v python 3.3 je zajímavá, ale když budu generovat nebo číst nějaké XML a ukládat do string bufferu, tak kvůli pozdravu českého uživatele bude celá anglická stránka čtyřikrát (či dvakrát) větší. V tomto by python 2 s UTF-8 šetrnější. IMHO by spíš mělo smysl udržovat UTF-8 a v případě potřeby náhodného přístupu explicitně vytvořit UCS-4 kopii.
UTF-8 je genialni na prenos, aspon z naseho pohledu, Asiate to vidi jinak :), ale interne se s nim pracuje blbe, protoze se musis "trefovat" do znaku pri kazdem indexovani nebo slicingu. Ale ty myslis to, ze proste defaultne bude pouzito UTF-8 a bude se provadet nejake copy-on-index? Hmm jako je to zajimave, ale asi by to chtelo benchmarky.
Asiatům je to jedno, bo v naprosté většině případů vidí dva byty jak v UCS-2, tak UTF-8 :-) A pořád je tam dost věcí (HTML, JavaScript, JSON, kódy v localization), které budou z velké části ASCII, takže i tak ušetří.
K druhé části - spíš mít dva různé typy pro různé účely. I to málo situací, kde se používá .charAt(), povětšinou stačí implementace po bytech, bo se třeba jen porovnávají dva řetězce, bere se substring, ale na nějaký kód apod (typicky nějaký parser, který při nalezení speciálního znaku (což je obvykle ASCII) vezme předchozí sekvenci bytů a vyrobí z něj String). Těch situací, kdy je skutečně vyžadován random access k char (codepoint) dle indexu, je jako šafránu. Takový UcsString by se případně mohl cachovat v rámci původního Utf8 String, i když pochybuju, že by to mělo dramatický přínos (s výjimkou GUI aplikací, ale tam ty řetězce obvykle nebývají enormně dlouhé).
"Asiatům je to jedno, bo v naprosté většině případů vidí dva byty jak v UCS-2, tak UTF-8 :-)"
No to právě ne, do těch dvou bajtů nacpeš jen 128+1920 = 2048 znaků. Jsou tam bohudík česká nabodeníčka, azbuka, alfabeta, hebrejština, ale CJK tam nejsou. Na tu jsou v UTF-8 potřeba tři bajty. Takže je to bolí dost, protože u nás je to sem tam dvoubajtový znak s nabodeníčkem (2 bajty), jinak většina textu má znaky na jeden bajt. Oni mají prakticky konstantně 2 bajty/znak (proto nebyli s UCS a UTF moc nadšeni a dost dlouho si drželi svoje kódování).
PS: předchozí odstavec má 453 bajtů v jednobajtovém kódování (ISO-8859-2) a 484 bajtů v UTF-8, což je v pohodě.
Máš pravdu, ten příklad je pro x86, už jsem to opravil.
Mimochodem ty příklady s hello world mám připravené pro víc architektur, takže v případě zájmu sosejte na https://github.com/tisnik/presentations/tree/master/assembler/03_gas_hello_world (pro PPC a s390 to vytvorili guruove na tu platformu, ja bych to nedal :-)
"Myšlenka v python 3.3 je zajímavá, ale když budu generovat nebo číst nějaké XML a ukládat do string bufferu, tak kvůli pozdravu českého uživatele bude celá anglická stránka čtyřikrát (či dvakrát) větší"
Bude to dvakrát větší (viz ten příklad s "ěščř...." na konci článku), ale například pro různé webservicy, kde se přenáší mraky datových XML nebo JSONy to je fajn, tam je to většinou čisté ASCII. Dtto SVG a podobné XML implementace.
Pokud ty data obsahují třeba jména nebo adresy (což obvykle obsahují), tak to bude plýtvat. Pokud půjde jenom o nějaké měření, souřadnice apod., tak ano - tam to bude ASCII.
Na druhé straně je pravda, že chytré implementace budou nejspíš serializovat rovnou do nějakého UTF-8 byte stream, nikoliv char stream či string. Viz třeba Jackson, který má parsery pro byte array, byte stream, char stream atd. (a kde ty první dva jsou dvakrát rychlejší než poslední zmíněný :-) ).
To je pravda, určitě to na vstupu/výstupu takto bude. Ale když si představíš, jak například nějaká aplikace zpracuje vstupní JSON, který dostane z web servicy:
vstup -> obrovský řetězec (tady se může plýtvat, záleží na knihovně) -> parsing -> (teď se klidně na původní řetězec může pustit GC) -> slovník (slovníků/polí)
A u toho slovníku ty "chytré řetězce" dost pomůžou, protože můžeme dostat něco takového:
{ "firstName" : "Méďa",
"surname": "Béďa",
"comment": "pije ",
"validated": True,
"ID": 42}
Takže samozřejmě hodnoty budou muset být v UCS-2 nebo u nějakých paznaků co tam uživatel dá v UCS-4 (kupodivu to má nízký kód), ale minimálně u klíčů to bude Latin-1 (předpokládáme příčetného programátora :-)
PS: čistě teoreticky ten původní string nepůjde na GC, pokud nějaká knihovna "optimalizuje" substring() tak, že se vrací jen reference někam doprostřed původního pole.
Ok předchozí příspěvek měl za "pije " znak http://www.fileformat.info/info/unicode/char/2615/index.htm dtto v poznámce (kupodivu to http://www.fileformat.info/info/unicode/char/2615/index.htm má nízký kód). Omlouvám se, redakční systém asi nepoužívá Unicode :-)
Jasně, u těch výsledných hodnot je to jasné, a tam to může mít smysl (*), hlavně to není tak drahé.
Já měl na mysli ten původní serializovaný řetězec, ale to se spíš týká situací, které z principu optimalizované nejsou, takže je to jedno (tedy načíst všechno do řetězce a potom deserializovat). Pokud ten deserializátor umí pracovat přímo s byte streamem, tak to nic navíc nestojí.
* - tedy, ono obvykle stejně nemá, neboť hodnota se přečte a pak se jenom předá dál (do databáze či opačným směrem, obvykle opět jako UTF-8). V tomto směru by pořád dával smysl spíš explicitní random access UCS-4 string.
Jen mozna doplnim, ze kdyz nekdo bude implementovat webove forum, twitter v.4.0, mozna i ticketovaci system, tak mu asi budou retezce "podat" do UCS-4: https://stackoverflow.com/a/18477578
jako by nestacily emoticony :)
Je to dvojsečný. Když něco někde naparsuju a pak to tahám po všech čertech, tak se to pořád kopíruje a kopíruje se toho víc, než jen pointer. Ale já zapoměl, std::string je mutabilní, takže jsem ho před drahnou dobu přestal používat. Mám vlastní implementaci a není to jeden objekt, už kvůli tomu, že na každou věc se hodí něco jiného.
Třeba stringview které se chystá do C++17 už mám ve vlastní verzi několik let a hodně věci se tím zjednoduší a zrychlí.
Mimochodem k tem retezcum v Atari BASICu - ten jazyk byl neskutecne pomaly, i v porovnani s ostatnimi Basicy, ale zrovna s retezci se tam pracovalo maximalne luxusne. Je to videt i z clanku - 'slicing' pomoci A$(od, do) na leve i prave strane prirazeni nahrazuje ty bezne LEFT$, RIGHT$, MID$ z MS Basicu. Navis slo delat i uzitecne triky, napriklad vytvoreni retezce se sto hvezdickami:
DIM A$(100)
A$="*"
A$(100)=A$
A$(2)=A$
Vi nekdo, proc se ted retezec naplni hvezdickami? :)
Diky maximalne jednoduche praci s retezci ("nekonecna" delka atd.) byl prechod na Pascal a potom na C dost sokujici :)
tak vzhledem k tomu, kdo to napsal http://www.weihenstephan.org/~michaste/pagetable/wait6502/pet3.png se nediv :)
Jinak pro Atarko se taky uvazovalo o MS Basicu, ale borci z MS meli problem to nacpat do osmi kilobajtu (to byl limit pametove mapy). Takze nakonec vznikl uplne jiny Atari Basic s par peknyma vecma (napriklad zpusob zkracovani prikazu je proste genialni).
Zajímavé jsou také descriptory proměnných v OpenVMS. Od základních datových typů včetně různých stringů až po strukturované proměnné. Přispěly k robustnosti a bezpečnosti tohoto OS. No, někdo taky může utrouit poznámku o jejich podílu na celkové složitosti a komplexnosti OpenVMS...
http://h30266.www3.hpe.com/odl/i64os/opsys/vmsos84/5841/5841pro_050.html#13_argumentsheading
Ten popis pro Javu platí až do verze 8. Od verze 9 se ukládání Stringů v paměti změní (viz JEP 254 – Compact Strings). Budou uloženy jako pole bajtů, přičemž podle obsahu řetězce to bude interpretováno (na základě uloženého příznaku) buď jako Latin1 nebo jako UTF-16 (tedy stejně, jako dosud). Rozhraní se nijak nemění. Pokud tedy půjde o řetězec, který lze reprezentovat pomocí Latin1 (což je s přehledem nejčastější případ, splňuje to drtivá většina různých „technických“ řetězců jako názvy tříd, metod, proměnných, XML elementů, klíčových slov v síťových protokolech, názvy souborů), bude uložen úsporně pomocí jednoho bajtu na znak.
Více méně ano, je to read only pohled na pole bytů, kde může být cokoliv. Ale protože kód zdrojového souboru je předepsán v UTF-8, tak string literal je automaticky v UTF-8, pokud nepoužijete ESC sekvence pro octal/hexa zápis. String můžete procházet standardním for range cyklem a jdete po jednotlivých UTF-8 znacích. V jazyce a standardní knihovně je extenzivní podpora pro UTF-8 (+UTF-16 a obecně Unicode), ale i kódovací/dekodovací knihovny přes standardní interface pro ASCII85, ASN.1, BASE64 a mnoho dalších.
Podrobněji od spoluautora zde: https://blog.golang.org/strings
Řetězce jsou neměnitelné. Tečka. Tohle pravidlo jsem přijal ve svém programátorském stylu v C++ před několika lety a od té doby nelituju. Spoustu problémů se tím řeší samo. Pokud chci upravit řetězec, musím vytvořit nový. Pokud chci nějak měnit řetězce na úrovni znaků, pak si ho převedu do znakového bufferu nebo vektoru
(z toho vyplývá, že std::string používám naprosto minimálně)
V prehledu ulozeni retezcu v pocitacovem praveku mi jeden zpusob chybi. Pouzival se na IQ151, ZX Spectrum, snad i na SAPI, pouzival se casto. Pokud byl retezec slozen jen ze 7-bitovych znaku, tak posledni znak mel nastaveny 7.bit (znak + 0x80). Nebylo tedy nutne plytvat jednim bytem na ukoncovaci znak nebo delku retezce. Uz si nevzpominam, je mozna ze nektere assemblery meli i specialni directivu/macro pro vytvareni takto ukoncenych retezcu.