Update API documentation

Implement a new system combining Doxygen with Sphinx using Breathe.
This commit is contained in:
Oliver Hamlet
2016-08-24 08:08:12 +01:00
parent 332b86c38b
commit 9c04741de2
21 changed files with 3553 additions and 378 deletions
+1 -3
View File
@@ -48,9 +48,7 @@ Thumbs.db
*.suo
*.sdf
*.opensdf
build/
docs/html
docs/latex
build
*.mo
bower_components
node_modules
+12
View File
@@ -46,6 +46,18 @@ Parameter | Values | Default |Description
You may also need to set `BOOST_ROOT` if CMake cannot find Boost.
## Building The API Documentation
The API documentation is built using [Doxygen](http://www.stack.nl/~dimitri/doxygen/), [Breathe](https://breathe.readthedocs.io/en/latest/) and [Sphinx](http://www.sphinx-doc.org/en/stable/). On Windows, install Doxygen and [Python](https://www.python.org) 2.7, add Doxygen's binary path, `C:\Python27` and `C:\Python27\Scripts` (or wherever you installed Python to) to your `%PATH%`, then:
```
python -m pip install breathe sphinx
cd docs/api
doxygen
cd ../..
sphinx-build -b html docs/api build/documentation/sphinx
```
## Packaging Releases
Packaging scripts are provided for creating an installer on Windows and compressed archives on Windows and Linux.
+2477
View File
File diff suppressed because it is too large Load Diff
+348
View File
@@ -0,0 +1,348 @@
# -*- coding: utf-8 -*-
#
# LOOT API documentation build configuration file, created by
# sphinx-quickstart on Sat Aug 13 21:09:25 2016.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'breathe',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'LOOT API'
copyright = u'2016, WrinklyNinja'
author = u'WrinklyNinja'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = u'latest'
# The full version, including alpha/beta/rc tags.
release = u'latest'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#
# today = ''
#
# Else, today_fmt is used as the format for a strftime call.
#
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = []
# The reST default role (used for this markup: `text`) to use for all
# documents.
#
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
# keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
#
# html_title = u'LOOT API v0.9.2'
# A shorter title for the navigation bar. Default is the same as html_title.
#
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#
# html_logo = None
# The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = []
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#
# html_extra_path = []
# If not None, a 'Last updated on:' timestamp is inserted at every page
# bottom, using the given strftime format.
# The empty string is equivalent to '%b %d, %Y'.
#
# html_last_updated_fmt = None
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#
# html_additional_pages = {}
# If false, no module index is generated.
#
# html_domain_indices = True
# If false, no index is generated.
#
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
#
# html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# 'ja' uses this config value.
# 'zh' user can custom change `jieba` dictionary path.
#
# html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#
# html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'LOOTAPIdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'LOOTAPI.tex', u'LOOT API Documentation',
u'WrinklyNinja', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#
# latex_use_parts = False
# If true, show page references after internal links.
#
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#
# latex_appendices = []
# It false, will not define \strong, \code, itleref, \crossref ... but only
# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
# packages.
#
# latex_keep_old_macro_names = True
# If false, no module index is generated.
#
# latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'lootapi', u'LOOT API Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'LOOTAPI', u'LOOT API Documentation',
author, 'LOOTAPI', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#
# texinfo_appendices = []
# If false, no module index is generated.
#
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#
# texinfo_no_detailmenu = False
breathe_projects = {
"loot_api":"../../build/documentation/xml/",
}
breathe_default_project = 'loot_api'
+52
View File
@@ -0,0 +1,52 @@
*******************
Credits & Copyright
*******************
The LOOT API is written by `WrinklyNinja`_ in C++ and makes use of the
`Boost`_, `libespm`_, `libgit2`_, `libloadorder`_, `Pseudosem`_ and `yaml-cpp`_
libraries. The copyright licenses for all of these and the LOOT API itself are
included below.
.. _WrinklyNinja: https://github.com/WrinklyNinja
.. _Boost: http://www.boost.org/
.. _libespm: https://github.com/WrinklyNinja/libespm
.. _libgit2: https://github.com/libgit2/libgit2
.. _libloadorder: https://github.com/WrinklyNinja/libloadorder
.. _Pseudosem: https://github.com/WrinklyNinja/pseudosem
.. _yaml-cpp: https://github.com/WrinklyNinja/yaml-cpp
Boost
=====
.. include:: ../licenses/Boost Software License v1.0.txt
:literal:
libgit2
=======
.. include:: ../licenses/GNU GPL v2 (libgit2).txt
:literal:
LOOT, Libespm & Libloadorder
============================
.. include:: ../licenses/GNU GPL v3.txt
:literal:
LOOT Documentation
==================
.. include:: ../licenses/GNU FDL v1.3.txt
:literal:
Pseudosem
=========
.. include:: ../licenses/MIT License (Pseudosem).txt
:literal:
yaml-cpp
========
.. include:: ../licenses/MIT License (yaml-cpp).txt
:literal:
+77
View File
@@ -0,0 +1,77 @@
***************
Version History
***************
0.9.2 - *3 August 2016*
=======================
* Fixed the wrong API binary being packaged. This caused the v0.9.0 and v0.9.1
API releases to actually be re-releases of a snapshot build made at some
point between v0.8.1 and v0.9.0: the affected API releases were taken
offline once this was discovered.
* Fixed ``loot_get_plugin_tags()`` remembering results and including them in the
results of subsequent calls.
* Fixed an error occurring when the user's temporary files directory didn't
exist and updating the masterlist tried to create a directory there.
* Fixed errors when reading some Oblivion plugins during sorting, including
the official DLC.
* libespm (2.5.5) and Pseudosem (1.1.0) dependencies have been updated to the
versions given in brackets.
0.9.1 - *23 June 2016*
======================
* No API changes.
0.9.0 - *21 May 2016*
=====================
* Moved API header location to the more standard ``include/loot/api.h``.
* Documented LOOT's masterlist versioning system.
* Made all API outputs fully const to make it clear they should not be
modified and to avoid internal const casting.
* Removed the ``loot_cleanup()`` function, as the one string it used to destroy
is now stored on the stack and so destroyed when the API is unloaded.
* The ``loot_db`` type is now an opaque struct, and functions that used to take
it as a value now take a pointer to it.
* Removed the ``loot_lang_any`` constant. The ``loot_lang_english`` constant
should be used instead.
0.8.1 - *27 September 2015*
===========================
* Fixed crash when loading plugins due to lack of thread safety.
* Fixed masterlist updater and validator not checking for valid condition
and regex syntax.
* Check for safe file paths when parsing conditions.
* Updated Boost (1.59.0), libgit2 (0.23.2) and CEF (branch 2454) dependencies.
This fixes the masterlist updater not working correctly for Windows Vista
users.
0.8.0 - *22 July 2015*
======================
* Fixed many miscellaneous bugs, including initialisation crashes and
incorrect metadata input/output handling.
* Fixed LOOT silently discarding some non-unique metadata: an error will now
occur when loading or attempting to apply such metadata.
* Fixed and improved LOOT's version comparison behaviour for a wide variety of
version string formats. This involved removing LOOT's usage of the Alphanum
code library.
* Improved plugin loading performance for computers with weaker multithreading
capabilities (eg. non-hyperthreaded dual-core or single-core CPUs).
* LOOT no longer outputs validity warnings for inactive plugins.
* Metadata syntax support changes, see the metadata syntax document for
details.
* Updated libgit2 to v0.23.0.
0.7.1 - *22 June 2015*
======================
* Fixed "No existing load order position" errors when sorting.
* Fixed output of Bash Tag removal suggestions in ``loot_write_minimal_list()``.
0.7.0 - *20 May 2015*
=====================
* Initial API release.
+12
View File
@@ -0,0 +1,12 @@
########
LOOT API
########
.. toctree::
introduction
miscellaneous
sorting
reference
history
credits
+14
View File
@@ -0,0 +1,14 @@
Introduction
============
LOOT is a utility that helps users avoid serious conflicts between their mods by
setting their plugins in an optimal load order. It also provides tens of
thousands of plugin-specific messages, including usage notes, requirements,
incompatibilities, bug warnings and installation mistake notifications, and
thousands of Bash Tag suggestions.
This metadata that LOOT supplies is stored in its masterlist, which is
maintained by the LOOT team using information provided by mod authors and users.
Users can also add to and modify the metadata used by LOOT through the use of
userlist files. The LOOT API provides a way for third-party developers to access
this metadata for use in their own programs.
+71
View File
@@ -0,0 +1,71 @@
*********************
Miscellaneous Details
*********************
String Encoding
===============
* All output strings are encoded in UTF-8.
* Input strings are expected to be encoded in UTF-8.
* File paths are case-sensitive if and only if the underlying file system is
case-sensitive.
* :cpp:func:`WriteMinimalList` writes a metadata list encoded in UTF-8.
Errors
======
All errors encountered are thrown as exceptions that inherit from
``std::exception``.
Metadata Files
==============
LOOT stores plugin metadata in YAML files. It distinguishes between *masterlist*
and *userlist* files: each game has a single masterlist, which is a public,
curated metadata store, and each LOOT user has a private userlist, which can
contain metadata added by the user. The two files use the same `syntax`_, but
metadata in the userlist extends or replaces metadata sourced from the
masterlist.
LOOT's plugin metadata can be conditional, eg. a plugin may require a patch only
if another plugin is also present. The API's :cpp:func:`LoadLists` method parses
metadata files into memory, but does not evaluate these conditions, so the
loaded metadata may contain metadata that is invalid for the installed game that
the :cpp:class:`loot::DatabaseInterface` object being operated on was created for.
The :cpp:func:`EvalLists` must be called to evaluate any conditions in the
loaded metadata. In doing so it discards any metadata with a condition that
evaluates to false, but the pre-evaluation metadata is cached internally so that
re-evaluation does not require the lists to be reloaded.
.. _syntax: https://loot.github.io/docs/0.9.2/LOOT%20Metadata%20Syntax.html
Caching
=======
All unevaluated metadata is cached between calls to :cpp:func:`LoadLists`.
Evaluated metadata is cached between calls to :cpp:func:`EvalLists`. Metadata
conditions and their results are cached between calls to :cpp:func:`EvalLists`,
so that every call to :cpp:func:`EvalLists` re-evaluates all conditions, but
conditions that are used more than once in the loaded metadata are only
evaluated once.
Plugin content is cached between calls to :cpp:func:`SortPlugins`, though no
other API function makes use of it.
Performance
===========
Loading metadata lists is a relatively costly operation, as is updating the
masterlist (which involves loading it). Evaluating the loaded metadata lists is
not very costly relative to loading them, though is performance depends on the
type and number of conditions used in the loaded metadata, and all the
conditions involve filesystem access.
Sorting plugins is expensive, as it involves loading all the FormIDs for all
the plugins, apart from the game's main master file, which is skipped as an
optimisation (it doesn't depend on anything else and is much bigger than any
other plugin, so is unnecessary and slow to load).
Getting plugin metadata once loaded is cheap, as is getting a masterlist's
revision.
+47
View File
@@ -0,0 +1,47 @@
*************
API Reference
*************
.. contents::
Enumerations
============
.. doxygenenum:: loot::GameType
.. doxygenenum:: loot::LanguageCode
.. doxygenenum:: loot::MessageType
.. doxygenenum:: loot::PluginCleanliness
Public-Field Data Structures
============================
.. doxygenstruct:: loot::MasterlistInfo
:members:
.. doxygenstruct:: loot::PluginMessage
:members:
.. doxygenstruct:: loot::PluginTags
:members:
Functions
=========
.. doxygenfunction:: loot::IsCompatible
.. doxygenfunction:: loot::CreateDatabase
Interfaces
==========
.. doxygenclass:: loot::DatabaseInterface
:members:
Classes
=======
.. doxygenclass:: loot::LootVersion
:members:
+111
View File
@@ -0,0 +1,111 @@
************************
LOOT's Sorting Algorithm
************************
LOOT's sorting algorithm consists of four stages:
.. contents::
:local:
Load plugin data
================
In this first stage, the plugins to be sorted are parsed and their FormIDs
stored. Parsing is multithreaded by dividing the plugins into buckets with
roughly equal total file sizes, and loading each bucket's plugins in a separate
thread. The number of buckets created is equal to the number of concurrent
threads that are hardware-supported (e.g. a dual-core CPU without hyperthreading
may report that it supports two threads).
When parsing plugins, all subrecords are skipped over for efficiency, apart from
the subrecords of the ``TES4`` header record.
Create plugin graph vertices
=================================
Once loaded, a directed graph is created and the plugins are added to it in
lexicographical order as vertices. Any metadata a plugin has in the masterlist
and userlist are then merged into its vertex's data store, and any metadata
conditions evaluated.
Create plugin graph edges
==============================
In this section, the terms *vertex* and *plugin* are used interchangeably, and
the iteration order 'for each plugin' is the order in which the vertices were
added to the graph.
For each plugin:
1. If the plugin is a master file, add edges going to all non-master files. If
the plugin is a non-master file, add edges coming from all master files.
2. Add edges coming from all the plugin's masters. Missing masters have no edges
added.
3. Add edges coming from all the plugin's requirements. Missing requirements
have no edges added.
4. Add edges coming from all the plugin's load after files that are installed
plugins.
At this point, all explicit interdependencies have been graphed. Plugin priority
metadata values must now be propagated down the dependency trees to ensure that
priority edges are added correctly later in the process. To do this:
1. Create a list of all vertices with a global or non-global priority value
greater than zero.
2. Sort the list in order of decreasing priority value.
3. For each vertex, perform a depth-first search, setting priorities at each
vertex visited until equal or larger values are encountered.
Now that the priorities have been propagated, the priority edges can be added.
For each plugin, if it has a global priority value of zero, overrides no records
and loads no archive, skip it, otherwise iterate over all other plugins and:
* If the other plugin's global and non-global priority values equal the
plugin's own values, or if both plugins have a global priority of zero and
have no FormIDs in common, skip the other plugin.
* Otherwise, add an edge from the plugin with lower global priority to the
plugin with higher global priority, if that edge does not cause a cycle. A
cycle is caused if a circular dependency is introduced, for example for two
vertices A and B, A -> B -> A is a cycle.
If the global priorities are equal, compare the non-global priorities
instead.
Plugin overlap edges are then added. Two plugins overlap if they contain the
same FormID, i.e. if they both edit the same record or if one edits a record the
other plugin adds.
For each plugin, skip it if it overrides no records, otherwise iterate over all
other plugins.
* If the plugin and other plugin override the same number of records, or do not
overlap, skip the other plugin.
* Otherwise, add an edge from the plugin which overrides more records to the
plugin that overrides fewer records, unless that edge would cause a cycle.
Finally, tie-break edges are added to ensure that sorting is consistent. For
each plugin, iterate over all other plugins and add an edge between each pair of
plugins in the direction given by the tie-break comparison function, unless that
edge would cause a cycle.
The tie-break comparison function compares current plugin load order positions,
falling back to plugin names.
* If both plugins have positions in the current load order, the function
preserves their existing relative order.
* If one plugin has a position and the other does not, the edge added goes from
the plugin with a position to the plugin without a position.
* If neither plugin has a load order position, a case-insensitive
lexicographical comparison of their filenames without file extensions is used
to decide their order.
Topologically sort the plugin graph
===================================
Note that edges for explicit interdependencies are the only edges allowed to
create cycles: this is because the first step of this stage is to check the
plugin graph for cycles, and throw an error if any are encountered, so that
metadata (or indeed plugin data) that cause them can be corrected.
Once the graph is confirmed to be cycle-free, a topological sort is performed on
the graph, outputting a list of plugins in their newly-sorted load order.
+25 -158
View File
@@ -21,141 +21,9 @@
along with LOOT. If not, see
<https://www.gnu.org/licenses/>.
*/
/**
* @mainpage
* @author WrinklyNinja
* @version 0.9.2
* @copyright
* The LOOT API is distributed under the GNU General Public License v3.0.
* For the full text of the license, see the "GNU GPL v3.txt" file
* included in the source archive.
*
* @section intro_sec Introduction
* LOOT is a utility that helps users avoid serious conflicts between
* their mods by setting their plugins in an optimal load order. It also
* provides tens of thousands of plugin-specific messages, including usage
* notes, requirements, incompatibilities, bug warnings and installation
* mistake notifications, and thousands of Bash Tag suggestions.
*
* This metadata that LOOT supplies is stored in its masterlist, which is
* maintained by the LOOT team using information provided by mod authors
* and users. Users can also add to and modify the metadata used by LOOT
* through the use of userlist files. The LOOT API provides a way for
* third-party developers to access this metadata for use in their own
* programs.
*
* All further API documentation is contained within the documentation for
* api.h.
*
* @section credit_sec Credits
* The LOOT API is written by [WrinklyNinja]
* (https://github.com/WrinklyNinja) in C/C++ and makes use of the
* [Boost](http://www.boost.org/),
* [libespm](https://github.com/WrinklyNinja/libespm),
* [libgit2](https://github.com/libgit2/libgit2),
* [libloadorder](https://github.com/WrinklyNinja/libloadorder/),
* [Pseudosem](https://github.com/WrinklyNinja/pseudosem) and
* [yaml-cpp](https://github.com/WrinklyNinja/yaml-cpp) libraries. Copyright
* license information for all these may be found in the
* "docs/licenses/Licenses.txt" file.
*
* @section history_sec Version History
* ## 0.9.2 - *3 August 2016*
*
* * Fixed the wrong API binary being packaged. This caused the v0.9.0 and v0.9.1 API releases to actually be re-releases of a snapshot build made at some point between v0.8.1 and v0.9.0: the affected API releases were taken offline once this was discovered.
* * Fixed `loot_get_plugin_tags()`` remembering results and including them in the results of subsequent calls.
* * Fixed an error occurring when the user's temporary files directory didn't exist and updating the masterlist tried to create a directory there.
* * Fixed errors when reading some Oblivion plugins during sorting, including the official DLC.
* * libespm (2.5.5) and Pseudosem (1.1.0) dependencies have been updated to the versions given in brackets.
*
* ## 0.9.1 - *23 June 2016*
*
* * No API changes.
*
* ## 0.9.0 - *21 May 2016*
*
* * Moved API header location to the more standard `include/loot/api.h`.
* * Documented LOOT's masterlist versioning system.
* * Made all API outputs fully const to make it clear they should not
* be modified and to avoid internal const casting.
* * Removed the `loot_cleanup()` function, as the one string it used to
* destroy is now stored on the stack and so destroyed when the API is
* unloaded.
* * The `loot_db` type is now an opaque struct, and functions that used
* to take it as a value now take a pointer to it.
* * Removed the `loot_lang_any` constant. The `loot_lang_english`
* constant should be used instead.
*
* ## 0.8.1 - *27 September 2015*
*
* * Fixed crash when loading plugins due to lack of thread safety.
* * Fixed masterlist updater and validator not checking for valid
* condition and regex syntax.
* * Check for safe file paths when parsing conditions.
* * Updated Boost (1.59.0), libgit2 (0.23.2) and CEF (branch 2454)
* dependencies. This fixes the masterlist updater not working
* correctly for Windows Vista users.
*
* ## 0.8.0 - *22 July 2015*
*
* * Fixed many miscellaneous bugs, including initialisation crashes and
* incorrect metadata input/output handling.
* * Fixed LOOT silently discarding some non-unique metadata: an error
* will now occur when loading or attempting to apply such metadata.
* * Fixed and improved LOOT's version comparison behaviour for a wide
* variety of version string formats. This involved removing LOOT's
* usage of the Alphanum code library.
* * Improved plugin loading performance for computers with weaker
* multithreading capabilities (eg. non-hyperthreaded dual-core or
* single-core CPUs).
* * LOOT no longer outputs validity warnings for inactive plugins.
* * Metadata syntax support changes, see the metadata syntax document
* for details.
* * Updated libgit2 to v0.23.0.
*
* ## 0.7.1 - *22 June 2015*
*
* * Fixed "No existing load order position" errors when sorting.
* * Fixed output of Bash Tag removal suggestions in
* `loot_write_minimal_list()`.
*
* ## 0.7.0 - *20 May 2015*
*
* * Initial API release.
*/
/**
* @file api.h
* @brief This file contains the API frontend.
*
* @note The LOOT API is *not* thread safe. Thread safety is a goal, but one
* that has not yet been achieved. Bear this in mind if using it in a
* multi-threaded client.
*
* @section var_sec Variable Types
*
* The LOOT API uses character strings and integers for information
* input/output.
* - All strings are null-terminated byte character strings encoded in UTF-8.
* - All codes are unsigned integers at least 16 bits in size.
* - All array sizes are unsigned integers at least 16 bits in size.
* - File paths are case-sensitive if and only if the underlying file system
* is case-sensitive.
*
* @section memory_sec Memory Management
*
* The LOOT API manages the memory of strings and arrays it returns, so such
* strings and arrays should not be deallocated by the client.
*
* Data returned by a function lasts until a function is called which returns
* data of the same type (eg. a string is stored until the client calls
* another function which returns a string, an integer array lasts until
* another integer array is returned, etc.).
*
* All allocated memory is freed when loot_destroy_db() is called, except the
* string allocated by loot_get_error_message(), which must be freed by
* calling loot_cleanup().
* @file
* @brief The main include file for the API.
*/
#ifndef LOOT_API_H
@@ -196,17 +64,17 @@ namespace loot {
* @details Checks whether the loaded API is compatible with the given
* version of the API, abstracting API stability policy away from
* clients. The version numbering used is major.minor.patch.
* @param versionMajor
* The major version number to check.
* @param versionMinor
* The minor version number to check.
* @param versionPatch
* The patch version number to check.
* @param major
* The major version number to check.
* @param minor
* The minor version number to check.
* @param patch
* The patch version number to check.
* @returns True if the API versions are compatible, false otherwise.
*/
LOOT_API bool IsCompatible(const unsigned int versionMajor,
const unsigned int versionMinor,
const unsigned int versionPatch);
LOOT_API bool IsCompatible(const unsigned int major,
const unsigned int minor,
const unsigned int patch);
/**@}*/
/**********************************************************************//**
@@ -218,21 +86,20 @@ LOOT_API bool IsCompatible(const unsigned int versionMajor,
* @brief Initialise a new database handle.
* @details Creates a handle for a database, which is then used by all
* database functions.
* @param db
* A pointer to the handle that is created by the function.
* @param clientGame
* A game code for which to create the handle.
* @param gamePath
* The relative or absolute path to the game folder, or `NULL`.
* If `NULL`, the API will attempt to detect the data path of the
* specified game.
* @param gameLocalPath
* The relative or absolute path to the game's folder in
* `%LOCALAPPDATA%`, or `NULL`. If `NULL`, the API will attempt to
* look up the path that `%LOCALAPPDATA%` corresponds to. This
* parameter is provided so that systems lacking that environmental
* variable (eg. Linux) can still use the API.
* @returns A return code.
* @param game
* A game code for which to create the handle.
* @param game_path
* The relative or absolute path to the game folder, or an empty string.
* If an empty string, the API will attempt to detect the data path of
* the specified game by searching for the game's main master file in a
* sibling Data folder and by searching for the game's Registry entry.
* @param game_local_path
* The relative or absolute path to the game's folder in
* `%%LOCALAPPDATA%` or an empty string. If an empty string, the API will
* attempt to look up the path that `%%LOCALAPPDATA%` corresponds to.
* This parameter is provided so that systems lacking that environmental
* variable (eg. Linux) can still use the API.
* @returns The new database handle.
*/
LOOT_API std::shared_ptr<DatabaseInterface> CreateDatabase(const GameType game,
const std::string& game_path,
+133 -183
View File
@@ -33,237 +33,187 @@
#include "loot/plugin_message.h"
#include "loot/plugin_tags.h"
/**
* @file
* @brief Contains the DatabaseInterface class.
*/
namespace loot {
/** @brief The interface provided by API's database handle. */
class DatabaseInterface {
public:
/**********************************************************************//**
* @name Database Loading Functions
*************************************************************************/
/**@{*/
/**
* @name Data Loading
* @{
*/
/**
* @brief Loads the masterlist and userlist from the paths specified.
* @details Can be called multiple times, each time replacing the
* previously-loaded data.
* @param masterlist_path
* A string containing the relative or absolute path to the masterlist
* file that should be loaded.
* @param userlist_path
* A string containing the relative or absolute path to the userlist
* file that should be loaded, or `NULL`. If `NULL`, no userlist will
* be loaded.
*/
* @brief Loads the masterlist and userlist from the paths specified.
* @details Can be called multiple times, each time replacing the
* previously-loaded data.
* @param masterlist_path
* A string containing the relative or absolute path to the masterlist
* file that should be loaded.
* @param userlist_path
* A string containing the relative or absolute path to the userlist
* file that should be loaded, or an empty string. If an empty string,
* no userlist will be loaded.
*/
virtual void LoadLists(const std::string& masterlist_path,
const std::string& userlist_path) = 0;
/**
* @brief Evaluates all conditions and regular expression metadata
* entries.
* @details Repeated calls re-evaluate the metadata from scratch. This
* function affects the output of all the database access
* functions.
* @param language
* The language code that is used for message language comparisons.
*/
* @brief Evaluates all conditions and regular expression metadata entries.
* @details Repeated calls re-evaluate the metadata from scratch. This
* function affects the output of all the database access functions.
* @param language
* The language code that is used for message language comparisons.
*/
virtual void EvalLists(const LanguageCode language) = 0;
/**********************************************************************//**
* @name LOOT Functionality Functions
*************************************************************************/
/**@{*/
/**
* @}
* @name Sorting
* @{
*/
/**
* @brief Calculates a new load order for the game's installed plugins
* (including inactive plugins) and outputs the sorted order.
* @details Pulls metadata from the masterlist and userlist if they are
* loaded, and reads the contents of each plugin. No changes are
* applied to the load order used by the game. This function does
* not load or evaluate the masterlist or userlist.
* @param db
* The database the function acts on.
* @param sortedPlugins
* A pointer to an array of plugin filenames in their sorted load
* order.
* @param numPlugins
* A pointer to the size of the outputted array.
* @returns A return code.
*/
* @brief Calculates a new load order for the game's installed plugins
* (including inactive plugins) and outputs the sorted order.
* @details Pulls metadata from the masterlist and userlist if they are
* loaded, and reads the contents of each plugin. No changes are
* applied to the load order used by the game. This function does
* not load or evaluate the masterlist or userlist.
* @returns A vector of plugin filenames in their sorted load order.
*/
virtual std::vector<std::string> SortPlugins() = 0;
/**
* @brief Applies the given load order.
* @param db
* The database the function acts on.
* @param loadOrder
* An array of plugin filenames in the load order to be set.
* @param numPlugins
* The size of the inputted array.
* @returns A return code.
*/
* @brief Applies the given load order.
* @param loadOrder
* A vector of plugin filenames in the load order to be set.
*/
virtual void ApplyLoadOrder(const std::vector<std::string>& loadOrder) = 0;
/**
* @brief Update the given masterlist.
* @details Uses Git to update the given masterlist to a given remote.
* If the masterlist doesn't exist, this will create it. This
* function also initialises a Git repository in the given
* masterlist's parent folder. If the masterlist was not already
* up-to-date, it will be re-loaded, but not re-evaluated.
*
* If a Git repository is already present, it will be used to
* perform a diff-only update, but if for any reason a
* fast-forward merge update is not possible, the existing
* repository will be deleted and a new repository cloned from
* the given remote.
* @param db
* The database the function acts on.
* @param masterlistPath
* A string containing the relative or absolute path to the masterlist
* file that should be updated. The filename must match the filename
* of the masterlist file in the given remote repository, otherwise it
* will not be updated correctly. Although LOOT itself expects this
* filename to be "masterlist.yaml", the API does not check for any
* specific filename.
* @param remoteURL
* The URL of the remote from which to fetch updates. This can also be
* a relative or absolute path to a local repository.
* @param remoteBranch
* The branch of the remote from which to apply updates. LOOT's
* official masterlists are versioned using separate branches for each
* new version of the masterlist syntax, so if you're using them,
* check their repositories to see which is the latest release branch.
* @param updated
* `true` if the masterlist was updated. `false` if no update was
* necessary, ie. it was already up-to-date. If `true`, the masterlist
* will have been re-loaded, but will need to be re-evaluated
* separately.
* @returns A return code.
*/
* @}
* @name Masterlist Update
* @{
*/
/**
* @brief Update the given masterlist.
* @details Uses Git to update the given masterlist to a given remote.
* If the masterlist doesn't exist, this will create it. This
* function also initialises a Git repository in the given
* masterlist's parent folder. If the masterlist was not already
* up-to-date, it will be re-loaded, but not re-evaluated.
*
* If a Git repository is already present, it will be used to
* perform a diff-only update, but if for any reason a
* fast-forward merge update is not possible, the existing
* repository will be deleted and a new repository cloned from
* the given remote.
* @param masterlist_path
* A string containing the relative or absolute path to the masterlist
* file that should be updated. The filename must match the filename
* of the masterlist file in the given remote repository, otherwise it
* will not be updated correctly. Although LOOT itself expects this
* filename to be "masterlist.yaml", the API does not check for any
* specific filename.
* @param remote_url
* The URL of the remote from which to fetch updates. This can also be
* a relative or absolute path to a local repository.
* @param remote_branch
* The branch of the remote from which to apply updates. LOOT's
* official masterlists are versioned using separate branches for each
* new version of the masterlist syntax, so if you're using them,
* check their repositories to see which is the latest release branch.
* @returns `true` if the masterlist was updated. `false` if no update was
* necessary, ie. it was already up-to-date. If `true`, the
* masterlist will have been re-loaded, but will need to be
* re-evaluated separately.
*/
virtual bool UpdateMasterlist(const std::string& masterlist_path,
const std::string& remote_url,
const std::string& remote_branch) = 0;
/**
* @brief Get the given masterlist's revision.
* @details Getting a masterlist's revision is only possible if it is
* found inside a local Git repository.
* @param db
* The database the function acts on.
* @param masterlistPath
* A string containing the relative or absolute path to the masterlist
* file that should be queried.
* @param getShortID
* If `true`, the shortest unique hexadecimal revision hash that is at
* least 7 characters long will be outputted. Otherwise, the full 40
* character hash will be outputted.
* @param revisionID
* A pointer to a string containing the outputted revision hash for
* the masterlist. If the masterlist doesn't exist, or there is no Git
* repository at its location, this will be `NULL`.
* @param revisionDate
* A pointer to a string containing the ISO 8601 formatted revision
* date, ie. YYYY-MM-DD. If the masterlist doesn't exist, or there is
* no Git repository at its location, this will be `NULL`.
* @param isModified
* A pointer to a boolean that is `true` if the masterlist has been
* edited since the outputted revision, or `false` if it is at exactly
* the revision given.
* @returns A return code.
*/
* @brief Get the given masterlist's revision.
* @details Getting a masterlist's revision is only possible if it is found
* inside a local Git repository.
* @param masterlist_path
* A string containing the relative or absolute path to the masterlist
* file that should be queried.
* @param get_short_id
* If `true`, the shortest unique hexadecimal revision hash that is at
* least 7 characters long will be outputted. Otherwise, the full 40
* character hash will be outputted.
* @returns The revision data.
*/
virtual MasterlistInfo GetMasterlistRevision(const std::string& masterlist_path,
const bool get_short_id) = 0;
/**@}*/
/**********************************************************************//**
* @name Database Access Functions
*************************************************************************/
/**@{*/
/**
* @}
* @name Plugin Data Access
* @{
*/
/**
* @brief Outputs the Bash Tags suggested for addition and removal by the
* database for the given plugin.
* @details loot_get_tag_map() must be called before this to ensure that
* the Bash Tag UIDs outputted by this function can be matched up
* to name strings.
* @param db
* The database the function acts on.
* @param plugin
* The filename of the plugin to look up Bash Tag suggestions for.
* @param tags_added
* A pointer to the outputted array of UIDs of the Bash Tags suggested
* for addition to the specified plugin. `NULL` if no Bash Tag
* additions are suggested.
* @param numTags_added
* A pointer to the size of the tags_added array. `0` if `tags_added`
* is `NULL`.
* @param tags_removed
* A pointer to the outputted array of UIDs of the Bash Tags suggested
* for removal from the specified plugin. `NULL` if no Bash Tag
* removals are suggested.
* @param numTags_removed
* A pointer to the size of the `tags_removed` array. `0` if
* `tags_removed` is `null`.
* @param userlistModified
* `true` if the Bash Tag suggestions were modified by the data in the
* userlist, `false` otherwise.
* @returns A return code.
* @brief Outputs the Bash Tags suggested for addition and removal by the
* database for the given plugin.
* @param plugin
* The filename of the plugin to look up Bash Tag suggestions for.
* @returns Bash Tag data for the plugin.
*/
virtual PluginTags GetPluginTags(const std::string& plugin) = 0;
/**
* @brief Outputs the messages associated with the given plugin in the
* database.
* @param db
* The database the function acts on.
* @param plugin
* The filename of the plugin to look up messages for.
* @param messages
* A pointer to the outputted array of messages associated with the
* specified plugin, given as loot_message structures. `NULL` if the
* plugin has no messages associated with it.
* @param numMessages
* A pointer to the size of the outputted array. If no messages are
* outputted, this will be `0`.
* @returns A return code.
*/
* @brief Outputs the messages associated with the given plugin in the
* database.
* @param plugin
* The filename of the plugin to look up messages for.
* @returns A vector of messages associated with the specified plugin. Empty
* if the plugin has no messages associated with it.
*/
virtual std::vector<PluginMessage> GetPluginMessages(const std::string& plugin) = 0;
/**
* @brief Determines the database's knowledge of a plugin's dirtiness.
* @details Outputs whether the plugin should be cleaned or not, or if
* no data is available. The mechanism used to determine that
* a plugin should not be cleaned is not very reliable, and is
* likely to fail if `loot_eval_lists()` was called with a
* language other than English. As such, some plugins that should
* not be cleaned may have the `loot_needs_cleaning_unknown`
* code outputted.
* @param db
* The database the function acts on.
* @param plugin
* The plugin to look up dirty status information for.
* @param needsCleaning
* A pointer to a plugin cleanliness code.
* @returns A return code.
*/
* @brief Determines the database's knowledge of a plugin's cleanliness.
* @details Outputs whether the plugin should be cleaned or not, or if
* no data is available. The mechanism used to determine that
* a plugin should not be cleaned is not very reliable, and is
* likely to fail if `EvalLists()` was called with a
* language other than English. As such, some plugins that should
* not be cleaned may have the `PluginCleanliness::unknown`
* code outputted.
* @param plugin
* The plugin to look up the cleanliness state for.
* @returns A plugin cleanliness code.
*/
virtual PluginCleanliness GetPluginCleanliness(const std::string& plugin) = 0;
/**
* @}
* @name Miscellaneous
* @{
*/
/**
* @brief Writes a minimal metadata file that only contains plugins with
* Bash Tag suggestions and/or dirty info, plus the suggestions and
* info themselves.
* @param db
* The database the function acts on.
* @param outputFile
* The path to which the file shall be written.
* The path to which the file shall be written.
* @param overwrite
* If `false` and `outputFile` already exists, no data will be
* written. Otherwise, data will be written.
* @returns A return code.
* If `false` and `outputFile` already exists, no data will be
* written. Otherwise, data will be written.
*/
virtual void WriteMinimalList(const std::string& outputFile,
const bool overwrite) = 0;
/**@}*/
/** @} */
};
}
+21 -6
View File
@@ -25,14 +25,29 @@ along with LOOT. If not, see
#ifndef LOOT_GAME_TYPE
#define LOOT_GAME_TYPE
/**
* @file
* @brief Contains the GameType codes used when creating a database handle.
*/
/**
* The namespace used by the LOOT API.
*/
namespace loot {
/** @brief Codes used to create database handles for specific games. */
enum struct GameType : unsigned int {
autodetect = 0,
tes4 = 1,
tes5 = 2,
fo3 = 3,
fonv = 4,
fo4 = 5,
/** Autodetect the game type. **Specifying this will cause an error for API users**. */
autodetect,
/** The Elder Scrolls IV: Oblivion */
tes4,
/** The Elder Scrolls IV: Skyrim */
tes5,
/** Fallout 3 */
fo3,
/** Fallout: New Vegas */
fonv,
/** Fallout 4 */
fo4,
};
}
+29 -11
View File
@@ -25,19 +25,37 @@ along with LOOT. If not, see
#ifndef LOOT_LANGUAGE_CODE
#define LOOT_LANGUAGE_CODE
/**
* @file
* @brief Contains the language codes used when evaluating masterlists and
* userlists.
*/
/**
* The namespace used by the LOOT API.
*/
namespace loot {
/**
* @brief Codes used to specify the preferred language for messages when
* evaluating masterlists and userlists.
* @details If a message is not available in the preferred language, its English
* string will be used. Note that messages with only one language
* string are assumed to be written in English, but this cannot be
* guaranteed (any violations should be reported as bugs so that they
* can be fixed).
*/
enum struct LanguageCode : unsigned int {
english = 1,
spanish = 2,
russian = 3,
french = 4,
chinese = 5,
polish = 6,
brazilian_portuguese = 7,
finnish = 8,
german = 9,
danish = 10,
korean = 11
english,
spanish,
russian,
french,
chinese,
polish,
brazilian_portuguese,
finnish,
german,
danish,
korean
};
}
+20
View File
@@ -43,14 +43,34 @@ properly. */
# define LOOT_API
#endif
/**
* @file
* @brief Contains the class used to get API version information.
*/
namespace loot {
/**
* @brief A purely static class that provides information about the version of
* the LOOT API that is being run.
*/
class LootVersion {
public:
/** @brief The major version number. */
LOOT_API static const unsigned int major;
/** @brief The minor version number. */
LOOT_API static const unsigned int minor;
/** @brief The patch version number. */
LOOT_API static const unsigned int patch;
/** @brief The source control revision that the API was built from. */
LOOT_API static const std::string revision;
/**
* @brief Get the API version as a string.
* @return A string of the form "major.minor.patch".
*/
LOOT_API static std::string string();
};
}
+25
View File
@@ -26,10 +26,35 @@
#include <string>
/**
* @file
* @brief Contains the MasterlistInfo structure.
*/
namespace loot {
/**
* @brief A structure that holds data about a masterlist's source control
* revision.
*/
struct MasterlistInfo {
/**
* @brief The revision hash for the masterlist. If the masterlist doesn't
* exist, or there is no Git repository at its location, this will be
* empty.
*/
std::string revision_id;
/**
* @brief A pointer to a string containing the ISO 8601 formatted revision
* date, ie. YYYY-MM-DD. If the masterlist doesn't exist, or there is
* no Git repository at its location, this will be empty.
*/
std::string revision_date;
/**
* @brief `true` if the masterlist has been edited since the outputted
* revision, or `false` if it is at exactly the revision given.
*/
bool is_modified;
};
}
+21 -3
View File
@@ -25,11 +25,29 @@ along with LOOT. If not, see
#ifndef LOOT_MESSAGE_TYPE
#define LOOT_MESSAGE_TYPE
/**
* @file
* @brief Contains the message type codes used by the PluginMessage structure.
*/
/**
* The namespace used by the LOOT API.
*/
namespace loot {
/** @brief Codes used to indicate the type of a message. */
enum struct MessageType : unsigned int {
say = 0,
warn = 1,
error = 2,
/** A notification message that is of no significant severity. */
say,
/**
* A warning message, used to indicate that an issue may be present that the
* user may wish to act on.
*/
warn,
/**
* An error message, used to indicate that an issue that requires user action
* is present.
*/
error,
};
}
+22
View File
@@ -24,11 +24,33 @@
#ifndef LOOT_PLUGIN_CLEANLINESS
#define LOOT_PLUGIN_CLEANLINESS
/**
* @file
* @brief Contains the plugin cleanliness codes used when getting the
* cleanliness state of a plugin.
*/
/**
* The namespace used by the LOOT API.
*/
namespace loot {
/**
* @brief Codes used to indicate the cleanliness of a plugin according to the
* information contained within the loaded masterlist/userlist.
*/
enum struct PluginCleanliness : unsigned int {
/** Indicates that the plugin is clean. */
clean,
/** Indicates that the plugin is dirty. */
dirty,
/**
* Indicates that the plugin contains dirty edits, but that they are
* part of the plugin's intended functionality and should not be removed.
*/
do_not_clean,
/**
* Indicates that no data is available on whether the plugin is dirty or not.
*/
unknown,
};
}
+12 -14
View File
@@ -26,23 +26,21 @@
#include "loot/message_type.h"
namespace loot {
/**
* @brief A structure that holds the type of a message and the message
* string itself.
* @file
* @brief Contains the PluginMessage structure.
*/
class PluginMessage {
public:
/**
* @var type
* The type of the message, specified using one of the message
* type codes.
* @var text
* The message string, which may be formatted using
* [GitHub Flavored Markdown]
* (https://help.github.com/articles/github-flavored-markdown).
*/
namespace loot {
/** @brief A structure that holds the type of a message and the message string itself. */
struct PluginMessage {
/** @brief The type of the message. */
MessageType type;
/**
* @brief The message string, which may be formatted using
* [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown).
*/
std::string text;
};
}

Some files were not shown because too many files have changed in this diff Show More