{"action":"created","comment":{"url":"https://api.github.com/repos/hoaproject/String/pulls/comments/22759154","id":22759154,"diff_hunk":"@@ -3,8 +3,608 @@\n <overlay xmlns=\"http://hoa-project.net/xyl/xylophone\">\n <yield id=\"chapter\">\n \n-  <p class=\"warning\">This chapter is not yet translated. Contributions are\n-  welcomed!</p>\n+  <p>Strings can sometimes be <strong>complex</strong>, especially when they use\n+  the <code>Unicode</code> encoding format. The <code>Hoa\\String</code> library\n+  provides several operations on UTF-8 strings.</p>\n+\n+  <h2 id=\"Table_of_contents\">Table of contents</h2>\n+\n+  <tableofcontents id=\"main-toc\" />\n+\n+  <h2 id=\"Introduction\" for=\"main-toc\">Introduction</h2>\n+\n+  <p>When we manipulate strings, the <a href=\"http://unicode.org/\">Unicode</a>\n+  format establishes itself because of its <strong>compatibility</strong> with\n+  historical formats (like ASCII) and its capacity to understand a\n+  <strong>large</strong> range of characters and symbols for all cultures and\n+  all regions in the world. PHP provides several tools to manipulate such\n+  strings, like the following extensions:\n+  <a href=\"http://php.net/mbstring\"><code>mbstring</code></a>,\n+  <a href=\"http://php.net/iconv\"><code>iconv</code></a> or also the excellent\n+  <a href=\"http://php.net/intl\"><code>intl</code></a>  which is based on\n+  <a href=\"http://icu-project.org/\">ICU</a>, the reference implementation of\n+  Unicode. Unfortunately, sometimes we have to mix these extensions to achieve\n+  our aims and at the cost of a certain <strong>complexity</strong> along with\n+  a regrettable <strong>verbosity</strong>.</p>\n+  <p>The <code>Hoa\\String</code> library answers to these issues by providing a\n+  <strong>simple</strong> way to manipulate strings with\n+  <strong>performance</strong> and <strong>efficiency</strong> in minds. It\n+  also provides some evoluated algorithms to perform <strong>search</strong>\n+  operations on strings.</p>\n+\n+  <h2 id=\"Unicode_strings\" for=\"main-toc\">Unicode strings</h2>\n+\n+  <p>The <code>Hoa\\String\\String</code> class represents a\n+  <strong>UTF-8</strong> Unicode strings and allows to manipulate it easily.\n+  This class implements the\n+  <a href=\"http://php.net/arrayaccess\"><code>ArrayAccess</code></a>,\n+  <a href=\"http://php.net/countable\"><code>Countable</code></a> and\n+  <a href=\"http://php.net/iteratoraggregate\"><code>IteratorAggregate</code></a>\n+  interfaces. We are going to use three examples in three different languages:\n+  French, Arab and Japanese. Thus:</p>\n+  <pre><code class=\"language-php\">$french   = new Hoa\\String\\String('Je t\\'aime');\n+$arabic   = new Hoa\\String\\String('أحبك');\n+$japanese = new Hoa\\String\\String('私はあなたを愛して');</code></pre>\n+  <p>Now, let's see what we can do on these three strings.</p>\n+\n+  <h3 id=\"String_manipulation\" for=\"main-toc\">String manipulation</h3>\n+\n+  <p>Let's start with <strong>elementary</strong> operations. If we would like\n+  to <strong>count</strong> the number of characters (not bytes), we will use\n+  the <a href=\"http://php.net/count\"><code>count</code> function</a>. Thus:</p>\n+  <pre><code class=\"language-php\">var_dump(\n+    count($french),\n+    count($arabic),\n+    count($japanese)\n+);\n+\n+/**\n+ * Will output:\n+ *     int(9)\n+ *     int(4)\n+ *     int(9)\n+ */</code></pre>\n+  <p>When we speak about text position, it is not suitable to speak about the\n+  right or the left, but rather about a <strong>beginning</strong> or an\n+  <strong>end</strong>, and based on the <strong>direction</strong> of writing.\n+  We can know this direction thanks to the\n+  <code>Hoa\\String\\String::getDirection</code> method. It returns the value of\n+  one of the following constants:</p>\n+  <ul>\n+    <li><code>Hoa\\String\\String::LTR</code>, for left-to-right, if the text is\n+    written from the left to the right,</li>\n+    <li><code>Hoa\\String\\String::RTL</code>, for right-to-left, if the text is\n+    written from the right to the left.</li>\n+  </ul>\n+  <p>Let's observe the result with our examples:</p>\n+  <pre><code class=\"language-php\">var_dump(\n+    $french->getDirection()   === Hoa\\String\\String::LTR, // is left-to-right?\n+    $arabic->getDirection()   === Hoa\\String\\String::RTL, // is right-to-left?\n+    $japanese->getDirection() === Hoa\\String\\String::LTR  // is left-to-right?\n+);\n+\n+/**\n+ * Will output:\n+ *     bool(true)\n+ *     bool(true)\n+ *     bool(true)\n+ */</code></pre>\n+  <p>The result of this method is computed thanks to the\n+  <code>Hoa\\String\\String::getCharDirection</code> static method which computes\n+  the direction of only one character.</p>\n+  <p>If we would like to <strong>concatenate</strong> another string to the end\n+  or to the beginning, we will respectively use the\n+  <code>Hoa\\String\\String::append</code> and\n+  <code>Hoa\\String\\String::prepend</code> methods. These methods, like most of\n+  the ones which modifies the string, return the object itself, in order to\n+  chain the calls. For instance:</p>\n+  <pre><code class=\"language-php\">echo $french->append('… et toi, m\\'aimes-tu ?')->prepend('Mam\\'zelle ! ');\n+\n+/**\n+ * Will output:\n+ *     Mam'zelle ! Je t'aime… et toi, m'aimes-tu ?\n+ */</code></pre>\n+  <p>We also have the <code>Hoa\\String\\String::toLowerCase</code> and\n+  <code>Hoa\\String\\String::toUpperCase</code> methods to, respectively, set the\n+  case of the string to lower or upper. For instance:</p>\n+  <pre><code class=\"language-php\">echo $french->toUpperCase();\n+\n+/**\n+ * Will output:\n+ *     MAM'ZELLE ! JE T'AIME… ET TOI, M'AIMES-TU ?\n+ */</code></pre>\n+  <p>We can also add characters to the beginning or to the end of the string to\n+  reach a <strong>minimum</strong> length. This operation is frequently called\n+  the <em>padding</em> (for historical reasons dating back to typewriters).\n+  That's why we have the <code>Hoa\\String\\String::pad</code> method which takes\n+  three arguments: the minimum length, characters to add and a constant\n+  indicating whether we have to add at the end or at the beginning of the string\n+  (respectively <code>Hoa\\String\\String::END</code>, by default, and\n+  <code>Hoa\\String\\String::BEGINNING</code>).</p>\n+  <pre><code class=\"language-php\">echo $arabic->pad(20, ' ');\n+\n+/**\n+ * Will output:\n+ *                     أحبك\n+ */</code></pre>\n+  <p>A similar operation allows to remove, by default, <strong>spaces</strong>\n+  at the beginning and at the end of the string thanks to the\n+  <code>Hoa\\String\\String::trim</code> method. For example, to retreive our\n+  original Arabic string:</p>\n+  <pre><code class=\"language-php\">echo $arabic->trim();\n+\n+/**\n+ * Will output:\n+ *     أحبك\n+ */</code></pre>\n+  <p>If we would like to remove other characters, we can use its first argument\n+  which must be a regular expression. Finally, its second argument allows to\n+  specify from what side we would like to remove character: at the beginning, at\n+  the end or both, still by using the <code>Hoa\\String\\String::BEGINNING</code>\n+  and <code>Hoa\\String\\String::END</code> constants.</p>\n+  <p>If we would like to remove other characters, we can use its first argument\n+  which must be an regular expression. Finally, its second argument allows to\n+  specify the side where to remove characters: at the beginning, at the end or\n+  both, still by using the <code>Hoa\\String\\String::BEGINNING</code> and\n+  <code>Hoa\\String\\String::END</code> constants. We can combine these constants\n+  to express “both sides”, which is the default value:\n+  <code class=\"language-php\">Hoa\\String\\String::BEGINNING |\n+  Hoa\\String\\String::END</code>. For example, to remove all the numbers and the\n+  spaces only at the end, we will write:</p>\n+  <pre><code class=\"language-php\">$arabic->trim('\\s|\\d', Hoa\\String\\String::END);</code></pre>\n+  <p>We can also <strong>reduce</strong> the string to a\n+  <strong>sub-string</strong> by specifying the position of the first character\n+  followed by the length of the sub-string to the\n+  <code>Hoa\\String\\String::reduce</code> method:</p>\n+  <pre><code class=\"language-php\">echo $french->reduce(3, 6)->reduce(2, 4);\n+\n+/**\n+ * Will output:\n+ *     aime\n+ */</code></pre>\n+  <p>If we would like to get a specific character, we can rely on the\n+  <code>ArrayAccess</code> interface. For instance, to get the first character\n+  of each of our examples (from their original definitions):</p>\n+  <pre><code class=\"language-php\">var_dump(\n+    $french[0],\n+    $arabic[0],\n+    $japanese[0]\n+);\n+\n+/**\n+ * Will output:\n+ *     string(1) \"J\"\n+ *     string(2) \"أ\"\n+ *     string(3) \"私\"\n+ */</code></pre>\n+  <p>If we would like the last character, we will use the -1 index. The index is\n+  not bounded to the length of the string. If the index exceeds this length,\n+  then a <em>modulo</em> will be applied.</p>\n+  <p>We can also modify or remove a specific character with this method. For\n+  example:</p>\n+  <pre><code class=\"language-php\">$french->append(' ?');\n+$french[-1] = '!';\n+echo $french;\n+\n+/**\n+ * Will output:\n+ *     Je t'aime !\n+ */</code></pre>\n+  <p>Another very useful method is the <strong>ASCII</strong> transformation.\n+  Be careful, this is not always possible, according to your settings. For\n+  example:</p>\n+  <pre><code class=\"language-php\">$title = new Hoa\\String\\String('Un été brûlant sur la côte');\n+echo $title->toAscii();\n+\n+/**\n+ * Will output:\n+ *     Un ete brulant sur la cote\n+ */</code></pre>\n+  <p>We can also transform from Arabic or Japanese to ASCII. Symbols, like\n+  Mathemetical symbols or emojis, are also transformed:</p>\n+  <pre><code class=\"language-php\">$emoji = new Hoa\\String\\String('I ❤ Unicode');\n+$maths = new Hoa\\String\\String('∀ i ∈ ℕ');\n+\n+echo $arabic->toAscii(), \"\\n\",\n+     $japanese->toAscii(), \"\\n\",\n+     $emoji->toAscii(), \"\\n\",\n+     $maths->toAscii(), \"\\n\";\n+\n+/**\n+ * Will output:\n+ *     ahbk\n+ *     sihaanatawo aishite\n+ *     I (heavy black heart)️ Unicode\n+ *     (for all) i (element of) N\n+ */</code></pre>\n+  <p>In order this method to work correctly, the\n+  <a href=\"http://php.net/intl\"><code>intl</code></a> extension needs to be\n+  present, so that the\n+  <a href=\"http://php.net/transliterator\"><code>Transliterator</code></a> class\n+  is present. If it does not exist, the\n+  <a href=\"http://php.net/normalizer\"><code>Normalizer</code></a> class must\n+  exist. If this class does not exist neither, the\n+  <code>Hoa\\String\\String::toAscii</code> method can still try a transformation,\n+  but it is less efficient. To activate this last solution, <code>true</code>\n+  must be passed as a single argument. This <em lang=\"fr\">tour de force</em> is\n+  not recommended in most cases.</p>\n+  <p>We also find the <code>getTransliterator</code> method which returns a\n+  <code>Transliterator</code> object, or <code>null</code> if this class does\n+  not exist. This method takes a transliteration identifier as argument. We\n+  suggest to <a href=\"http://userguide.icu-project.org/transforms/general\">read\n+  the documentation about the transliterator of ICU</a> to understand this\n+  identifier. The <code>transliterate</code> method allows to transliterate the\n+  current string based on an identifier and a beginning index and an end\n+  one. This method works the same way than the\n+  <a href=\"http://php.net/transliterator.transliterate\"><code>Transliterator::transliterate</code></a>\n+  method.</p>\n+  <p>More generally, to change the <strong>encoding</strong> format, we can use\n+  the <code>Hoa\\String\\String::transcode</code> static method, with a string as\n+  first argument, the original encoding format as second argument and the\n+  expected encoding format as third argument (UTF-8 by default). The get the\n+  list of encoding formats, we have to refer to the\n+  <a href=\"http://php.net/iconv\"><code>iconv</code></a> extension or to use the\n+  following command line in a terminal:</p>\n+  <pre><code class=\"language-php\">$ iconv --list</code></pre>\n+  <p>To know if a string is encoded in UTF-8, we can use the\n+  <code>Hoa\\String\\String::isUtf8</code> static method; for instance:</p>\n+  <pre><code class=\"language-php\">var_dump(\n+    Hoa\\String\\String::isUtf8('a'),\n+    Hoa\\String\\String::isUtf8(Hoa\\String\\String::transcode('a', 'UTF-8', 'UTF-16'))\n+);\n+\n+/**\n+ * Will output:\n+ *     bool(true)\n+ *     bool(false)\n+ */</code></pre>\n+  <p>We can <strong>split</strong> the string into several sub-strings by using\n+  the <code>Hoa\\String\\String::split</code> method. As first argument, we have a\n+  regular expression (of kind <a href=\"http://pcre.org/\">PCRE</a>), then an\n+  integer representing the maximum number of elements to return and finally a\n+  combination of constants. These constants are the same as the ones of\n+  <a href=\"http://php.net/preg_split\"><code>preg_split</code></a>.</p>\n+  <p>By default, the second argument is set to -1, which means infinity, and the\n+  last argument is set to <code>PREG_SPLIT_NO_EMPTY</code>. Thus, if we would\n+  like to get all the words of a string, we will write:</p>\n+  <pre><code class=\"language-php\">print_r($title->split('#\\b|\\s#'));\n+\n+/**\n+ * Will output:\n+ *     Array\n+ *     (\n+ *         [0] => Un\n+ *         [1] => ete\n+ *         [2] => brulant\n+ *         [3] => sur\n+ *         [4] => la\n+ *         [5] => cote\n+ *     )\n+ */</code></pre>\n+  <p>If we would like to <strong>iterate</strong> over all the\n+  <strong>characters</strong>, it is recommended to use the\n+  <code>IteratorAggregate</code> method, being the\n+  <code>Hoa\\String\\String::getIterator</code> method. Let's see on the Arabic\n+  example:</p>\n+  <pre><code class=\"language-php\">foreach($arabic as $letter)\n+    echo $letter, \"\\n\";\n+\n+/**\n+ * Will output:\n+ *     أ\n+ *     ح\n+ *     ب\n+ *     ك\n+ */</code></pre>\n+  <p>We notice that the iteration is based on the text direction, it means that\n+  the first element of the iteration is the first letter of the string starting\n+  from the beginning.</p>\n+  <p>Of course, if we would like to get an array of characters, we can use the\n+  <a href=\"http://php.net/iterator_to_array\"><code>iterator_to_array</code></a>\n+  PHP function:</p>\n+  <pre><code class=\"language-php\">print_r(iterator_to_array($arabic));\n+\n+/**\n+ * Will output:\n+ *     Array\n+ *     (\n+ *         [0] => أ\n+ *         [1] => ح\n+ *         [2] => ب\n+ *         [3] => ك\n+ *     )\n+ */</code></pre>\n+\n+  <h3 id=\"Comparison_and_search\" for=\"main-toc\">Comparison and search</h3>\n+\n+  <p>Strings can also be <strong>compared</strong> thanks to the\n+  <code>Hoa\\String\\String::compare</code> method:</p>\n+  <pre><code class=\"language-php\">$string = new Hoa\\String\\String('abc');\n+var_dump(\n+    $string->compare('wxyz')\n+);\n+\n+/**\n+ * Will output:\n+ *     string(-1)\n+ */</code></pre>\n+  <p>This methods returns -1 if the initial string comes before (in the\n+  alphabetical order), 0 if it is identical and 1 if it comes after. If we\n+  would like to use all the power of the underlying mechanism, we can call the\n+  <code>Hoa\\String\\String::getCollator</code> static method (if the\n+  <a href=\"http://php.net/Collator\"><code>Collator</code></a> class exists, else\n+  <code>Hoa\\String\\String::compare</code> will use a simple byte to bytes\n+  comparison without taking care of the other parameters). Thus, if we would\n+  like to sort an array of strings, we will write:</p>\n+  <pre><code class=\"language-php\">$strings = array('c', 'Σ', 'd', 'x', 'α', 'a');\n+Hoa\\String\\String::getCollator()->sort($strings);\n+print_r($strings);\n+\n+/**\n+ * Could output:\n+ *     Array\n+ *     (\n+ *         [0] => a\n+ *         [1] => c\n+ *         [2] => d\n+ *         [3] => x\n+ *         [4] => α\n+ *         [5] => Σ\n+ *     )\n+ */</code></pre>\n+  <p>Comparison between two strings depends on the <strong>locale</strong>, it\n+  means of the localization of the system, like the language, the country, the\n+  region etc. We can use the\n+  <a href=\"@hack:chapter=Locale\"><code>Hoa\\Locale</code> library</a> to modify\n+  these data, but it's not a dependence of <code>Hoa\\String</code>.</p>\n+  <p>We can also know if a string <strong>matches</strong> a certain pattern,\n+  still expressed with a regular expression. To achieve that, we will use the\n+  <code>Hoa\\String\\String::match</code> method. This method relies on the\n+  <a href=\"http://php.net/preg_match\"><code>preg_match</code></a> and\n+  <a href=\"http://php.net/preg_match_all\"><code>preg_match_all</code></a> PHP\n+  functions, but by modifying the pattern's options to ensure the Unicode\n+  support. We have the following parameters: the pattern, a variable passed by\n+  reference to collect the matches, flags, an offset and finally a boolean\n+  indicating whether the search is global or not (respectively if we have to use\n+  <code>preg_match_all</code> or <code>preg_match</code>). By default, the\n+  search is not global.</p>\n+  <p>Thus, we will check that our French example contains <code>aime</code> with\n+  a direct object complement:</p>\n+  <pre><code class=\"language-php\">$french->match('#(?:(?&amp;lt;direct_object>\\w)[\\'\\b])aime#', $matches);\n+var_dump($matches['direct_object']);\n+\n+/**\n+ * Will output:\n+ *     string(1) \"t\"\n+ */</code></pre>\n+  <p>This method returns <code>false</code> if an error is raised (for example\n+  if the pattern is not correct), 0 if no match has been found, the number of\n+  matches else.</p>\n+  <p>Similarly, we can <strong>search</strong> and <strong>replace</strong>\n+  sub-strings by other sub-strings based on a pattern, still expressed with a\n+  regular expression. To achieve that, we will use the\n+  <code>Hoa\\String\\String::replace</code> method. This method uses the\n+  <a href=\"http://php.net/preg_replace\"><code>preg_replace</code></a> and\n+  <a href=\"http://php.net/preg_replace_callback\"><code>preg_replace_callback</code></a>\n+  PHP functions, but still by modifying the pattern's options to ensure the\n+  Unicode support. As first argument, we find one or more patterns, as second\n+  argument, one or more replacements and as last argument the limit of\n+  replacements to apply. If the replacement is a callable, then the\n+  <code>preg_replace_callback</code> function will be used.</p>\n+  <p>Thus, we will modify our French example to be more polite:</p>\n+  <pre><code class=\"language-php\">$french->replace('#(?:\\w[\\'\\b])(?&amp;lt;verb>aime)#', function ( $matches ) {\n+\n+    return 'vous ' . $matches['verb'];\n+});\n+\n+echo $french;\n+\n+/**\n+ * Will output:\n+ *     Je vous aime\n+ */</code></pre>\n+  <p>The <code>Hoa\\String\\String</code> class provides constants which are\n+  aliases of existing PHP constants and ensure a better readability of the\n+  code:</p>\n+  <ul>\n+    <li><code>Hoa\\String\\String::WITHOUT_EMPTY</code>, alias of\n+    <code>PREG_SPLIT_NO_EMPTY</code>,</li>\n+    <li><code>Hoa\\String\\String::WITH_DELIMITERS</code>, alias of\n+    <code>PREG_SPLIT_DELIM_CAPTURE</code>,</li>\n+    <li><code>Hoa\\String\\String::WITH_OFFSET</code>, alias of\n+    <code>PREG_OFFSET_CAPTURE</code> and\n+    <code>PREG_SPLIT_OFFSET_CAPTURE</code>,</li>\n+    <li><code>Hoa\\String\\String::GROUP_BY_PATTERN</code>, alias of\n+    <code>PREG_PATTERN_ORDER</code>,</li>\n+    <li><code>Hoa\\String\\String::GROUP_BY_TUPLE</code>, alias of\n+    <code>PREG_SET_ORDER</code>.</li>\n+  </ul>\n+  <p>Because they are strict aliases, we can write:</p>\n+  <pre><code class=\"language-php\">$string = new Hoa\\String\\String('abc1 defg2 hikl3 xyz4');\n+$string->match(\n+    '#(\\w+)(\\d)#',\n+    $matches,\n+    Hoa\\String\\String::WITH_OFFSET\n+  | Hoa\\String\\String::GROUP_BY_TUPLE,\n+    0,\n+    true\n+);</code></pre>\n+\n+  <h3 id=\"Characters\" for=\"main-toc\">Characters</h3>\n+\n+  <p>The <code>Hoa\\String\\String</code> class offers static methods working on a\n+  single Unicode character. We have already mentionned the\n+  <code>getCharDirection</code> method which allows to know the\n+  <strong>direction</strong> of a character. We also have the\n+  <code>getCharWidth</code> which counts the <strong>number of columns</strong>\n+  necessary to print a single character. Thus:</p>\n+  <pre><code class=\"language-php\">var_dump(\n+    Hoa\\String\\String::getCharWidth(Hoa\\String\\String::fromCode(0x7f)),\n+    Hoa\\String\\String::getCharWidth('a'),\n+    Hoa\\String\\String::getCharWidth('㽠')\n+);\n+\n+/**\n+ * Will output:\n+ *     int(-1)\n+ *     int(1)\n+ *     int(2)\n+ */</code></pre>\n+  <p>This method returns -1 or 0 if the character is not\n+  <strong>printable</strong> (for instance, if this is a control character, like\n+  <code>0x7f</code> which corresponds to <code>DELETE</code>), 1 or more if this\n+  is a character that can be printed. In our example, <code>㽠</code> requires\n+  2 columns to be printed.</p>\n+  <p>To get more semantics, we have the\n+  <code>Hoa\\String\\String::isCharPrintable</code> method which allows to know\n+  whether a character is printable or not.</p>\n+  <p>If we would like to count the number of columns necessary for a whole\n+  string, we have to use the <code>Hoa\\String\\String::getWidth</code> method.\n+  Thus:</p>\n+  <pre><code class=\"language-php\">var_dump(\n+    $french->getWidth(),\n+    $arabic->getWidth(),\n+    $japanese->getWidth()\n+);\n+\n+/**\n+ * Will output:\n+ *     int(9)\n+ *     int(4)\n+ *     int(18)\n+ */</code></pre>\n+  <p>Try this in your terminal with a <strong>monospaced</strong> font. You will\n+  observe that Japanese requires 18 columns to be printed. This measure is very\n+  useful if we would like to know the length of a string to position it\n+  efficiently.</p>\n+  <p>The <code>getCharWidth</code> method is different of <code>getWidth</code>\n+  because it includes control characters. This method is intended to be used,\n+  for example, with terminals (please, see the\n+  <a href=\"@hack:chapter=Console\"><code>Hoa\\Console</code> library</a>).</p>\n+  <p>Finally, if this time we are not interested by Unicode characters but\n+  rather by <strong>machine</strong> characters <code>char</code> (being\n+  1 byte), we have an extra operation. The\n+  <code>Hoa\\String\\String::getBytesLength</code> method will count the\n+  <strong>length</strong> of the string in bytes:</p>\n+  <pre><code class=\"language-php\">var_dump(\n+    $arabic->getBytesLength(),\n+    $japanese->getBytesLength()\n+);\n+\n+/**\n+ * Will output:\n+ *     int(8)\n+ *     int(27)\n+ */</code></pre>\n+  <p>If we compare these results with the ones of the\n+  <code>Hoa\\String\\String::count</code> method, we understand that the Arabic\n+  characters are encoded with 2 bytes whereas Japanese characteres are encoded\n+  with 3 bytes. We can also get a specific byte thanks to the\n+  <code>Hoa\\String\\String::getByteAt</code> method. Once again, the index is not\n+  bounded.</p>\n+\n+  <h3 id=\"Code-point\" for=\"main-toc\">Code-point</h3>\n+\n+  <p>Each character is represented by an integer, called a\n+  <strong>code-point</strong>. To get the code-point of a character, we can\n+  use the <code>Hoa\\String\\String::toCode</code> static method, and to get a\n+  character based on its code-point, we can use the\n+  <code>Hoa\\String\\String::fromCode</code> static method. We also have the\n+  <code>Hoa\\String\\String::toBinaryCode</code> method which returns the binary\n+  representation of a character. Let's take an example:</p>\n+  <pre><code class=\"language-php\">var_dump(\n+    Hoa\\String\\String::toCode('Σ'),\n+    Hoa\\String\\String::toBinaryCode('Σ'),\n+    Hoa\\String\\String::fromCode(0x1a9)\n+);\n+\n+/**\n+ * Will output:\n+ *     int(931)\n+ *     string(32) \"1100111010100011\"\n+ *     string(2) \"Σ\"\n+ */</code></pre>\n+\n+  <h2 id=\"Search_algorithms\" for=\"main-toc\">Search algorithms</h2>\n+\n+  <p>The <code>Hoa\\String</code> library provides sophisticated\n+  <strong>search</strong> algorithms on strings through the\n+  <code>Hoa\\String\\Search</code> class.</p>\n+  <p>We will study the <code>Hoa\\String\\Search::approximated</code> algorithm\n+  which searches a sub-string in a string up to <strong><em>k</em>\n+  differences</strong> (a difference is an addition, a deletion or a\n+  modification). Let's take the classical example of a DNA representation: We\n+  will search all the sub-strings approximating <code>GATAA</code> with\n+  1 difference (maximum) in <code>CAGATAAGAGAA</code>. So, we will write:</p>\n+  <pre><code class=\"language-php\">$x      = 'GATAA';\n+$y      = 'CAGATAAGAGAA';\n+$k      = 1;\n+$search = Hoa\\String\\Search::approximated($y, $x, $k);\n+$n      = count($search);\n+\n+echo 'Try to match ', $x, ' in ', $y, ' with at most ', $k, ' difference(s):', \"\\n\";\n+echo $n, ' match(es) found:', \"\\n\";\n+\n+foreach($search as $position)\n+    echo '    • ', substr($y, $position['i'], $position['l'), \"\\n\";\n+\n+/**\n+ * Will output:\n+ *     Try to match GATAA in CAGATAAGAGAA with at most 1 difference(s):\n+ *     4 match(es) found:\n+ *         • AGATA\n+ *         • GATAA\n+ *         • ATAAG\n+ *         • GAGAA\n+ */</code></pre>\n+  <p>This methods returns an array of arrays. Each sub-array represents a result\n+  and contains three indexes: <code>i</code> for the position of the first\n+  character (byte) of the result, <code>j</code> for the position of the last\n+  character and <code>l</code> for the length of the result (simply\n+  <code>j</code> - <code>i</code>). Thus, we can compute the results by using\n+  our initial string (here <code class=\"language-php\">$y</code>) and its\n+  indexes.</p>\n+  <p>With our example, we have four results. The first is <code>AGATA</code>,\n+  being <code>GATA<em>A</em></code> with one moved character, and\n+  <code>AGATA</code> exists in <code>C<em>AGATA</em>AGAGAA</code>.  The second\n+  result is <code>GATAA</code>, our sub-string, which well and truly exists in\n+  <code>CA<em>GATAA</em>GAGAA</code>. The third result is <code>ATAAG</code>,\n+  being <code><em>G</em>ATAA</code> with one moved character, and\n+  <code>ATAAG</code> exists in <code>CAG<em>ATAAG</em>AGAA</code>. Finally, the\n+  last result is <code>GAGAA</code>, being <code>GA<em>T</em>AA</code> with one\n+  modified character, and <code>GAGAA</code> exists in\n+  <code>CAGATAA<em>GAGAA</em></code>.</p>\n+  <p>Let's another example, more concrete this time. We will consider the","path":"Documentation/En/Index.xyl","position":577,"original_position":577,"commit_id":"68eef79cbafdf385a0cee9876bba6cc2e6e8d69c","original_commit_id":"68eef79cbafdf385a0cee9876bba6cc2e6e8d69c","user":{"login":"osaris","id":125797,"avatar_url":"https://avatars.githubusercontent.com/u/125797?v=3","gravatar_id":"","url":"https://api.github.com/users/osaris","html_url":"https://github.com/osaris","followers_url":"https://api.github.com/users/osaris/followers","following_url":"https://api.github.com/users/osaris/following{/other_user}","gists_url":"https://api.github.com/users/osaris/gists{/gist_id}","starred_url":"https://api.github.com/users/osaris/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/osaris/subscriptions","organizations_url":"https://api.github.com/users/osaris/orgs","repos_url":"https://api.github.com/users/osaris/repos","events_url":"https://api.github.com/users/osaris/events{/privacy}","received_events_url":"https://api.github.com/users/osaris/received_events","type":"User","site_admin":false},"body":"missing word between let's and another ?","created_at":"2015-01-10T14:06:40Z","updated_at":"2015-01-10T14:06:40Z","html_url":"https://github.com/hoaproject/String/pull/20#discussion_r22759154","pull_request_url":"https://api.github.com/repos/hoaproject/String/pulls/20","_links":{"self":{"href":"https://api.github.com/repos/hoaproject/String/pulls/comments/22759154"},"html":{"href":"https://github.com/hoaproject/String/pull/20#discussion_r22759154"},"pull_request":{"href":"https://api.github.com/repos/hoaproject/String/pulls/20"}}},"pull_request":{"url":"https://api.github.com/repos/hoaproject/String/pulls/20","id":27020821,"html_url":"https://github.com/hoaproject/String/pull/20","diff_url":"https://github.com/hoaproject/String/pull/20.diff","patch_url":"https://github.com/hoaproject/String/pull/20.patch","issue_url":"https://api.github.com/repos/hoaproject/String/issues/20","number":20,"state":"open","locked":false,"title":"Translate documentation into English","user":{"login":"Hywan","id":946104,"avatar_url":"https://avatars.githubusercontent.com/u/946104?v=3","gravatar_id":"","url":"https://api.github.com/users/Hywan","html_url":"https://github.com/Hywan","followers_url":"https://api.github.com/users/Hywan/followers","following_url":"https://api.github.com/users/Hywan/following{/other_user}","gists_url":"https://api.github.com/users/Hywan/gists{/gist_id}","starred_url":"https://api.github.com/users/Hywan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Hywan/subscriptions","organizations_url":"https://api.github.com/users/Hywan/orgs","repos_url":"https://api.github.com/users/Hywan/repos","events_url":"https://api.github.com/users/Hywan/events{/privacy}","received_events_url":"https://api.github.com/users/Hywan/received_events","type":"User","site_admin":false},"body":"Fix #9.","created_at":"2015-01-08T10:59:21Z","updated_at":"2015-01-10T14:06:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":"01efebfca58be75078d187d86a38920888059600","assignee":{"login":"Hywan","id":946104,"avatar_url":"https://avatars.githubusercontent.com/u/946104?v=3","gravatar_id":"","url":"https://api.github.com/users/Hywan","html_url":"https://github.com/Hywan","followers_url":"https://api.github.com/users/Hywan/followers","following_url":"https://api.github.com/users/Hywan/following{/other_user}","gists_url":"https://api.github.com/users/Hywan/gists{/gist_id}","starred_url":"https://api.github.com/users/Hywan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Hywan/subscriptions","organizations_url":"https://api.github.com/users/Hywan/orgs","repos_url":"https://api.github.com/users/Hywan/repos","events_url":"https://api.github.com/users/Hywan/events{/privacy}","received_events_url":"https://api.github.com/users/Hywan/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/hoaproject/String/pulls/20/commits","review_comments_url":"https://api.github.com/repos/hoaproject/String/pulls/20/comments","review_comment_url":"https://api.github.com/repos/hoaproject/String/pulls/comments/{number}","comments_url":"https://api.github.com/repos/hoaproject/String/issues/20/comments","statuses_url":"https://api.github.com/repos/hoaproject/String/statuses/68eef79cbafdf385a0cee9876bba6cc2e6e8d69c","head":{"label":"Hywan:doc_en","ref":"doc_en","sha":"68eef79cbafdf385a0cee9876bba6cc2e6e8d69c","user":{"login":"Hywan","id":946104,"avatar_url":"https://avatars.githubusercontent.com/u/946104?v=3","gravatar_id":"","url":"https://api.github.com/users/Hywan","html_url":"https://github.com/Hywan","followers_url":"https://api.github.com/users/Hywan/followers","following_url":"https://api.github.com/users/Hywan/following{/other_user}","gists_url":"https://api.github.com/users/Hywan/gists{/gist_id}","starred_url":"https://api.github.com/users/Hywan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Hywan/subscriptions","organizations_url":"https://api.github.com/users/Hywan/orgs","repos_url":"https://api.github.com/users/Hywan/repos","events_url":"https://api.github.com/users/Hywan/events{/privacy}","received_events_url":"https://api.github.com/users/Hywan/received_events","type":"User","site_admin":false},"repo":{"id":24115093,"name":"String","full_name":"Hywan/String","owner":{"login":"Hywan","id":946104,"avatar_url":"https://avatars.githubusercontent.com/u/946104?v=3","gravatar_id":"","url":"https://api.github.com/users/Hywan","html_url":"https://github.com/Hywan","followers_url":"https://api.github.com/users/Hywan/followers","following_url":"https://api.github.com/users/Hywan/following{/other_user}","gists_url":"https://api.github.com/users/Hywan/gists{/gist_id}","starred_url":"https://api.github.com/users/Hywan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Hywan/subscriptions","organizations_url":"https://api.github.com/users/Hywan/orgs","repos_url":"https://api.github.com/users/Hywan/repos","events_url":"https://api.github.com/users/Hywan/events{/privacy}","received_events_url":"https://api.github.com/users/Hywan/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Hywan/String","description":"The Hoa\\String library.","fork":true,"url":"https://api.github.com/repos/Hywan/String","forks_url":"https://api.github.com/repos/Hywan/String/forks","keys_url":"https://api.github.com/repos/Hywan/String/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Hywan/String/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Hywan/String/teams","hooks_url":"https://api.github.com/repos/Hywan/String/hooks","issue_events_url":"https://api.github.com/repos/Hywan/String/issues/events{/number}","events_url":"https://api.github.com/repos/Hywan/String/events","assignees_url":"https://api.github.com/repos/Hywan/String/assignees{/user}","branches_url":"https://api.github.com/repos/Hywan/String/branches{/branch}","tags_url":"https://api.github.com/repos/Hywan/String/tags","blobs_url":"https://api.github.com/repos/Hywan/String/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Hywan/String/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Hywan/String/git/refs{/sha}","trees_url":"https://api.github.com/repos/Hywan/String/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Hywan/String/statuses/{sha}","languages_url":"https://api.github.com/repos/Hywan/String/languages","stargazers_url":"https://api.github.com/repos/Hywan/String/stargazers","contributors_url":"https://api.github.com/repos/Hywan/String/contributors","subscribers_url":"https://api.github.com/repos/Hywan/String/subscribers","subscription_url":"https://api.github.com/repos/Hywan/String/subscription","commits_url":"https://api.github.com/repos/Hywan/String/commits{/sha}","git_commits_url":"https://api.github.com/repos/Hywan/String/git/commits{/sha}","comments_url":"https://api.github.com/repos/Hywan/String/comments{/number}","issue_comment_url":"https://api.github.com/repos/Hywan/String/issues/comments/{number}","contents_url":"https://api.github.com/repos/Hywan/String/contents/{+path}","compare_url":"https://api.github.com/repos/Hywan/String/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Hywan/String/merges","archive_url":"https://api.github.com/repos/Hywan/String/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Hywan/String/downloads","issues_url":"https://api.github.com/repos/Hywan/String/issues{/number}","pulls_url":"https://api.github.com/repos/Hywan/String/pulls{/number}","milestones_url":"https://api.github.com/repos/Hywan/String/milestones{/number}","notifications_url":"https://api.github.com/repos/Hywan/String/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Hywan/String/labels{/name}","releases_url":"https://api.github.com/repos/Hywan/String/releases{/id}","created_at":"2014-09-16T19:46:05Z","updated_at":"2014-08-15T16:26:07Z","pushed_at":"2015-01-09T21:53:25Z","git_url":"git://github.com/Hywan/String.git","ssh_url":"git@github.com:Hywan/String.git","clone_url":"https://github.com/Hywan/String.git","svn_url":"https://github.com/Hywan/String","homepage":"http://hoa-project.net/","size":318,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"hoaproject:master","ref":"master","sha":"c3e510b9aaf685e9bba2dcddd7ee23850faddfe4","user":{"login":"hoaproject","id":1519718,"avatar_url":"https://avatars.githubusercontent.com/u/1519718?v=3","gravatar_id":"","url":"https://api.github.com/users/hoaproject","html_url":"https://github.com/hoaproject","followers_url":"https://api.github.com/users/hoaproject/followers","following_url":"https://api.github.com/users/hoaproject/following{/other_user}","gists_url":"https://api.github.com/users/hoaproject/gists{/gist_id}","starred_url":"https://api.github.com/users/hoaproject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hoaproject/subscriptions","organizations_url":"https://api.github.com/users/hoaproject/orgs","repos_url":"https://api.github.com/users/hoaproject/repos","events_url":"https://api.github.com/users/hoaproject/events{/privacy}","received_events_url":"https://api.github.com/users/hoaproject/received_events","type":"Organization","site_admin":false},"repo":{"id":5538851,"name":"String","full_name":"hoaproject/String","owner":{"login":"hoaproject","id":1519718,"avatar_url":"https://avatars.githubusercontent.com/u/1519718?v=3","gravatar_id":"","url":"https://api.github.com/users/hoaproject","html_url":"https://github.com/hoaproject","followers_url":"https://api.github.com/users/hoaproject/followers","following_url":"https://api.github.com/users/hoaproject/following{/other_user}","gists_url":"https://api.github.com/users/hoaproject/gists{/gist_id}","starred_url":"https://api.github.com/users/hoaproject/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hoaproject/subscriptions","organizations_url":"https://api.github.com/users/hoaproject/orgs","repos_url":"https://api.github.com/users/hoaproject/repos","events_url":"https://api.github.com/users/hoaproject/events{/privacy}","received_events_url":"https://api.github.com/users/hoaproject/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hoaproject/String","description":"The Hoa\\String library.","fork":false,"url":"https://api.github.com/repos/hoaproject/String","forks_url":"https://api.github.com/repos/hoaproject/String/forks","keys_url":"https://api.github.com/repos/hoaproject/String/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hoaproject/String/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hoaproject/String/teams","hooks_url":"https://api.github.com/repos/hoaproject/String/hooks","issue_events_url":"https://api.github.com/repos/hoaproject/String/issues/events{/number}","events_url":"https://api.github.com/repos/hoaproject/String/events","assignees_url":"https://api.github.com/repos/hoaproject/String/assignees{/user}","branches_url":"https://api.github.com/repos/hoaproject/String/branches{/branch}","tags_url":"https://api.github.com/repos/hoaproject/String/tags","blobs_url":"https://api.github.com/repos/hoaproject/String/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hoaproject/String/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hoaproject/String/git/refs{/sha}","trees_url":"https://api.github.com/repos/hoaproject/String/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hoaproject/String/statuses/{sha}","languages_url":"https://api.github.com/repos/hoaproject/String/languages","stargazers_url":"https://api.github.com/repos/hoaproject/String/stargazers","contributors_url":"https://api.github.com/repos/hoaproject/String/contributors","subscribers_url":"https://api.github.com/repos/hoaproject/String/subscribers","subscription_url":"https://api.github.com/repos/hoaproject/String/subscription","commits_url":"https://api.github.com/repos/hoaproject/String/commits{/sha}","git_commits_url":"https://api.github.com/repos/hoaproject/String/git/commits{/sha}","comments_url":"https://api.github.com/repos/hoaproject/String/comments{/number}","issue_comment_url":"https://api.github.com/repos/hoaproject/String/issues/comments/{number}","contents_url":"https://api.github.com/repos/hoaproject/String/contents/{+path}","compare_url":"https://api.github.com/repos/hoaproject/String/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hoaproject/String/merges","archive_url":"https://api.github.com/repos/hoaproject/String/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hoaproject/String/downloads","issues_url":"https://api.github.com/repos/hoaproject/String/issues{/number}","pulls_url":"https://api.github.com/repos/hoaproject/String/pulls{/number}","milestones_url":"https://api.github.com/repos/hoaproject/String/milestones{/number}","notifications_url":"https://api.github.com/repos/hoaproject/String/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hoaproject/String/labels{/name}","releases_url":"https://api.github.com/repos/hoaproject/String/releases{/id}","created_at":"2012-08-24T10:31:31Z","updated_at":"2015-01-07T10:01:58Z","pushed_at":"2015-01-07T10:01:57Z","git_url":"git://github.com/hoaproject/String.git","ssh_url":"git@github.com:hoaproject/String.git","clone_url":"https://github.com/hoaproject/String.git","svn_url":"https://github.com/hoaproject/String","homepage":"http://hoa-project.net/","size":636,"stargazers_count":28,"watchers_count":28,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":6,"mirror_url":null,"open_issues_count":5,"forks":6,"open_issues":5,"watchers":28,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/hoaproject/String/pulls/20"},"html":{"href":"https://github.com/hoaproject/String/pull/20"},"issue":{"href":"https://api.github.com/repos/hoaproject/String/issues/20"},"comments":{"href":"https://api.github.com/repos/hoaproject/String/issues/20/comments"},"review_comments":{"href":"https://api.github.com/repos/hoaproject/String/pulls/20/comments"},"review_comment":{"href":"https://api.github.com/repos/hoaproject/String/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/hoaproject/String/pulls/20/commits"},"statuses":{"href":"https://api.github.com/repos/hoaproject/String/statuses/68eef79cbafdf385a0cee9876bba6cc2e6e8d69c"}}}}