1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789 |
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <meta name="generator" content=
- "HTML Tidy for Linux/x86 (vers 1st November 2002), see www.w3.org">
- <meta name="description" content=
- "A simple, portable and lightweigt C++ library for easy handling of UTF-8 encoded strings">
- <meta name="keywords" content="UTF-8 C++ portable utf8 unicode generic templates">
- <meta name="author" content="Nemanja Trifunovic">
- <title>
- UTF8-CPP: UTF-8 with C++ in a Portable Way
- </title>
- <style type="text/css">
- <!--
- span.return_value {
- color: brown;
- }
- span.keyword {
- color: blue;
- }
- span.preprocessor {
- color: navy;
- }
- span.literal {
- color: olive;
- }
- span.comment {
- color: green;
- }
- code {
- font-weight: bold;
- }
- ul.toc {
- list-style-type: none;
- }
- p.version {
- font-size: small;
- font-style: italic;
- }
- -->
- </style>
- </head>
- <body>
- <h1>
- UTF8-CPP: UTF-8 with C++ in a Portable Way
- </h1>
- <p>
- <a href="https://sourceforge.net/projects/utfcpp">The Sourceforge project page</a>
- </p>
- <div id="toc">
- <h2>
- Table of Contents
- </h2>
- <ul class="toc">
- <li>
- <a href="#introduction">Introduction</a>
- </li>
- <li>
- <a href="#examples">Examples of Use</a>
- <ul class="toc">
- <li>
- <a href=#introsample>Introductionary Sample </a>
- </li>
- <li>
- <a href=#validfile>Checking if a file contains valid UTF-8 text</a>
- </li>
- <li>
- <a href=#fixinvalid>Ensure that a string contains valid UTF-8 text</a>
- </li>
- </ul>
- <li>
- <a href="#reference">Reference</a>
- <ul class="toc">
- <li>
- <a href="#funutf8">Functions From utf8 Namespace </a>
- </li>
- <li>
- <a href="#typesutf8">Types From utf8 Namespace </a>
- </li>
- <li>
- <a href="#fununchecked">Functions From utf8::unchecked Namespace </a>
- </li>
- <li>
- <a href="#typesunchecked">Types From utf8::unchecked Namespace </a>
- </li>
- </ul>
- </li>
- <li>
- <a href="#points">Points of Interest</a>
- </li>
- <li>
- <a href="#links">Links</a>
- </li>
- </ul>
- </div>
- <h2 id="introduction">
- Introduction
- </h2>
- <p>
- Many C++ developers miss an easy and portable way of handling Unicode encoded
- strings. The original C++ Standard (known as C++98 or C++03) is Unicode agnostic.
- C++11 provides some support for Unicode on core language and library level:
- u8, u, and U character and string literals, char16_t and char32_t character types,
- u16string and u32string library classes, and codecvt support for conversions
- between Unicode encoding forms.
- In the meantime, developers use third party libraries like ICU, OS specific capabilities, or simply
- roll out their own solutions.
- </p>
- <p>
- In order to easily handle UTF-8 encoded Unicode strings, I came up with a small
- generic library. For anybody used to work with STL algorithms and iterators, it should be
- easy and natural to use. The code is freely available for any purpose - check out
- the license at the beginning of the utf8.h file. If you run into
- bugs or performance issues, please let me know and I'll do my best to address them.
- </p>
- <p>
- The purpose of this article is not to offer an introduction to Unicode in general,
- and UTF-8 in particular. If you are not familiar with Unicode, be sure to check out
- <a href="http://www.unicode.org/">Unicode Home Page</a> or some other source of
- information for Unicode. Also, it is not my aim to advocate the use of UTF-8
- encoded strings in C++ programs; if you want to handle UTF-8 encoded strings from
- C++, I am sure you have good reasons for it.
- </p>
- <h2 id="examples">
- Examples of use
- </h2>
- <h3 id="introsample">
- Introductionary Sample
- </h3>
- <p>
- To illustrate the use of the library, let's start with a small but complete program
- that opens a file containing UTF-8 encoded text, reads it line by line, checks each line
- for invalid UTF-8 byte sequences, and converts it to UTF-16 encoding and back to UTF-8:
- </p>
- <pre>
- <span class="preprocessor">#include <fstream></span>
- <span class="preprocessor">#include <iostream></span>
- <span class="preprocessor">#include <string></span>
- <span class="preprocessor">#include <vector></span>
- <span class="preprocessor">#include "utf8.h"</span>
- <span class="keyword">using namespace</span> std;
- <span class="keyword">int</span> main(<span class="keyword">int</span> argc, <span class="keyword">char</span>** argv)
- {
- <span class="keyword">if</span> (argc != <span class="literal">2</span>) {
- cout << <span class="literal">"\nUsage: docsample filename\n"</span>;
- <span class="keyword">return</span> <span class="literal">0</span>;
- }
- <span class="keyword">const char</span>* test_file_path = argv[1];
- <span class="comment">// Open the test file (contains UTF-8 encoded text)</span>
- ifstream fs8(test_file_path);
- <span class="keyword">if</span> (!fs8.is_open()) {
- cout << <span class=
- "literal">"Could not open "</span> << test_file_path << endl;
- <span class="keyword">return</span> <span class="literal">0</span>;
- }
- <span class="keyword">unsigned</span> line_count = <span class="literal">1</span>;
- string line;
- <span class="comment">// Play with all the lines in the file</span>
- <span class="keyword">while</span> (getline(fs8, line)) {
- <span class="comment">// check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)</span>
- string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
- <span class="keyword">if</span> (end_it != line.end()) {
- cout << <span class=
- "literal">"Invalid UTF-8 encoding detected at line "</span> << line_count << <span
- class="literal">"\n"</span>;
- cout << <span class=
- "literal">"This part is fine: "</span> << string(line.begin(), end_it) << <span
- class="literal">"\n"</span>;
- }
- <span class="comment">// Get the line length (at least for the valid part)</span>
- <span class="keyword">int</span> length = utf8::distance(line.begin(), end_it);
- cout << <span class=
- "literal">"Length of line "</span> << line_count << <span class=
- "literal">" is "</span> << length << <span class="literal">"\n"</span>;
- <span class="comment">// Convert it to utf-16</span>
- vector<unsigned short> utf16line;
- utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
- <span class="comment">// And back to utf-8</span>
- string utf8line;
- utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
- <span class="comment">// Confirm that the conversion went OK:</span>
- <span class="keyword">if</span> (utf8line != string(line.begin(), end_it))
- cout << <span class=
- "literal">"Error in UTF-16 conversion at line: "</span> << line_count << <span
- class="literal">"\n"</span>;
- line_count++;
- }
- <span class="keyword">return</span> <span class="literal">0</span>;
- }
- </pre>
- <p>
- In the previous code sample, for each line we performed
- a detection of invalid UTF-8 sequences with <code>find_invalid</code>; the number
- of characters (more precisely - the number of Unicode code points, including the end
- of line and even BOM if there is one) in each line was
- determined with a use of <code>utf8::distance</code>; finally, we have converted
- each line to UTF-16 encoding with <code>utf8to16</code> and back to UTF-8 with
- <code>utf16to8</code>.
- </p>
- <h3 id="validfile">Checking if a file contains valid UTF-8 text</h3>
- <p>
- Here is a function that checks whether the content of a file is valid UTF-8 encoded text without
- reading the content into the memory:
- </p>
- <pre>
- <span class="keyword">bool</span> valid_utf8_file(i<span class="keyword">const char</span>* file_name)
- {
- ifstream ifs(file_name);
- <span class="keyword">if</span> (!ifs)
- <span class="keyword">return false</span>; <span class="comment">// even better, throw here</span>
- istreambuf_iterator<<span class="keyword">char</span>> it(ifs.rdbuf());
- istreambuf_iterator<<span class="keyword">char</span>> eos;
- <span class="keyword">return</span> utf8::is_valid(it, eos);
- }
- </pre>
- <p>
- Because the function <code>utf8::is_valid()</code> works with input iterators, we were able
- to pass an <code>istreambuf_iterator</code> to it and read the content of the file directly
- without loading it to the memory first.</p>
- <p>
- Note that other functions that take input iterator arguments can be used in a similar way. For
- instance, to read the content of a UTF-8 encoded text file and convert the text to UTF-16, just
- do something like:
- </p>
- <pre>
- utf8::utf8to16(it, eos, back_inserter(u16string));
- </pre>
- <h3 id="fixinvalid">Ensure that a string contains valid UTF-8 text</h3>
- <p>
- If we have some text that "probably" contains UTF-8 encoded text and we want to
- replace any invalid UTF-8 sequence with a replacement character, something like
- the following function may be used:
- </p>
- <pre>
- <span class="keyword">void</span> fix_utf8_string(std::string& str)
- {
- std::string temp;
- utf8::replace_invalid(str.begin(), str.end(), back_inserter(temp));
- str = temp;
- }
- </pre>
- <p>The function will replace any invalid UTF-8 sequence with a Unicode replacement character.
- There is an overloaded function that enables the caller to supply their own replacement character.
- </p>
- <h2 id="reference">
- Reference
- </h2>
- <h3 id="funutf8">
- Functions From utf8 Namespace
- </h3>
- <h4>
- utf8::append
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence
- to a UTF-8 string.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- octet_iterator append(uint32_t cp, octet_iterator result);
-
- </pre>
- <p>
- <code>octet_iterator</code>: an output iterator.<br>
- <code>cp</code>: a 32 bit integer representing a code point to append to the
- sequence.<br>
- <code>result</code>: an output iterator to the place in the sequence where to
- append the code point.<br>
- <span class="return_value">Return value</span>: an iterator pointing to the place
- after the newly appended sequence.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">unsigned char</span> u[<span class="literal">5</span>] = {<span
- class="literal">0</span>,<span class="literal">0</span>,<span class=
- "literal">0</span>,<span class="literal">0</span>,<span class="literal">0</span>};
- <span class="keyword">unsigned char</span>* end = append(<span class=
- "literal">0x0448</span>, u);
- assert (u[<span class="literal">0</span>] == <span class=
- "literal">0xd1</span> && u[<span class="literal">1</span>] == <span class=
- "literal">0x88</span> && u[<span class="literal">2</span>] == <span class=
- "literal">0</span> && u[<span class="literal">3</span>] == <span class=
- "literal">0</span> && u[<span class="literal">4</span>] == <span class=
- "literal">0</span>);
- </pre>
- <p>
- Note that <code>append</code> does not allocate any memory - it is the burden of
- the caller to make sure there is enough memory allocated for the operation. To make
- things more interesting, <code>append</code> can add anywhere between 1 and 4
- octets to the sequence. In practice, you would most often want to use
- <code>std::back_inserter</code> to ensure that the necessary memory is allocated.
- </p>
- <p>
- In case of an invalid code point, a <code>utf8::invalid_code_point</code> exception
- is thrown.
- </p>
- <h4>
- utf8::next
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Given the iterator to the beginning of the UTF-8 sequence, it returns the code
- point and moves the iterator to the next position.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- uint32_t next(octet_iterator& it, octet_iterator end);
-
- </pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
- encoded code point. After the function returns, it is incremented to point to the
- beginning of the next code point.<br>
- <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
- gets equal to <code>end</code> during the extraction of a code point, an
- <code>utf8::not_enough_room</code> exception is thrown.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- processed UTF-8 code point.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- <span class="keyword">char</span>* w = twochars;
- <span class="keyword">int</span> cp = next(w, twochars + <span class="literal">6</span>);
- assert (cp == <span class="literal">0x65e5</span>);
- assert (w == twochars + <span class="literal">3</span>);
- </pre>
- <p>
- This function is typically used to iterate through a UTF-8 encoded string.
- </p>
- <p>
- In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
- thrown.
- </p>
- <h4>
- utf8::peek_next
- </h4>
- <p class="version">
- Available in version 2.1 and later.
- </p>
- <p>
- Given the iterator to the beginning of the UTF-8 sequence, it returns the code
- point for the following sequence without changing the value of the iterator.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- uint32_t peek_next(octet_iterator it, octet_iterator end);
-
- </pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>it</code>: an iterator pointing to the beginning of an UTF-8
- encoded code point.<br>
- <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
- gets equal to <code>end</code> during the extraction of a code point, an
- <code>utf8::not_enough_room</code> exception is thrown.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- processed UTF-8 code point.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- <span class="keyword">char</span>* w = twochars;
- <span class="keyword">int</span> cp = peek_next(w, twochars + <span class="literal">6</span>);
- assert (cp == <span class="literal">0x65e5</span>);
- assert (w == twochars);
- </pre>
- <p>
- In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
- thrown.
- </p>
- <h4>
- utf8::prior
- </h4>
- <p class="version">
- Available in version 1.02 and later.
- </p>
- <p>
- Given a reference to an iterator pointing to an octet in a UTF-8 sequence, it
- decreases the iterator until it hits the beginning of the previous UTF-8 encoded
- code point and returns the 32 bits representation of the code point.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- uint32_t prior(octet_iterator& it, octet_iterator start);
-
- </pre>
- <p>
- <code>octet_iterator</code>: a bidirectional iterator.<br>
- <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
- After the function returns, it is decremented to point to the beginning of the
- previous code point.<br>
- <code>start</code>: an iterator to the beginning of the sequence where the search
- for the beginning of a code point is performed. It is a
- safety measure to prevent passing the beginning of the string in the search for a
- UTF-8 lead octet.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- previous code point.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- <span class="keyword">unsigned char</span>* w = twochars + <span class=
- "literal">3</span>;
- <span class="keyword">int</span> cp = prior (w, twochars);
- assert (cp == <span class="literal">0x65e5</span>);
- assert (w == twochars);
- </pre>
- <p>
- This function has two purposes: one is two iterate backwards through a UTF-8
- encoded string. Note that it is usually a better idea to iterate forward instead,
- since <code>utf8::next</code> is faster. The second purpose is to find a beginning
- of a UTF-8 sequence if we have a random position within a string. Note that in that
- case <code>utf8::prior</code> may not detect an invalid UTF-8 sequence in some scenarios:
- for instance if there are superfluous trail octets, it will just skip them.
- </p>
- <p>
- <code>it</code> will typically point to the beginning of
- a code point, and <code>start</code> will point to the
- beginning of the string to ensure we don't go backwards too far. <code>it</code> is
- decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence
- beginning with that octet is decoded to a 32 bit representation and returned.
- </p>
- <p>
- In case <code>start</code> is reached before a UTF-8 lead octet is hit, or if an
- invalid UTF-8 sequence is started by the lead octet, an <code>invalid_utf8</code>
- exception is thrown.
- </p>
- <p>In case <code>start</code> equals <code>it</code>, a <code>not_enough_room</code>
- exception is thrown.
- <h4>
- utf8::previous
- </h4>
- <p class="version">
- Deprecated in version 1.02 and later.
- </p>
- <p>
- Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
- decreases the iterator until it hits the beginning of the previous UTF-8 encoded
- code point and returns the 32 bits representation of the code point.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- uint32_t previous(octet_iterator& it, octet_iterator pass_start);
-
- </pre>
- <p>
- <code>octet_iterator</code>: a random access iterator.<br>
- <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
- After the function returns, it is decremented to point to the beginning of the
- previous code point.<br>
- <code>pass_start</code>: an iterator to the point in the sequence where the search
- for the beginning of a code point is aborted if no result was reached. It is a
- safety measure to prevent passing the beginning of the string in the search for a
- UTF-8 lead octet.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- previous code point.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- <span class="keyword">unsigned char</span>* w = twochars + <span class=
- "literal">3</span>;
- <span class="keyword">int</span> cp = previous (w, twochars - <span class=
- "literal">1</span>);
- assert (cp == <span class="literal">0x65e5</span>);
- assert (w == twochars);
- </pre>
- <p>
- <code>utf8::previous</code> is deprecated, and <code>utf8::prior</code> should
- be used instead, although the existing code can continue using this function.
- The problem is the parameter <code>pass_start</code> that points to the position
- just before the beginning of the sequence. Standard containers don't have the
- concept of "pass start" and the function can not be used with their iterators.
- </p>
- <p>
- <code>it</code> will typically point to the beginning of
- a code point, and <code>pass_start</code> will point to the octet just before the
- beginning of the string to ensure we don't go backwards too far. <code>it</code> is
- decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence
- beginning with that octet is decoded to a 32 bit representation and returned.
- </p>
- <p>
- In case <code>pass_start</code> is reached before a UTF-8 lead octet is hit, or if an
- invalid UTF-8 sequence is started by the lead octet, an <code>invalid_utf8</code>
- exception is thrown
- </p>
- <h4>
- utf8::advance
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Advances an iterator by the specified number of code points within an UTF-8
- sequence.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator, typename distance_type>
- <span class=
- "keyword">void</span> advance (octet_iterator& it, distance_type n, octet_iterator end);
-
- </pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>distance_type</code>: an integral type convertible to <code>octet_iterator</code>'s difference type.<br>
- <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
- encoded code point. After the function returns, it is incremented to point to the
- nth following code point.<br>
- <code>n</code>: a positive integer that shows how many code points we want to
- advance.<br>
- <code>end</code>: end of the UTF-8 sequence to be processed. If <code>it</code>
- gets equal to <code>end</code> during the extraction of a code point, an
- <code>utf8::not_enough_room</code> exception is thrown.<br>
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- <span class="keyword">unsigned char</span>* w = twochars;
- advance (w, <span class="literal">2</span>, twochars + <span class="literal">6</span>);
- assert (w == twochars + <span class="literal">5</span>);
- </pre>
- <p>
- This function works only "forward". In case of a negative <code>n</code>, there is
- no effect.
- </p>
- <p>
- In case of an invalid code point, a <code>utf8::invalid_code_point</code> exception
- is thrown.
- </p>
- <h4>
- utf8::distance
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Given the iterators to two UTF-8 encoded code points in a seqence, returns the
- number of code points between them.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- <span class=
- "keyword">typename</span> std::iterator_traits<octet_iterator>::difference_type distance (octet_iterator first, octet_iterator last);
-
- </pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>first</code>: an iterator to a beginning of a UTF-8 encoded code point.<br>
- <code>last</code>: an iterator to a "post-end" of the last UTF-8 encoded code
- point in the sequence we are trying to determine the length. It can be the
- beginning of a new code point, or not.<br>
- <span class="return_value">Return value</span> the distance between the iterators,
- in code points.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- size_t dist = utf8::distance(twochars, twochars + <span class="literal">5</span>);
- assert (dist == <span class="literal">2</span>);
- </pre>
- <p>
- This function is used to find the length (in code points) of a UTF-8 encoded
- string. The reason it is called <em>distance</em>, rather than, say,
- <em>length</em> is mainly because developers are used that <em>length</em> is an
- O(1) function. Computing the length of an UTF-8 string is a linear operation, and
- it looked better to model it after <code>std::distance</code> algorithm.
- </p>
- <p>
- In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
- thrown. If <code>last</code> does not point to the past-of-end of a UTF-8 seqence,
- a <code>utf8::not_enough_room</code> exception is thrown.
- </p>
- <h4>
- utf8::utf16to8
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts a UTF-16 encoded string to UTF-8.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> u16bit_iterator, <span class=
- "keyword">typename</span> octet_iterator>
- octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
-
- </pre>
- <p>
- <code>u16bit_iterator</code>: an input iterator.<br>
- <code>octet_iterator</code>: an output iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-16 encoded
- string to convert.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-16 encoded
- string to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-8 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-8 string.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">unsigned short</span> utf16string[] = {<span class=
- "literal">0x41</span>, <span class="literal">0x0448</span>, <span class=
- "literal">0x65e5</span>, <span class="literal">0xd834</span>, <span class=
- "literal">0xdd1e</span>};
- vector<<span class="keyword">unsigned char</span>> utf8result;
- utf16to8(utf16string, utf16string + <span class=
- "literal">5</span>, back_inserter(utf8result));
- assert (utf8result.size() == <span class="literal">10</span>);
- </pre>
- <p>
- In case of invalid UTF-16 sequence, a <code>utf8::invalid_utf16</code> exception is
- thrown.
- </p>
- <h4>
- utf8::utf8to16
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts an UTF-8 encoded string to UTF-16
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> u16bit_iterator, typename octet_iterator>
- u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
-
- </pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>u16bit_iterator</code>: an output iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
- string to convert. < br /> <code>end</code>: an iterator pointing to
- pass-the-end of the UTF-8 encoded string to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-16 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-16 string.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span> utf8_with_surrogates[] = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e"</span>;
- vector <<span class="keyword">unsigned short</span>> utf16result;
- utf8to16(utf8_with_surrogates, utf8_with_surrogates + <span class=
- "literal">9</span>, back_inserter(utf16result));
- assert (utf16result.size() == <span class="literal">4</span>);
- assert (utf16result[<span class="literal">2</span>] == <span class=
- "literal">0xd834</span>);
- assert (utf16result[<span class="literal">3</span>] == <span class=
- "literal">0xdd1e</span>);
- </pre>
- <p>
- In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
- thrown. If <code>end</code> does not point to the past-of-end of a UTF-8 seqence, a
- <code>utf8::not_enough_room</code> exception is thrown.
- </p>
- <h4>
- utf8::utf32to8
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts a UTF-32 encoded string to UTF-8.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator, typename u32bit_iterator>
- octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
-
- </pre>
- <p>
- <code>octet_iterator</code>: an output iterator.<br>
- <code>u32bit_iterator</code>: an input iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-32 encoded
- string to convert.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-32 encoded
- string to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-8 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-8 string.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">int</span> utf32string[] = {<span class=
- "literal">0x448</span>, <span class="literal">0x65E5</span>, <span class=
- "literal">0x10346</span>, <span class="literal">0</span>};
- vector<<span class="keyword">unsigned char</span>> utf8result;
- utf32to8(utf32string, utf32string + <span class=
- "literal">3</span>, back_inserter(utf8result));
- assert (utf8result.size() == <span class="literal">9</span>);
- </pre>
- <p>
- In case of invalid UTF-32 string, a <code>utf8::invalid_code_point</code> exception
- is thrown.
- </p>
- <h4>
- utf8::utf8to32
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts a UTF-8 encoded string to UTF-32.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator, <span class=
- "keyword">typename</span> u32bit_iterator>
- u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
-
- </pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>u32bit_iterator</code>: an output iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
- string to convert.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 encoded string
- to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-32 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-32 string.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- vector<<span class="keyword">int</span>> utf32result;
- utf8to32(twochars, twochars + <span class=
- "literal">5</span>, back_inserter(utf32result));
- assert (utf32result.size() == <span class="literal">2</span>);
- </pre>
- <p>
- In case of an invalid UTF-8 seqence, a <code>utf8::invalid_utf8</code> exception is
- thrown. If <code>end</code> does not point to the past-of-end of a UTF-8 seqence, a
- <code>utf8::not_enough_room</code> exception is thrown.
- </p>
- <h4>
- utf8::find_invalid
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Detects an invalid sequence within a UTF-8 string.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- octet_iterator find_invalid(octet_iterator start, octet_iterator end);
- </pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
- test for validity.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to test
- for validity.<br>
- <span class="return_value">Return value</span>: an iterator pointing to the first
- invalid octet in the UTF-8 string. In case none were found, equals
- <code>end</code>.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span> utf_invalid[] = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88\xfa"</span>;
- <span class=
- "keyword">char</span>* invalid = find_invalid(utf_invalid, utf_invalid + <span class=
- "literal">6</span>);
- assert (invalid == utf_invalid + <span class="literal">5</span>);
- </pre>
- <p>
- This function is typically used to make sure a UTF-8 string is valid before
- processing it with other functions. It is especially important to call it if before
- doing any of the <em>unchecked</em> operations on it.
- </p>
- <h4>
- utf8::is_valid
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Checks whether a sequence of octets is a valid UTF-8 string.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- <span class="keyword">bool</span> is_valid(octet_iterator start, octet_iterator end);
-
- </pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
- test for validity.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to test
- for validity.<br>
- <span class="return_value">Return value</span>: <code>true</code> if the sequence
- is a valid UTF-8 string; <code>false</code> if not.
- </p>
- Example of use:
- <pre>
- <span class="keyword">char</span> utf_invalid[] = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88\xfa"</span>;
- <span class="keyword">bool</span> bvalid = is_valid(utf_invalid, utf_invalid + <span
- class="literal">6</span>);
- assert (bvalid == false);
- </pre>
- <p>
- <code>is_valid</code> is a shorthand for <code>find_invalid(start, end) ==
- end;</code>. You may want to use it to make sure that a byte seqence is a valid
- UTF-8 string without the need to know where it fails if it is not valid.
- </p>
- <h4>
- utf8::replace_invalid
- </h4>
- <p class="version">
- Available in version 2.0 and later.
- </p>
- <p>
- Replaces all invalid UTF-8 sequences within a string with a replacement marker.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator, <span class=
- "keyword">typename</span> output_iterator>
- output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement);
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator, <span class=
- "keyword">typename</span> output_iterator>
- output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out);
-
- </pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>output_iterator</code>: an output iterator.<br>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 string to
- look for invalid UTF-8 sequences.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 string to look
- for invalid UTF-8 sequences.<br>
- <code>out</code>: An output iterator to the range where the result of replacement
- is stored.<br>
- <code>replacement</code>: A Unicode code point for the replacement marker. The
- version without this parameter assumes the value <code>0xfffd</code><br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the UTF-8 string with replaced invalid sequences.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span> invalid_sequence[] = <span class=
- "literal">"a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z"</span>;
- vector<<span class="keyword">char</span>> replace_invalid_result;
- replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), back_inserter(replace_invalid_result), <span
- class="literal">'?'</span>);
- bvalid = is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
- assert (bvalid);
- <span class="keyword">char</span>* fixed_invalid_sequence = <span class=
- "literal">"a????z"</span>;
- assert (std::equal(replace_invalid_result.begin(), replace_invalid_result.end(), fixed_invalid_sequence));
- </pre>
- <p>
- <code>replace_invalid</code> does not perform in-place replacement of invalid
- sequences. Rather, it produces a copy of the original string with the invalid
- sequences replaced with a replacement marker. Therefore, <code>out</code> must not
- be in the <code>[start, end]</code> range.
- </p>
- <p>
- If <code>end</code> does not point to the past-of-end of a UTF-8 sequence, a
- <code>utf8::not_enough_room</code> exception is thrown.
- </p>
- <h4>
- utf8::starts_with_bom
- </h4>
- <p class="version">
- Available in version 2.3 and later. Relaces deprecated <code>is_bom()</code> function.
- </p>
- <p>
- Checks whether an octet sequence starts with a UTF-8 byte order mark (BOM)
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- <span class="keyword">bool</span> starts_with_bom (octet_iterator it, octet_iterator end);
- </pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>it</code>: beginning of the octet sequence to check<br>
- <code>end</code>: pass-end of the sequence to check<br>
- <span class="return_value">Return value</span>: <code>true</code> if the sequence
- starts with a UTF-8 byte order mark; <code>false</code> if not.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">unsigned char</span> byte_order_mark[] = {<span class=
- "literal">0xef</span>, <span class="literal">0xbb</span>, <span class=
- "literal">0xbf</span>};
- <span class="keyword">bool</span> bbom = starts_with_bom(byte_order_mark, byte_order_mark + <span class="keyword">sizeof</span>(byte_order_mark));
- assert (bbom == <span class="literal">true</span>);
- </pre>
- <p>
- The typical use of this function is to check the first three bytes of a file. If
- they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8
- encoded text.
- </p>
- <h4>
- utf8::is_bom
- </h4>
- <p class="version">
- Available in version 1.0 and later. Deprecated in version 2.3. <code>starts_with_bom()</code> should be used
- instead.
- </p>
- <p>
- Checks whether a sequence of three octets is a UTF-8 byte order mark (BOM)
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- <span class="keyword">bool</span> is_bom (octet_iterator it); <span class="comment"> // Deprecated</span>
- </pre>
- <p>
- <code>octet_iterator</code>: an input iterator.<br>
- <code>it</code>: beginning of the 3-octet sequence to check<br>
- <span class="return_value">Return value</span>: <code>true</code> if the sequence
- is UTF-8 byte order mark; <code>false</code> if not.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">unsigned char</span> byte_order_mark[] = {<span class=
- "literal">0xef</span>, <span class="literal">0xbb</span>, <span class=
- "literal">0xbf</span>};
- <span class="keyword">bool</span> bbom = is_bom(byte_order_mark);
- assert (bbom == <span class="literal">true</span>);
- </pre>
- <p>
- The typical use of this function is to check the first three bytes of a file. If
- they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8
- encoded text.
- </p>
- <p>
- If a sequence is
- shorter than three bytes, an invalid iterator will be dereferenced. Therefore, this function is deprecated
- in favor of <code>starts_with_bom()</code>that takes the end of sequence as an argument.
- </p>
- <h3 id="typesutf8">
- Types From utf8 Namespace
- </h3>
- <h4>utf8::exception
- </h4>
- <p class="version">
- Available in version 2.3 and later.
- </p>
- <p>
- Base class for the exceptions thrown by UTF CPP library functions.
- </p>
- <pre>
- <span class="keyword">class</span> exception : <span class="keyword">public</span> std::exception {};
- </pre>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">try</span> {
- code_that_uses_utf_cpp_library();
- }
- <span class="keyword">catch</span>(<span class="keyword">const</span> utf8::exception& utfcpp_ex) {
- cerr << utfcpp_ex.what();
- }
- </pre>
-
- <h4>utf8::invalid_code_point
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Thrown by UTF8 CPP functions such as <code>advance</code> and <code>next</code> if an UTF-8 sequence represents and invalid code point.
- </p>
- <pre>
- <span class="keyword">class</span> invalid_code_point : <span class="keyword">public</span> exception {
- <span class="keyword">public</span>:
- uint32_t code_point() <span class="keyword">const</span>;
- };
- </pre>
- <p>
- Member function <code>code_point()</code> can be used to determine the invalid code point that
- caused the exception to be thrown.
- </p>
- <h4>utf8::invalid_utf8
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Thrown by UTF8 CPP functions such as <code>next</code> and <code>prior</code> if an invalid UTF-8 sequence
- is detected during decoding.
- </p>
- <pre>
- <span class="keyword">class</span> invalid_utf8 : <span class="keyword">public</span> exception {
- <span class="keyword">public</span>:
- uint8_t utf8_octet() <span class="keyword">const</span>;
- };
- </pre>
- <p>
- Member function <code>utf8_octet()</code> can be used to determine the beginning of the byte
- sequence that caused the exception to be thrown.
- </p>
- </pre>
- <h4>utf8::invalid_utf16
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Thrown by UTF8 CPP function <code>utf16to8</code> if an invalid UTF-16 sequence
- is detected during decoding.
- </p>
- <pre>
- <span class="keyword">class</span> invalid_utf16 : <span class="keyword">public</span> exception {
- <span class="keyword">public</span>:
- uint16_t utf16_word() <span class="keyword">const</span>;
- };
- </pre>
- <p>
- Member function <code>utf16_word()</code> can be used to determine the UTF-16 code unit
- that caused the exception to be thrown.
- </p>
- <h4>utf8::not_enough_room
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Thrown by UTF8 CPP functions such as <code>next</code> if the end of the decoded UTF-8 sequence
- was reached before the code point was decoded.
- </p>
- <pre>
- <span class="keyword">class</span> not_enough_room : <span class="keyword">public</span> exception {};
- </pre>
- <h4>
- utf8::iterator
- </h4>
- <p class="version">
- Available in version 2.0 and later.
- </p>
- <p>
- Adapts the underlying octet iterator to iterate over the sequence of code points,
- rather than raw octets.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class="keyword">typename</span> octet_iterator>
- <span class="keyword">class</span> iterator;
- </pre>
-
- <h5>Member functions</h5>
- <dl>
- <dt><code>iterator();</code> <dd> the deafult constructor; the underlying <code>octet_iterator</code> is
- constructed with its default constructor.
- <dt><code><span class="keyword">explicit</span> iterator (const octet_iterator& octet_it,
- const octet_iterator& range_start,
- const octet_iterator& range_end);</code> <dd> a constructor
- that initializes the underlying <code>octet_iterator</code> with <code>octet_it</code>
- and sets the range in which the iterator is considered valid.
- <dt><code>octet_iterator base () <span class="keyword">const</span>;</code> <dd> returns the
- underlying <code>octet_iterator</code>.
- <dt><code>uint32_t operator * () <span class="keyword">const</span>;</code> <dd> decodes the utf-8 sequence
- the underlying <code>octet_iterator</code> is pointing to and returns the code point.
- <dt><code><span class="keyword">bool operator</span> == (const iterator& rhs)
- <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
- if the two underlaying iterators are equal.
- <dt><code><span class="keyword">bool operator</span> != (const iterator& rhs)
- <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
- if the two underlaying iterators are not equal.
- <dt><code>iterator& <span class="keyword">operator</span> ++ (); </code> <dd> the prefix increment - moves
- the iterator to the next UTF-8 encoded code point.
- <dt><code>iterator <span class="keyword">operator</span> ++ (<span class="keyword">int</span>); </code> <dd>
- the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
- <dt><code>iterator& <span class="keyword">operator</span> -- (); </code> <dd> the prefix decrement - moves
- the iterator to the previous UTF-8 encoded code point.
- <dt><code>iterator <span class="keyword">operator</span> -- (<span class="keyword">int</span>); </code> <dd>
- the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
- </dl>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* threechars = <span class="literal">"\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88"</span>;
- utf8::iterator<<span class="keyword">char</span>*> it(threechars, threechars, threechars + <span class="literal">9</span>);
- utf8::iterator<<span class="keyword">char</span>*> it2 = it;
- assert (it2 == it);
- assert (*it == <span class="literal">0x10346</span>);
- assert (*(++it) == <span class="literal">0x65e5</span>);
- assert ((*it++) == <span class="literal">0x65e5</span>);
- assert (*it == <span class="literal">0x0448</span>);
- assert (it != it2);
- utf8::iterator<<span class="keyword">char</span>*> endit (threechars + <span class="literal">9</span>, threechars, threechars + <span class="literal">9</span>);
- assert (++it == endit);
- assert (*(--it) == <span class="literal">0x0448</span>);
- assert ((*it--) == <span class="literal">0x0448</span>);
- assert (*it == <span class="literal">0x65e5</span>);
- assert (--it == utf8::iterator<<span class="keyword">char</span>*>(threechars, threechars, threechars + <span class="literal">9</span>));
- assert (*it == <span class="literal">0x10346</span>);
- </pre>
- <p>
- The purpose of <code>utf8::iterator</code> adapter is to enable easy iteration as well as the use of STL
- algorithms with UTF-8 encoded strings. Increment and decrement operators are implemented in terms of
- <code>utf8::next()</code> and <code>utf8::prior()</code> functions.
- </p>
- <p>
- Note that <code>utf8::iterator</code> adapter is a checked iterator. It operates on the range specified in
- the constructor; any attempt to go out of that range will result in an exception. Even the comparison operators
- require both iterator object to be constructed against the same range - otherwise an exception is thrown. Typically,
- the range will be determined by sequence container functions <code>begin</code> and <code>end</code>, i.e.:
- </p>
- <pre>
- std::string s = <span class="literal">"example"</span>;
- utf8::iterator i (s.begin(), s.begin(), s.end());
- </pre>
- <h3 id="fununchecked">
- Functions From utf8::unchecked Namespace
- </h3>
- <h4>
- utf8::unchecked::append
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence
- to a UTF-8 string.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- octet_iterator append(uint32_t cp, octet_iterator result);
-
- </pre>
- <p>
- <code>cp</code>: A 32 bit integer representing a code point to append to the
- sequence.<br>
- <code>result</code>: An output iterator to the place in the sequence where to
- append the code point.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the newly appended sequence.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">unsigned char</span> u[<span class="literal">5</span>] = {<span
- class="literal">0</span>,<span class="literal">0</span>,<span class=
- "literal">0</span>,<span class="literal">0</span>,<span class="literal">0</span>};
- <span class="keyword">unsigned char</span>* end = unchecked::append(<span class=
- "literal">0x0448</span>, u);
- assert (u[<span class="literal">0</span>] == <span class=
- "literal">0xd1</span> && u[<span class="literal">1</span>] == <span class=
- "literal">0x88</span> && u[<span class="literal">2</span>] == <span class=
- "literal">0</span> && u[<span class="literal">3</span>] == <span class=
- "literal">0</span> && u[<span class="literal">4</span>] == <span class=
- "literal">0</span>);
- </pre>
- <p>
- This is a faster but less safe version of <code>utf8::append</code>. It does not
- check for validity of the supplied code point, and may produce an invalid UTF-8
- sequence.
- </p>
- <h4>
- utf8::unchecked::next
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Given the iterator to the beginning of a UTF-8 sequence, it returns the code point
- and moves the iterator to the next position.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- uint32_t next(octet_iterator& it);
-
- </pre>
- <p>
- <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
- encoded code point. After the function returns, it is incremented to point to the
- beginning of the next code point.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- processed UTF-8 code point.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- <span class="keyword">char</span>* w = twochars;
- <span class="keyword">int</span> cp = unchecked::next(w);
- assert (cp == <span class="literal">0x65e5</span>);
- assert (w == twochars + <span class="literal">3</span>);
- </pre>
- <p>
- This is a faster but less safe version of <code>utf8::next</code>. It does not
- check for validity of the supplied UTF-8 sequence.
- </p>
- <h4>
- utf8::unchecked::peek_next
- </h4>
- <p class="version">
- Available in version 2.1 and later.
- </p>
- <p>
- Given the iterator to the beginning of a UTF-8 sequence, it returns the code point.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- uint32_t peek_next(octet_iterator it);
-
- </pre>
- <p>
- <code>it</code>: an iterator pointing to the beginning of an UTF-8
- encoded code point.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- processed UTF-8 code point.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- <span class="keyword">char</span>* w = twochars;
- <span class="keyword">int</span> cp = unchecked::peek_next(w);
- assert (cp == <span class="literal">0x65e5</span>);
- assert (w == twochars);
- </pre>
- <p>
- This is a faster but less safe version of <code>utf8::peek_next</code>. It does not
- check for validity of the supplied UTF-8 sequence.
- </p>
- <h4>
- utf8::unchecked::prior
- </h4>
- <p class="version">
- Available in version 1.02 and later.
- </p>
- <p>
- Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
- decreases the iterator until it hits the beginning of the previous UTF-8 encoded
- code point and returns the 32 bits representation of the code point.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- uint32_t prior(octet_iterator& it);
-
- </pre>
- <p>
- <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
- After the function returns, it is decremented to point to the beginning of the
- previous code point.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- previous code point.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- <span class="keyword">char</span>* w = twochars + <span class="literal">3</span>;
- <span class="keyword">int</span> cp = unchecked::prior (w);
- assert (cp == <span class="literal">0x65e5</span>);
- assert (w == twochars);
- </pre>
- <p>
- This is a faster but less safe version of <code>utf8::prior</code>. It does not
- check for validity of the supplied UTF-8 sequence and offers no boundary checking.
- </p>
- <h4>
- utf8::unchecked::previous (deprecated, see utf8::unchecked::prior)
- </h4>
- <p class="version">
- Deprecated in version 1.02 and later.
- </p>
- <p>
- Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it
- decreases the iterator until it hits the beginning of the previous UTF-8 encoded
- code point and returns the 32 bits representation of the code point.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- uint32_t previous(octet_iterator& it);
-
- </pre>
- <p>
- <code>it</code>: a reference pointing to an octet within a UTF-8 encoded string.
- After the function returns, it is decremented to point to the beginning of the
- previous code point.<br>
- <span class="return_value">Return value</span>: the 32 bit representation of the
- previous code point.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- <span class="keyword">char</span>* w = twochars + <span class="literal">3</span>;
- <span class="keyword">int</span> cp = unchecked::previous (w);
- assert (cp == <span class="literal">0x65e5</span>);
- assert (w == twochars);
- </pre>
- <p>
- The reason this function is deprecated is just the consistency with the "checked"
- versions, where <code>prior</code> should be used instead of <code>previous</code>.
- In fact, <code>unchecked::previous</code> behaves exactly the same as <code>
- unchecked::prior</code>
- </p>
- <p>
- This is a faster but less safe version of <code>utf8::previous</code>. It does not
- check for validity of the supplied UTF-8 sequence and offers no boundary checking.
- </p>
- <h4>
- utf8::unchecked::advance
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Advances an iterator by the specified number of code points within an UTF-8
- sequence.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator, typename distance_type>
- <span class="keyword">void</span> advance (octet_iterator& it, distance_type n);
-
- </pre>
- <p>
- <code>it</code>: a reference to an iterator pointing to the beginning of an UTF-8
- encoded code point. After the function returns, it is incremented to point to the
- nth following code point.<br>
- <code>n</code>: a positive integer that shows how many code points we want to
- advance.<br>
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- <span class="keyword">char</span>* w = twochars;
- unchecked::advance (w, <span class="literal">2</span>);
- assert (w == twochars + <span class="literal">5</span>);
- </pre>
- <p>
- This function works only "forward". In case of a negative <code>n</code>, there is
- no effect.
- </p>
- <p>
- This is a faster but less safe version of <code>utf8::advance</code>. It does not
- check for validity of the supplied UTF-8 sequence and offers no boundary checking.
- </p>
- <h4>
- utf8::unchecked::distance
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Given the iterators to two UTF-8 encoded code points in a seqence, returns the
- number of code points between them.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator>
- <span class=
- "keyword">typename</span> std::iterator_traits<octet_iterator>::difference_type distance (octet_iterator first, octet_iterator last);
- </pre>
- <p>
- <code>first</code>: an iterator to a beginning of a UTF-8 encoded code point.<br>
- <code>last</code>: an iterator to a "post-end" of the last UTF-8 encoded code
- point in the sequence we are trying to determine the length. It can be the
- beginning of a new code point, or not.<br>
- <span class="return_value">Return value</span> the distance between the iterators,
- in code points.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- size_t dist = utf8::unchecked::distance(twochars, twochars + <span class=
- "literal">5</span>);
- assert (dist == <span class="literal">2</span>);
- </pre>
- <p>
- This is a faster but less safe version of <code>utf8::distance</code>. It does not
- check for validity of the supplied UTF-8 sequence.
- </p>
- <h4>
- utf8::unchecked::utf16to8
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts a UTF-16 encoded string to UTF-8.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> u16bit_iterator, <span class=
- "keyword">typename</span> octet_iterator>
- octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
-
- </pre>
- <p>
- <code>start</code>: an iterator pointing to the beginning of the UTF-16 encoded
- string to convert.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-16 encoded
- string to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-8 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-8 string.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">unsigned short</span> utf16string[] = {<span class=
- "literal">0x41</span>, <span class="literal">0x0448</span>, <span class=
- "literal">0x65e5</span>, <span class="literal">0xd834</span>, <span class=
- "literal">0xdd1e</span>};
- vector<<span class="keyword">unsigned char</span>> utf8result;
- unchecked::utf16to8(utf16string, utf16string + <span class=
- "literal">5</span>, back_inserter(utf8result));
- assert (utf8result.size() == <span class="literal">10</span>);
- </pre>
- <p>
- This is a faster but less safe version of <code>utf8::utf16to8</code>. It does not
- check for validity of the supplied UTF-16 sequence.
- </p>
- <h4>
- utf8::unchecked::utf8to16
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts an UTF-8 encoded string to UTF-16
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> u16bit_iterator, typename octet_iterator>
- u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
-
- </pre>
- <p>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
- string to convert. < br /> <code>end</code>: an iterator pointing to
- pass-the-end of the UTF-8 encoded string to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-16 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-16 string.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span> utf8_with_surrogates[] = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e"</span>;
- vector <<span class="keyword">unsigned short</span>> utf16result;
- unchecked::utf8to16(utf8_with_surrogates, utf8_with_surrogates + <span class=
- "literal">9</span>, back_inserter(utf16result));
- assert (utf16result.size() == <span class="literal">4</span>);
- assert (utf16result[<span class="literal">2</span>] == <span class=
- "literal">0xd834</span>);
- assert (utf16result[<span class="literal">3</span>] == <span class=
- "literal">0xdd1e</span>);
- </pre>
- <p>
- This is a faster but less safe version of <code>utf8::utf8to16</code>. It does not
- check for validity of the supplied UTF-8 sequence.
- </p>
- <h4>
- utf8::unchecked::utf32to8
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts a UTF-32 encoded string to UTF-8.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator, <span class=
- "keyword">typename</span> u32bit_iterator>
- octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
-
- </pre>
- <p>
- <code>start</code>: an iterator pointing to the beginning of the UTF-32 encoded
- string to convert.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-32 encoded
- string to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-8 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-8 string.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">int</span> utf32string[] = {<span class=
- "literal">0x448</span>, <span class="literal">0x65e5</span>, <span class=
- "literal">0x10346</span>, <span class="literal">0</span>};
- vector<<span class="keyword">unsigned char</span>> utf8result;
- utf32to8(utf32string, utf32string + <span class=
- "literal">3</span>, back_inserter(utf8result));
- assert (utf8result.size() == <span class="literal">9</span>);
- </pre>
- <p>
- This is a faster but less safe version of <code>utf8::utf32to8</code>. It does not
- check for validity of the supplied UTF-32 sequence.
- </p>
- <h4>
- utf8::unchecked::utf8to32
- </h4>
- <p class="version">
- Available in version 1.0 and later.
- </p>
- <p>
- Converts a UTF-8 encoded string to UTF-32.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class=
- "keyword">typename</span> octet_iterator, typename u32bit_iterator>
- u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
-
- </pre>
- <p>
- <code>start</code>: an iterator pointing to the beginning of the UTF-8 encoded
- string to convert.<br>
- <code>end</code>: an iterator pointing to pass-the-end of the UTF-8 encoded string
- to convert.<br>
- <code>result</code>: an output iterator to the place in the UTF-32 string where to
- append the result of conversion.<br>
- <span class="return_value">Return value</span>: An iterator pointing to the place
- after the appended UTF-32 string.
- </p>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* twochars = <span class=
- "literal">"\xe6\x97\xa5\xd1\x88"</span>;
- vector<<span class="keyword">int</span>> utf32result;
- unchecked::utf8to32(twochars, twochars + <span class=
- "literal">5</span>, back_inserter(utf32result));
- assert (utf32result.size() == <span class="literal">2</span>);
- </pre>
- <p>
- This is a faster but less safe version of <code>utf8::utf8to32</code>. It does not
- check for validity of the supplied UTF-8 sequence.
- </p>
- <h3 id="typesunchecked">
- Types From utf8::unchecked Namespace
- </h3>
- <h4>
- utf8::iterator
- </h4>
- <p class="version">
- Available in version 2.0 and later.
- </p>
- <p>
- Adapts the underlying octet iterator to iterate over the sequence of code points,
- rather than raw octets.
- </p>
- <pre>
- <span class="keyword">template</span> <<span class="keyword">typename</span> octet_iterator>
- <span class="keyword">class</span> iterator;
- </pre>
-
- <h5>Member functions</h5>
- <dl>
- <dt><code>iterator();</code> <dd> the deafult constructor; the underlying <code>octet_iterator</code> is
- constructed with its default constructor.
- <dt><code><span class="keyword">explicit</span> iterator (const octet_iterator& octet_it);
- </code> <dd> a constructor
- that initializes the underlying <code>octet_iterator</code> with <code>octet_it</code>
- <dt><code>octet_iterator base () <span class="keyword">const</span>;</code> <dd> returns the
- underlying <code>octet_iterator</code>.
- <dt><code>uint32_t operator * () <span class="keyword">const</span>;</code> <dd> decodes the utf-8 sequence
- the underlying <code>octet_iterator</code> is pointing to and returns the code point.
- <dt><code><span class="keyword">bool operator</span> == (const iterator& rhs)
- <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
- if the two underlaying iterators are equal.
- <dt><code><span class="keyword">bool operator</span> != (const iterator& rhs)
- <span class="keyword">const</span>;</code> <dd> returns <span class="keyword">true</span>
- if the two underlaying iterators are not equal.
- <dt><code>iterator& <span class="keyword">operator</span> ++ (); </code> <dd> the prefix increment - moves
- the iterator to the next UTF-8 encoded code point.
- <dt><code>iterator <span class="keyword">operator</span> ++ (<span class="keyword">int</span>); </code> <dd>
- the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
- <dt><code>iterator& <span class="keyword">operator</span> -- (); </code> <dd> the prefix decrement - moves
- the iterator to the previous UTF-8 encoded code point.
- <dt><code>iterator <span class="keyword">operator</span> -- (<span class="keyword">int</span>); </code> <dd>
- the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
- </dl>
- <p>
- Example of use:
- </p>
- <pre>
- <span class="keyword">char</span>* threechars = <span class="literal">"\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88"</span>;
- utf8::unchecked::iterator<<span class="keyword">char</span>*> un_it(threechars);
- utf8::unchecked::iterator<<span class="keyword">char</span>*> un_it2 = un_it;
- assert (un_it2 == un_it);
- assert (*un_it == <span class="literal">0x10346</span>);
- assert (*(++un_it) == <span class="literal">0x65e5</span>);
- assert ((*un_it++) == <span class="literal">0x65e5</span>);
- assert (*un_it == <span class="literal">0x0448</span>);
- assert (un_it != un_it2);
- utf8::::unchecked::iterator<<span class="keyword">char</span>*> un_endit (threechars + <span class="literal">9</span>);
- assert (++un_it == un_endit);
- assert (*(--un_it) == <span class="literal">0x0448</span>);
- assert ((*un_it--) == <span class="literal">0x0448</span>);
- assert (*un_it == <span class="literal">0x65e5</span>);
- assert (--un_it == utf8::unchecked::iterator<<span class="keyword">char</span>*>(threechars));
- assert (*un_it == <span class="literal">0x10346</span>);
- </pre>
- <p>
- This is an unchecked version of <code>utf8::iterator</code>. It is faster in many cases, but offers
- no validity or range checks.
- </p>
- <h2 id="points">
- Points of interest
- </h2>
- <h4>
- Design goals and decisions
- </h4>
- <p>
- The library was designed to be:
- </p>
- <ol>
- <li>
- Generic: for better or worse, there are many C++ string classes out there, and
- the library should work with as many of them as possible.
- </li>
- <li>
- Portable: the library should be portable both accross different platforms and
- compilers. The only non-portable code is a small section that declares unsigned
- integers of different sizes: three typedefs. They can be changed by the users of
- the library if they don't match their platform. The default setting should work
- for Windows (both 32 and 64 bit), and most 32 bit and 64 bit Unix derivatives.
- </li>
- <li>
- Lightweight: follow the "pay only for what you use" guideline.
- </li>
- <li>
- Unintrusive: avoid forcing any particular design or even programming style on the
- user. This is a library, not a framework.
- </li>
- </ol>
- <h4>
- Alternatives
- </h4>
- <p>
- In case you want to look into other means of working with UTF-8 strings from C++,
- here is the list of solutions I am aware of:
- </p>
- <ol>
- <li>
- <a href="http://icu.sourceforge.net/">ICU Library</a>. It is very powerful,
- complete, feature-rich, mature, and widely used. Also big, intrusive,
- non-generic, and doesn't play well with the Standard Library. I definitelly
- recommend looking at ICU even if you don't plan to use it.
- </li>
- <li>
- C++11 language and library features. Still far from complete, and not widely
- supported by compiler vendors.
- </li>
- <li>
- <a href=
- "http://www.gtkmm.org/gtkmm2/docs/tutorial/html/ch03s04.html">Glib::ustring</a>.
- A class specifically made to work with UTF-8 strings, and also feel like
- <code>std::string</code>. If you prefer to have yet another string class in your
- code, it may be worth a look. Be aware of the licensing issues, though.
- </li>
- <li>
- Platform dependent solutions: Windows and POSIX have functions to convert strings
- from one encoding to another. That is only a subset of what my library offers,
- but if that is all you need it may be good enough.
- </li>
- </ol>
- <h2 id="links">
- Links
- </h2>
- <ol>
- <li>
- <a href="http://www.unicode.org/">The Unicode Consortium</a>.
- </li>
- <li>
- <a href="http://icu.sourceforge.net/">ICU Library</a>.
- </li>
- <li>
- <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8 at Wikipedia</a>
- </li>
- <li>
- <a href="http://www.cl.cam.ac.uk/~mgk25/unicode.html">UTF-8 and Unicode FAQ for
- Unix/Linux</a>
- </li>
- </ol>
- </body>
- </html>
|