diff options
author | Alex Zolotarev <deathbaba@gmail.com> | 2010-12-05 19:24:16 +0300 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-22 22:33:57 +0300 |
commit | d6e12b7ce4bcbf0ccd1c07eb25de143422913c34 (patch) | |
tree | a7e910c330ce4da9b4f2d8be76067adece2561c4 /3party/utfcpp |
One Month In Minsk. Made in Belarus.
Diffstat (limited to '3party/utfcpp')
-rw-r--r-- | 3party/utfcpp/doc/ReleaseNotes | 9 | ||||
-rw-r--r-- | 3party/utfcpp/doc/utf8cpp.html | 1629 | ||||
-rw-r--r-- | 3party/utfcpp/source/utf8.h | 34 | ||||
-rw-r--r-- | 3party/utfcpp/source/utf8/checked.h | 319 | ||||
-rw-r--r-- | 3party/utfcpp/source/utf8/core.h | 346 | ||||
-rw-r--r-- | 3party/utfcpp/source/utf8/unchecked.h | 228 |
6 files changed, 2565 insertions, 0 deletions
diff --git a/3party/utfcpp/doc/ReleaseNotes b/3party/utfcpp/doc/ReleaseNotes new file mode 100644 index 0000000000..857a72b756 --- /dev/null +++ b/3party/utfcpp/doc/ReleaseNotes @@ -0,0 +1,9 @@ +utf8 cpp library +Release 2.2.4 + +This is a minor bug fix release that improves converting from utf-16 to utf-8 error detection. + +Changes from version 2.2.3 +- Bug fix [2857454] dereference invalid iterator when lead surrogate was last element of the string. + +Files included in the release: utf8.h, core.h, checked.h, unchecked.h, utf8cpp.html, ReleaseNotes diff --git a/3party/utfcpp/doc/utf8cpp.html b/3party/utfcpp/doc/utf8cpp.html new file mode 100644 index 0000000000..069c2be521 --- /dev/null +++ b/3party/utfcpp/doc/utf8cpp.html @@ -0,0 +1,1629 @@ +<!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> + </li> + <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="#conclusion">Conclusion</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, + 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 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>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>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>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 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::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>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_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 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>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>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>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>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>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>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>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>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>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::is_bom + </h4> + <p class="version"> + Available in version 1.0 and later. + </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); +</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 id="typesutf8"> + Types From utf8 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, + 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" 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="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> diff --git a/3party/utfcpp/source/utf8.h b/3party/utfcpp/source/utf8.h new file mode 100644 index 0000000000..82b13f59f9 --- /dev/null +++ b/3party/utfcpp/source/utf8.h @@ -0,0 +1,34 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "utf8/checked.h" +#include "utf8/unchecked.h" + +#endif // header guard diff --git a/3party/utfcpp/source/utf8/checked.h b/3party/utfcpp/source/utf8/checked.h new file mode 100644 index 0000000000..ff75eb7892 --- /dev/null +++ b/3party/utfcpp/source/utf8/checked.h @@ -0,0 +1,319 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" +#include <stdexcept> + +namespace utf8 +{ + // Exceptions that may be thrown from the library functions. + class invalid_code_point : public std::exception { + uint32_t cp; + public: + invalid_code_point(uint32_t cp) : cp(cp) {} + virtual const char* what() const throw() { return "Invalid code point"; } + uint32_t code_point() const {return cp;} + }; + + class invalid_utf8 : public std::exception { + uint8_t u8; + public: + invalid_utf8 (uint8_t u) : u8(u) {} + virtual const char* what() const throw() { return "Invalid UTF-8"; } + uint8_t utf8_octet() const {return u8;} + }; + + class invalid_utf16 : public std::exception { + uint16_t u16; + public: + invalid_utf16 (uint16_t u) : u16(u) {} + virtual const char* what() const throw() { return "Invalid UTF-16"; } + uint16_t utf16_word() const {return u16;} + }; + + class not_enough_room : public std::exception { + public: + virtual const char* what() const throw() { return "Not enough space"; } + }; + + /// The library API - functions intended to be called by the users + + template <typename octet_iterator, typename output_iterator> + output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) + { + while (start != end) { + octet_iterator sequence_start = start; + internal::utf_error err_code = internal::validate_next(start, end); + switch (err_code) { + case internal::UTF8_OK : + for (octet_iterator it = sequence_start; it != start; ++it) + *out++ = *it; + break; + case internal::NOT_ENOUGH_ROOM: + throw not_enough_room(); + case internal::INVALID_LEAD: + append (replacement, out); + ++start; + break; + case internal::INCOMPLETE_SEQUENCE: + case internal::OVERLONG_SEQUENCE: + case internal::INVALID_CODE_POINT: + append (replacement, out); + ++start; + // just one replacement mark for the sequence + while (internal::is_trail(*start) && start != end) + ++start; + break; + } + } + return out; + } + + template <typename octet_iterator, typename output_iterator> + inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) + { + static const uint32_t replacement_marker = internal::mask16(0xfffd); + return replace_invalid(start, end, out, replacement_marker); + } + + template <typename octet_iterator> + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (!internal::is_code_point_valid(cp)) + throw invalid_code_point(cp); + + if (cp < 0x80) // one octet + *(result++) = static_cast<uint8_t>(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0); + *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0); + *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); + } + else { // four octets + *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0); + *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80); + *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); + } + return result; + } + + template <typename octet_iterator> + uint32_t next(octet_iterator& it, octet_iterator end) + { + uint32_t cp = 0; + internal::utf_error err_code = internal::validate_next(it, end, &cp); + switch (err_code) { + case internal::UTF8_OK : + break; + case internal::NOT_ENOUGH_ROOM : + throw not_enough_room(); + case internal::INVALID_LEAD : + case internal::INCOMPLETE_SEQUENCE : + case internal::OVERLONG_SEQUENCE : + throw invalid_utf8(*it); + case internal::INVALID_CODE_POINT : + throw invalid_code_point(cp); + } + return cp; + } + + template <typename octet_iterator> + uint32_t peek_next(octet_iterator it, octet_iterator end) + { + return next(it, end); + } + + template <typename octet_iterator> + uint32_t prior(octet_iterator& it, octet_iterator start) + { + octet_iterator end = it; + while (internal::is_trail(*(--it))) + if (it < start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + octet_iterator temp = it; + return next(temp, end); + } + + /// Deprecated in versions that include "prior" + template <typename octet_iterator> + uint32_t previous(octet_iterator& it, octet_iterator pass_start) + { + octet_iterator end = it; + while (internal::is_trail(*(--it))) + if (it == pass_start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + octet_iterator temp = it; + return next(temp, end); + } + + template <typename octet_iterator, typename distance_type> + void advance (octet_iterator& it, distance_type n, octet_iterator end) + { + for (distance_type i = 0; i < n; ++i) + next(it, end); + } + + template <typename octet_iterator> + typename std::iterator_traits<octet_iterator>::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits<octet_iterator>::difference_type dist; + for (dist = 0; first < last; ++dist) + next(first, last); + return dist; + } + + template <typename u16bit_iterator, typename octet_iterator> + octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = internal::mask16(*start++); + // Take care of surrogate pairs first + if (internal::is_lead_surrogate(cp)) { + if (start != end) { + uint32_t trail_surrogate = internal::mask16(*start++); + if (internal::is_trail_surrogate(trail_surrogate)) + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + else + throw invalid_utf16(static_cast<uint16_t>(trail_surrogate)); + } + else + throw invalid_utf16(static_cast<uint16_t>(cp)); + + } + // Lone trail surrogate + else if (internal::is_trail_surrogate(cp)) + throw invalid_utf16(static_cast<uint16_t>(cp)); + + result = append(cp, result); + } + return result; + } + + template <typename u16bit_iterator, typename octet_iterator> + u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + { + while (start != end) { + uint32_t cp = next(start, end); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast<uint16_t>(cp); + } + return result; + } + + template <typename octet_iterator, typename u32bit_iterator> + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = append(*(start++), result); + + return result; + } + + template <typename octet_iterator, typename u32bit_iterator> + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start < end) + (*result++) = next(start, end); + + return result; + } + + // The iterator class + template <typename octet_iterator> + class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> { + octet_iterator it; + octet_iterator range_start; + octet_iterator range_end; + public: + iterator () {}; + explicit iterator (const octet_iterator& octet_it, + const octet_iterator& range_start, + const octet_iterator& range_end) : + it(octet_it), range_start(range_start), range_end(range_end) + { + if (it < range_start || it > range_end) + throw std::out_of_range("Invalid utf-8 iterator position"); + } + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return next(temp, range_end); + } + bool operator == (const iterator& rhs) const + { + if (range_start != rhs.range_start || range_end != rhs.range_end) + throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + next(it, range_end); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + next(it, range_end); + return temp; + } + iterator& operator -- () + { + prior(it, range_start); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + prior(it, range_start); + return temp; + } + }; // class iterator + +} // namespace utf8 + +#endif //header guard + + diff --git a/3party/utfcpp/source/utf8/core.h b/3party/utfcpp/source/utf8/core.h new file mode 100644 index 0000000000..5a55f0655c --- /dev/null +++ b/3party/utfcpp/source/utf8/core.h @@ -0,0 +1,346 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include <iterator> + +namespace utf8 +{ + // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers + // You may need to change them to match your system. + // These typedefs have the same names as ones from cstdint, or boost/cstdint + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; + +// Helper code - not intended to be directly called by the library users. May be changed at any time +namespace internal +{ + // Unicode constants + // Leading (high) surrogates: 0xd800 - 0xdbff + // Trailing (low) surrogates: 0xdc00 - 0xdfff + const uint16_t LEAD_SURROGATE_MIN = 0xd800u; + const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; + const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; + const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; + const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); + const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; + + // Maximum valid value for a Unicode code point + const uint32_t CODE_POINT_MAX = 0x0010ffffu; + + template<typename octet_type> + inline uint8_t mask8(octet_type oc) + { + return static_cast<uint8_t>(0xff & oc); + } + template<typename u16_type> + inline uint16_t mask16(u16_type oc) + { + return static_cast<uint16_t>(0xffff & oc); + } + template<typename octet_type> + inline bool is_trail(octet_type oc) + { + return ((mask8(oc) >> 6) == 0x2); + } + + template <typename u16> + inline bool is_lead_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); + } + + template <typename u16> + inline bool is_trail_surrogate(u16 cp) + { + return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template <typename u16> + inline bool is_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template <typename u32> + inline bool is_code_point_valid(u32 cp) + { + return (cp <= CODE_POINT_MAX && !is_surrogate(cp) && cp != 0xfffe && cp != 0xffff); + } + + template <typename octet_iterator> + inline typename std::iterator_traits<octet_iterator>::difference_type + sequence_length(octet_iterator lead_it) + { + uint8_t lead = mask8(*lead_it); + if (lead < 0x80) + return 1; + else if ((lead >> 5) == 0x6) + return 2; + else if ((lead >> 4) == 0xe) + return 3; + else if ((lead >> 3) == 0x1e) + return 4; + else + return 0; + } + + inline bool is_overlong_sequence(uint32_t cp, int length) + { + if (cp < 0x80) { + if (length != 1) + return true; + } + else if (cp < 0x800) { + if (length != 2) + return true; + } + else if (cp < 0x10000) { + if (length != 3) + return true; + } + + return false; + } + + enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; + + /// get_sequence_x functions decode utf-8 sequences of the length x + + template <typename octet_iterator> + utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t* code_point) + { + if (it != end) { + if (code_point) + *code_point = mask8(*it); + return UTF8_OK; + } + return NOT_ENOUGH_ROOM; + } + + template <typename octet_iterator> + utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t* code_point) + { + utf_error ret_code = NOT_ENOUGH_ROOM; + + if (it != end) { + uint32_t cp = mask8(*it); + if (++it != end) { + if (is_trail(*it)) { + cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); + + if (code_point) + *code_point = cp; + ret_code = UTF8_OK; + } + else + ret_code = INCOMPLETE_SEQUENCE; + } + else + ret_code = NOT_ENOUGH_ROOM; + } + + return ret_code; + } + + template <typename octet_iterator> + utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t* code_point) + { + utf_error ret_code = NOT_ENOUGH_ROOM; + + if (it != end) { + uint32_t cp = mask8(*it); + if (++it != end) { + if (is_trail(*it)) { + cp = ((cp << 12) & 0xffff) + ((mask8(*it) << 6) & 0xfff); + if (++it != end) { + if (is_trail(*it)) { + cp += (*it) & 0x3f; + + if (code_point) + *code_point = cp; + ret_code = UTF8_OK; + } + else + ret_code = INCOMPLETE_SEQUENCE; + } + else + ret_code = NOT_ENOUGH_ROOM; + } + else + ret_code = INCOMPLETE_SEQUENCE; + } + else + ret_code = NOT_ENOUGH_ROOM; + } + + return ret_code; + } + + template <typename octet_iterator> + utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t* code_point) + { + utf_error ret_code = NOT_ENOUGH_ROOM; + + if (it != end) { + uint32_t cp = mask8(*it); + if (++it != end) { + if (is_trail(*it)) { + cp = ((cp << 18) & 0x1fffff) + ((mask8(*it) << 12) & 0x3ffff); + if (++it != end) { + if (is_trail(*it)) { + cp += (mask8(*it) << 6) & 0xfff; + if (++it != end) { + if (is_trail(*it)) { + cp += (*it) & 0x3f; + + if (code_point) + *code_point = cp; + ret_code = UTF8_OK; + } + else + ret_code = INCOMPLETE_SEQUENCE; + } + else + ret_code = NOT_ENOUGH_ROOM; + } + else + ret_code = INCOMPLETE_SEQUENCE; + } + else + ret_code = NOT_ENOUGH_ROOM; + } + else + ret_code = INCOMPLETE_SEQUENCE; + } + else + ret_code = NOT_ENOUGH_ROOM; + } + + return ret_code; + } + + template <typename octet_iterator> + utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t* code_point) + { + // Save the original value of it so we can go back in case of failure + // Of course, it does not make much sense with i.e. stream iterators + octet_iterator original_it = it; + + uint32_t cp = 0; + // Determine the sequence length based on the lead octet + typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type; + octet_difference_type length = sequence_length(it); + if (length == 0) + return INVALID_LEAD; + + // Now that we have a valid sequence length, get trail octets and calculate the code point + utf_error err = UTF8_OK; + switch (length) { + case 1: + err = get_sequence_1(it, end, &cp); + break; + case 2: + err = get_sequence_2(it, end, &cp); + break; + case 3: + err = get_sequence_3(it, end, &cp); + break; + case 4: + err = get_sequence_4(it, end, &cp); + break; + } + + if (err == UTF8_OK) { + // Decoding succeeded. Now, security checks... + if (is_code_point_valid(cp)) { + if (!is_overlong_sequence(cp, length)){ + // Passed! Return here. + if (code_point) + *code_point = cp; + ++it; + return UTF8_OK; + } + else + err = OVERLONG_SEQUENCE; + } + else + err = INVALID_CODE_POINT; + } + + // Failure branch - restore the original value of the iterator + it = original_it; + return err; + } + + template <typename octet_iterator> + inline utf_error validate_next(octet_iterator& it, octet_iterator end) { + return validate_next(it, end, 0); + } + +} // namespace internal + + /// The library API - functions intended to be called by the users + + // Byte order mark + const uint8_t bom[] = {0xef, 0xbb, 0xbf}; + + template <typename octet_iterator> + octet_iterator find_invalid(octet_iterator start, octet_iterator end) + { + octet_iterator result = start; + while (result != end) { + internal::utf_error err_code = internal::validate_next(result, end); + if (err_code != internal::UTF8_OK) + return result; + } + return result; + } + + template <typename octet_iterator> + inline bool is_valid(octet_iterator start, octet_iterator end) + { + return (find_invalid(start, end) == end); + } + + template <typename octet_iterator> + inline bool is_bom (octet_iterator it) + { + return ( + (internal::mask8(*it++)) == bom[0] && + (internal::mask8(*it++)) == bom[1] && + (internal::mask8(*it)) == bom[2] + ); + } +} // namespace utf8 + +#endif // header guard + + diff --git a/3party/utfcpp/source/utf8/unchecked.h b/3party/utfcpp/source/utf8/unchecked.h new file mode 100644 index 0000000000..d3110cb88e --- /dev/null +++ b/3party/utfcpp/source/utf8/unchecked.h @@ -0,0 +1,228 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" + +namespace utf8 +{ + namespace unchecked + { + template <typename octet_iterator> + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (cp < 0x80) // one octet + *(result++) = static_cast<uint8_t>(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0); + *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0); + *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); + } + else { // four octets + *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0); + *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80); + *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); + } + return result; + } + + template <typename octet_iterator> + uint32_t next(octet_iterator& it) + { + uint32_t cp = internal::mask8(*it); + typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it); + switch (length) { + case 1: + break; + case 2: + it++; + cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); + break; + case 3: + ++it; + cp = ((cp << 12) & 0xffff) + ((internal::mask8(*it) << 6) & 0xfff); + ++it; + cp += (*it) & 0x3f; + break; + case 4: + ++it; + cp = ((cp << 18) & 0x1fffff) + ((internal::mask8(*it) << 12) & 0x3ffff); + ++it; + cp += (internal::mask8(*it) << 6) & 0xfff; + ++it; + cp += (*it) & 0x3f; + break; + } + ++it; + return cp; + } + + template <typename octet_iterator> + uint32_t peek_next(octet_iterator it) + { + return next(it); + } + + template <typename octet_iterator> + uint32_t prior(octet_iterator& it) + { + while (internal::is_trail(*(--it))) ; + octet_iterator temp = it; + return next(temp); + } + + // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous) + template <typename octet_iterator> + inline uint32_t previous(octet_iterator& it) + { + return prior(it); + } + + template <typename octet_iterator, typename distance_type> + void advance (octet_iterator& it, distance_type n) + { + for (distance_type i = 0; i < n; ++i) + next(it); + } + + template <typename octet_iterator> + typename std::iterator_traits<octet_iterator>::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits<octet_iterator>::difference_type dist; + for (dist = 0; first < last; ++dist) + next(first); + return dist; + } + + template <typename u16bit_iterator, typename octet_iterator> + octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = internal::mask16(*start++); + // Take care of surrogate pairs first + if (internal::is_lead_surrogate(cp)) { + uint32_t trail_surrogate = internal::mask16(*start++); + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + } + result = append(cp, result); + } + return result; + } + + template <typename u16bit_iterator, typename octet_iterator> + u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + { + while (start != end) { + uint32_t cp = next(start); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast<uint16_t>(cp); + } + return result; + } + + template <typename octet_iterator, typename u32bit_iterator> + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = append(*(start++), result); + + return result; + } + + template <typename octet_iterator, typename u32bit_iterator> + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start < end) + (*result++) = next(start); + + return result; + } + + // The iterator class + template <typename octet_iterator> + class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> { + octet_iterator it; + public: + iterator () {}; + explicit iterator (const octet_iterator& octet_it): it(octet_it) {} + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return next(temp); + } + bool operator == (const iterator& rhs) const + { + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + std::advance(it, internal::sequence_length(it)); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + std::advance(it, internal::sequence_length(it)); + return temp; + } + iterator& operator -- () + { + prior(it); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + prior(it); + return temp; + } + }; // class iterator + + } // namespace utf8::unchecked +} // namespace utf8 + + +#endif // header guard + |