77c267b49e
git-svn-id: http://svn.code.sf.net/p/utfcpp/code@71 a809a056-fc17-0410-9590-b4f493f8b08e
1102 lines
43 KiB
HTML
1102 lines
43 KiB
HTML
<!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>
|
|
Boost UTF8
|
|
</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;
|
|
}
|
|
-->
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<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>
|
|
</li>
|
|
<li>
|
|
<a href="#reference">Reference</a>
|
|
</li>
|
|
<li>
|
|
<a href="#points">Points of Interest</a>
|
|
</li>
|
|
<li>
|
|
<a href="#conclusion">Conclusion</a>
|
|
</li>
|
|
<li>
|
|
<a href="#references">References</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<h2 id="introduction">
|
|
Introduction
|
|
</h2>
|
|
<p>
|
|
Many C++ developers miss an easy and portable way of handling Unicode encoded
|
|
strings. C++ Standard is currently Unicode agnostic, and while some work is being
|
|
done to introduce Unicode to the next incarnation called C++0x, for the moment
|
|
nothing of the sort is available. In the meantime, developers use 3rd 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 have come up with a set
|
|
of template functions. For anybody used to work with STL algorithms, they 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>
|
|
<p>
|
|
To illustrate the use of Boost UTF8 library, we shall open a file containing UTF-8
|
|
encoded text, check whether it starts with a byte order mark, read each line into a
|
|
<code>std::string</code>, check it for validity, convert the text to UTF-16, 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 <boost/utf8.hpp></span>
|
|
|
|
<span class="keyword">using namespace</span> std;
|
|
<span class="keyword">using namespace</span> boost;
|
|
|
|
<span class="keyword">int</span> main()
|
|
{
|
|
<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 (must be UTF-8 encoded)</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="comment">// Read the first line of the file</span>
|
|
<span class="keyword">unsigned</span> line_count = <span class="literal">1</span>;
|
|
string line;
|
|
<span class="keyword">if</span> (!getline(fs8, line))
|
|
<span class="keyword">return</span> <span class="literal">0</span>;
|
|
<span class="comment">// Look for utf-8 byte-order mark at the beginning</span>
|
|
<span class="keyword">if</span> (line.size() > <span class="literal">2</span>) {
|
|
<span class="keyword">if</span> (utf8::is_bom(line.c_str()))
|
|
cout << <span class=
|
|
"literal">"There is a byte order mark at the beginning of the file\n"</span>;
|
|
}
|
|
<span class="comment">// Play with all the lines in the file</span>
|
|
<span class="keyword">do</span> {
|
|
<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>;
|
|
getline(fs8, line);
|
|
line_count++;
|
|
} <span class="keyword">while</span> (!fs8.eof());
|
|
<span class="keyword">return</span> <span class="literal">0</span>;
|
|
}
|
|
</pre>
|
|
<p>
|
|
In the previous code sample, we have seen the use of the following functions from
|
|
<code>utf8</code> namespace: first we used <code>is_bom</code> function to detect
|
|
UTF-8 byte order mark at the beginning of the file; then 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) 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>
|
|
<h2 id="reference">
|
|
Reference
|
|
</h2>
|
|
<h3>
|
|
Functions From utf8 Namespace
|
|
</h3>
|
|
<h4>
|
|
utf8::append
|
|
</h4>
|
|
<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 = 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>
|
|
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>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::prior
|
|
</h4>
|
|
<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, octet_iterator start);
|
|
|
|
</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>
|
|
<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.
|
|
</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>pass_end</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>
|
|
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>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>
|
|
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::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>
|
|
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;
|
|
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>
|
|
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;
|
|
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>
|
|
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>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>
|
|
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>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>
|
|
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>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>
|
|
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>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::is_bom
|
|
</h4>
|
|
<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);
|
|
</pre>
|
|
<p>
|
|
<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>
|
|
<h3>
|
|
Functions From utf8::unchecked Namespace
|
|
</h3>
|
|
<h4>
|
|
utf8::unchecked::append
|
|
</h4>
|
|
<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>
|
|
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::prior
|
|
</h4>
|
|
<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::advance
|
|
</h4>
|
|
<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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
<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" guidline.
|
|
</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>
|
|
<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, especially given the fact that
|
|
these functions are mature and tested in production.
|
|
</li>
|
|
</ol>
|
|
<h2 id="conclusion">
|
|
Conclusion
|
|
</h2>
|
|
<p>
|
|
Until Unicode becomes officially recognized by the C++ Standard Library, we need to
|
|
use other means to work with UTF-8 strings. Template functions I describe in this
|
|
article may be a good step in this direction.
|
|
</p>
|
|
<h2 id="references">
|
|
References
|
|
</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>
|