From ec6b7ab22b193dc7e5a55f14503cdf0443738680 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 22 Dec 2023 08:08:58 +0000 Subject: [PATCH] Deploy to GitHub pages --- .buildinfo | 4 + .nojekyll | 0 _sources/cpp/dictionary_compiler.rst.txt | 6 + _sources/cpp/index.rst.txt | 6 + _sources/index.rst.txt | 33 + _sources/python/dictionary.rst.txt | 14 + _sources/python/index.rst.txt | 24 + _static/alabaster.css | 703 +++++++++++++++++ _static/basic.css | 925 +++++++++++++++++++++++ _static/custom.css | 1 + _static/doctools.js | 156 ++++ _static/documentation_options.js | 13 + _static/file.png | Bin 0 -> 286 bytes _static/language_data.js | 199 +++++ _static/logo.png | Bin 0 -> 32092 bytes _static/minus.png | Bin 0 -> 90 bytes _static/plus.png | Bin 0 -> 90 bytes _static/pygments.css | 84 ++ _static/searchtools.js | 574 ++++++++++++++ _static/sphinx_highlight.js | 154 ++++ cpp/dictionary_compiler.html | 176 +++++ cpp/index.html | 249 ++++++ genindex.html | 256 +++++++ index.html | 164 ++++ objects.inv | Bin 0 -> 1372 bytes python/dictionary.html | 196 +++++ python/index.html | 235 ++++++ search.html | 141 ++++ searchindex.js | 1 + 29 files changed, 4314 insertions(+) create mode 100644 .buildinfo create mode 100644 .nojekyll create mode 100644 _sources/cpp/dictionary_compiler.rst.txt create mode 100644 _sources/cpp/index.rst.txt create mode 100644 _sources/index.rst.txt create mode 100644 _sources/python/dictionary.rst.txt create mode 100644 _sources/python/index.rst.txt create mode 100644 _static/alabaster.css create mode 100644 _static/basic.css create mode 100644 _static/custom.css create mode 100644 _static/doctools.js create mode 100644 _static/documentation_options.js create mode 100644 _static/file.png create mode 100644 _static/language_data.js create mode 100644 _static/logo.png create mode 100644 _static/minus.png create mode 100644 _static/plus.png create mode 100644 _static/pygments.css create mode 100644 _static/searchtools.js create mode 100644 _static/sphinx_highlight.js create mode 100644 cpp/dictionary_compiler.html create mode 100644 cpp/index.html create mode 100644 genindex.html create mode 100644 index.html create mode 100644 objects.inv create mode 100644 python/dictionary.html create mode 100644 python/index.html create mode 100644 search.html create mode 100644 searchindex.js diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 000000000..ac8ed01fb --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 5f294d9e690338c9631d7c9174ec8464 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/_sources/cpp/dictionary_compiler.rst.txt b/_sources/cpp/dictionary_compiler.rst.txt new file mode 100644 index 000000000..336a3b024 --- /dev/null +++ b/_sources/cpp/dictionary_compiler.rst.txt @@ -0,0 +1,6 @@ +DictionaryCompiler +============================================ + +.. doxygenclass:: keyvi::dictionary::DictionaryCompiler + :project: doxygen_keyvi + :members: diff --git a/_sources/cpp/index.rst.txt b/_sources/cpp/index.rst.txt new file mode 100644 index 000000000..66b496ba5 --- /dev/null +++ b/_sources/cpp/index.rst.txt @@ -0,0 +1,6 @@ +Index +===== + +.. doxygenclass:: keyvi::index::Index + :project: doxygen_keyvi + :members: diff --git a/_sources/index.rst.txt b/_sources/index.rst.txt new file mode 100644 index 000000000..492132977 --- /dev/null +++ b/_sources/index.rst.txt @@ -0,0 +1,33 @@ +.. keyvi documentation master file + +Welcome to keyvi! +================= + +Keyvi - the short form for "Key value index" is a key value store (KVS) optimized for size and lookup speed. The usage +of shared memory makes it scalable and resistant. The biggest difference to other stores is the underlying data +structure based on `finite state machine `_. Storage is very space +efficient, fast and by design makes various sorts of approximate matching be it fuzzy string matching or geo highly +efficient. The immutable FST data structure can be used stand-alone for static datasets. If you need online writes, +you can use keyvi index, a "near realtime index". The index can be used as embedded key value store, e.g. if you +already have a network stack in your application. A out of the box network enabled store is available with +`keyvi-server `_. + +The core of keyvi is written in C++, binding are available for Rust and Python. + + +API Documentation +================= + +.. toctree:: + :maxdepth: 2 + :caption: C++ API + + cpp/dictionary_compiler + cpp/index + +.. toctree:: + :maxdepth: 2 + :caption: Python API + + python/dictionary + python/index diff --git a/_sources/python/dictionary.rst.txt b/_sources/python/dictionary.rst.txt new file mode 100644 index 000000000..de3a4dfbb --- /dev/null +++ b/_sources/python/dictionary.rst.txt @@ -0,0 +1,14 @@ +Dictionary +============================================ + +The Dictionary provides read access to a singkle keyvi file. + +.. code-block:: python + + from keyvi.dictionary import Dictionary + + d=Dictionary("data.kv") + + +.. autoclass:: keyvi.dictionary.Dictionary + :members: diff --git a/_sources/python/index.rst.txt b/_sources/python/index.rst.txt new file mode 100644 index 000000000..08a481d8d --- /dev/null +++ b/_sources/python/index.rst.txt @@ -0,0 +1,24 @@ +Index +===== + +An index is a near-realtime updateable data structure with full CRUD functionality. + + +.. code-block:: python + + from keyvi.index import Index + from keyvi.index import ReadOnlyIndex + + index = Index("/tmp/index-directory") + index.Set("a", "{'b': 3}") + index.Flush() + + ri = ReadOnlyIndex("/tmp/index-directory") + + +.. autoclass:: keyvi.index.Index + :members: + + +.. autoclass:: keyvi.index.ReadOnlyIndex + :members: diff --git a/_static/alabaster.css b/_static/alabaster.css new file mode 100644 index 000000000..c358876e6 --- /dev/null +++ b/_static/alabaster.css @@ -0,0 +1,703 @@ +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Georgia, serif; + font-size: 17px; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 940px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 220px; +} + +div.sphinxsidebar { + width: 220px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 940px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Georgia, serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: Georgia, serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +div.sphinxsidebar .badge { + border-bottom: none; +} + +div.sphinxsidebar .badge:hover { + border-bottom: none; +} + +/* To address an issue with donation coming after search */ +div.sphinxsidebar h3.donation { + margin-top: 10px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Georgia, serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: Georgia, serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #EEE; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + + +/* relbar */ + +.related { + line-height: 30px; + width: 100%; + font-size: 0.9rem; +} + +.related.top { + border-bottom: 1px solid #EEE; + margin-bottom: 20px; +} + +.related.bottom { + border-top: 1px solid #EEE; +} + +.related ul { + padding: 0; + margin: 0; + list-style: none; +} + +.related li { + display: inline; +} + +nav#rellinks { + float: right; +} + +nav#rellinks li+li:before { + content: "|"; +} + +nav#breadcrumbs li+li:before { + content: "\00BB"; +} + +/* Hide certain items when printing */ +@media print { + div.related { + display: none; + } +} \ No newline at end of file diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 000000000..30fee9d0f --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,925 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/_static/custom.css b/_static/custom.css new file mode 100644 index 000000000..2a924f1d6 --- /dev/null +++ b/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 000000000..d06a71d75 --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/_static/documentation_options.js b/_static/documentation_options.js new file mode 100644 index 000000000..7e4c114f2 --- /dev/null +++ b/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/_static/language_data.js b/_static/language_data.js new file mode 100644 index 000000000..250f5665f --- /dev/null +++ b/_static/language_data.js @@ -0,0 +1,199 @@ +/* + * language_data.js + * ~~~~~~~~~~~~~~~~ + * + * This script contains the language-specific data used by searchtools.js, + * namely the list of stopwords, stemmer, scorer and splitter. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; + + +/* Non-minified version is copied as a separate JS file, is available */ + +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/_static/logo.png b/_static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1de638d501d346381ddfb1d04c1f34ef8db19846 GIT binary patch literal 32092 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

M7kC}3KU0S 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 literal 0 HcmV?d00001 diff --git a/_static/minus.png b/_static/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..d96755fdaf8bb2214971e0db9c1fd3077d7c419d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu=nj kDsEF_5m^0CR;1wuP-*O&G^0G}KYk!hp00i_>zopr08q^qX#fBK literal 0 HcmV?d00001 diff --git a/_static/plus.png b/_static/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..7107cec93a979b9a5f64843235a16651d563ce2d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu>-2 m3q%Vub%g%s<8sJhVPMczOq}xhg9DJoz~JfX=d#Wzp$Pyb1r*Kz literal 0 HcmV?d00001 diff --git a/_static/pygments.css b/_static/pygments.css new file mode 100644 index 000000000..57c7df37b --- /dev/null +++ b/_static/pygments.css @@ -0,0 +1,84 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #8f5902; font-style: italic } /* Comment */ +.highlight .err { color: #a40000; border: 1px solid #ef2929 } /* Error */ +.highlight .g { color: #000000 } /* Generic */ +.highlight .k { color: #004461; font-weight: bold } /* Keyword */ +.highlight .l { color: #000000 } /* Literal */ +.highlight .n { color: #000000 } /* Name */ +.highlight .o { color: #582800 } /* Operator */ +.highlight .x { color: #000000 } /* Other */ +.highlight .p { color: #000000; font-weight: bold } /* Punctuation */ +.highlight .ch { color: #8f5902; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #8f5902 } /* Comment.Preproc */ +.highlight .cpf { color: #8f5902; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #8f5902; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #8f5902; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #a40000 } /* Generic.Deleted */ +.highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */ +.highlight .ges { color: #000000 } /* Generic.EmphStrong */ +.highlight .gr { color: #ef2929 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #745334 } /* Generic.Prompt */ +.highlight .gs { color: #000000; font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */ +.highlight .kc { color: #004461; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #004461; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #004461; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #004461; font-weight: bold } /* Keyword.Pseudo */ +.highlight .kr { color: #004461; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #004461; font-weight: bold } /* Keyword.Type */ +.highlight .ld { color: #000000 } /* Literal.Date */ +.highlight .m { color: #990000 } /* Literal.Number */ +.highlight .s { color: #4e9a06 } /* Literal.String */ +.highlight .na { color: #c4a000 } /* Name.Attribute */ +.highlight .nb { color: #004461 } /* Name.Builtin */ +.highlight .nc { color: #000000 } /* Name.Class */ +.highlight .no { color: #000000 } /* Name.Constant */ +.highlight .nd { color: #888888 } /* Name.Decorator */ +.highlight .ni { color: #ce5c00 } /* Name.Entity */ +.highlight .ne { color: #cc0000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #000000 } /* Name.Function */ +.highlight .nl { color: #f57900 } /* Name.Label */ +.highlight .nn { color: #000000 } /* Name.Namespace */ +.highlight .nx { color: #000000 } /* Name.Other */ +.highlight .py { color: #000000 } /* Name.Property */ +.highlight .nt { color: #004461; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #000000 } /* Name.Variable */ +.highlight .ow { color: #004461; font-weight: bold } /* Operator.Word */ +.highlight .pm { color: #000000; font-weight: bold } /* Punctuation.Marker */ +.highlight .w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */ +.highlight .mb { color: #990000 } /* Literal.Number.Bin */ +.highlight .mf { color: #990000 } /* Literal.Number.Float */ +.highlight .mh { color: #990000 } /* Literal.Number.Hex */ +.highlight .mi { color: #990000 } /* Literal.Number.Integer */ +.highlight .mo { color: #990000 } /* Literal.Number.Oct */ +.highlight .sa { color: #4e9a06 } /* Literal.String.Affix */ +.highlight .sb { color: #4e9a06 } /* Literal.String.Backtick */ +.highlight .sc { color: #4e9a06 } /* Literal.String.Char */ +.highlight .dl { color: #4e9a06 } /* Literal.String.Delimiter */ +.highlight .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4e9a06 } /* Literal.String.Double */ +.highlight .se { color: #4e9a06 } /* Literal.String.Escape */ +.highlight .sh { color: #4e9a06 } /* Literal.String.Heredoc */ +.highlight .si { color: #4e9a06 } /* Literal.String.Interpol */ +.highlight .sx { color: #4e9a06 } /* Literal.String.Other */ +.highlight .sr { color: #4e9a06 } /* Literal.String.Regex */ +.highlight .s1 { color: #4e9a06 } /* Literal.String.Single */ +.highlight .ss { color: #4e9a06 } /* Literal.String.Symbol */ +.highlight .bp { color: #3465a4 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #000000 } /* Name.Function.Magic */ +.highlight .vc { color: #000000 } /* Name.Variable.Class */ +.highlight .vg { color: #000000 } /* Name.Variable.Global */ +.highlight .vi { color: #000000 } /* Name.Variable.Instance */ +.highlight .vm { color: #000000 } /* Name.Variable.Magic */ +.highlight .il { color: #990000 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/_static/searchtools.js b/_static/searchtools.js new file mode 100644 index 000000000..7918c3fab --- /dev/null +++ b/_static/searchtools.js @@ -0,0 +1,574 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + } + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms) + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + `Search finished, found ${resultCount} page(s) matching the search query.` + ); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent !== undefined) return docContent.textContent; + console.warn( + "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + /** + * execute search (requires search index to be loaded) + */ + query: (query) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + // array of [docname, title, anchor, descr, score, filename] + let results = []; + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + let score = Math.round(100 * queryLower.length / title.length) + results.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id] of foundEntries) { + let score = Math.round(100 * queryLower.length / entry.length) + results.push([ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // lookup as object + objectTerms.forEach((term) => + results.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort((a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; + }); + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + results = results.reverse(); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord) && !terms[word]) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord) && !titleTerms[word]) + arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); + }); + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + else fileMap.set(file, [word]); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords) => { + const text = Search.htmlToText(htmlText); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/_static/sphinx_highlight.js b/_static/sphinx_highlight.js new file mode 100644 index 000000000..8a96c69a1 --- /dev/null +++ b/_static/sphinx_highlight.js @@ -0,0 +1,154 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore( + span, + parent.insertBefore( + rest, + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '

" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/cpp/dictionary_compiler.html b/cpp/dictionary_compiler.html new file mode 100644 index 000000000..4db3fad37 --- /dev/null +++ b/cpp/dictionary_compiler.html @@ -0,0 +1,176 @@ + + + + + + + + DictionaryCompiler — keyvi documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

DictionaryCompiler

+
+
+template<keyvi::dictionary::fsa::internal::value_store_t ValueStoreType = fsa::internal::value_store_t::KEY_ONLY>
class DictionaryCompiler
+

Dictionary Compiler

+
+
Template Parameters:
+
    +
  • ValueStoreType – The type of the value store to use

  • +
  • N – Array size for fixed size value vectors, ignored otherwise

  • +
+
+
+
+

Public Functions

+
+
+inline explicit DictionaryCompiler(const keyvi::util::parameters_t &params = keyvi::util::parameters_t())
+

Instantiate a dictionary compiler.

+

Note the memory limit only limits the memory used for internal buffers, memory usage for small short-lived objects and the library itself is not part of the limit.

+
+
Parameters:
+

params – compiler parameters

+
+
+
+ +
+
+inline void Compile(callback_t progress_callback = nullptr, void *user_data = nullptr)
+

Do the final compilation

+
+ +
+
+inline void SetManifest(const std::string &manifest)
+

Set a custom manifest to be embedded into the index file.

+
+
Parameters:
+

manifest – as string

+
+
+
+ +
+
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/cpp/index.html b/cpp/index.html new file mode 100644 index 000000000..4bea3b3a9 --- /dev/null +++ b/cpp/index.html @@ -0,0 +1,249 @@ + + + + + + + + Index — keyvi documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Index

+
+
+class Index : public keyvi::index::internal::BaseIndexReader<internal::IndexWriterWorker, internal::Segment>
+
+

Public Functions

+
+
+inline void Set(const std::string &key, const std::string &value)
+

Set key to given value

+
+
Parameters:
+
    +
  • key – the key

  • +
  • value – the value

  • +
+
+
+
+ +
+
+template<typename ContainerType>
inline void MSet(const std::shared_ptr<ContainerType> &key_values)
+

Set multiple keys and to multiple values

+
+
Parameters:
+

key_values – a set of keys and values, the container must implement an iterator where each entry has uses .first for the key and .second for the value, e.g. std::map

+
+
+
+ +
+
+inline void Delete(const std::string &key)
+

Delete a key

+
+
Parameters:
+

key – the key

+
+
+
+ +
+
+inline void Flush(const bool async = false)
+

Flush the index, persists all pending writes and makes the accessible.

+
+
Parameters:
+

async – if true only trigger a flush, if false(default) wait until flush has been executed.

+
+
+
+ +
+
+inline void ForceMerge(const size_t max_segments = 1)
+

Force merge all segment to the number of segments given (default 1)

+
+
Parameters:
+

max_segments – maximum number of segments the index should have afterwards

+
+
+
+ +
+
+inline dictionary::Match operator[](const std::string &key)
+

Get a match for the given key

+
+
Parameters:
+

key – the key

+
+
+
+ +
+
+inline bool Contains(const std::string &key)
+

Check if an entry for a given key exists

+
+
Parameters:
+

key – the key

+
+
+
+ +
+
+inline dictionary::MatchIterator::MatchIteratorPair GetNear(const std::string &query, const size_t minimum_exact_prefix = 2, const bool greedy = false)
+

Match a key near: Match as much as possible exact given the minimum prefix length and then return everything below.

+

If greedy is True it matches everything below the minimum_prefix_length, but in the order of exact first.

+
+
Parameters:
+
    +
  • query – a query to match against

  • +
  • minimum_exact_prefix – prefix length to be matched exact

  • +
  • greedy – if true matches everything below minimum prefix

  • +
+
+
+
+ +
+
+inline dictionary::MatchIterator::MatchIteratorPair GetFuzzy(const std::string &query, const int32_t max_edit_distance, const size_t minimum_exact_prefix = 2)
+

Match approximate given the query and edit distance

+
+
Parameters:
+
    +
  • query – a query to match against

  • +
  • max_edit_distance – the max edit distance allowed for a single match

  • +
  • minimum_exact_prefix – prefix length to be matched exact

  • +
+
+
+
+ +
+
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/genindex.html b/genindex.html new file mode 100644 index 000000000..d8a8fc9b9 --- /dev/null +++ b/genindex.html @@ -0,0 +1,256 @@ + + + + + + + Index — keyvi documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +

Index

+ +
+ D + | F + | G + | I + | K + | L + | R + | S + +
+

D

+ + + +
+ +

F

+ + +
+ +

G

+ + + +
+ +

I

+ + +
+ +

K

+ + + +
+ +

L

+ + + +
+ +

R

+ + +
+ +

S

+ + +
+ + + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 000000000..d38df0d77 --- /dev/null +++ b/index.html @@ -0,0 +1,164 @@ + + + + + + + + Welcome to keyvi! — keyvi documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Welcome to keyvi!

+

Keyvi - the short form for “Key value index” is a key value store (KVS) optimized for size and lookup speed. The usage +of shared memory makes it scalable and resistant. The biggest difference to other stores is the underlying data +structure based on finite state machine. Storage is very space +efficient, fast and by design makes various sorts of approximate matching be it fuzzy string matching or geo highly +efficient. The immutable FST data structure can be used stand-alone for static datasets. If you need online writes, +you can use keyvi index, a “near realtime index”. The index can be used as embedded key value store, e.g. if you +already have a network stack in your application. A out of the box network enabled store is available with +keyvi-server.

+

The core of keyvi is written in C++, binding are available for Rust and Python.

+
+
+

API Documentation

+
+

C++ API

+ +
+
+

Python API

+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/objects.inv b/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..1638e9b452debb20bc96c5db0cf89873e907b632 GIT binary patch literal 1372 zcmV-i1*7^SAX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkwWqEdK z3L_v^WpZ%ZEX>4U6X>%ZBZ*6dL zWpi_7WFU2OX>MmAdTeQ8E(&#98ww}#S`_Sny zLb|eyVv5W5uP?&`(TurT>Q(%6@NqtWaIS+d3hqXUhCJahwjX%B zhM>@C4uPJ{Is&k}uVgm;Fu6ZPvhO#oO1oMo)qvCFpQwd3jTuIQ$8pHTeW2$Ly%qX? zmZysxiXzzJ?1-N8oUh)g@^t}uAi3u6UGV`^k7A5Y<9@wqqMfylVr*q)j==1O!q|Vv zJdAxxsAA+57;{p0pl^8+DJb-atAblJrSdyX3!O*F;yk6kzv|LFLgp_a{I9ay-j&t% z+a{}vqJ~u#a}7Ndf0x1@B@!Ne|GNCyd-GJC9Z4ir2dRP%V3lPn(L73uE|Z-C>}~-L ztwJ}Q@0;#}CK-YF6U1f{o;yoghxefxKEqz5pW}70Ja>Aeik{tsZ=(A?FE)u7G^gWC zX)fRv^2OO}h0zPf?1mQ6li75~>B`#m7!N|@vT|spe>rvjvQgrGvb&%U7_l_-2Iw5RR zFvylexU1Cv2=+9CoSVbgLL)E_*++(JUxk{~3RZHJsP2b7WuDa>)G5F49cxDMwmw7BD8!l=iY zLxcqkS)uTx9GzbYN`=jd4>;@aDW~GQF z8MP2$QkhJ-PUwV|5Yi&l_0&*&$40JALR&HAy3|FULLLn%aug%BC&Iz_QgH4$mghMh z5|Wr@XOcza*@`R2q2RihdWaZDdD5~WqzVy?hTN=w4mBGQ!0gOWDehT}n>Av{Wg!TQh>=)bWC6!m zS{`+%N0G4x@{IjFsg!W&IIPmtBCbH%;3#almTL+Eaycd(3)|F&kys_dHgPd_m@OE= z7&F&)kf{M+Jk?bKU$b^sg(^;_;#lFB?iZ%XGs|m`7wTy>i^&3#XurB_pSDNt;k8Em z4YAP#Q=Lw$^!+qhrLqGz+kDt|)Pc9DT*uHbw0e((&8t`A>*!Ypxwh8sQ(h}|llI%T eBXTbtg?U|z<*v^9Sv~5m?w|7oO#TPKE>`muYpQGj literal 0 HcmV?d00001 diff --git a/python/dictionary.html b/python/dictionary.html new file mode 100644 index 000000000..6e183d599 --- /dev/null +++ b/python/dictionary.html @@ -0,0 +1,196 @@ + + + + + + + + Dictionary — keyvi documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Dictionary

+

The Dictionary provides read access to a singkle keyvi file.

+
from keyvi.dictionary import Dictionary
+
+d=Dictionary("data.kv")
+
+
+
+
+class keyvi.dictionary.Dictionary
+

Cython implementation of _Dictionary

+
+
+Get(self, in_0: bytes | str) Any
+
+ +
+
+GetFuzzy()
+

Overload:

+
+
+GetFuzzy(self, in_0: bytes | str, max_edit_distance: int) Any
+
+ +

Overload:

+
+
+GetFuzzy(self, in_0: bytes | str, max_edit_distance: int, minimum_exact_prefix: int) Any
+
+ +
+ +
+
+GetManifest(self) str
+
+ +
+
+GetNear()
+

Overload:

+
+
+GetNear(self, in_0: bytes | str, minimum_prefix_length: int) Any
+
+ +

Overload:

+
+
+GetNear(self, in_0: bytes | str, minimum_prefix_length: int, greedy: bool) Any
+
+ +
+ +
+
+Lookup(self, in_0: bytes | str) Any
+
+ +
+
+LookupText(self, in_0: bytes | str) Any
+
+ +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/python/index.html b/python/index.html new file mode 100644 index 000000000..4d9398974 --- /dev/null +++ b/python/index.html @@ -0,0 +1,235 @@ + + + + + + + + Index — keyvi documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Index

+

An index is a near-realtime updateable data structure with full CRUD functionality.

+
from keyvi.index import Index
+from keyvi.index import ReadOnlyIndex
+
+index = Index("/tmp/index-directory")
+index.Set("a", "{'b': 3}")
+index.Flush()
+
+ri = ReadOnlyIndex("/tmp/index-directory")
+
+
+
+
+class keyvi.index.Index
+

Cython implementation of _Index

+
+
+Delete(self, in_0: bytes | str) None
+
+ +
+
+Flush()
+

Overload:

+
+
+Flush(self) None
+
+ +

Overload:

+
+
+Flush(self, in_0: bool) None
+
+ +
+ +
+
+Get()
+

Return the value for key if key is in the dictionary, else default.

+
+ +
+
+GetFuzzy(self, in_0: bytes | str, max_edit_distance: int, minimum_exact_prefix: int) Any
+
+ +
+
+GetNear()
+

Overload:

+
+
+GetNear(self, in_0: bytes | str, minimum_prefix_length: int) Any
+
+ +

Overload:

+
+
+GetNear(self, in_0: bytes | str, minimum_prefix_length: int, greedy: bool) Any
+
+ +
+ +
+
+Set(self, in_0: bytes | str, in_1: bytes | str) None
+
+ +
+ +
+
+class keyvi.index.ReadOnlyIndex
+

Cython implementation of _ReadOnlyIndex

+
+
+Get()
+

Return the value for key if key is in the dictionary, else default.

+
+ +
+
+GetFuzzy(self, in_0: bytes | str, max_edit_distance: int, minimum_exact_prefix: int) Any
+
+ +
+
+GetNear()
+

Overload:

+
+
+GetNear(self, in_0: bytes | str, minimum_prefix_length: int) Any
+
+ +

Overload:

+
+
+GetNear(self, in_0: bytes | str, minimum_prefix_length: int, greedy: bool) Any
+
+ +
+ +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/search.html b/search.html new file mode 100644 index 000000000..a1d139f0c --- /dev/null +++ b/search.html @@ -0,0 +1,141 @@ + + + + + + + Search — keyvi documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/searchindex.js b/searchindex.js new file mode 100644 index 000000000..def7466ce --- /dev/null +++ b/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["cpp/dictionary_compiler", "cpp/index", "index", "python/dictionary", "python/index"], "filenames": ["cpp/dictionary_compiler.rst", "cpp/index.rst", "index.rst", "python/dictionary.rst", "python/index.rst"], "titles": ["DictionaryCompiler", "Index", "Welcome to keyvi!", "Dictionary", "Index"], "terms": {"templat": [0, 1], "keyvi": [0, 1, 3, 4], "dictionari": [0, 1, 2, 4], "fsa": 0, "intern": [0, 1], "value_store_t": 0, "valuestoretyp": 0, "key_onli": 0, "class": [0, 1, 3, 4], "compil": 0, "paramet": [0, 1], "The": [0, 2, 3], "type": 0, "valu": [0, 1, 2, 4], "store": [0, 2], "us": [0, 1, 2], "n": 0, "arrai": 0, "size": [0, 2], "fix": 0, "vector": 0, "ignor": 0, "otherwis": 0, "public": [0, 1], "function": [0, 1, 4], "inlin": [0, 1], "explicit": 0, "const": [0, 1], "util": 0, "parameters_t": 0, "param": 0, "instanti": 0, "note": 0, "memori": [0, 2], "limit": 0, "onli": [0, 1], "buffer": 0, "usag": [0, 2], "small": 0, "short": [0, 2], "live": 0, "object": 0, "librari": 0, "itself": 0, "i": [0, 1, 2, 4], "part": 0, "void": [0, 1], "callback_t": 0, "progress_callback": 0, "nullptr": 0, "user_data": 0, "do": 0, "final": 0, "setmanifest": 0, "std": [0, 1], "string": [0, 1, 2], "manifest": 0, "set": [0, 1, 4], "custom": 0, "embed": [0, 2], "index": [0, 2], "file": [0, 3], "baseindexread": 1, "indexwriterwork": 1, "segment": 1, "kei": [1, 2, 4], "given": 1, "typenam": 1, "containertyp": 1, "mset": 1, "shared_ptr": 1, "key_valu": 1, "multipl": 1, "contain": 1, "must": 1, "implement": [1, 3, 4], "an": [1, 4], "iter": 1, "where": 1, "each": 1, "entri": 1, "ha": 1, "first": 1, "second": 1, "e": [1, 2], "g": [1, 2], "map": 1, "delet": [1, 4], "flush": [1, 4], "bool": [1, 3, 4], "async": 1, "fals": 1, "persist": 1, "all": 1, "pend": 1, "write": [1, 2], "make": [1, 2], "access": [1, 3], "true": 1, "trigger": 1, "default": [1, 4], "wait": 1, "until": 1, "been": 1, "execut": 1, "forcemerg": 1, "size_t": 1, "max_seg": 1, "1": 1, "forc": 1, "merg": 1, "number": 1, "maximum": 1, "should": 1, "have": [1, 2], "afterward": 1, "match": [1, 2], "oper": 1, "get": [1, 3, 4], "check": 1, "exist": 1, "matchiter": 1, "matchiteratorpair": 1, "getnear": [1, 3, 4], "queri": 1, "minimum_exact_prefix": [1, 3, 4], "2": 1, "greedi": [1, 3, 4], "much": 1, "possibl": 1, "exact": 1, "minimum": 1, "prefix": 1, "length": 1, "return": [1, 4], "everyth": 1, "below": 1, "If": [1, 2], "minimum_prefix_length": [1, 3, 4], "order": 1, "against": 1, "getfuzzi": [1, 3, 4], "int32_t": 1, "max_edit_dist": [1, 3, 4], "approxim": [1, 2], "edit": 1, "distanc": 1, "max": 1, "allow": 1, "singl": 1, "form": 2, "kv": [2, 3], "optim": 2, "lookup": [2, 3], "speed": 2, "share": 2, "scalabl": 2, "resist": 2, "biggest": 2, "differ": 2, "other": 2, "underli": 2, "data": [2, 3, 4], "structur": [2, 4], "base": 2, "finit": 2, "state": 2, "machin": 2, "storag": 2, "veri": 2, "space": 2, "effici": 2, "fast": 2, "design": 2, "variou": 2, "sort": 2, "fuzzi": 2, "geo": 2, "highli": 2, "immut": 2, "fst": 2, "can": 2, "stand": 2, "alon": 2, "static": 2, "dataset": 2, "you": 2, "need": 2, "onlin": 2, "realtim": [2, 4], "alreadi": 2, "network": 2, "stack": 2, "your": 2, "applic": 2, "A": 2, "out": 2, "box": 2, "enabl": 2, "avail": 2, "server": 2, "core": 2, "written": 2, "bind": 2, "ar": 2, "rust": 2, "dictionarycompil": 2, "readonlyindex": [2, 4], "provid": 3, "read": 3, "singkl": 3, "from": [3, 4], "import": [3, 4], "d": 3, "cython": [3, 4], "_dictionari": 3, "self": [3, 4], "in_0": [3, 4], "byte": [3, 4], "str": [3, 4], "ani": [3, 4], "overload": [3, 4], "int": [3, 4], "getmanifest": 3, "lookuptext": 3, "updat": 4, "full": 4, "crud": 4, "tmp": 4, "directori": 4, "b": 4, "3": 4, "ri": 4, "_index": 4, "none": 4, "els": 4, "in_1": 4, "_readonlyindex": 4}, "objects": {"": [[0, 0, 1, "_CPPv4I_N5keyvi10dictionary3fsa8internal13value_store_tEEN5keyvi10dictionary18DictionaryCompilerE", "keyvi::dictionary::DictionaryCompiler"], [0, 1, 1, "_CPPv4N5keyvi10dictionary18DictionaryCompiler7CompileE10callback_tPv", "keyvi::dictionary::DictionaryCompiler::Compile"], [0, 2, 1, "_CPPv4N5keyvi10dictionary18DictionaryCompiler7CompileE10callback_tPv", "keyvi::dictionary::DictionaryCompiler::Compile::progress_callback"], [0, 2, 1, "_CPPv4N5keyvi10dictionary18DictionaryCompiler7CompileE10callback_tPv", "keyvi::dictionary::DictionaryCompiler::Compile::user_data"], [0, 1, 1, "_CPPv4N5keyvi10dictionary18DictionaryCompiler18DictionaryCompilerERKN5keyvi4util12parameters_tE", "keyvi::dictionary::DictionaryCompiler::DictionaryCompiler"], [0, 2, 1, "_CPPv4N5keyvi10dictionary18DictionaryCompiler18DictionaryCompilerERKN5keyvi4util12parameters_tE", "keyvi::dictionary::DictionaryCompiler::DictionaryCompiler::params"], [0, 1, 1, "_CPPv4N5keyvi10dictionary18DictionaryCompiler11SetManifestERKNSt6stringE", "keyvi::dictionary::DictionaryCompiler::SetManifest"], [0, 2, 1, "_CPPv4N5keyvi10dictionary18DictionaryCompiler11SetManifestERKNSt6stringE", "keyvi::dictionary::DictionaryCompiler::SetManifest::manifest"], [0, 3, 1, "_CPPv4I_N5keyvi10dictionary3fsa8internal13value_store_tEEN5keyvi10dictionary18DictionaryCompilerE", "keyvi::dictionary::DictionaryCompiler::ValueStoreType"], [1, 0, 1, "_CPPv4N5keyvi5index5IndexE", "keyvi::index::Index"], [1, 1, 1, "_CPPv4N5keyvi5index5Index8ContainsERKNSt6stringE", "keyvi::index::Index::Contains"], [1, 2, 1, "_CPPv4N5keyvi5index5Index8ContainsERKNSt6stringE", "keyvi::index::Index::Contains::key"], [1, 1, 1, "_CPPv4N5keyvi5index5Index6DeleteERKNSt6stringE", "keyvi::index::Index::Delete"], [1, 2, 1, "_CPPv4N5keyvi5index5Index6DeleteERKNSt6stringE", "keyvi::index::Index::Delete::key"], [1, 1, 1, "_CPPv4N5keyvi5index5Index5FlushEKb", "keyvi::index::Index::Flush"], [1, 2, 1, "_CPPv4N5keyvi5index5Index5FlushEKb", "keyvi::index::Index::Flush::async"], [1, 1, 1, "_CPPv4N5keyvi5index5Index10ForceMergeEK6size_t", "keyvi::index::Index::ForceMerge"], [1, 2, 1, "_CPPv4N5keyvi5index5Index10ForceMergeEK6size_t", "keyvi::index::Index::ForceMerge::max_segments"], [1, 1, 1, "_CPPv4N5keyvi5index5Index8GetFuzzyERKNSt6stringEK7int32_tK6size_t", "keyvi::index::Index::GetFuzzy"], [1, 2, 1, "_CPPv4N5keyvi5index5Index8GetFuzzyERKNSt6stringEK7int32_tK6size_t", "keyvi::index::Index::GetFuzzy::max_edit_distance"], [1, 2, 1, "_CPPv4N5keyvi5index5Index8GetFuzzyERKNSt6stringEK7int32_tK6size_t", "keyvi::index::Index::GetFuzzy::minimum_exact_prefix"], [1, 2, 1, "_CPPv4N5keyvi5index5Index8GetFuzzyERKNSt6stringEK7int32_tK6size_t", "keyvi::index::Index::GetFuzzy::query"], [1, 1, 1, "_CPPv4N5keyvi5index5Index7GetNearERKNSt6stringEK6size_tKb", "keyvi::index::Index::GetNear"], [1, 2, 1, "_CPPv4N5keyvi5index5Index7GetNearERKNSt6stringEK6size_tKb", "keyvi::index::Index::GetNear::greedy"], [1, 2, 1, "_CPPv4N5keyvi5index5Index7GetNearERKNSt6stringEK6size_tKb", "keyvi::index::Index::GetNear::minimum_exact_prefix"], [1, 2, 1, "_CPPv4N5keyvi5index5Index7GetNearERKNSt6stringEK6size_tKb", "keyvi::index::Index::GetNear::query"], [1, 1, 1, "_CPPv4I0EN5keyvi5index5Index4MSetEvRKNSt10shared_ptrI13ContainerTypeEE", "keyvi::index::Index::MSet"], [1, 3, 1, "_CPPv4I0EN5keyvi5index5Index4MSetEvRKNSt10shared_ptrI13ContainerTypeEE", "keyvi::index::Index::MSet::ContainerType"], [1, 2, 1, "_CPPv4I0EN5keyvi5index5Index4MSetEvRKNSt10shared_ptrI13ContainerTypeEE", "keyvi::index::Index::MSet::key_values"], [1, 1, 1, "_CPPv4N5keyvi5index5Index3SetERKNSt6stringERKNSt6stringE", "keyvi::index::Index::Set"], [1, 2, 1, "_CPPv4N5keyvi5index5Index3SetERKNSt6stringERKNSt6stringE", "keyvi::index::Index::Set::key"], [1, 2, 1, "_CPPv4N5keyvi5index5Index3SetERKNSt6stringERKNSt6stringE", "keyvi::index::Index::Set::value"], [1, 1, 1, "_CPPv4N5keyvi5index5IndexixERKNSt6stringE", "keyvi::index::Index::operator[]"], [1, 2, 1, "_CPPv4N5keyvi5index5IndexixERKNSt6stringE", "keyvi::index::Index::operator[]::key"]], "keyvi.dictionary": [[3, 4, 1, "", "Dictionary"]], "keyvi.dictionary.Dictionary": [[3, 5, 1, "", "Get"], [3, 5, 1, "", "GetFuzzy"], [3, 5, 1, "", "GetManifest"], [3, 5, 1, "", "GetNear"], [3, 5, 1, "", "Lookup"], [3, 5, 1, "", "LookupText"]], "keyvi.index": [[4, 4, 1, "", "Index"], [4, 4, 1, "", "ReadOnlyIndex"]], "keyvi.index.Index": [[4, 5, 1, "", "Delete"], [4, 5, 1, "", "Flush"], [4, 5, 1, "", "Get"], [4, 5, 1, "", "GetFuzzy"], [4, 5, 1, "", "GetNear"], [4, 5, 1, "", "Set"]], "keyvi.index.ReadOnlyIndex": [[4, 5, 1, "", "Get"], [4, 5, 1, "", "GetFuzzy"], [4, 5, 1, "", "GetNear"]]}, "objtypes": {"0": "cpp:class", "1": "cpp:function", "2": "cpp:functionParam", "3": "cpp:templateParam", "4": "py:class", "5": "py:method"}, "objnames": {"0": ["cpp", "class", "C++ class"], "1": ["cpp", "function", "C++ function"], "2": ["cpp", "functionParam", "C++ function parameter"], "3": ["cpp", "templateParam", "C++ template parameter"], "4": ["py", "class", "Python class"], "5": ["py", "method", "Python method"]}, "titleterms": {"dictionarycompil": 0, "index": [1, 4], "welcom": 2, "keyvi": 2, "api": 2, "document": 2, "c": 2, "python": 2, "dictionari": 3}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 60}, "alltitles": {"DictionaryCompiler": [[0, "dictionarycompiler"]], "Index": [[1, "index"], [4, "index"]], "Welcome to keyvi!": [[2, "welcome-to-keyvi"]], "API Documentation": [[2, "api-documentation"]], "C++ API": [[2, null]], "Python API": [[2, null]], "Dictionary": [[3, "dictionary"]]}, "indexentries": {"keyvi::dictionary::dictionarycompiler (c++ class)": [[0, "_CPPv4I_N5keyvi10dictionary3fsa8internal13value_store_tEEN5keyvi10dictionary18DictionaryCompilerE"]], "keyvi::dictionary::dictionarycompiler::compile (c++ function)": [[0, "_CPPv4N5keyvi10dictionary18DictionaryCompiler7CompileE10callback_tPv"]], "keyvi::dictionary::dictionarycompiler::dictionarycompiler (c++ function)": [[0, "_CPPv4N5keyvi10dictionary18DictionaryCompiler18DictionaryCompilerERKN5keyvi4util12parameters_tE"]], "keyvi::dictionary::dictionarycompiler::setmanifest (c++ function)": [[0, "_CPPv4N5keyvi10dictionary18DictionaryCompiler11SetManifestERKNSt6stringE"]], "keyvi::index::index (c++ class)": [[1, "_CPPv4N5keyvi5index5IndexE"]], "keyvi::index::index::contains (c++ function)": [[1, "_CPPv4N5keyvi5index5Index8ContainsERKNSt6stringE"]], "keyvi::index::index::delete (c++ function)": [[1, "_CPPv4N5keyvi5index5Index6DeleteERKNSt6stringE"]], "keyvi::index::index::flush (c++ function)": [[1, "_CPPv4N5keyvi5index5Index5FlushEKb"]], "keyvi::index::index::forcemerge (c++ function)": [[1, "_CPPv4N5keyvi5index5Index10ForceMergeEK6size_t"]], "keyvi::index::index::getfuzzy (c++ function)": [[1, "_CPPv4N5keyvi5index5Index8GetFuzzyERKNSt6stringEK7int32_tK6size_t"]], "keyvi::index::index::getnear (c++ function)": [[1, "_CPPv4N5keyvi5index5Index7GetNearERKNSt6stringEK6size_tKb"]], "keyvi::index::index::mset (c++ function)": [[1, "_CPPv4I0EN5keyvi5index5Index4MSetEvRKNSt10shared_ptrI13ContainerTypeEE"]], "keyvi::index::index::set (c++ function)": [[1, "_CPPv4N5keyvi5index5Index3SetERKNSt6stringERKNSt6stringE"]], "keyvi::index::index::operator[] (c++ function)": [[1, "_CPPv4N5keyvi5index5IndexixERKNSt6stringE"]], "dictionary (class in keyvi.dictionary)": [[3, "keyvi.dictionary.Dictionary"]], "get() (keyvi.dictionary.dictionary method)": [[3, "keyvi.dictionary.Dictionary.Get"]], "getfuzzy() (keyvi.dictionary.dictionary method)": [[3, "keyvi.dictionary.Dictionary.GetFuzzy"]], "getmanifest() (keyvi.dictionary.dictionary method)": [[3, "keyvi.dictionary.Dictionary.GetManifest"]], "getnear() (keyvi.dictionary.dictionary method)": [[3, "keyvi.dictionary.Dictionary.GetNear"]], "lookup() (keyvi.dictionary.dictionary method)": [[3, "keyvi.dictionary.Dictionary.Lookup"]], "lookuptext() (keyvi.dictionary.dictionary method)": [[3, "keyvi.dictionary.Dictionary.LookupText"]], "delete() (keyvi.index.index method)": [[4, "keyvi.index.Index.Delete"]], "flush() (keyvi.index.index method)": [[4, "keyvi.index.Index.Flush"]], "get() (keyvi.index.index method)": [[4, "keyvi.index.Index.Get"]], "get() (keyvi.index.readonlyindex method)": [[4, "keyvi.index.ReadOnlyIndex.Get"]], "getfuzzy() (keyvi.index.index method)": [[4, "keyvi.index.Index.GetFuzzy"]], "getfuzzy() (keyvi.index.readonlyindex method)": [[4, "keyvi.index.ReadOnlyIndex.GetFuzzy"]], "getnear() (keyvi.index.index method)": [[4, "keyvi.index.Index.GetNear"]], "getnear() (keyvi.index.readonlyindex method)": [[4, "keyvi.index.ReadOnlyIndex.GetNear"]], "index (class in keyvi.index)": [[4, "keyvi.index.Index"]], "readonlyindex (class in keyvi.index)": [[4, "keyvi.index.ReadOnlyIndex"]], "set() (keyvi.index.index method)": [[4, "keyvi.index.Index.Set"]]}}) \ No newline at end of file