From 94dc953ba91da43c4e424ff8439f3396b2519b5c Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Thu, 9 Apr 2020 19:53:59 +0200 Subject: [PATCH] Publish --- .nojekyll | 0 annotated.html | 205 ++ atom-one-dark.css | 96 + base.css | 3 + bgnoise.png | Bin 0 -> 37055 bytes changelog.html | 216 ++ classcti_1_1continuable__base.html | 927 ++++++++ classcti_1_1exceptional__result.html | 206 ++ classcti_1_1promise__base.html | 370 +++ classcti_1_1promisify.html | 262 +++ classcti_1_1result.html | 290 +++ configuration.html | 175 ++ deprecated.html | 174 ++ files.html | 187 ++ group___base.html | 510 +++++ group___connections.html | 460 ++++ group___operations.html | 175 ++ group___primitives.html | 293 +++ group___promisify.html | 193 ++ group___result.html | 288 +++ group___testing.html | 340 +++ group___transforms.html | 190 ++ group___traversal.html | 382 ++++ group___types.html | 247 ++ highlight.min.js | 3 + index.html | 191 ++ installation.html | 201 ++ m-dark+doxygen.compiled.css | 2780 +++++++++++++++++++++++ modules.html | 197 ++ namespacecti.html | 585 +++++ namespacecti_1_1transforms.html | 286 +++ namespaces.html | 194 ++ pages.html | 203 ++ search.js | 786 +++++++ searchdata.js | 2 + structcti_1_1cancellation__result.html | 174 ++ structcti_1_1empty__result.html | 174 ++ structcti_1_1exception__arg__t.html | 174 ++ structcti_1_1is__ready__arg__t.html | 174 ++ structcti_1_1unpack__arg__t.html | 174 ++ structcti_1_1use__continuable__t.html | 207 ++ terminal.css | 85 + terminal.js | 44 + tutorial-awaiting-continuables.html | 219 ++ tutorial-chaining-continuables.html | 276 +++ tutorial-connecting-continuables.html | 256 +++ tutorial-creating-continuables.html | 206 ++ tutorial-promisify-continuables.html | 204 ++ tutorial-transforming-continuables.html | 200 ++ tutorial.html | 175 ++ typed.js | 1040 +++++++++ 51 files changed, 15399 insertions(+) create mode 100644 .nojekyll create mode 100644 annotated.html create mode 100644 atom-one-dark.css create mode 100644 base.css create mode 100644 bgnoise.png create mode 100644 changelog.html create mode 100644 classcti_1_1continuable__base.html create mode 100644 classcti_1_1exceptional__result.html create mode 100644 classcti_1_1promise__base.html create mode 100644 classcti_1_1promisify.html create mode 100644 classcti_1_1result.html create mode 100644 configuration.html create mode 100644 deprecated.html create mode 100644 files.html create mode 100644 group___base.html create mode 100644 group___connections.html create mode 100644 group___operations.html create mode 100644 group___primitives.html create mode 100644 group___promisify.html create mode 100644 group___result.html create mode 100644 group___testing.html create mode 100644 group___transforms.html create mode 100644 group___traversal.html create mode 100644 group___types.html create mode 100644 highlight.min.js create mode 100644 index.html create mode 100644 installation.html create mode 100644 m-dark+doxygen.compiled.css create mode 100644 modules.html create mode 100644 namespacecti.html create mode 100644 namespacecti_1_1transforms.html create mode 100644 namespaces.html create mode 100644 pages.html create mode 100644 search.js create mode 100644 searchdata.js create mode 100644 structcti_1_1cancellation__result.html create mode 100644 structcti_1_1empty__result.html create mode 100644 structcti_1_1exception__arg__t.html create mode 100644 structcti_1_1is__ready__arg__t.html create mode 100644 structcti_1_1unpack__arg__t.html create mode 100644 structcti_1_1use__continuable__t.html create mode 100644 terminal.css create mode 100644 terminal.js create mode 100644 tutorial-awaiting-continuables.html create mode 100644 tutorial-chaining-continuables.html create mode 100644 tutorial-connecting-continuables.html create mode 100644 tutorial-creating-continuables.html create mode 100644 tutorial-promisify-continuables.html create mode 100644 tutorial-transforming-continuables.html create mode 100644 tutorial.html create mode 100644 typed.js diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/annotated.html b/annotated.html new file mode 100644 index 0000000..c968980 --- /dev/null +++ b/annotated.html @@ -0,0 +1,205 @@ + + + + + + + Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

Classes

+
    +
  • + namespace cti Declares the continuable library namespace. +
      +
    • namespace transforms The namespace transforms declares callable objects that transform any continuable_base to an object or to a continuable_base itself.
    • +
    • struct cancellation_result A class which is convertible to any result and that definitely holds a default constructed exception which signals the cancellation of the asynchronous control flow.
    • +
    • class continuable_base The main class of the continuable library, it provides the functionality for chaining callbacks and continuations together to a unified hierarchy.
    • +
    • struct empty_result A class which is convertible to any result and that definitely holds no value so the real result gets invalidated when this object is passed to it.
    • +
    • struct exception_arg_t Represents the tag type that is used to disambiguate the callback operator() in order to take the exception asynchronous chain.
    • +
    • class exceptional_result A class which is convertible to any result and that holds an exception which is then passed to the converted result object.
    • +
    • struct is_ready_arg_t Represents the tag type that is used to query the continuation for whether it resolves the callback instantly with its arguments without having side effects.
    • +
    • class promise_base The promise_base makes it possible to resolve an asynchronous continuable through it's result or through an error type.
    • +
    • class promisify Helper class for converting callback taking callable types into a a continuable. Various styles are supported.
    • +
    • class result The result class can carry the three kinds of results an asynchronous operation possibly can return, it's implemented in a variant like data structure which is also specialized to hold arbitrary arguments.
    • +
    • struct unpack_arg_t Represents the tag type that is used to unpack the result of a continuation.
    • +
    • struct use_continuable_t Type used as an ASIO completion token to specify an asynchronous operation that should return a continuable_base.
    • + +
    +
  • +
+ +
+
+
+
+ + + + + + diff --git a/atom-one-dark.css b/atom-one-dark.css new file mode 100644 index 0000000..1616aaf --- /dev/null +++ b/atom-one-dark.css @@ -0,0 +1,96 @@ +/* + +Atom One Dark by Daniel Gamage +Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax + +base: #282c34 +mono-1: #abb2bf +mono-2: #818896 +mono-3: #5c6370 +hue-1: #56b6c2 +hue-2: #61aeee +hue-3: #c678dd +hue-4: #98c379 +hue-5: #e06c75 +hue-5-2: #be5046 +hue-6: #d19a66 +hue-6-2: #e6c07b + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #abb2bf; + background: #282c34; +} + +.hljs-comment, +.hljs-quote { + color: #5c6370; + font-style: italic; +} + +.hljs-doctag, +.hljs-keyword, +.hljs-formula { + color: #c678dd; +} + +.hljs-section, +.hljs-name, +.hljs-selector-tag, +.hljs-deletion, +.hljs-subst { + color: #e06c75; +} + +.hljs-literal { + color: #56b6c2; +} + +.hljs-string, +.hljs-regexp, +.hljs-addition, +.hljs-attribute, +.hljs-meta-string { + color: #98c379; +} + +.hljs-built_in, +.hljs-class .hljs-title { + color: #e6c07b; +} + +.hljs-attr, +.hljs-variable, +.hljs-template-variable, +.hljs-type, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-number { + color: #d19a66; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-link, +.hljs-meta, +.hljs-selector-id, +.hljs-title { + color: #61aeee; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-link { + text-decoration: underline; +} diff --git a/base.css b/base.css new file mode 100644 index 0000000..3a954dc --- /dev/null +++ b/base.css @@ -0,0 +1,3 @@ +main { + background: url(bgnoise.png); +} diff --git a/bgnoise.png b/bgnoise.png new file mode 100644 index 0000000000000000000000000000000000000000..2912433c798f2343845739a8a41d16236689816a GIT binary patch literal 37055 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 R{l)+Q002ovPDHLkV1nTM6rTV9 literal 0 HcmV?d00001 diff --git a/changelog.html b/changelog.html new file mode 100644 index 0000000..91ccca4 --- /dev/null +++ b/changelog.html @@ -0,0 +1,216 @@ + + + + + + + Changelog | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Changelog +

+ +

A description of the changes made to continuable.

+

Versions

Following versions were released:

4.0.0

Various issues have been resolved:

Following methods and functions have been added:

Various improvements to continuable_base:

An asychronous initiation function comparable to std::async:

The asynchronous facilities make it possible now to start with a handler instead of a continuation:

async([] {
+  // ...
+}).then(...);
  • async Makes it possible to start with a handler instead of a continuation, comparable to std::async
  • async_on allows to specify an additional executor parameter

The result class and modifying the asynchronous control flow

Every continuation handler used in continuable_base::then, continuable_base::next and continuable_base::fail allows now to return a result which represents the asynchronous result.

This allows recovering from failures or throwing of exception types from handlers when exceptions are disabled.

Result handling and

  • result
  • rethrow Throws an exception or error code from a result or failure handler
  • cancel Throws a default constructed exception type or error code from a result or failure handler to signal cancellation.
  • stop Can be used to stop an asynchronous continuation chain, no handler which comes after stop was received won't be called.
  • make_result Creates a present result from the given values.

Special result types

  • empty_result A class which is convertible to any result and that definitely holds no value so the real result gets invalidated when this object is passed to it.
  • cancellation_result A class which is convertible to any result and that definitely holds a default constructed exception which signals the cancellation of the asynchronous control flow.
  • exceptional_result A class which is convertible to any result and that holds an exception which is then passed to the converted result object.

Optimize 'ready' continuables:

Continuables which are 'ready' and side effect free can now be unpacked synchronously. Mainly such continuables are created through make_ready_continuable, make_exceptional_continuable and make_cancelling_continuable.

  • continuable_base::is_ready Returns true when the continuable can provide its result immediately, and its lazy invocation would be side-effect free.
  • continuable_base::unpack Invalidates the continuable and returns its immediate invocation result.
  • make_cancelling_continuable Returns a continuable_base with the parameterized result which never resolves its promise and thus cancels the asynchronous continuation chain through throwing a default constructed exception_t.

Including various helper tags for the underlying changed continuation object structure:

asio asynchronous initiate token:

The use_continuable_t special tag can be used to make (boost) asio return a continuable_base.

#include <continuable/continuable.hpp>
+#include <continuable/external/asio.hpp>
+#include <asio.hpp>
+
+// ...
+
+asio::tcp::resolver resolver(...);
+resolver.async_resolve("127.0.0.1", "daytime", cti::use_continuable)
+  .then([](asio::udp::resolver::iterator iterator) {
+    // ...
+  });

Iterating over an asynchronous control flow:

The loop function was added which makes is possible to emulate an asynchronous loop, that is comparable to a co_await with for.

  • loop
  • loop_result Can be used to indicate a specific result inside an asynchronous loop.
  • loop_break Can be used to create a loop_result which causes the loop to be cancelled and resolved with the given arguments.
  • loop_continue Can be used to create a loop_result which causes the loop to be repeated.
  • range_loop Can be used to create an asynchronous loop over a specific range.
  • range_loop Can be used to create an asynchronous loop over a specific range.
  • plain_t Represents the type that is used to disable the special meaning of types which are returned by a asynchronous result handler. See cti::plain for details.
  • make_plain Can be used to disable the special meaning for a returned value in asynchronous handler functions.

Synchronous wait transforms:

The wait transforms allows to block the current thread until a continuable_base was resolved.

Various changes:

Many more unlisted changes including:

Additional various bugfixes have been made.

3.0.0

New helper functions

New helper functions were added to create ready continuables:

Improvements to connections

The implementation of connections were rewritten entirely. It is possible now to connect runtime sized containers as well as deeply nested sequences. See Connecting continuables for details.

Additionally connection overloads were added that accept two iterators in order to come closer to the interface of the standard library.

Also populate was added which makes it possible to populate a dynamic container from continuable_base objects.

Disabled copies for promises and continuables entirely

The promise_base and continuable_base is now non copyable. This change should make it easier to work with the move only semantic of continuables in order to make less mistakes.

Traversal API

A new traversal API for synchronous and asynchronous pack traversal was added which makes it easy to specify new connection types.

2.0.0

Error handling

Usually it is inconvenient to handle error codes and exceptions in an asynchronous context, as we all know std::future supports error handling through exceptions already. We now introduce this capability to the continuable library while allowing error codes to be used as well.

Consider the function cti::continuable<> get_bad_continuable() which always resolves through an error, then you may handle the error code or exception as following:

get_bad_continuable()
+  .then([] {
+    // ... never invoked
+  })
+  .then([] {
+    // ... never invoked as well
+  })
+  .fail([] (std::exception_ptr e) {
+    try {
+      std::rethrow_exception(e);
+    } catch(std::exception const& e) {
+      // Handle the exception here
+    }
+  });

Abstracting callbacks as promises

Since a callback may be called through an error or result the cri::promise class was added in order ro provide a similar interface to std::promise:

auto http_request(std::string url) {
+  return cti::make_continuable<std::string>(
+    [url = std::move(url)](cti::promise<std::string> promise) {
+      // Perform the actual request through a different library,
+      // resolve the promise upon completion of the task.
+      promise.set_value("<html> ... </html>");
+      // ...or promise.set_exception(...);
+    });
+}

co_await support

Experimental coroutine (co_await and co_return) support was added, this is available on MSVC 2017 and Clang 5.0.

int i = co_await cti::make_continuable<int>([](auto&& promise) {
+  promise.set_value(0);
+});

Minor improvements

The library was improved in other ways:

  • constexpr and noexcept improvements
  • Compile-time improvements
  • Documentation improvements

Header split

Since the overall library size was increased the headers were split into smaller chunks.

1.0.0

  • Documentation and readme changes
  • Change the assertion type of some GTest macros from expected to assertion.

0.8.0 (unstable)

  • Fixes a major issue with handling the ownership for consumed continuables which led to unintended invocations.
  • Adds partial application support which makes it possible to chain callbacks which accept less arguments then the curret signature.

    http_request("github.com")
    +  .then([] {
    +    // ...
    +  });
  • Adds Support for sequential invocation:

    http_request("github.com") >> http_request("atom.io")
    +  .then([] (std::string github, std::string atom) {
    +    // ...
    +  });

0.7.0 (unstable)

  • Continuation syntactic sugar
  • Executor support
  • Connection support

Semantic versioning and stability

Continuable strictly follows the rules of semantic versioning, the API is kept stable across minor versions.

The CI driven unit-tests are observed through the Clang sanitizers (asan, ubsan and lsan - when compiling with Clang) or Valgrind (when compiling with GCC) in order to prevent regressions.

+
+
+
+
+ + + + + + diff --git a/classcti_1_1continuable__base.html b/classcti_1_1continuable__base.html new file mode 100644 index 0000000..875466d --- /dev/null +++ b/classcti_1_1continuable__base.html @@ -0,0 +1,927 @@ + + + + + + + cti::continuable_base class | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+
template<typename Data, typename Annotation>
+ cti::continuable_base class +

+

The main class of the continuable library, it provides the functionality for chaining callbacks and continuations together to a unified hierarchy.

+ + + + + + + + + + + + + + +
Template parameters
DataThe internal data which is used to store the current continuation and intermediate lazy connection result.
AnnotationThe internal data used to store the current signature hint or strategy used for combining lazy connections.
+
+

Contents

+ +
+

The most important method is the cti::continuable_base::then() method, which allows to attach a callback to the continuable.

Use the continuable types defined in continuable/continuable.hpp, in order to use this class.

+
+

Constructors, destructors, conversion operators

+
+
+ continuable_base(Data data) explicit +
+
Constructor accepting the data object while erasing the annotation.
+
+
template<typename OtherData, std::enable_if_t<detail::base::can_accept_continuation<Data, Annotation, detail::traits::unrefcv_t<OtherData>>::value>* = nullptr>
+ continuable_base(OtherData&& data) +
+
Constructor accepting any object convertible to the data object, while erasing the annotation.
+
+
template<typename OData, std::enable_if_t<std::is_convertible<detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr>
+ continuable_base(continuable_base<OData, Annotation>&& other) +
+
Constructor taking the data of other continuable_base objects while erasing the hint.
+
+
template<typename OData, typename OAnnotation>
+ continuable_base(continuable_base<OData, OAnnotation>&& other) +
+
Constructor taking the data of other continuable_base objects while erasing the hint.
+
+ ~continuable_base() +
+
The destructor automatically invokes the continuable_base if it wasn't consumed yet.
+
+
+
+

Public functions

+
+
+
template<typename T, typename E = detail::types::this_thread_executor_tag>
+ auto then(T&& callback, + E&& executor = detail::types::this_thread_executor_tag{}) && -> auto +
+
Main method of the continuable_base to chain the current continuation with a new callback.
+
+
template<typename OData, typename OAnnotation>
+ auto then(continuable_base<OData, OAnnotation>&& continuation) && -> auto +
+
Additional overload of the continuable_base::then() method which is accepting a continuable_base itself.
+
+
template<typename T, typename E = detail::types::this_thread_executor_tag>
+ auto fail(T&& callback, + E&& executor = detail::types::this_thread_executor_tag{}) && -> auto +
+
Main method of the continuable_base to catch exceptions and error codes in case the asynchronous control flow failed and was resolved through an error code or exception.
+
+
template<typename OData, typename OAnnotation>
+ auto fail(continuable_base<OData, OAnnotation>&& continuation) && -> auto +
+
Additional overload of the continuable_base::fail() method which is accepting a continuable_base itself.
+
+
template<typename T, typename E = detail::types::this_thread_executor_tag>
+ auto next(T&& callback, + E&& executor = detail::types::this_thread_executor_tag{}) && -> auto +
+
A method which allows to use an overloaded callable for the error as well as the valid result path.
+
+
template<typename... Args>
+ auto as() && -> auto +
+
Returns a continuable_base which will have its signature converted to the given Args.
+
+
template<typename T>
+ auto apply(T&& transform) && -> auto +
+
A method which allows to apply a callable object to this continuable.
+
+
template<typename T>
+ auto operator|(T&& right) && -> auto +
+
The pipe operator | is an alias for the continuable::then method.
+
+
template<typename OData, typename OAnnotation>
+ auto operator&&(continuable_base<OData, OAnnotation>&& right) && -> auto +
+
Invokes both continuable_base objects parallel and calls the callback with the result of both continuable_base objects.
+
+
template<typename OData, typename OAnnotation>
+ auto operator||(continuable_base<OData, OAnnotation>&& right) && -> auto +
+
Invokes both continuable_base objects parallel and calls the callback once with the first result available.
+
+
template<typename OData, typename OAnnotation>
+ auto operator>>(continuable_base<OData, OAnnotation>&& right) && -> auto +
+
Invokes both continuable_base objects sequential and calls the callback with the result of both continuable_base objects.
+
+ void done() && +
+
Invokes the continuation chain manually even before the cti::continuable_base is destructed. This will release the object.
+
+ auto finish() && -> auto +
+
Materializes the continuation expression template and finishes the current applied strategy such that the resulting continuable will always be a concrete type and Continuable::is_concrete holds.
+
+ auto is_ready() const -> bool noexcept +
+
Returns true when the continuable can provide its result immediately, and its lazy invocation would be side-effect free.
+
+ auto unpack() && -> auto +
+
Invalidates the continuable and returns its immediate invocation result.
+
+ auto is_frozen() const -> bool noexcept +
+
Predicate to check whether the cti::continuable_base is frozen or not.
+
+ auto freeze(bool enabled = true) &noexcept -> continuable_base& +
+
Prevents the automatic invocation of the continuation chain which happens on destruction of the continuable_base. You may still invoke the chain through the continuable_base::done method.
+
+ auto freeze(bool enabled = true) &&noexcept -> continuable_base&& +
+
Prevents the automatic invocation of the continuation chain which happens on destruction of the continuable_base. You may still invoke the chain through the continuable_base::done method.
+
+ auto operator co_await() && -> auto +
+
Implements the operator for awaiting on continuables using co_await.
+
+
+
+

Function documentation

+
+

+
+ template<typename Data, typename Annotation> + template<typename OData, std::enable_if_t<std::is_convertible<detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr> +
+ cti::continuable_base<Data, Annotation>::continuable_base(continuable_base<OData, Annotation>&& other) +

+

Constructor taking the data of other continuable_base objects while erasing the hint.

+

This constructor makes it possible to replace the internal data object of the continuable by any object which is useful for type-erasure.

+
+
+

+
+ template<typename Data, typename Annotation> + template<typename OData, typename OAnnotation> +
+ cti::continuable_base<Data, Annotation>::continuable_base(continuable_base<OData, OAnnotation>&& other) +

+

Constructor taking the data of other continuable_base objects while erasing the hint.

+

This constructor makes it possible to replace the internal data object of the continuable by any object which is useful for type-erasure.

+
+
+

+
+ template<typename Data, typename Annotation> +
+ cti::continuable_base<Data, Annotation>::~continuable_base() +

+

The destructor automatically invokes the continuable_base if it wasn't consumed yet.

+

In order to invoke the continuable early you may call the continuable_base::done() method.

The continuable_base::freeze method disables the automatic invocation on destruction without invalidating the object.

+
+
+

+
+ template<typename Data, typename Annotation> + template<typename T, typename E = detail::types::this_thread_executor_tag> +
+ auto cti::continuable_base<Data, Annotation>::then(T&& callback, + E&& executor = detail::types::this_thread_executor_tag{}) && +

+

Main method of the continuable_base to chain the current continuation with a new callback.

+ + + + + + + + + + + + + + + + + + + + +
Parameters
callback

The callback which is used to process the current asynchronous result on arrival. The callback is required to accept the current result at least partially (or nothing of the result).

(http_request("github.com") && http_request("atom.io"))
+  .then([](std::string github, std::string atom) {
+    // We use the whole result
+  });
+
+(http_request("github.com") && http_request("atom.io"))
+  .then([](std::string github) {
+    // We only use the result partially
+  });
+
+(http_request("github.com") && http_request("atom.io"))
+  .then([] {
+    // We discard the result
+  });
executor

The optional executor which is used to dispatch the callback. The executor needs to accept callable objects callable through an operator() through its operator() itself. The executor can be move-only, but it's not required to. The default executor which is used when omitting the argument dispatches the callback on the current executing thread. Consider the example shown below:

auto executor = [](auto&& work) {
+  // Dispatch the work here or forward it to an executor of
+  // your choice.
+  std::forward<decltype(work)>(work)();
+};
+
+http_request("github.com")
+  .then([](std::string github) {
+    // Do something...
+   }, executor);
Returns

Returns a continuable_base with an asynchronous return type depending on the return value of the callback:

Callback returnsResulting type
voidcontinuable_base with <>
Argcontinuable_base with <Arg>
std::pair<First, Second>continuable_base with <First, Second>
std::tuple<Args...>continuable_base with <Args...>
cti::result<Args...>continuable_base with <Args...>
continuable_base<Arg...>continuable_base with <Args...>

Which means the result type of the continuable_base is equal to the plain types the callback returns (std::tuple and std::pair arguments are unwrapped). A single continuable_base as argument is resolved and the result type is equal to the resolved continuable_base. A cti::result can be used to cancel the continuation or to transition to the exception handler. The special unwrapping of types can be disabled through wrapping such objects through a call to cti::make_plain. Consider the following examples:

http_request("github.com")
+  .then([](std::string github) { return; })
+  .then([] { }); // <void>
+
+http_request("github.com")
+  .then([](std::string github) { return 0; })
+  .then([](int a) { }); // <int>
+
+http_request("github.com")
+  .then([](std::string github) { return std::make_pair(1, 2); })
+  .then([](int a, int b) { }); // <int, int>
+
+http_request("github.com")
+  .then([](std::string github) { return std::make_tuple(1, 2, 3); })
+  .then([](int a, int b, int c) { }); // <int, int, int>
+
+http_request("github.com")
+  .then([](std::string github) { return http_request("atom.io"); })
+  .then([](std::string atom) { }); // <std::string>
+
+http_request("example.com")
+  .then([](std::string content) -> result<std::string> {
+    return rethrow(std::make_exception_ptr(std::exception{}));
+  })
+  .fail([] -> result<std::string> {
+    return recover("Hello World!");
+  })
+  .then([](std::string content) -> result<std::string> {
+    return cancel();
+  })
+ +
+
+

+
+ template<typename Data, typename Annotation> + template<typename OData, typename OAnnotation> +
+ auto cti::continuable_base<Data, Annotation>::then(continuable_base<OData, OAnnotation>&& continuation) && +

+

Additional overload of the continuable_base::then() method which is accepting a continuable_base itself.

+ + + + + + + + + + + + + + + + +
Parameters
continuation

A continuable_base reflecting the continuation which is used to continue the call hierarchy. The result of the current continuable is discarded and the given continuation is invoked as shown below.

http_request("github.com")
+  .then(http_request("atom.io"))
+  .then([](std::string atom) {
+    // ...
+  });
ReturnsReturns a continuable_base representing the next asynchronous result to continue within the asynchronous call hierarchy.
+ +
+
+

+
+ template<typename Data, typename Annotation> + template<typename T, typename E = detail::types::this_thread_executor_tag> +
+ auto cti::continuable_base<Data, Annotation>::fail(T&& callback, + E&& executor = detail::types::this_thread_executor_tag{}) && +

+

Main method of the continuable_base to catch exceptions and error codes in case the asynchronous control flow failed and was resolved through an error code or exception.

+ + + + + + + + + + + + + + + + + + + + +
Parameters
callbackThe callback which is used to process the current asynchronous error result on arrival. In case the continuable_base is using exceptions, the usage is as shown below:
executorThe optional executor which is used to dispatch the callback. See the description in then above.
ReturnsReturns a continuable_base with an asynchronous return type depending on the previous result type.
+
http_request("github.com")
+  .then([](std::string github) { })
+  .fail([](std::exception_ptr ep) {
+    // Check whether the exception_ptr is valid (not default constructed)
+    // if bool(ep) == false this means that the operation was cancelled
+    // by the user or application (promise.set_canceled() or
+    // make_cancelling_continuable()).
+    if (ep) {
+      // Handle the error here
+      try {
+        std::rethrow_exception(ep);
+      } catch (std::exception& e) {
+        e.what(); // Handle the exception
+      }
+    }
+  });

In case exceptions are disabled, std::error_condition is used as error result instead of std::exception_ptr.

http_request("github.com")
+  .then([](std::string github) { })
+  .fail([](std::error_condition error) {
+    error.message(); // Handle the error here
+  });
+
+
+

+
+ template<typename Data, typename Annotation> + template<typename OData, typename OAnnotation> +
+ auto cti::continuable_base<Data, Annotation>::fail(continuable_base<OData, OAnnotation>&& continuation) && +

+

Additional overload of the continuable_base::fail() method which is accepting a continuable_base itself.

+ + + + + + + + + + + + + + + + +
Parameters
continuation

A continuable_base reflecting the continuation which is used to continue the call hierarchy on errors. The result of the current continuable is discarded and the given continuation is invoked as shown below.

http_request("github.com")
+  .fail(http_request("atom.io"))
ReturnsReturns a continuable_base with an asynchronous return type depending on the previous result type.
+ +
+
+

+
+ template<typename Data, typename Annotation> + template<typename T, typename E = detail::types::this_thread_executor_tag> +
+ auto cti::continuable_base<Data, Annotation>::next(T&& callback, + E&& executor = detail::types::this_thread_executor_tag{}) && +

+

A method which allows to use an overloaded callable for the error as well as the valid result path.

+ + + + + + + + + + + + + + + + + + + + +
Parameters
callbackThe callback which is used to process the current asynchronous result and error on arrival.
executorThe optional executor which is used to dispatch the callback. See the description in then above.
ReturnsReturns a continuable_base with an asynchronous return type depending on the current result type.
+
struct my_callable {
+  void operator() (std::string result) {
+    // ...
+  }
+  void operator() (cti::exception_arg_t, cti::exception_t) {
+    // ...
+  }
+
+// Will receive errors and results
+http_request("github.com")
+  .next(my_callable{});
+
+
+

+
+ template<typename Data, typename Annotation> + template<typename... Args> +
+ auto cti::continuable_base<Data, Annotation>::as() && +

+

Returns a continuable_base which will have its signature converted to the given Args.

+ + + + + + + +
ReturnsReturns a continuable_base with an asynchronous return type matching the given Args.
+

A signature can only be converted if it can be partially applied from the previous one as shown below: continuable<long> c = make_ready_continuable(0, 1, 2).as<long>();

+
+
+

+
+ template<typename Data, typename Annotation> + template<typename T> +
+ auto cti::continuable_base<Data, Annotation>::apply(T&& transform) && +

+

A method which allows to apply a callable object to this continuable.

+ + + + + + + + + + + + + + + + +
Parameters
transformA callable objects that transforms a continuable to a different object.
ReturnsReturns the result of the given transform when this continuable is passed into it.
+ +
+
+

+
+ template<typename Data, typename Annotation> + template<typename T> +
+ auto cti::continuable_base<Data, Annotation>::operator|(T&& right) && +

+

The pipe operator | is an alias for the continuable::then method.

+ + + + + + + + + + + + + + + + +
Parameters
rightThe argument on the right-hand side to connect.
ReturnsSee the corresponding continuable_base::then method for the explanation of the return type.
+ +
+
+

+
+ template<typename Data, typename Annotation> + template<typename OData, typename OAnnotation> +
+ auto cti::continuable_base<Data, Annotation>::operator&&(continuable_base<OData, OAnnotation>&& right) && +

+

Invokes both continuable_base objects parallel and calls the callback with the result of both continuable_base objects.

+ + + + + + + + + + + + + + + + +
Parameters
rightThe continuable on the right-hand side to connect.
Returns

Returns a continuable_base with a result type matching the result of the left continuable_base combined with the right continuable_base. The returned continuable_base will be in an intermediate lazy state, further calls to its continuable_base::operator && will add other continuable_base objects to the current invocation chain.

(http_request("github.com") && http_request("atom.io"))
+  .then([](std::string github, std::string atom) {
+    // ...
+  });
+
+auto request = http_request("github.com") && http_request("atom.io");
+(std::move(request) && http_request("travis-ci.org"))
+   // All three requests are invoked in parallel although we added
+   // the request to "travis-ci.org" last.
+  .then([](std::string github, std::string atom, std::string travis) {
+    // ...
+  });
+ +
+
+

+
+ template<typename Data, typename Annotation> + template<typename OData, typename OAnnotation> +
+ auto cti::continuable_base<Data, Annotation>::operator||(continuable_base<OData, OAnnotation>&& right) && +

+

Invokes both continuable_base objects parallel and calls the callback once with the first result available.

+ + + + + + + + + + + + + + + + +
Parameters
rightThe continuable on the right-hand side to connect. The right continuable is required to have the same result as the left connected continuable_base.
Returns

Returns a continuable_base with a result type matching the combined result which of all connected continuable_base objects. The returned continuable_base will be in an intermediate lazy state, further calls to its continuable_base::operator || will add other continuable_base objects to the current invocation chain.

(http_request("github.com") || http_request("atom.io"))
+  .then([](std::string github_or_atom) {
+    // ...
+  });
+
+(make_ready_continuable(10, 'A') || make_ready_continuable(29, 'B'))
+  .then([](int a, char b) {
+    // ...
+  });
+ +
+
+

+
+ template<typename Data, typename Annotation> + template<typename OData, typename OAnnotation> +
+ auto cti::continuable_base<Data, Annotation>::operator>>(continuable_base<OData, OAnnotation>&& right) && +

+

Invokes both continuable_base objects sequential and calls the callback with the result of both continuable_base objects.

+ + + + + + + + + + + + + + + + +
Parameters
rightThe continuable on the right-hand side to connect.
Returns

Returns a continuable_base with a result type matching the result of the left continuable_base combined with the right continuable_base.

(http_request("github.com") >> http_request("atom.io"))
+  .then([](std::string github, std::string atom) {
+    // The callback is called with the result of both requests,
+    // however, the request to atom was started after the request
+    // to github was finished.
+  });
+ +
+
+

+
+ template<typename Data, typename Annotation> +
+ void cti::continuable_base<Data, Annotation>::done() && +

+

Invokes the continuation chain manually even before the cti::continuable_base is destructed. This will release the object.

+ +
+
+

+
+ template<typename Data, typename Annotation> +
+ auto cti::continuable_base<Data, Annotation>::finish() && +

+

Materializes the continuation expression template and finishes the current applied strategy such that the resulting continuable will always be a concrete type and Continuable::is_concrete holds.

+

This can be used in the case where we are chaining continuations lazily through a strategy, for instance when applying operators for expressing connections and then want to return a materialized continuable_base which uses the strategy respectively.

auto do_both() {
+  return (wait(10s) || wait_key_pressed(KEY_SPACE)).finish();
+}
+
+// Without a call to finish() this would lead to
+// an unintended evaluation strategy:
+do_both() || wait(5s);
+
+
+

+
+ template<typename Data, typename Annotation> +
+ bool cti::continuable_base<Data, Annotation>::is_ready() const noexcept +

+

Returns true when the continuable can provide its result immediately, and its lazy invocation would be side-effect free.

+ +
+
+

+
+ template<typename Data, typename Annotation> +
+ auto cti::continuable_base<Data, Annotation>::unpack() && +

+

Invalidates the continuable and returns its immediate invocation result.

+ + + + + + + +
ReturnsA result<Args...> where Args... represent the current asynchronous parameters or the currently stored exception.
+

This method can be used to specialize the asynchronous control flow based on whether the continuable_base is_ready at every time, which is true for a continuable created through the following functions:

  • make_ready_continuable
  • make_exceptional_continuable
+
+
+

+
+ template<typename Data, typename Annotation> +
+ bool cti::continuable_base<Data, Annotation>::is_frozen() const noexcept +

+

Predicate to check whether the cti::continuable_base is frozen or not.

+ + + + + + + +
ReturnsReturns true when the continuable_base is frozen.
+ +
+
+

+
+ template<typename Data, typename Annotation> +
+ continuable_base& cti::continuable_base<Data, Annotation>::freeze(bool enabled = true) &noexcept +

+

Prevents the automatic invocation of the continuation chain which happens on destruction of the continuable_base. You may still invoke the chain through the continuable_base::done method.

+ + + + + + + + + + +
Parameters
enabledIndicates whether the freeze is enabled or disabled.
+

This is useful for storing a continuable_base inside a continuation chain while storing it for further usage.

+
+
+

+
+ template<typename Data, typename Annotation> +
+ continuable_base&& cti::continuable_base<Data, Annotation>::freeze(bool enabled = true) &&noexcept +

+

Prevents the automatic invocation of the continuation chain which happens on destruction of the continuable_base. You may still invoke the chain through the continuable_base::done method.

+ + + + + + + + + + +
Parameters
enabledIndicates whether the freeze is enabled or disabled.
+

This is useful for storing a continuable_base inside a continuation chain while storing it for further usage.

+
+
+

+
+ template<typename Data, typename Annotation> +
+ auto cti::continuable_base<Data, Annotation>::operator co_await() && +

+

Implements the operator for awaiting on continuables using co_await.

+

The operator is only enabled if CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE is defined and the toolchain supports experimental coroutines.

The return type of the co_await expression is specified as following:

Continuation typeco_await returns
continuable_base with <>void
continuable_base with <Arg>Arg
continuable_base with <Args...>std::tuple<Args...>

When exceptions are used the usage is as intuitive as shown below:

// Handling the exception isn't required and
+// the try catch clause may be omitted.
+try {
+  std::string response = co_await http_request("github.com");
+} (std::exception& e) {
+  e.what();
+}

In case the library is configured to use error codes or a custom exception type the return type of the co_await expression is changed. The result is returned through a cti::result<...>.

Continuation typeco_await returns
continuable_base with <>result<void>
continuable_base with <Arg>result<Arg>
continuable_base with <Args...>result<Args...>
+
+
+
+
+
+
+ + + + + + diff --git a/classcti_1_1exceptional__result.html b/classcti_1_1exceptional__result.html new file mode 100644 index 0000000..fa1a474 --- /dev/null +++ b/classcti_1_1exceptional__result.html @@ -0,0 +1,206 @@ + + + + + + + cti::exceptional_result class | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ cti::exceptional_result class +

+

A class which is convertible to any result and that holds an exception which is then passed to the converted result object.

+
+

Contents

+ +
+ +
+

Public functions

+
+
+ void set_exception(exception_t exception) +
+
Sets an exception.
+
+ auto get_exception() &noexcept -> exception_t& +
+
Returns the contained exception.
+
+ auto get_exception() const &noexcept -> exception_t const & +
+
Returns the contained exception.
+
+ auto get_exception() &&noexcept -> exception_t&& +
+
Returns the contained exception.
+
+
+
+
+
+
+ + + + + + diff --git a/classcti_1_1promise__base.html b/classcti_1_1promise__base.html new file mode 100644 index 0000000..92c3444 --- /dev/null +++ b/classcti_1_1promise__base.html @@ -0,0 +1,370 @@ + + + + + + + cti::promise_base class | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+
template<typename Data, typename Hint>
+ cti::promise_base class +

+

The promise_base makes it possible to resolve an asynchronous continuable through it's result or through an error type.

+
+

Contents

+ +
+

Use the promise type defined in continuable/continuable_types.hpp, in order to use this class.

If we want to resolve the promise_base trough the call operator, and we want to resolve it through an exception, we must call it with a exception_arg_t as first and the exception as second argument. Additionally the promise is resolveable only through its call operator when invoked as an r-value.

+
+

Constructors, destructors, conversion operators

+
+
+ promise_base() defaulted explicit +
+
Constructor for constructing an empty promise.
+
+ promise_base(Data data) explicit +
+
Constructor accepting the data object.
+
+
template<typename OData, std::enable_if_t<std::is_convertible<detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr>
+ promise_base(OData&& data) +
+
Constructor accepting any object convertible to the data object.
+
+ operator bool() const explicit noexcept +
+
Returns true if the continuation is valid (non empty).
+
+
+
+

Public functions

+
+
+
template<typename OData, std::enable_if_t<std::is_convertible<detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr>
+ auto operator=(OData&& data) -> promise_base& +
+
Assignment operator accepting any object convertible to the data object.
+
+ void operator()(Args... args) &&noexcept +
+
Resolves the continuation with the given values.
+
+ void operator()(exception_arg_t tag, + exception_t exception) &&noexcept +
+
Resolves the continuation with the given exception.
+
+ void set_value(Args... args) noexcept +
+
Resolves the continuation with the given values.
+
+ void set_exception(exception_t exception) noexcept +
+
Resolves the continuation with the given exception.
+
+ void set_canceled() noexcept +
+
Resolves the continuation with the cancellation token which is represented by a default constructed exception_t.
+
+
+
+

Function documentation

+
+

+
+ template<typename Data, typename Hint> +
+ cti::promise_base<Data, Hint>::operator bool() const explicit noexcept +

+

Returns true if the continuation is valid (non empty).

+ + + + + + + + + + +
Exceptions
Thismethod never throws an exception.
+ +
+
+

+
+ template<typename Data, typename Hint> +
+ void cti::promise_base<Data, Hint>::operator()(Args... args) &&noexcept +

+

Resolves the continuation with the given values.

+ + + + + + + + + + +
Exceptions
Thismethod never throws an exception.
+ +
+
+

+
+ template<typename Data, typename Hint> +
+ void cti::promise_base<Data, Hint>::operator()(exception_arg_t tag, + exception_t exception) &&noexcept +

+

Resolves the continuation with the given exception.

+ + + + + + + + + + +
Exceptions
Thismethod never throws an exception.
+ +
+
+

+
+ template<typename Data, typename Hint> +
+ void cti::promise_base<Data, Hint>::set_value(Args... args) noexcept +

+

Resolves the continuation with the given values.

+ + + + + + + + + + +
Exceptions
Thismethod never throws an exception.
+ +
+
+

+
+ template<typename Data, typename Hint> +
+ void cti::promise_base<Data, Hint>::set_exception(exception_t exception) noexcept +

+

Resolves the continuation with the given exception.

+ + + + + + + + + + +
Exceptions
Thismethod never throws an exception.
+ +
+
+

+
+ template<typename Data, typename Hint> +
+ void cti::promise_base<Data, Hint>::set_canceled() noexcept +

+

Resolves the continuation with the cancellation token which is represented by a default constructed exception_t.

+ + + + + + + + + + +
Exceptions
Thismethod never throws an exception.
+ +
+
+
+
+
+
+ + + + + + diff --git a/classcti_1_1promisify.html b/classcti_1_1promisify.html new file mode 100644 index 0000000..5d47006 --- /dev/null +++ b/classcti_1_1promisify.html @@ -0,0 +1,262 @@ + + + + + + + cti::promisify class | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+
template<typename... Result>
+ cti::promisify class +

+

Helper class for converting callback taking callable types into a a continuable. Various styles are supported.

+ + + + + + + + + + +
Template parameters
ResultThe result of the converted continuable, this should align with the arguments that are passed to the callback.
+
+

Contents

+ +
+
  • from: Converts callback taking callable types into continuables which pass an error code as first parameter and the rest of the result afterwards.
+
+

Public static functions

+
+
+
template<typename Callable, typename... Args>
+ static auto from(Callable&& callable, + Args && ... args) -> auto +
+
Converts callback taking callable types into a continuable. This applies to calls which pass an error code as first parameter and the rest of the asynchronous result afterwards.
+
+
template<typename Resolver, typename Callable, typename... Args>
+ static auto with(Resolver&& resolver, + Callable&& callable, + Args && ... args) -> auto +
+
Converts callback taking callable types into a continuable. This applies to calls which pass an error code as first parameter and the rest of the asynchronous result afterwards.
+
+
+
+

Function documentation

+
+

+
+ template<typename... Result> + template<typename Callable, typename... Args> +
+ static auto cti::promisify<Result>::from(Callable&& callable, + Args && ... args) +

+

Converts callback taking callable types into a continuable. This applies to calls which pass an error code as first parameter and the rest of the asynchronous result afterwards.

+

See an example of how to promisify boost asio's async_resolve below:

auto async_resolve(std::string host, std::string service) {
+  return cti::promisify<asio::ip::udp::resolver::iterator>::from(
+      [&](auto&&... args) {
+        resolver_.async_resolve(std::forward<decltype(args)>(args)...);
+      },
+      std::move(host), std::move(service));
+}

A given error variable is converted to the used error type. If this isn't possible you need to create a custom resolver callable object

+
+
+

+
+ template<typename... Result> + template<typename Resolver, typename Callable, typename... Args> +
+ static auto cti::promisify<Result>::with(Resolver&& resolver, + Callable&& callable, + Args && ... args) +

+

Converts callback taking callable types into a continuable. This applies to calls which pass an error code as first parameter and the rest of the asynchronous result afterwards.

+

This modification of from additionally takes a resolver callable object which is used to resolve the promise from the given result.

See an example of how to promisify boost asio's async_resolve below:

auto async_resolve(std::string host, std::string service) {
+  return cti::promisify<asio::ip::udp::resolver::iterator>::with(
+      [](auto&& promise, auto&& e, auto&&... args) {
+        if (e) {
+          promise.set_exception(std::forward<decltype(e)>(e));
+        } else {
+          promise.set_value(std::forward<decltype(args)>(args)...);
+        }
+      },
+      [&](auto&&... args) {
+        resolver_.async_resolve(std::forward<decltype(args)>(args)...);
+      },
+      std::move(host), std::move(service));
+}
+
+
+
+
+
+
+ + + + + + diff --git a/classcti_1_1result.html b/classcti_1_1result.html new file mode 100644 index 0000000..0bac161 --- /dev/null +++ b/classcti_1_1result.html @@ -0,0 +1,290 @@ + + + + + + + cti::result class | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+
template<typename... T>
+ cti::result class +

+

The result class can carry the three kinds of results an asynchronous operation possibly can return, it's implemented in a variant like data structure which is also specialized to hold arbitrary arguments.

+ +

The result can be in the following three states:

  • no result: If the operation didn't finish
  • a value: If the operation finished successfully
  • an exception: If the operation finished with an exception or was cancelled.

The interface of the result object is similar to the one proposed in the std::expected proposal:

result<std::string> result = make_result("Hello World!");
+bool(result);
+result.is_value();
+result.is_exception();
+*result; // Same as result.get_value()
+result.get_value();
+result.get_exception();
+
+

Public static functions

+
+
+ static auto from(T... values) -> result +
+
Creates a present result from the given values.
+
+ static auto from(exception_arg_t, + exception_t exception) -> result +
+
Creates a present result from the given exception.
+
+ static auto empty() -> result +
+
Creates an empty result.
+
+
+
+

Constructors, destructors, conversion operators

+
+
+ operator bool() const explicit constexpr noexcept +
+
Returns true if the state of the result holds the result.
+
+
+
+

Public functions

+
+
+ void set_empty() +
+
Set the result to an empty state.
+
+ void set_value(T... values) +
+
Set the result to a the state which holds the corresponding value.
+
+ void set_exception(exception_t exception) +
+
Set the result into a state which holds the corresponding exception.
+
+ void set_canceled() +
+
Set the result into a state which holds the cancellation token.
+
+ auto is_empty() const -> bool noexcept +
+
Returns true if the state of the result is empty.
+
+ auto is_value() const -> bool noexcept +
+
Returns true if the state of the result holds the result.
+
+ auto is_exception() const -> bool noexcept +
+
Returns true if the state of the result holds a present exception.
+
+ auto get_value() &noexcept -> decltype(auto) +
+
Returns the values of the result, if the result doesn't hold the value the behaviour is undefined but will assert in debug mode.
+
+ auto get_value() const &noexcept -> decltype(auto) +
+
Returns the values of the result, if the result doesn't hold the value the behaviour is undefined but will assert in debug mode.
+
+ auto get_value() &&noexcept -> decltype(auto) +
+
Returns the values of the result, if the result doesn't hold the value the behaviour is undefined but will assert in debug mode.
+
+ auto operator*() &noexcept -> decltype(auto) +
+
Returns the values of the result, if the result doesn't hold the value the behaviour is undefined but will assert in debug mode.
+
+ auto operator*() const &noexcept -> decltype(auto) +
+
Returns the values of the result, if the result doesn't hold the value the behaviour is undefined but will assert in debug mode.
+
+ auto operator*() &&noexcept -> decltype(auto) +
+
Returns the values of the result, if the result doesn't hold the value the behaviour is undefined but will assert in debug mode.
+
+ auto get_exception() &noexcept -> exception_t& +
+
Returns the exception of the result, if the result doesn't hold an exception the behaviour is undefined but will assert in debug mode.
+
+ auto get_exception() const &noexcept -> exception_t const & +
+
Returns the exception of the result, if the result doesn't hold an exception the behaviour is undefined but will assert in debug mode.
+
+ auto get_exception() &&noexcept -> exception_t&& +
+
Returns the exception of the result, if the result doesn't hold an exception the behaviour is undefined but will assert in debug mode.
+
+
+
+
+
+
+ + + + + + diff --git a/configuration.html b/configuration.html new file mode 100644 index 0000000..b9429b1 --- /dev/null +++ b/configuration.html @@ -0,0 +1,175 @@ + + + + + + + Configuration | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Configuration +

+ +

Covers optional preprocessor macros that change the libraries behaviour.

+

By default the library doesn't require any preprocessor definitions to be defined in order to work. However it is possible to define some in order to change the libraries behaviour:

Preprocessor definitionConsequence
CONTINUABLE_WITH_NO_EXCEPTIONSExceptions are disabled and std::error_condition is used as error_type . See Using fail and exceptions for details.
CONTINUABLE_WITH_CUSTOM_ERROR_TYPEExceptions are disabled and the type defined by CONTINUABLE_WITH_CUSTOM_ERROR_TYPE is used as error_type . See Using fail and exceptions for details.
CONTINUABLE_WITH_UNHANDLED_EXCEPTIONSAllows unhandled exceptions in asynchronous call hierarchies. See Using fail and exceptions for details.
CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACKAllows to customize the final callback which can be used to implement custom unhandled asynchronous exception handlers.
CONTINUABLE_WITH_IMMEDIATE_TYPESDon't decorate the used type erasure, which is done to keep type names minimal for better error messages in debug builds.
CONTINUABLE_WITH_EXPERIMENTAL_COROUTINEEnables support for experimental coroutines and co_await expressions. See continuable_base::operator co_await() for details.
+
+
+
+
+ + + + + + diff --git a/deprecated.html b/deprecated.html new file mode 100644 index 0000000..c95e9b2 --- /dev/null +++ b/deprecated.html @@ -0,0 +1,174 @@ + + + + + + + Deprecated List | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Deprecated List +

+ +
Member cti::dispatch_error_tag
The dispatch_error_tag was deprecated in order to move closer to the types specified in the "A Unified Future" proposal especially regarding naming types similar.
Member cti::error_type
The error_type was deprecated in order to move closer to the types specified in the "A Unified Future" proposal especially regarding naming types similar.
Member cti::query_arg_t
The query_arg_t was deprecated because of its new naming unpack_arg_t.
+
+
+
+
+ + + + + + diff --git a/files.html b/files.html new file mode 100644 index 0000000..6a774a1 --- /dev/null +++ b/files.html @@ -0,0 +1,187 @@ + + + + + + + Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

Files

+
    +
+ +
+
+
+
+ + + + + + diff --git a/group___base.html b/group___base.html new file mode 100644 index 0000000..7783100 --- /dev/null +++ b/group___base.html @@ -0,0 +1,510 @@ + + + + + + + Base module | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Base module

+

provides classes and functions to create continuable_base objects.

+
+

Contents

+ +
+
+

Classes

+
+
+
template<typename Data, typename Annotation>
+ class cti::continuable_base +
+
The main class of the continuable library, it provides the functionality for chaining callbacks and continuations together to a unified hierarchy.
+
+
template<typename Data, typename Hint>
+ class cti::promise_base +
+
The promise_base makes it possible to resolve an asynchronous continuable through it's result or through an error type.
+
+
+
+

Typedefs

+
+
+
template<typename T>
+ using is_continuable = detail::base::is_continuable<T> +
+
Deduces to a true_type if the given type is a continuable_base.
+
+
+
+

Functions

+
+
+
template<typename... Args, typename Continuation>
+ auto make_continuable(Continuation&& continuation) -> auto constexpr +
+
Creates a continuable_base from a promise/callback taking function.
+
+
template<typename... Args>
+ auto make_ready_continuable(Args && ... args) -> auto +
+
Returns a continuable_base with no result which instantly resolves the promise with no values.
+
+
template<typename... Args, typename Exception>
+ auto make_exceptional_continuable(Exception&& exception) -> auto constexpr +
+
Returns a continuable_base with the parameterized result which instantly resolves the promise with the given error type.
+
+
template<typename... Signature>
+ auto make_cancelling_continuable() -> auto +
+
Returns a continuable_base with the parameterized result which never resolves its promise and thus cancels the asynchronous continuation chain through throwing a default constructed exception_t.
+
+
template<typename T>
+ auto make_plain(T&& value) -> auto +
+
Can be used to disable the special meaning for a returned value in asynchronous handler functions.
+
+
template<typename... Args>
+ auto recover(Args && ... args) -> result<detail::traits::unrefcv_t<Args>...> +
+
Can be used to recover to from a failure handler, the result handler which comes after will be called with the corresponding result.
+
+ auto rethrow(exception_t exception) -> exceptional_result +
+
Can be used to rethrow an exception to the asynchronous continuation chain, the failure handler which comes after will be called with the corresponding exception.
+
+ auto cancel() -> cancellation_result +
+
Can be used to cancel an asynchronous continuation chain, the next failure handler which comes after cancel will be called with a default constructed exception_t object.
+
+ auto stop() -> empty_result +
+
Can be used to stop an asynchronous continuation chain, no handler which comes after stop was received won't be called.
+
+
+
+

Typedef documentation

+
+

+
+ template<typename T> +
+ using is_continuable = detail::base::is_continuable<T> +

+

Deduces to a true_type if the given type is a continuable_base.

+ +
+
+
+

Function documentation

+
+

+
+ template<typename... Args, typename Continuation> +
+ auto make_continuable(Continuation&& continuation) constexpr +

+

Creates a continuable_base from a promise/callback taking function.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Template parameters
Args

The types (signature hint) the given promise is resolved with.

  • Some arguments indicate the types the promise will be invoked with.

    auto ct = cti::make_continuable<int, std::string>([](auto&& promise) {
    +  promise.set_value(200, "<html>...</html>");
    +});
  • void as argument indicates that the promise will be invoked with no arguments:

    auto ct = cti::make_continuable<void>([](auto&& promise) {
    +  promise.set_value();
    +});
  • No arguments Since version 3.0.0 make_continuable always requires to be given valid arguments! You should always give the type hint a callback is called with because it's required for intermediate actions like connecting continuables. You may omit the signature hint if you are erasing the type of the continuable right after creation.

    // This won't work because the arguments are missing:
    +auto ct = cti::make_continuable([](auto&& promise) {
    +  promise.set_value(0.f, 'c');
    +});
    +
    +// However, you are allowed to do this:
    +cti::continuable<float, char> ct = [](auto&& promise) {
    +  promise.set_value(callback)(0.f, 'c');
    +};
Continuation
Parameters
continuation

The continuation the continuable is created from. The continuation must be a callable type accepting a callback parameter which represents the object invokable with the asynchronous result of this continuable.

auto ct = cti::make_continuable<std::string>([](auto&& promise) {
+  promise.set_value("result");
+});

The callback may be stored or moved. In some cases the callback may be copied if supported by the underlying callback chain, in order to invoke the call chain multiple times. It's recommended to accept any callback instead of erasing it.

// Good practice:
+auto ct = cti::make_continuable<std::string>([](auto&& promise) {
+  promise.set_value("result");
+});
+
+// Good practice using a callable object:
+struct Continuation {
+  template<typename T>
+  void operator() (T&& continuation) && {
+    // ...
+  }
+}
+
+auto ct = cti::make_continuable<std::string>(Continuation{});
+
+// Bad practice (because of unnecessary type erasure):
+auto ct = cti::make_continuable<std::string>(
+  [](cti::promise<std::string> promise) {
+    promise.set_value("result");
+  });
ReturnsA continuable_base with unspecified template parameters which wraps the given continuation. In order to convert the continuable_base to a known type you need to apply type erasure through the continuable or promise facilities.
+ +
+
+

+
+ template<typename... Args> +
+ auto make_ready_continuable(Args && ... args) +

+

Returns a continuable_base with no result which instantly resolves the promise with no values.

+ +
+
+

+
+ template<typename... Args, typename Exception> +
+ auto make_exceptional_continuable(Exception&& exception) constexpr +

+

Returns a continuable_base with the parameterized result which instantly resolves the promise with the given error type.

+ + + + + + + + + + + + + + +
Template parameters
ArgsThe fake signature of the returned continuable.
Exception
+

See an example below:

std::logic_error exception("Some issue!");
+auto ptr = std::make_exception_ptr(exception);
+auto ct = cti::make_exceptional_continuable<int>(ptr);
+
+
+

+
+ template<typename... Signature> +
+ auto make_cancelling_continuable() +

+

Returns a continuable_base with the parameterized result which never resolves its promise and thus cancels the asynchronous continuation chain through throwing a default constructed exception_t.

+ + + + + + + + + + +
Template parameters
SignatureThe fake signature of the returned continuable.
+

This can be used to cancel an asynchronous continuation chain when returning a continuable_base from a handler where other paths could possibly continue the asynchronous chain. See an example below:

do_sth().then([weak = this->weak_from_this()]() -> continuable<> {
+  if (auto me = weak.lock()) {
+    return do_sth_more();
+  } else {
+    // Abort the asynchronous continuation chain since the
+    // weakly referenced object expired previously.
+    return make_cancelling_continuable<void>();
+  }
+});

The default unhandled exception handler ignores exception types that don't evaluate to true when being converted to a bool. This saves expensive construction of std::exception_ptr or similar types, where only one exception type is used for signaling the cancellation.

+
+
+

+
+ template<typename T> +
+ auto make_plain(T&& value) +

+

Can be used to disable the special meaning for a returned value in asynchronous handler functions.

+

Several types have a special meaning when being returned from a callable passed to asynchronous handler functions like:

For instance such types are std::tuple, std::pair and cti::result.

Wrapping such an object through a call to make_plain disables the special meaning for such objects as shown below:

continuable<result<int, int> c = http_request("example.com")
+  .then([](std::string content) {
+    return make_plain(make_result(0, 1));
+  })
+
+
+

+
+ template<typename... Args> +
+ result<detail::traits::unrefcv_t<Args>...> recover(Args && ... args) +

+

Can be used to recover to from a failure handler, the result handler which comes after will be called with the corresponding result.

+

The exceptional_result returned by this function can be returned from any result or failure handler in order to rethrow the exception.

http_request("example.com")
+  .then([](std::string content) {
+    return recover(1, 2);
+  })
+  .fail([](cti::exception_t exception) {
+    return recover(1, 2);
+  })
+  .then([](int a, int b) {
+    // Recovered from the failure
+  })

A corresponding result is returned by recover

http_request("example.com")
+  .then([](std::string content) -> cti::result<int, int> {
+    return recover(1, 2);
+  })
+  .fail([](cti::exception_t exception) -> cti::result<int, int> {
+    return recover(1, 2);
+  })
+  .then([](int a, int b) -> cti::result<int, int> {
+    // Recovered from the failure
+  })
+
+
+

+ exceptional_result rethrow(exception_t exception) +

+

Can be used to rethrow an exception to the asynchronous continuation chain, the failure handler which comes after will be called with the corresponding exception.

+

The exceptional_result returned by this function can be returned from any result or failure handler in order to rethrow the exception.

http_request("example.com")
+  .then([](std::string content) {
+    return rethrow(std::make_exception_ptr(std::exception{}));
+  })
+  .fail([](cti::exception_t exception) {
+    return rethrow(std::make_exception_ptr(std::exception{}));
+  })
+  .next([](auto&&...) {
+    return rethrow(std::make_exception_ptr(std::exception{}));
+  });

The returned exceptional_result is convertible to any result as shown below:

http_request("example.com")
+  .then([](std::string content) -> cti::result<> {
+    return rethrow(std::make_exception_ptr(std::exception{}));
+  })
+  .fail([](cti::exception_t exception) -> cti::result<> {
+    return rethrow(std::make_exception_ptr(std::exception{}));
+  })
+  .next([](auto&&...) -> cti::result<> {
+    return rethrow(std::make_exception_ptr(std::exception{}));
+  });
+
+
+

+ cancellation_result cancel() +

+

Can be used to cancel an asynchronous continuation chain, the next failure handler which comes after cancel will be called with a default constructed exception_t object.

+

The cancellation_result returned by this function can be returned from any result or failure handler in order to cancel the chain.

http_request("example.com")
+  .then([](std::string content) {
+    return cancel();
+  })
+  .fail([](cti::exception_t exception) {
+    return cancel();
+  })
+  .next([](auto&&...) {
+    return cancel();
+  });

The returned empty_result is convertible to any result as shown below:

http_request("example.com")
+  .then([](std::string content) -> cti::result<> {
+    return cancel();
+  })
+  .fail([](cti::exception_t exception) -> cti::result<> {
+    return cancel();
+  })
+  .next([](auto&&...) -> cti::result<> {
+    return cancel();
+  });
+
+
+

+ empty_result stop() +

+

Can be used to stop an asynchronous continuation chain, no handler which comes after stop was received won't be called.

+ +
+
+
+
+
+
+ + + + + + diff --git a/group___connections.html b/group___connections.html new file mode 100644 index 0000000..bbe6158 --- /dev/null +++ b/group___connections.html @@ -0,0 +1,460 @@ + + + + + + + Connections module | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Connections module

+

provides functions to connect continuable_bases through various strategies.

+
+

Contents

+ +
+
+

Functions

+
+
+
template<typename... Args>
+ auto when_all(Args && ... args) -> auto +
+
Connects the given arguments with an all logic. All continuables contained inside the given nested pack are invoked at once. On completion the final handler is called with the aggregated result of all continuables.
+
+
template<typename Iterator, std::enable_if_t<detail::range::is_iterator<Iterator>::value>* = nullptr>
+ auto when_all(Iterator begin, + Iterator end) -> auto +
+
Connects the given arguments with an all logic. The content of the iterator is moved out and converted to a temporary std::vector which is then passed to when_all.
+
+
template<typename... Args>
+ auto when_seq(Args && ... args) -> auto +
+
Connects the given arguments with a sequential logic. All continuables contained inside the given nested pack are invoked one after one. On completion the final handler is called with the aggregated result of all continuables.
+
+
template<typename Iterator, std::enable_if_t<detail::range::is_iterator<Iterator>::value>* = nullptr>
+ auto when_seq(Iterator begin, + Iterator end) -> auto +
+
Connects the given arguments with a sequential logic. The content of the iterator is moved out and converted to a temporary std::vector which is then passed to when_seq.
+
+
template<typename... Args>
+ auto when_any(Args && ... args) -> auto +
+
Connects the given arguments with an any logic. All continuables contained inside the given nested pack are invoked at once. On completion of one continuable the final handler is called with the result of the resolved continuable.
+
+
template<typename Iterator, std::enable_if_t<detail::range::is_iterator<Iterator>::value>* = nullptr>
+ auto when_any(Iterator begin, + Iterator end) -> auto +
+
Connects the given arguments with an any logic. The content of the iterator is moved out and converted to a temporary std::vector which is then passed to when_all.
+
+
template<template<typename, typename> class C = std::vector, typename First, typename... Args>
+ auto populate(First&& first, + Args && ... args) -> C<std::decay_t<First>, std::allocator<std::decay_t<First>>> +
+
Populates a homogeneous container from the given arguments. All arguments need to be convertible to the first one, by default std::vector is used as container type.
+
+
+
+

Function documentation

+
+

+
+ template<typename... Args> +
+ auto when_all(Args && ... args) +

+

Connects the given arguments with an all logic. All continuables contained inside the given nested pack are invoked at once. On completion the final handler is called with the aggregated result of all continuables.

+ + + + + + + + + + +
Parameters
args

Arbitrary arguments which are connected. Every type is allowed as arguments, continuables may be contained inside tuple like types (std::tuple) or in homogeneous containers such as std::vector. Non continuable arguments are preserved and passed to the final result as shown below:

cti::when_all(
+    cti::make_ready_continuable(0, 1),
+    2, //< See this plain value
+    cti::populate(cti::make_ready_continuable(3),  // Creates a runtime
+                  cti::make_ready_continuable(4)), // sized container.
+    std::make_tuple(std::make_tuple(cti::make_ready_continuable(5))))
+      .then([](int r0, int r1, int r2, std::vector<int> r34,
+               std::tuple<std::tuple<int>> r5) {
+        // ...
+      });
+ +
+
+

+
+ template<typename Iterator, std::enable_if_t<detail::range::is_iterator<Iterator>::value>* = nullptr> +
+ auto when_all(Iterator begin, + Iterator end) +

+

Connects the given arguments with an all logic. The content of the iterator is moved out and converted to a temporary std::vector which is then passed to when_all.

+ + + + + + + + + + + + + + +
Parameters
beginThe begin iterator to the range which will be moved out and used as the arguments to the all connection
endThe end iterator to the range which will be moved out and used as the arguments to the all connection
+
// cti::populate just creates a std::vector from the two continuables.
+auto v = cti::populate(cti::make_ready_continuable(0),
+                       cti::make_ready_continuable(1));
+
+cti::when_all(v.begin(), v.end())
+  .then([](std::vector<int> r01) {
+    // ...
+  });
+
+
+

+
+ template<typename... Args> +
+ auto when_seq(Args && ... args) +

+

Connects the given arguments with a sequential logic. All continuables contained inside the given nested pack are invoked one after one. On completion the final handler is called with the aggregated result of all continuables.

+ + + + + + + + + + +
Parameters
args

Arbitrary arguments which are connected. Every type is allowed as arguments, continuables may be contained inside tuple like types (std::tuple) or in homogeneous containers such as std::vector. Non continuable arguments are preserved and passed to the final result as shown below:

cti::when_seq(
+    cti::make_ready_continuable(0, 1),
+    2, //< See this plain value
+    cti::populate(cti::make_ready_continuable(3),  // Creates a runtime
+                  cti::make_ready_continuable(4)), // sized container.
+    std::make_tuple(std::make_tuple(cti::make_ready_continuable(5))))
+      .then([](int r0, int r1, int r2, std::vector<int> r34,
+               std::tuple<std::tuple<int>> r5) {
+        // ...
+      });
+ +
+
+

+
+ template<typename Iterator, std::enable_if_t<detail::range::is_iterator<Iterator>::value>* = nullptr> +
+ auto when_seq(Iterator begin, + Iterator end) +

+

Connects the given arguments with a sequential logic. The content of the iterator is moved out and converted to a temporary std::vector which is then passed to when_seq.

+ + + + + + + + + + + + + + +
Parameters
beginThe begin iterator to the range which will be moved out and used as the arguments to the sequential connection
endThe end iterator to the range which will be moved out and used as the arguments to the sequential connection
+
// cti::populate just creates a std::vector from the two continuables.
+auto v = cti::populate(cti::make_ready_continuable(0),
+                       cti::make_ready_continuable(1));
+
+cti::when_seq(v.begin(), v.end())
+  .then([](std::vector<int> r01) {
+    // ...
+  });
+
+
+

+
+ template<typename... Args> +
+ auto when_any(Args && ... args) +

+

Connects the given arguments with an any logic. All continuables contained inside the given nested pack are invoked at once. On completion of one continuable the final handler is called with the result of the resolved continuable.

+ + + + + + + + + + +
Parameters
args

Arbitrary arguments which are connected. Every type is allowed as arguments, continuables may be contained inside tuple like types (std::tuple) or in homogeneous containers such as std::vector. Non continuable arguments are preserved and passed to the final result as shown below:

cti::when_any(
+    cti::make_ready_continuable(0, 1),
+    2, //< See this plain value
+    cti::populate(cti::make_ready_continuable(3),  // Creates a runtime
+                  cti::make_ready_continuable(4)), // sized container.
+    std::make_tuple(std::make_tuple(cti::make_ready_continuable(5))))
+      .then([](int r0) {
+        // ...
+      });
+ +
+
+

+
+ template<typename Iterator, std::enable_if_t<detail::range::is_iterator<Iterator>::value>* = nullptr> +
+ auto when_any(Iterator begin, + Iterator end) +

+

Connects the given arguments with an any logic. The content of the iterator is moved out and converted to a temporary std::vector which is then passed to when_all.

+ + + + + + + + + + + + + + +
Parameters
beginThe begin iterator to the range which will be moved out and used as the arguments to the all connection
endThe end iterator to the range which will be moved out and used as the arguments to the all connection
+
// cti::populate just creates a std::vector from the two continuables.
+auto v = cti::populate(cti::make_ready_continuable(0),
+                       cti::make_ready_continuable(1));
+
+cti::when_any(v.begin(), v.end())
+  .then([](int r01) {
+    // ...
+  });
+
+
+

+
+ template<template<typename, typename> class C = std::vector, typename First, typename... Args> +
+ C<std::decay_t<First>, std::allocator<std::decay_t<First>>> populate(First&& first, + Args && ... args) +

+

Populates a homogeneous container from the given arguments. All arguments need to be convertible to the first one, by default std::vector is used as container type.

+ + + + + + + + + + + + + + + + + + +
Template parameters
CThe container type which is used to store the arguments into.
First
Args
+

This method mainly helps to create a homogeneous container from a runtime known count of continuables which type isn't exactly known. All continuables which are passed to this function should be originating from the same source or a method called with the same types of arguments:

auto container = cti::populate(cti::make_ready_continuable(0),
+                               cti::make_ready_continuable(1)),
+
+for (int i = 2; i < 5; ++i) {
+  // You may add more continuables to the container afterwards
+  container.emplace_back(cti::make_ready_continuable(i));
+}
+
+cti::when_any(std::move(container))
+  .then([](int) {
+    // ...
+  });

Additionally it is possible to change the targeted container as below:

auto container = cti::populate<std::list>(cti::make_ready_continuable(0),
+                                          cti::make_ready_continuable(1)),
+
+
+
+
+
+
+ + + + + + diff --git a/group___operations.html b/group___operations.html new file mode 100644 index 0000000..0e56205 --- /dev/null +++ b/group___operations.html @@ -0,0 +1,175 @@ + + + + + + + Operations module | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Operations module

+

provides functions to work with asynchronous control flows.

+
+

Function documentation

+
+
+
+
+
+ + + + + + diff --git a/group___primitives.html b/group___primitives.html new file mode 100644 index 0000000..c2c12a7 --- /dev/null +++ b/group___primitives.html @@ -0,0 +1,293 @@ + + + + + + + Primitives module | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Primitives module

+

provides basic tag types for creating a customized callbacks and continuations.

+
+

Contents

+ +
+

For the callback and the continuation Args... represents the asynchronous result:

template<typename... Args>
+struct continuation {
+  void operator() (callback<Args...>);
+  bool operator() (cti::is_ready_arg_t) const;
+  result<Args...> operator() (cti::unpack_arg_t);
+};
template<typename... Args>
+struct callback {
+  void operator() (Args...) &&;
+  void operator() (cti::exception_arg_t, cti::exception_t) &&;
+};
+
+

Classes

+
+
+ struct cti::is_ready_arg_t +
+
Represents the tag type that is used to query the continuation for whether it resolves the callback instantly with its arguments without having side effects.
+
+ struct cti::unpack_arg_t +
+
Represents the tag type that is used to unpack the result of a continuation.
+
+ struct cti::exception_arg_t +
+
Represents the tag type that is used to disambiguate the callback operator() in order to take the exception asynchronous chain.
+
+
+
+

Typedefs

+
+
+
template<typename... Args>
+ using signature_arg_t = detail::identity<Args...> +
+
Represents the tag type that is used to specify the signature hint of a continuable_base or promise_base.
+
+ using query_arg_t = unpack_arg_t deprecated +
+
Represents the tag type that is used to unpack the result of a continuation.
+
+ using dispatch_error_tag = exception_arg_t deprecated +
+
Represents the tag type that is used to disambiguate the callback operator() in order to take the exception asynchronous chain.
+
+ using exception_t = detail::types::exception_t +
+
Represents the type that is used as exception type.
+
+ using error_type = exception_t deprecated +
+
Represents the type that is used as exception type.
+
+
template<typename T>
+ using plain_t = detail::types::plain_tag<T> +
+
Represents the type that is used to disable the special meaning of types which are returned by a asynchronous result handler. See cti::plain for details.
+
+
+
+

Typedef documentation

+
+

+
+ template<typename... Args> +
+ using signature_arg_t = detail::identity<Args...> +

+

Represents the tag type that is used to specify the signature hint of a continuable_base or promise_base.

+ +
+
+

+ typedef unpack_arg_t query_arg_t +

+

Represents the tag type that is used to unpack the result of a continuation.

+ +
+
+

+ typedef exception_arg_t dispatch_error_tag +

+

Represents the tag type that is used to disambiguate the callback operator() in order to take the exception asynchronous chain.

+ +
+
+

+ using exception_t = detail::types::exception_t +

+

Represents the type that is used as exception type.

+

By default this type deduces to std::exception_ptr. If CONTINUABLE_WITH_NO_EXCEPTIONS is defined the type will be a std::error_condition. A custom error type may be set through defining CONTINUABLE_WITH_CUSTOM_ERROR_TYPE.

+
+
+

+ typedef exception_t error_type +

+

Represents the type that is used as exception type.

+

By default this type deduces to std::exception_ptr. If CONTINUABLE_WITH_NO_EXCEPTIONS is defined the type will be a std::error_condition. A custom error type may be set through defining CONTINUABLE_WITH_CUSTOM_ERROR_TYPE.

+
+
+

+
+ template<typename T> +
+ using plain_t = detail::types::plain_tag<T> +

+

Represents the type that is used to disable the special meaning of types which are returned by a asynchronous result handler. See cti::plain for details.

+ +
+
+
+
+
+
+ + + + + + diff --git a/group___promisify.html b/group___promisify.html new file mode 100644 index 0000000..6cad859 --- /dev/null +++ b/group___promisify.html @@ -0,0 +1,193 @@ + + + + + + + Promisify module | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Promisify module

+

provides helper methods to convert various callback styles to continuable_bases.

+
+

Contents

+ +
+
+

Classes

+
+
+
template<typename... Result>
+ class cti::promisify +
+
Helper class for converting callback taking callable types into a a continuable. Various styles are supported.
+
+
+
+
+
+
+ + + + + + diff --git a/group___result.html b/group___result.html new file mode 100644 index 0000000..4f487ba --- /dev/null +++ b/group___result.html @@ -0,0 +1,288 @@ + + + + + + + Result module | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Result module

+

provides the result class and corresponding utility functions to work with the result of an asynchronous operation which can possibly yield:

+
+

Contents

+ +
+
  • no result: If the operation didn't finish
  • a value: If the operation finished successfully
  • an exception: If the operation finished with an exception or was cancelled.
+
+

Classes

+
+
+ struct cti::empty_result +
+
A class which is convertible to any result and that definitely holds no value so the real result gets invalidated when this object is passed to it.
+
+ struct cti::cancellation_result +
+
A class which is convertible to any result and that definitely holds a default constructed exception which signals the cancellation of the asynchronous control flow.
+
+ class cti::exceptional_result +
+
A class which is convertible to any result and that holds an exception which is then passed to the converted result object.
+
+
template<typename... T>
+ class cti::result +
+
The result class can carry the three kinds of results an asynchronous operation possibly can return, it's implemented in a variant like data structure which is also specialized to hold arbitrary arguments.
+
+
+
+

Typedefs

+
+
+ using void_arg_t = detail::void_arg_t +
+
A tag which represents present void values in result.
+
+
+
+

Functions

+
+
+
template<std::size_t I, typename... T>
+ auto get(result<T...>& result) -> decltype(auto) +
+
Returns the value at position I of the given result.
+
+
template<std::size_t I, typename... T>
+ auto get(result<T...> const& result) -> decltype(auto) +
+
Returns the value at position I of the given result.
+
+
template<std::size_t I, typename... T>
+ auto get(result<T...>&& result) -> decltype(auto) +
+
Returns the value at position I of the given result.
+
+
template<typename... T, typename Result = result<detail::traits::unrefcv_t<T>...>>
+ auto make_result(T && ... values) -> Result +
+
Creates a present result from the given values.
+
+ auto make_result(exception_arg_t, + exception_t exception) -> exceptional_result +
+
Creates an exceptional_result from the given exception.
+
+
+
+

Typedef documentation

+
+

+ using void_arg_t = detail::void_arg_t +

+

A tag which represents present void values in result.

+ +
+
+
+

Function documentation

+
+

+
+ template<typename... T, typename Result = result<detail::traits::unrefcv_t<T>...>> +
+ Result make_result(T && ... values) +

+

Creates a present result from the given values.

+

This could be used to pass the result of the next handler to the same asynchronous path it came from as shown below:

make_ready_continuable().next([&](auto&&... args) {
+  result<> captured = make_result(std::forward<decltype(args)>(args)...);
+  return shutdown().then([captured = std::move(captured)]() mutable {
+    return std::move(captured);
+  });
+});
+
+
+

+ exceptional_result make_result(exception_arg_t, + exception_t exception) +

+

Creates an exceptional_result from the given exception.

+

This could be used to pass the result of the next handler to the same asynchronous path it came from as shown below:

make_ready_continuable().next([&](auto&&... args) {
+  result<> captured = make_result(std::forward<decltype(args)>(args)...);
+  return shutdown().then([captured = std::move(captured)]() mutable {
+    return std::move(captured);
+  });
+});
+
+
+
+
+
+
+ + + + + + diff --git a/group___testing.html b/group___testing.html new file mode 100644 index 0000000..9d9cb54 --- /dev/null +++ b/group___testing.html @@ -0,0 +1,340 @@ + + + + + + + Testing module | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Testing module

+

provides macro shortcuts for testing asynchronous continuations through GTest.

+
+

Contents

+ +
+
+

Defines

+
+
+ #define ASSERT_ASYNC_COMPLETION(CONTINUABLE) +
+
Asserts that the final callback of the given continuable was called with any result.
+
+ #define ASSERT_ASYNC_EXCEPTION_COMPLETION(CONTINUABLE) +
+
Asserts that the final callback of the given continuable was called with any exceptional result.
+
+ #define ASSERT_ASYNC_CANCELLATION(CONTINUABLE) +
+
Asserts that the final callback of the given continuable is called with a cancelled result which is represented by a default constructed exception_t.
+
+ #define ASSERT_ASYNC_INCOMPLETION(CONTINUABLE) +
+
Asserts that the final callback of the given continuable is never called with any result.
+
+ #define ASSERT_ASYNC_VALIDATION(CONTINUABLE, + VALIDATOR) +
+
Expects the continuation to be called and forwards it's arguments to the given validator which can then do assertions on the result.
+
+ #define ASSERT_ASYNC_BINARY_VALIDATION(VALIDATOR, + ...) +
+
Asserts that the continuation was called and forwards it's arguments to the given validator which can then do assertions on the result.
+
+ #define ASSERT_ASYNC_BINARY_EXCEPTION_VALIDATION(VALIDATOR, + ...) +
+
Asserts that the continuation was resolved through an error and forwards it's error result to the given validator which can then do assertions on the error result.
+
+ #define EXPECT_ASYNC_RESULT(...) +
+
Expects that the continuable is finished with the given result.
+
+ #define EXPECT_ASYNC_EXCEPTION_RESULT(...) +
+
Asserts that the continuable is finished with the given exception.
+
+ #define ASSERT_ASYNC_RESULT(...) +
+
Asserts that the continuable is finished with the given result.
+
+ #define ASSERT_ASYNC_TYPES(CONTINUABLE, + ...) +
+
Asserts that the continuable is finished with the given type of arguments without validating it against equality.
+
+ #define ASSERT_ASYNC_EXCEPTION_RESULT(...) +
+
Asserts that the continuable is finished with the given exception.
+
+
+
+

Define documentation

+
+

+ #define ASSERT_ASYNC_COMPLETION(CONTINUABLE) +

+

Asserts that the final callback of the given continuable was called with any result.

+ +
+
+

+ #define ASSERT_ASYNC_EXCEPTION_COMPLETION(CONTINUABLE) +

+

Asserts that the final callback of the given continuable was called with any exceptional result.

+ +
+
+

+ #define ASSERT_ASYNC_CANCELLATION(CONTINUABLE) +

+

Asserts that the final callback of the given continuable is called with a cancelled result which is represented by a default constructed exception_t.

+ +
+
+

+ #define ASSERT_ASYNC_INCOMPLETION(CONTINUABLE) +

+

Asserts that the final callback of the given continuable is never called with any result.

+ +
+
+

+ #define ASSERT_ASYNC_BINARY_VALIDATION(VALIDATOR, + ...) +

+

Asserts that the continuation was called and forwards it's arguments to the given validator which can then do assertions on the result.

+

A validator consists of a binary consumer with a signature as in in the example shown below:

auto validator = [](auto expected, auto actual) {
+  EXPECT_EQ(expected, actual);
+};

The macro is usable as shown in the following example:

continuable<string> async_get(std::string);
+// ...
+auto validator = [](auto expected, auto actual) {
+  EXPECT_EQ(expected, actual);
+};
+
+ASSERT_ASYNC_BINARY_VALIDATION(validator, async_get("hello"), "hello")

The validator is called for every expecting and actual result.

+
+
+

+ #define ASSERT_ASYNC_BINARY_EXCEPTION_VALIDATION(VALIDATOR, + ...) +

+

Asserts that the continuation was resolved through an error and forwards it's error result to the given validator which can then do assertions on the error result.

+ +
+
+

+ #define EXPECT_ASYNC_RESULT(...) +

+

Expects that the continuable is finished with the given result.

+
continuable<string> async_get(std::string);
+// ...
+
+EXPECT_ASYNC_RESULT(async_get("hello"), "hello");
+
+
+

+ #define EXPECT_ASYNC_EXCEPTION_RESULT(...) +

+

Asserts that the continuable is finished with the given exception.

+ +
+
+

+ #define ASSERT_ASYNC_RESULT(...) +

+

Asserts that the continuable is finished with the given result.

+
continuable<string> async_get(std::string);
+// ...
+
+ASSERT_ASYNC_RESULT(async_get("hello"), "hello");
+
+
+

+ #define ASSERT_ASYNC_TYPES(CONTINUABLE, + ...) +

+

Asserts that the continuable is finished with the given type of arguments without validating it against equality.

+
continuable<string> async_get(std::string);
+// ...
+
+ASSERT_ASYNC_TYPES(async_get("hello"), std::string);
+
+
+

+ #define ASSERT_ASYNC_EXCEPTION_RESULT(...) +

+

Asserts that the continuable is finished with the given exception.

+ +
+
+
+
+
+
+ + + + + + diff --git a/group___transforms.html b/group___transforms.html new file mode 100644 index 0000000..7fd390d --- /dev/null +++ b/group___transforms.html @@ -0,0 +1,190 @@ + + + + + + + Transforms module | Continuable + + + + + + + + + + + + + + +
+
+ + + + + + diff --git a/group___traversal.html b/group___traversal.html new file mode 100644 index 0000000..49dc21c --- /dev/null +++ b/group___traversal.html @@ -0,0 +1,382 @@ + + + + + + + Traversal module | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Traversal module

+

provides functions to traverse and remap nested packs.

+
+

Contents

+ +
+
+

Typedefs

+
+
+ using async_traverse_visit_tag = detail::traversal::async_traverse_visit_tag +
+
A tag which is passed to the operator() of the visitor if an element is visited synchronously through traverse_pack_async.
+
+ using async_traverse_detach_tag = detail::traversal::async_traverse_detach_tag +
+
A tag which is passed to the operator() of the visitor if an element is visited after the traversal was detached through traverse_pack_async.
+
+ using async_traverse_complete_tag = detail::traversal::async_traverse_complete_tag +
+
A tag which is passed to the operator() of the visitor if the asynchronous pack traversal was finished through traverse_pack_async.
+
+
template<typename T>
+ using async_traverse_in_place_tag = detail::traversal::async_traverse_in_place_tag<T> +
+
A tag to identify that a mapper shall be constructed in-place from the first argument passed to traverse_pack_async.
+
+
+
+

Functions

+
+
+
template<typename Visitor, typename... T>
+ auto traverse_pack_async(Visitor&& visitor, + T && ... pack) -> auto +
+
Traverses the pack with the given visitor in an asynchronous way.
+
+
template<typename Mapper, typename... T>
+ auto map_pack(Mapper&& mapper, + T && ... pack) -> decltype(auto) +
+
Maps the pack with the given mapper.
+
+
template<typename... T>
+ auto spread_this(T && ... args) -> detail::traversal::spreading::spread_box<std::decay_t<T>...> constexpr noexcept(…) +
+
Indicate that the result shall be spread across the parent container if possible. This can be used to create a mapper function used in map_pack that maps one element to an arbitrary count (1:n).
+
+
template<typename Mapper, typename... T>
+ void traverse_pack(Mapper&& mapper, + T && ... pack) +
+
Traverses the pack with the given visitor.
+
+
+
+

Typedef documentation

+
+

+ using async_traverse_visit_tag = detail::traversal::async_traverse_visit_tag +

+

A tag which is passed to the operator() of the visitor if an element is visited synchronously through traverse_pack_async.

+ +
+
+

+ using async_traverse_detach_tag = detail::traversal::async_traverse_detach_tag +

+

A tag which is passed to the operator() of the visitor if an element is visited after the traversal was detached through traverse_pack_async.

+ +
+
+

+ using async_traverse_complete_tag = detail::traversal::async_traverse_complete_tag +

+

A tag which is passed to the operator() of the visitor if the asynchronous pack traversal was finished through traverse_pack_async.

+ +
+
+

+
+ template<typename T> +
+ using async_traverse_in_place_tag = detail::traversal::async_traverse_in_place_tag<T> +

+

A tag to identify that a mapper shall be constructed in-place from the first argument passed to traverse_pack_async.

+ +
+
+
+

Function documentation

+
+

+
+ template<typename Visitor, typename... T> +
+ auto traverse_pack_async(Visitor&& visitor, + T && ... pack) +

+

Traverses the pack with the given visitor in an asynchronous way.

+ + + + + + + + + + + + + + + + + + + + +
Parameters
visitorA visitor object which provides the three operator() overloads that were described above. Additionally the visitor must be compatible for referencing it from a boost::intrusive_ptr. The visitor should must have a virtual destructor!
packThe arbitrary parameter pack which is traversed asynchronously. Nested objects inside containers and tuple like types are traversed recursively.
ReturnsA std::shared_ptr that references an instance of the given visitor object.
+

This function works in the same way as traverse_pack, however, we are able to suspend and continue the traversal at later time. Thus we require a visitor callable object which provides three operator() overloads as depicted by the code sample below:

struct my_async_visitor {
+  template <typename T>
+  bool operator()(async_traverse_visit_tag, T&& element) {
+    return true;
+  }
+
+  template <typename T, typename N>
+  void operator()(async_traverse_detach_tag, T&& element, N&& next) {
+  }
+
+  template <typename T>
+  void operator()(async_traverse_complete_tag, T&& pack) {
+  }
+};

See traverse_pack for a detailed description about the traversal behaviour and capabilities.

+
+
+

+
+ template<typename Mapper, typename... T> +
+ decltype(auto) map_pack(Mapper&& mapper, + T && ... pack) +

+

Maps the pack with the given mapper.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameters
mapperA callable object, which accept an arbitrary type and maps it to another type or the same one.
packAn arbitrary variadic pack which may contain any type.
ReturnsThe mapped element or in case the pack contains multiple elements, the pack is wrapped into a std::tuple.
Exceptions
std::exceptionlike objects which are thrown by an invocation to the mapper.
+

This function tries to visit all plain elements which may be wrapped in:

  • homogeneous containers (std::vector, std::list)
  • heterogenous containers (std::tuple, std::pair, std::array) and re-assembles the pack with the result of the mapper. Mapping from one type to a different one is supported.

Elements that aren't accepted by the mapper are routed through and preserved through the hierarchy.

// Maps all integers to floats
+map_pack([](int value) {
+  return float(value);
+},
+1, std::make_tuple(2, std::vector<int>{3, 4}), 5);
+
+
+

+
+ template<typename... T> +
+ detail::traversal::spreading::spread_box<std::decay_t<T>...> spread_this(T && ... args) constexpr noexcept(…) +

+

Indicate that the result shall be spread across the parent container if possible. This can be used to create a mapper function used in map_pack that maps one element to an arbitrary count (1:n).

+ +
+
+

+
+ template<typename Mapper, typename... T> +
+ void traverse_pack(Mapper&& mapper, + T && ... pack) +

+

Traverses the pack with the given visitor.

+

This function works in the same way as map_pack, however, the result of the mapper isn't preserved.

See map_pack for a detailed description.

+
+
+
+
+
+
+ + + + + + diff --git a/group___types.html b/group___types.html new file mode 100644 index 0000000..0460bdc --- /dev/null +++ b/group___types.html @@ -0,0 +1,247 @@ + + + + + + + Types module | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Types module

+

provides the continuable and promise facility for type erasure.

+
+

Contents

+ +
+
+

Typedefs

+
+
+
template<typename... Args>
+ using continuation_capacity = detail::erasure::continuation_capacity<Args...> +
+
Deduces to the preferred continuation capacity for a possible small functor optimization. The given capacity size is always enough to to avoid any allocation when storing a ready continuable_base.
+
+
template<typename... Args>
+ using continuable = continuable_base<detail::erasure::continuation<Args...>, signature_arg_t<Args...>> +
+
Defines a non-copyable continuation type which uses the function2 backend for type erasure.
+
+
template<typename... Args>
+ using promise = promise_base<detail::erasure::callback<Args...>, signature_arg_t<Args...>> +
+
Defines a non-copyable promise type which is using the function2 backend for type erasure.
+
+ using work = promise_base<detail::erasure::work, signature_arg_t<>> +
+
Defines a non-copyable type erasure which is capable of carrying callable objects passed to executors.
+
+
+
+

Typedef documentation

+
+

+
+ template<typename... Args> +
+ using continuation_capacity = detail::erasure::continuation_capacity<Args...> +

+

Deduces to the preferred continuation capacity for a possible small functor optimization. The given capacity size is always enough to to avoid any allocation when storing a ready continuable_base.

+ +
+
+

+
+ template<typename... Args> +
+ using continuable = continuable_base<detail::erasure::continuation<Args...>, signature_arg_t<Args...>> +

+

Defines a non-copyable continuation type which uses the function2 backend for type erasure.

+

Usable like: continuable<int, float>

+
+
+

+
+ template<typename... Args> +
+ using promise = promise_base<detail::erasure::callback<Args...>, signature_arg_t<Args...>> +

+

Defines a non-copyable promise type which is using the function2 backend for type erasure.

+

Usable like: promise<int, float>

+
+
+

+ using work = promise_base<detail::erasure::work, signature_arg_t<>> +

+

Defines a non-copyable type erasure which is capable of carrying callable objects passed to executors.

+

The work behaves like a promise<> but the work type erasure uses extra stack space for small object optimization. Additionally the outstanding work can be resolved through an exception.

+
+
+
+
+
+
+ + + + + + diff --git a/highlight.min.js b/highlight.min.js new file mode 100644 index 0000000..f30a334 --- /dev/null +++ b/highlight.min.js @@ -0,0 +1,3 @@ +/*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */ +!function(e){var t="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):t&&(t.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return t.hljs}))}(function(e){function t(e){return e.replace(/&/g,"&").replace(//g,">")}function r(e){return e.nodeName.toLowerCase()}function a(e,t){var r=e&&e.exec(t);return r&&0===r.index}function n(e){return E.test(e)}function i(e){var t,r,a,i,s=e.className+" ";if(s+=e.parentNode?e.parentNode.className:"",r=M.exec(s))return w(r[1])?r[1]:"no-highlight";for(s=s.split(/\s+/),t=0,a=s.length;a>t;t++)if(i=s[t],n(i)||w(i))return i}function s(e){var t,r={},a=Array.prototype.slice.call(arguments,1);for(t in e)r[t]=e[t];return a.forEach(function(e){for(t in e)r[t]=e[t]}),r}function c(e){var t=[];return function a(e,n){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?n+=i.nodeValue.length:1===i.nodeType&&(t.push({event:"start",offset:n,node:i}),n=a(i,n),r(i).match(/br|hr|img|input/)||t.push({event:"stop",offset:n,node:i}));return n}(e,0),t}function o(e,a,n){function i(){return e.length&&a.length?e[0].offset!==a[0].offset?e[0].offset"}function c(e){u+=""}function o(e){("start"===e.event?s:c)(e.node)}for(var l=0,u="",d=[];e.length||a.length;){var b=i();if(u+=t(n.substring(l,b[0].offset)),l=b[0].offset,b===e){d.reverse().forEach(c);do o(b.splice(0,1)[0]),b=i();while(b===e&&b.length&&b[0].offset===l);d.reverse().forEach(s)}else"start"===b[0].event?d.push(b[0].node):d.pop(),o(b.splice(0,1)[0])}return u+t(n.substr(l))}function l(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(t){return s(e,{v:null},t)})),e.cached_variants||e.eW&&[s(e)]||[e]}function u(e){function t(e){return e&&e.source||e}function r(r,a){return new RegExp(t(r),"m"+(e.cI?"i":"")+(a?"g":""))}function a(n,i){if(!n.compiled){if(n.compiled=!0,n.k=n.k||n.bK,n.k){var s={},c=function(t,r){e.cI&&(r=r.toLowerCase()),r.split(" ").forEach(function(e){var r=e.split("|");s[r[0]]=[t,r[1]?Number(r[1]):1]})};"string"==typeof n.k?c("keyword",n.k):k(n.k).forEach(function(e){c(e,n.k[e])}),n.k=s}n.lR=r(n.l||/\w+/,!0),i&&(n.bK&&(n.b="\\b("+n.bK.split(" ").join("|")+")\\b"),n.b||(n.b=/\B|\b/),n.bR=r(n.b),n.e||n.eW||(n.e=/\B|\b/),n.e&&(n.eR=r(n.e)),n.tE=t(n.e)||"",n.eW&&i.tE&&(n.tE+=(n.e?"|":"")+i.tE)),n.i&&(n.iR=r(n.i)),null==n.r&&(n.r=1),n.c||(n.c=[]),n.c=Array.prototype.concat.apply([],n.c.map(function(e){return l("self"===e?n:e)})),n.c.forEach(function(e){a(e,n)}),n.starts&&a(n.starts,i);var o=n.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([n.tE,n.i]).map(t).filter(Boolean);n.t=o.length?r(o.join("|"),!0):{exec:function(){return null}}}}a(e)}function d(e,r,n,i){function s(e,t){var r,n;for(r=0,n=t.c.length;n>r;r++)if(a(t.c[r].bR,e))return t.c[r]}function c(e,t){if(a(e.eR,t)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?c(e.parent,t):void 0}function o(e,t){return!n&&a(t.iR,e)}function l(e,t){var r=v.cI?t[0].toLowerCase():t[0];return e.k.hasOwnProperty(r)&&e.k[r]}function p(e,t,r,a){var n=a?"":L.classPrefix,i='',i+t+s}function m(){var e,r,a,n;if(!N.k)return t(E);for(n="",r=0,N.lR.lastIndex=0,a=N.lR.exec(E);a;)n+=t(E.substring(r,a.index)),e=l(N,a),e?(M+=e[1],n+=p(e[0],t(a[0]))):n+=t(a[0]),r=N.lR.lastIndex,a=N.lR.exec(E);return n+t(E.substr(r))}function f(){var e="string"==typeof N.sL;if(e&&!x[N.sL])return t(E);var r=e?d(N.sL,E,!0,k[N.sL]):b(E,N.sL.length?N.sL:void 0);return N.r>0&&(M+=r.r),e&&(k[N.sL]=r.top),p(r.language,r.value,!1,!0)}function g(){C+=null!=N.sL?f():m(),E=""}function _(e){C+=e.cN?p(e.cN,"",!0):"",N=Object.create(e,{parent:{value:N}})}function h(e,t){if(E+=e,null==t)return g(),0;var r=s(t,N);if(r)return r.skip?E+=t:(r.eB&&(E+=t),g(),r.rB||r.eB||(E=t)),_(r,t),r.rB?0:t.length;var a=c(N,t);if(a){var n=N;n.skip?E+=t:(n.rE||n.eE||(E+=t),g(),n.eE&&(E=t));do N.cN&&(C+=R),N.skip||(M+=N.r),N=N.parent;while(N!==a.parent);return a.starts&&_(a.starts,""),n.rE?0:t.length}if(o(t,N))throw new Error('Illegal lexeme "'+t+'" for mode "'+(N.cN||"")+'"');return E+=t,t.length||1}var v=w(e);if(!v)throw new Error('Unknown language: "'+e+'"');u(v);var y,N=i||v,k={},C="";for(y=N;y!==v;y=y.parent)y.cN&&(C=p(y.cN,"",!0)+C);var E="",M=0;try{for(var B,S,$=0;;){if(N.t.lastIndex=$,B=N.t.exec(r),!B)break;S=h(r.substring($,B.index),B[0]),$=B.index+S}for(h(r.substr($)),y=N;y.parent;y=y.parent)y.cN&&(C+=R);return{r:M,value:C,language:e,top:N}}catch(A){if(A.message&&-1!==A.message.indexOf("Illegal"))return{r:0,value:t(r)};throw A}}function b(e,r){r=r||L.languages||k(x);var a={r:0,value:t(e)},n=a;return r.filter(w).forEach(function(t){var r=d(t,e,!1);r.language=t,r.r>n.r&&(n=r),r.r>a.r&&(n=a,a=r)}),n.language&&(a.second_best=n),a}function p(e){return L.tabReplace||L.useBR?e.replace(B,function(e,t){return L.useBR&&"\n"===e?"
":L.tabReplace?t.replace(/\t/g,L.tabReplace):""}):e}function m(e,t,r){var a=t?C[t]:r,n=[e.trim()];return e.match(/\bhljs\b/)||n.push("hljs"),-1===e.indexOf(a)&&n.push(a),n.join(" ").trim()}function f(e){var t,r,a,s,l,u=i(e);n(u)||(L.useBR?(t=document.createElementNS("http://www.w3.org/1999/xhtml","div"),t.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):t=e,l=t.textContent,a=u?d(u,l,!0):b(l),r=c(t),r.length&&(s=document.createElementNS("http://www.w3.org/1999/xhtml","div"),s.innerHTML=a.value,a.value=o(r,c(s),l)),a.value=p(a.value),e.innerHTML=a.value,e.className=m(e.className,u,a.language),e.result={language:a.language,re:a.r},a.second_best&&(e.second_best={language:a.second_best.language,re:a.second_best.r}))}function g(e){L=s(L,e)}function _(){if(!_.called){_.called=!0;var e=document.querySelectorAll("pre code");N.forEach.call(e,f)}}function h(){addEventListener("DOMContentLoaded",_,!1),addEventListener("load",_,!1)}function v(t,r){var a=x[t]=r(e);a.aliases&&a.aliases.forEach(function(e){C[e]=t})}function y(){return k(x)}function w(e){return e=(e||"").toLowerCase(),x[e]||x[C[e]]}var N=[],k=Object.keys,x={},C={},E=/^(no-?highlight|plain|text)$/i,M=/\blang(?:uage)?-([\w-]+)\b/i,B=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,R="
",L={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};return e.highlight=d,e.highlightAuto=b,e.fixMarkup=p,e.highlightBlock=f,e.configure=g,e.initHighlighting=_,e.initHighlightingOnLoad=h,e.registerLanguage=v,e.listLanguages=y,e.getLanguage=w,e.inherit=s,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.C=function(t,r,a){var n=e.inherit({cN:"comment",b:t,e:r,c:[]},a||{});return n.c.push(e.PWM),n.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),n},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e.registerLanguage("apache",function(e){var t={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:!0,c:[e.HCM,{cN:"section",b:""},{cN:"attribute",b:/\w+/,r:0,k:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"meta",b:"\\s\\[",e:"\\]$"},{cN:"variable",b:"[\\$%]\\{",e:"\\}",c:["self",t]},t,e.QSM]}}],i:/\S/}}),e.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},r={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/\b-?[a-z\._]+\b/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,r,a,t]}}),e.registerLanguage("coffeescript",function(e){var t={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super yield import export from as default await then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",built_in:"npm require console print module global window document"},r="[A-Za-z$_][0-9A-Za-z$_]*",a={cN:"subst",b:/#\{/,e:/}/,k:t},n=[e.BNM,e.inherit(e.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/"""/,e:/"""/,c:[e.BE,a]},{b:/"/,e:/"/,c:[e.BE,a]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[a,e.HCM]},{b:"//[gim]*",r:0},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{b:"@"+r},{sL:"javascript",eB:!0,eE:!0,v:[{b:"```",e:"```"},{b:"`",e:"`"}]}];a.c=n;var i=e.inherit(e.TM,{b:r}),s="(\\(.*\\))?\\s*\\B[-=]>",c={cN:"params",b:"\\([^\\(]",rB:!0,c:[{b:/\(/,e:/\)/,k:t,c:["self"].concat(n)}]};return{aliases:["coffee","cson","iced"],k:t,i:/\/\*/,c:n.concat([e.C("###","###"),e.HCM,{cN:"function",b:"^\\s*"+r+"\\s*=\\s*"+s,e:"[-=]>",rB:!0,c:[i,c]},{b:/[:\(,=]\s*/,r:0,c:[{cN:"function",b:s,e:"[-=]>",rB:!0,c:[c]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[i]},i]},{b:r+":",e:":",rB:!0,rE:!0,r:0}])}}),e.registerLanguage("cpp",function(e){var t={cN:"keyword",b:"\\b[a-z\\d_]*_t\\b"},r={cN:"string",v:[{b:'(u8?|U)?L?"',e:'"',i:"\\n",c:[e.BE]},{b:'(u8?|U)?R"',e:'"',c:[e.BE]},{b:"'\\\\?.",e:"'",i:"."}]},a={cN:"number",v:[{b:"\\b(0b[01']+)"},{b:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{b:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],r:0},n={cN:"meta",b:/#\s*[a-z]+\b/,e:/$/,k:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},c:[{b:/\\\n/,r:0},e.inherit(r,{cN:"meta-string"}),{cN:"meta-string",b:/<[^\n>]*>/,e:/$/,i:"\\n"},e.CLCM,e.CBCM]},i=e.IR+"\\s*\\(",s={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and or not",built_in:"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",literal:"true false nullptr NULL"},c=[t,e.CLCM,e.CBCM,a,r];return{aliases:["c","cc","h","c++","h++","hpp"],k:s,i:"",k:s,c:["self",t]},{b:e.IR+"::",k:s},{v:[{b:/=/,e:/;/},{b:/\(/,e:/\)/},{bK:"new throw return else",e:/;/}],k:s,c:c.concat([{b:/\(/,e:/\)/,k:s,c:c.concat(["self"]),r:0}]),r:0},{cN:"function",b:"("+e.IR+"[\\*&\\s]+)+"+i,rB:!0,e:/[{;=]/,eE:!0,k:s,i:/[^\w\s\*&]/,c:[{b:i,rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:s,r:0,c:[e.CLCM,e.CBCM,r,a,t]},e.CLCM,e.CBCM,n]},{cN:"class",bK:"class struct",e:/[{;:]/,c:[{b://,c:["self"]},e.TM]}]),exports:{preprocessor:n,strings:r,k:s}}}),e.registerLanguage("cs",function(e){var t={keyword:"abstract as base bool break byte case catch char checked const continue decimal default delegate do double enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long nameof object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while add alias ascending async await by descending dynamic equals from get global group into join let on orderby partial remove select set value var where yield",literal:"null false true"},r={cN:"string",b:'@"',e:'"',c:[{b:'""'}]},a=e.inherit(r,{i:/\n/}),n={cN:"subst",b:"{",e:"}",k:t},i=e.inherit(n,{i:/\n/}),s={cN:"string",b:/\$"/,e:'"',i:/\n/,c:[{b:"{{"},{b:"}}"},e.BE,i]},c={cN:"string",b:/\$@"/,e:'"',c:[{b:"{{"},{b:"}}"},{b:'""'},n]},o=e.inherit(c,{i:/\n/,c:[{b:"{{"},{b:"}}"},{b:'""'},i]});n.c=[c,s,r,e.ASM,e.QSM,e.CNM,e.CBCM],i.c=[o,s,a,e.ASM,e.QSM,e.CNM,e.inherit(e.CBCM,{i:/\n/})];var l={v:[c,s,r,e.ASM,e.QSM]},u=e.IR+"(<"+e.IR+"(\\s*,\\s*"+e.IR+")*>)?(\\[\\])?";return{aliases:["csharp"],k:t,i:/::/,c:[e.C("///","$",{rB:!0,c:[{cN:"doctag",v:[{b:"///",r:0},{b:""},{b:""}]}]}),e.CLCM,e.CBCM,{cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},l,e.CNM,{bK:"class interface",e:/[{;=]/,i:/[^\s:]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:"namespace",e:/[{;=]/,i:/[^\s:]/,c:[e.inherit(e.TM,{b:"[a-zA-Z](\\.?\\w)*"}),e.CLCM,e.CBCM]},{cN:"meta",b:"^\\s*\\[",eB:!0,e:"\\]",eE:!0,c:[{cN:"meta-string",b:/"/,e:/"/}]},{bK:"new return throw await else",r:0},{cN:"function",b:"("+u+"\\s+)+"+e.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:t,c:[{b:e.IR+"\\s*\\(",rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,r:0,c:[l,e.CNM,e.CBCM]},e.CLCM,e.CBCM]}]}}),e.registerLanguage("css",function(e){var t="[a-zA-Z-][a-zA-Z0-9_-]*",r={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:t,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,r]}]}}),e.registerLanguage("diff",function(e){return{aliases:["patch"],c:[{cN:"meta",r:10,v:[{b:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"comment",v:[{b:/Index: /,e:/$/},{b:/={3,}/,e:/$/},{b:/^\-{3}/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+{3}/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"addition",b:"^\\!",e:"$"}]}}),e.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}}),e.registerLanguage("ini",function(e){var t={cN:"string",c:[e.BE],v:[{b:"'''",e:"'''",r:10},{b:'"""',e:'"""',r:10},{b:'"',e:'"'},{b:"'",e:"'"}]};return{aliases:["toml"],cI:!0,i:/\S/,c:[e.C(";","$"),e.HCM,{cN:"section",b:/^\s*\[+/,e:/\]+/},{b:/^[a-z0-9\[\]_-]+\s*=\s*/,e:"$",rB:!0,c:[{cN:"attr",b:/[a-z0-9\[\]_-]+/},{b:/=/,eW:!0,r:0,c:[{cN:"literal",b:/\bon|off|true|false|yes|no\b/},{cN:"variable",v:[{b:/\$[\w\d"][\w\d_]*/},{b:/\$\{(.*?)}/}]},t,{cN:"number",b:/([\+\-]+)?[\d]+_[\d_]+/},e.NM]}]}]}}),e.registerLanguage("java",function(e){var t="[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*",r=t+"(<"+t+"(\\s*,\\s*"+t+")*>)?",a="false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",n="\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",i={cN:"number",b:n,r:0};return{aliases:["jsp"],k:a,i:/<\/|#/,c:[e.C("/\\*\\*","\\*/",{r:0,c:[{b:/\w+@/,r:0},{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:"class",bK:"class interface",e:/[{;=]/,eE:!0,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},e.UTM]},{bK:"new throw return else",r:0},{cN:"function",b:"("+r+"\\s+)+"+e.UIR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:a,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"params",b:/\(/,e:/\)/,k:a,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},i,{cN:"meta",b:"@[A-Za-z]+"}]}}),e.registerLanguage("javascript",function(e){var t="[A-Za-z$_][0-9A-Za-z$_]*",r={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:r,c:[]},i={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,i,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:r,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,i,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:t+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:t,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+t+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:t},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:r,c:s}]}]},{b://,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:t}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}}),e.registerLanguage("json",function(e){var t={literal:"true false null"},r=[e.QSM,e.CNM],a={e:",",eW:!0,eE:!0,c:r,k:t},n={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(a,{b:/:/})],i:"\\S"},i={b:"\\[",e:"\\]",c:[e.inherit(a)],i:"\\S"};return r.splice(r.length,0,n,i),{c:r,k:t,i:"\\S"}}),e.registerLanguage("makefile",function(e){var t={cN:"variable",v:[{b:"\\$\\("+e.UIR+"\\)",c:[e.BE]},{b:/\$[@%`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},e.C("",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"|$)",e:">",k:{name:"style"},c:[r],starts:{e:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"|$)",e:">",k:{name:"script"},c:[r],starts:{e:"",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},r]}]}}),e.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],c:[{cN:"section",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"quote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"^```w*s*$",e:"^```s*$"},{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"string",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"symbol",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:/^\[[^\n]+\]:/,rB:!0,c:[{cN:"symbol",b:/\[/,e:/\]/,eB:!0,eE:!0},{cN:"link",b:/:\s*/,e:/$/,eB:!0}]}]}}),e.registerLanguage("nginx",function(e){var t={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+e.UIR}]},r={eW:!0,l:"[a-z/_]+",k:{literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[e.HCM,{cN:"string",c:[e.BE,t],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{b:"([a-z]+):/",e:"\\s",eW:!0,eE:!0,c:[t]},{cN:"regexp",c:[e.BE,t],v:[{b:"\\s\\^",e:"\\s|{|;",rE:!0},{b:"~\\*?\\s+",e:"\\s|{|;",rE:!0},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},t]};return{aliases:["nginxconf"],c:[e.HCM,{b:e.UIR+"\\s+{",rB:!0,e:"{",c:[{cN:"section",b:e.UIR}],r:0},{b:e.UIR+"\\s",e:";|{",rB:!0,c:[{cN:"attribute",b:e.UIR,starts:r}],r:0}],i:"[^\\s\\}]"}}),e.registerLanguage("objectivec",function(e){var t={cN:"built_in",b:"\\b(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)\\w+"},r={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},a=/[a-zA-Z@][a-zA-Z0-9_]*/,n="@interface @class @protocol @implementation";return{aliases:["mm","objc","obj-c"],k:r,l:a,i:""}]}]},{cN:"class",b:"("+n.split(" ").join("|")+")\\b",e:"({|$)",eE:!0,k:n,l:a,c:[e.UTM]},{b:"\\."+e.UIR,r:0}]}}),e.registerLanguage("perl",function(e){var t="getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when",r={cN:"subst",b:"[$@]\\{",e:"\\}",k:t},a={b:"->{",e:"}"},n={v:[{b:/\$\d/},{b:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{b:/[\$%@][^\s\w{]/,r:0}]},i=[e.BE,r,n],s=[n,e.HCM,e.C("^\\=\\w","\\=cut",{eW:!0}),a,{cN:"string",c:i,v:[{b:"q[qwxr]?\\s*\\(",e:"\\)",r:5},{b:"q[qwxr]?\\s*\\[",e:"\\]",r:5},{b:"q[qwxr]?\\s*\\{",e:"\\}",r:5},{b:"q[qwxr]?\\s*\\|",e:"\\|",r:5},{b:"q[qwxr]?\\s*\\<",e:"\\>",r:5},{b:"qw\\s+q",e:"q",r:5},{b:"'",e:"'",c:[e.BE]},{b:'"',e:'"'},{b:"`",e:"`",c:[e.BE]},{b:"{\\w+}",c:[],r:0},{b:"-?\\w+\\s*\\=\\>",c:[],r:0}]},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\/\\/|"+e.RSR+"|\\b(split|return|print|reverse|grep)\\b)\\s*",k:"split return print reverse grep",r:0,c:[e.HCM,{cN:"regexp",b:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",r:10},{cN:"regexp",b:"(m|qr)?/",e:"/[a-z]*",c:[e.BE],r:0}]},{cN:"function",bK:"sub",e:"(\\s*\\(.*?\\))?[;{]",eE:!0,r:5,c:[e.TM]},{b:"-\\w\\b",r:0},{b:"^__DATA__$",e:"^__END__$",sL:"mojolicious",c:[{b:"^@@.*",e:"$",cN:"comment"}]}];return r.c=s,a.c=s,{aliases:["pl","pm"],l:/[\w\.]+/,k:t,c:s}}),e.registerLanguage("php",function(e){var t={b:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},r={cN:"meta",b:/<\?(php)?|\?>/},a={cN:"string",c:[e.BE,r],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},n={v:[e.BNM,e.CNM]};return{aliases:["php3","php4","php5","php6"],cI:!0,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[e.HCM,e.C("//","$",{c:[r]}),e.C("/\\*","\\*/",{c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.C("__halt_compiler.+?;",!1,{eW:!0,k:"__halt_compiler",l:e.UIR}),{cN:"string",b:/<<<['"]?\w+['"]?$/,e:/^\w+;?$/,c:[e.BE,{cN:"subst",v:[{b:/\$\w+/},{b:/\{\$/,e:/\}/}]}]},r,{cN:"keyword",b:/\$this\b/},t,{b:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{cN:"function",bK:"function",e:/[;{]/,eE:!0,i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",t,e.CBCM,a,n]}]},{cN:"class",bK:"class interface",e:"{",eE:!0,i:/[:\(\$"]/,c:[{bK:"extends implements"},e.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[e.UTM]},{bK:"use",e:";",c:[e.UTM]},{b:"=>"},a,n]}}),e.registerLanguage("python",function(e){var t={keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},r={cN:"meta",b:/^(>>>|\.\.\.) /},a={cN:"subst",b:/\{/,e:/\}/,k:t,i:/#/},n={cN:"string",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[r],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[r],r:10},{b:/(fr|rf|f)'''/,e:/'''/,c:[r,a]},{b:/(fr|rf|f)"""/,e:/"""/,c:[r,a]},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},{b:/(fr|rf|f)'/,e:/'/,c:[a]},{b:/(fr|rf|f)"/,e:/"/,c:[a]},e.ASM,e.QSM]},i={cN:"number",r:0,v:[{b:e.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:e.CNR+"[lLjJ]?"}]},s={cN:"params",b:/\(/,e:/\)/,c:["self",r,i,n]};return a.c=[n,i,r],{aliases:["py","gyp"],k:t,i:/(<\/|->|\?)|=>/,c:[r,i,n,e.HCM,{v:[{cN:"function",bK:"def"},{cN:"class",bK:"class"}],e:/:/,i:/[${=;\n,]/,c:[e.UTM,s,{b:/->/,eW:!0,k:"None"}]},{cN:"meta",b:/^[\t ]*@/,e:/$/},{b:/\b(print|exec)\(/}]}}),e.registerLanguage("ruby",function(e){ +var t="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",r={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},a={cN:"doctag",b:"@[A-Za-z]+"},n={b:"#<",e:">"},i=[e.C("#","$",{c:[a]}),e.C("^\\=begin","^\\=end",{c:[a],r:10}),e.C("^__END__","\\n$")],s={cN:"subst",b:"#\\{",e:"}",k:r},c={cN:"string",c:[e.BE,s],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/`/,e:/`/},{b:"%[qQwWx]?\\(",e:"\\)"},{b:"%[qQwWx]?\\[",e:"\\]"},{b:"%[qQwWx]?{",e:"}"},{b:"%[qQwWx]?<",e:">"},{b:"%[qQwWx]?/",e:"/"},{b:"%[qQwWx]?%",e:"%"},{b:"%[qQwWx]?-",e:"-"},{b:"%[qQwWx]?\\|",e:"\\|"},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{b:/<<(-?)\w+$/,e:/^\s*\w+$/}]},o={cN:"params",b:"\\(",e:"\\)",endsParent:!0,k:r},l=[c,n,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{b:"<\\s*",c:[{b:"("+e.IR+"::)?"+e.IR}]}].concat(i)},{cN:"function",bK:"def",e:"$|;",c:[e.inherit(e.TM,{b:t}),o].concat(i)},{b:e.IR+"::"},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":(?!\\s)",c:[c,{b:t}],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{cN:"params",b:/\|/,e:/\|/,k:r},{b:"("+e.RSR+"|unless)\\s*",k:"unless",c:[n,{cN:"regexp",c:[e.BE,s],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}].concat(i),r:0}].concat(i);s.c=l,o.c=l;var u="[>?]>",d="[\\w#]+\\(\\w+\\):\\d+:\\d+>",b="(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>",p=[{b:/^\s*=>/,starts:{e:"$",c:l}},{cN:"meta",b:"^("+u+"|"+d+"|"+b+")",starts:{e:"$",c:l}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:r,i:/\/\*/,c:i.concat(p).concat(l)}}),e.registerLanguage("shell",function(e){return{aliases:["console"],c:[{cN:"meta",b:"^\\s{0,3}[\\w\\d\\[\\]()@-]*[>%$#]",starts:{e:"$",sL:"bash"}}]}}),e.registerLanguage("sql",function(e){var t=e.C("--","$");return{cI:!0,i:/[<>{}*#]/,c:[{bK:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment",e:/;/,eW:!0,l:/[\w\.]+/,k:{keyword:"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text varchar varying void"},c:[{cN:"string",b:"'",e:"'",c:[e.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[e.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[e.BE]},e.CNM,e.CBCM,t]},e.CBCM,t]}}),e}); \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..b0dc825 --- /dev/null +++ b/index.html @@ -0,0 +1,191 @@ + + + + + + + Continuable + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+ + + + + +

Overview

Continuable is a C++14 library that provides full support for:

  • lazy async continuation chaining based on callbacks (then) and expression templates, callbacks are wrapped nicely as promises.
  • no enforced type-erasure which means we need less heap allocations than comparable libraries, strictly following the "don't + pay for what you don't use" principle.
  • support for all, any and sequential connections between continuables through expressive operator overloads &&, || and >> as well as free functions when_all, when_any and when_seq.
  • asynchronous error handling through exceptions, error codes and user defined types.
  • syntactic sugar for instance: partial invocation, tuple unpacking, co_await support and executors.
  • encapsuled from any runtime, larger framework or executors makes it possible to use continuable even in smaller or esoteric usage scenarios.

Getting started

Continuable is a header-only library with zero compilation dependencies. The Installation and Configuration are explained in its own chapter.

The Tutorial is everything you need in order to get to know the libraries API. Beside of this, there is a detailed in-source documentation provided.

Continuable follows the semantic versioning schema and changes are listed in the Changelog.

Contributing and Questions

Through the Github issue tracker you are welcomed to ask for questions, contribute code or request new features. Also I would like to hear your personal opinion about the library design or your personal experience in using the library to improve it.

License

Continuable is licensed under the MIT license:

Copyright(c) 2015 - 2020 Denis Blank <denis.blank at outlook dot com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+
+
+
+
+ + + + + + diff --git a/installation.html b/installation.html new file mode 100644 index 0000000..67e9b64 --- /dev/null +++ b/installation.html @@ -0,0 +1,201 @@ + + + + + + + Installation | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Installation +

+ +

An explanation on how to install continuable on various platforms.

+ +

Requirements

Continuable requires a fairly new toolchain and was verified to work with following compilers:

  • Visual Studio 2017+ Update 2
  • Clang 5.0+
  • GCC 6.0+

Although the build is observed with the listed compilers earlier versions might work.

Dependencies

Continuable is a header-only library with one required header-only dependency:

Additionally GTest is required as optional dependency for the asynchronous unit testing macros defined in continuable/support/gtest.hpp if those are used:

  • google/googletest is used as unit testing framework and to provide asynchronous testing macros.

For the examples and unit tests there might be more dependencies used, which are fetched through git submodules.

Installation

Making continuable available inside your project is possible through various ways.

Through CMake

The continuable build is driven by CMake and the project exposes CMake interface targets when being used by external projects:

add_subdirectory(continuable)
+# continuable provides an interface target which makes it's
+# headers available to all projects using the continuable library.
+target_link_libraries(my_project continuable)

When adding the continuable subdirectory as git submodule this should work out of the box.

git submodule add https://github.com/Naios/continuable.git

Additionally the CMake project exports a continuable target which is importable through the find_package CMake command when installed:

mkdir build
+cd build
+cmake ..
+cmake --build . --target INSTALL --config Release

In your CMakeLists.txt:

find_package(continuable REQUIRED)

Through package managers

Continuable is present in some package managers and registries already, and might be installed from there.

By using the amalgamation header

For major versions there is an amalgamation header provided which can be included without any dependency:

By copying the headers

If you don't want to rely on CMake or package managers it is possible to copy and include the include directories of continuable and Naios/function2 into your project.

As an improvement git submodules could be used:

git submodule add https://github.com/Naios/continuable.git
+git submodule add https://github.com/Naios/function2.git

Building the unit tests

In order to build the unit tests clone the repository recursively with all submodules:

# Shell:
+git clone --recursive https://github.com/Naios/continuable.git

Then CMake can be used to generate a project solution for testing.

+
+
+
+
+ + + + + + diff --git a/m-dark+doxygen.compiled.css b/m-dark+doxygen.compiled.css new file mode 100644 index 0000000..ca8255e --- /dev/null +++ b/m-dark+doxygen.compiled.css @@ -0,0 +1,2780 @@ +/* Generated using `./postprocess.py m-dark.css m-doxygen.css -o m-dark+doxygen.compiled.css`. Do not edit. */ + +/* + This file is part of m.css. + + Copyright © 2017, 2018, 2019 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +*, ::before, ::after { box-sizing: border-box; } +body { margin: 0; } +.m-container { + width: 100%; + margin: auto; + padding-left: 1rem; + padding-right: 1rem; +} +.m-row { + margin-left: -1rem; + margin-right: -1rem; +} +.m-row:after { + content: ' '; + clear: both; + display: table; +} +.m-row > [class*='m-col-'] { + position: relative; + padding: 1rem; +} +[class*='m-clearfix-']::after { + display: block; + content: ' '; + clear: both; +} +[class*='m-show-'] { + display: none; +} +.m-container-inflate, :not(.m-row) > [class*='m-col-'] { + margin-bottom: 1rem; +} +.m-container-inflate:last-child, :not(.m-row) > [class*='m-col-']:last-child { + margin-bottom: 0; +} +.m-container.m-nopad, [class*='m-col-'].m-nopad, +.m-container.m-nopadx, [class*='m-col-'].m-nopadx, +.m-container.m-nopadl, [class*='m-col-'].m-nopadl { + padding-left: 0; +} +.m-container.m-nopad, [class*='m-col-'].m-nopad, +.m-container.m-nopadx, [class*='m-col-'].m-nopadx, +.m-container.m-nopadr, [class*='m-col-'].m-nopadr { + padding-right: 0; +} +[class*='m-col-'].m-nopad, [class*='m-col-'].m-nopady, [class*='m-col-'].m-nopadt { + padding-top: 0; +} +[class*='m-col-'].m-nopad, [class*='m-col-'].m-nopady, [class*='m-col-'].m-nopadb, +.m-container-inflate.m-nopadb { + padding-bottom: 0; +} +[class*='m-col-t-'] { float: left; } +.m-left-t { + padding-right: 1rem; + float: left; +} +.m-right-t, [class*='m-col-t-'].m-right-t { + padding-left: 1rem; + float: right; +} +.m-center-t, [class*='m-col-t-'].m-center-t { + float: none; +} +.m-center-t, [class*='m-col-t-'].m-center-t { + margin-left: auto; + margin-right: auto; + float: none; +} +.m-col-t-1 { width: calc(1 * 100% / 12); } +.m-col-t-2 { width: calc(2 * 100% / 12); } +.m-col-t-3 { width: calc(3 * 100% / 12); } +.m-col-t-4 { width: calc(4 * 100% / 12); } +.m-col-t-5 { width: calc(5 * 100% / 12); } +.m-col-t-6 { width: calc(6 * 100% / 12); } +.m-col-t-7 { width: calc(7 * 100% / 12); } +.m-col-t-8 { width: calc(8 * 100% / 12); } +.m-col-t-9 { width: calc(9 * 100% / 12); } +.m-col-t-10 { width: calc(10 * 100% / 12); } +.m-col-t-11 { width: calc(11 * 100% / 12); } +.m-col-t-12 { width: calc(12 * 100% / 12); } +.m-push-t-1 { left: calc(1 * 100% / 12); } +.m-push-t-2 { left: calc(2 * 100% / 12); } +.m-push-t-3 { left: calc(3 * 100% / 12); } +.m-push-t-4 { left: calc(4 * 100% / 12); } +.m-push-t-5 { left: calc(5 * 100% / 12); } +.m-push-t-6 { left: calc(6 * 100% / 12); } +.m-push-t-7 { left: calc(7 * 100% / 12); } +.m-push-t-8 { left: calc(8 * 100% / 12); } +.m-push-t-9 { left: calc(9 * 100% / 12); } +.m-push-t-10 { left: calc(10 * 100% / 12); } +.m-push-t-11 { left: calc(11 * 100% / 12); } +.m-pull-t-1 { right: calc(1 * 100% / 12); } +.m-pull-t-2 { right: calc(2 * 100% / 12); } +.m-pull-t-3 { right: calc(3 * 100% / 12); } +.m-pull-t-4 { right: calc(4 * 100% / 12); } +.m-pull-t-5 { right: calc(5 * 100% / 12); } +.m-pull-t-6 { right: calc(6 * 100% / 12); } +.m-pull-t-7 { right: calc(7 * 100% / 12); } +.m-pull-t-8 { right: calc(8 * 100% / 12); } +.m-pull-t-9 { right: calc(9 * 100% / 12); } +.m-pull-t-10 { right: calc(10 * 100% / 12); } +.m-pull-t-11 { right: calc(11 * 100% / 12); } +@media screen and (min-width: 576px) { + .m-container { width: 560px; } + .m-container-inflatable .m-col-s-10 .m-container-inflate:not([class*='m-left-']):not([class*='m-right-']) { + margin-left: -10%; + margin-right: -10%; + } + .m-container-inflatable .m-col-s-10 .m-container-inflate.m-left-s { + margin-left: -10%; + } + .m-container-inflatable .m-col-s-10 .m-container-inflate.m-right-s { + margin-right: -10%; + } + [class*='m-col-s-'] { float: left; } + .m-left-s { + padding-right: 1rem; + float: left; + } + .m-right-s, [class*='m-col-s-'].m-right-s { + padding-left: 1rem; + float: right; + } + .m-center-s, [class*='m-col-s-'].m-center-s { + margin-left: auto; + margin-right: auto; + float: none; + } + .m-col-s-1 { width: calc(1 * 100% / 12); } + .m-col-s-2 { width: calc(2 * 100% / 12); } + .m-col-s-3 { width: calc(3 * 100% / 12); } + .m-col-s-4 { width: calc(4 * 100% / 12); } + .m-col-s-5 { width: calc(5 * 100% / 12); } + .m-col-s-6 { width: calc(6 * 100% / 12); } + .m-col-s-7 { width: calc(7 * 100% / 12); } + .m-col-s-8 { width: calc(8 * 100% / 12); } + .m-col-s-9 { width: calc(9 * 100% / 12); } + .m-col-s-10 { width: calc(10 * 100% / 12); } + .m-col-s-11 { width: calc(11 * 100% / 12); } + .m-col-s-12 { width: calc(12 * 100% / 12); } + .m-push-s-0 { left: calc(0 * 100% / 12); } + .m-push-s-1 { left: calc(1 * 100% / 12); } + .m-push-s-2 { left: calc(2 * 100% / 12); } + .m-push-s-3 { left: calc(3 * 100% / 12); } + .m-push-s-4 { left: calc(4 * 100% / 12); } + .m-push-s-5 { left: calc(5 * 100% / 12); } + .m-push-s-6 { left: calc(6 * 100% / 12); } + .m-push-s-7 { left: calc(7 * 100% / 12); } + .m-push-s-8 { left: calc(8 * 100% / 12); } + .m-push-s-9 { left: calc(9 * 100% / 12); } + .m-push-s-10 { left: calc(10 * 100% / 12); } + .m-push-s-11 { left: calc(11 * 100% / 12); } + .m-pull-s-0 { right: calc(0 * 100% / 12); } + .m-pull-s-1 { right: calc(1 * 100% / 12); } + .m-pull-s-2 { right: calc(2 * 100% / 12); } + .m-pull-s-3 { right: calc(3 * 100% / 12); } + .m-pull-s-4 { right: calc(4 * 100% / 12); } + .m-pull-s-5 { right: calc(5 * 100% / 12); } + .m-pull-s-6 { right: calc(6 * 100% / 12); } + .m-pull-s-7 { right: calc(7 * 100% / 12); } + .m-pull-s-8 { right: calc(8 * 100% / 12); } + .m-pull-s-9 { right: calc(9 * 100% / 12); } + .m-pull-s-10 { right: calc(10 * 100% / 12); } + .m-pull-s-11 { right: calc(11 * 100% / 12); } + .m-clearfix-t::after { display: none; } + .m-hide-s { display: none; } + .m-show-s { display: block; } + .m-col-s-none { + width: auto; + float: none; + } +} +@media screen and (min-width: 768px) { + .m-container { width: 750px; } + .m-container-inflatable .m-col-m-10 .m-container-inflate:not([class*='m-left-']):not([class*='m-right-']) { + margin-left: -10%; + margin-right: -10%; + } + .m-container-inflatable .m-col-m-10 .m-container-inflate.m-left-m { + margin-left: -10%; + } + .m-container-inflatable .m-col-m-10 .m-container-inflate.m-right-m { + margin-right: -10%; + } + [class*='m-col-m-'] { float: left; } + .m-left-m { + padding-right: 1rem; + float: left; + } + .m-right-m, [class*='m-col-m-'].m-right-m { + padding-left: 1rem; + float: right; + } + .m-center-m, [class*='m-col-m-'].m-center-m { + margin-left: auto; + margin-right: auto; + float: none; + } + .m-col-m-1 { width: calc(1 * 100% / 12); } + .m-col-m-2 { width: calc(2 * 100% / 12); } + .m-col-m-3 { width: calc(3 * 100% / 12); } + .m-col-m-4 { width: calc(4 * 100% / 12); } + .m-col-m-5 { width: calc(5 * 100% / 12); } + .m-col-m-6 { width: calc(6 * 100% / 12); } + .m-col-m-7 { width: calc(7 * 100% / 12); } + .m-col-m-8 { width: calc(8 * 100% / 12); } + .m-col-m-9 { width: calc(9 * 100% / 12); } + .m-col-m-10 { width: calc(10 * 100% / 12); } + .m-col-m-11 { width: calc(11 * 100% / 12); } + .m-col-m-12 { width: calc(12 * 100% / 12); } + .m-push-m-0 { left: calc(0 * 100% / 12); } + .m-push-m-1 { left: calc(1 * 100% / 12); } + .m-push-m-2 { left: calc(2 * 100% / 12); } + .m-push-m-3 { left: calc(3 * 100% / 12); } + .m-push-m-4 { left: calc(4 * 100% / 12); } + .m-push-m-5 { left: calc(5 * 100% / 12); } + .m-push-m-6 { left: calc(6 * 100% / 12); } + .m-push-m-7 { left: calc(7 * 100% / 12); } + .m-push-m-8 { left: calc(8 * 100% / 12); } + .m-push-m-9 { left: calc(9 * 100% / 12); } + .m-push-m-10 { left: calc(10 * 100% / 12); } + .m-push-m-11 { left: calc(11 * 100% / 12); } + .m-pull-m-0 { right: calc(0 * 100% / 12); } + .m-pull-m-1 { right: calc(1 * 100% / 12); } + .m-pull-m-2 { right: calc(2 * 100% / 12); } + .m-pull-m-3 { right: calc(3 * 100% / 12); } + .m-pull-m-4 { right: calc(4 * 100% / 12); } + .m-pull-m-5 { right: calc(5 * 100% / 12); } + .m-pull-m-6 { right: calc(6 * 100% / 12); } + .m-pull-m-7 { right: calc(7 * 100% / 12); } + .m-pull-m-8 { right: calc(8 * 100% / 12); } + .m-pull-m-9 { right: calc(9 * 100% / 12); } + .m-pull-m-10 { right: calc(10 * 100% / 12); } + .m-pull-m-11 { right: calc(11 * 100% / 12); } + .m-clearfix-s::after { display: none; } + .m-hide-m { display: none; } + .m-show-m { display: block; } + .m-col-m-none { + width: auto; + float: none; + } +} +@media screen and (min-width: 992px) { + .m-container { width: 960px; } + .m-container-inflatable .m-col-l-10 .m-container-inflate:not([class*='m-left-']):not([class*='m-right-']) { + margin-left: -10%; + margin-right: -10%; + } + .m-container-inflatable .m-col-l-10 .m-container-inflate.m-left-l { + margin-left: -10%; + } + .m-container-inflatable .m-col-l-10 .m-container-inflate.m-right-l { + margin-right: -10%; + } + [class*='m-col-l-'] { float: left; } + .m-left-l { + padding-right: 1rem; + float: left; + } + .m-right-l, [class*='m-col-l-'].m-right-l { + padding-left: 1rem; + float: right; + } + .m-center-l, [class*='m-col-l-'].m-center-l { + margin-left: auto; + margin-right: auto; + float: none; + } + .m-col-l-1 { width: calc(1 * 100% / 12); } + .m-col-l-2 { width: calc(2 * 100% / 12); } + .m-col-l-3 { width: calc(3 * 100% / 12); } + .m-col-l-4 { width: calc(4 * 100% / 12); } + .m-col-l-5 { width: calc(5 * 100% / 12); } + .m-col-l-6 { width: calc(6 * 100% / 12); } + .m-col-l-7 { width: calc(7 * 100% / 12); } + .m-col-l-8 { width: calc(8 * 100% / 12); } + .m-col-l-9 { width: calc(9 * 100% / 12); } + .m-col-l-10 { width: calc(10 * 100% / 12); } + .m-col-l-11 { width: calc(11 * 100% / 12); } + .m-col-l-12 { width: calc(12 * 100% / 12); } + .m-push-l-0 { left: calc(0 * 100% / 12); } + .m-push-l-1 { left: calc(1 * 100% / 12); } + .m-push-l-2 { left: calc(2 * 100% / 12); } + .m-push-l-3 { left: calc(3 * 100% / 12); } + .m-push-l-4 { left: calc(4 * 100% / 12); } + .m-push-l-5 { left: calc(5 * 100% / 12); } + .m-push-l-6 { left: calc(6 * 100% / 12); } + .m-push-l-7 { left: calc(7 * 100% / 12); } + .m-push-l-8 { left: calc(8 * 100% / 12); } + .m-push-l-9 { left: calc(9 * 100% / 12); } + .m-push-l-10 { left: calc(10 * 100% / 12); } + .m-push-l-11 { left: calc(11 * 100% / 12); } + .m-pull-l-0 { right: calc(0 * 100% / 12); } + .m-pull-l-1 { right: calc(1 * 100% / 12); } + .m-pull-l-2 { right: calc(2 * 100% / 12); } + .m-pull-l-3 { right: calc(3 * 100% / 12); } + .m-pull-l-4 { right: calc(4 * 100% / 12); } + .m-pull-l-5 { right: calc(5 * 100% / 12); } + .m-pull-l-6 { right: calc(6 * 100% / 12); } + .m-pull-l-7 { right: calc(7 * 100% / 12); } + .m-pull-l-8 { right: calc(8 * 100% / 12); } + .m-pull-l-9 { right: calc(9 * 100% / 12); } + .m-pull-l-10 { right: calc(10 * 100% / 12); } + .m-pull-l-11 { right: calc(11 * 100% / 12); } + .m-clearfix-m::after { display: none; } + .m-hide-l { display: none; } + .m-show-l { display: block; } + .m-col-l-none { + width: auto; + float: none; + } +} + +html { + font-size: 16px; + background-color: #2f363f; +} +body { + font-family: 'Source Sans Pro', sans-serif; + font-size: 1rem; + color: #dcdcdc; +} +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + font-weight: 600; +} +h1 { + margin-bottom: 1rem; +} +h2, h3, h4, h5, h6 { + margin-bottom: 0.5rem; +} +p, ul, ol, dl { + margin-top: 0; +} +ul, ol { + padding-left: 2rem; +} +ul ol, ul ul, ol ol, ol ul { + margin-bottom: 0; +} +main p { + text-indent: 1.5rem; + text-align: justify; +} +main p.m-noindent, li > p, dd > p, table.m-table td > p { + text-indent: 0; + text-align: left; +} +blockquote { + margin-top: 0; + margin-left: 1rem; + margin-right: 1rem; + padding: 1rem; + border-left-style: solid; + border-left-width: 0.25rem; +} +hr { + width: 75%; + border-width: 0.0625rem; + border-style: solid; +} +blockquote, hr { + border-color: #405363; +} +pre { + font-family: 'Source Code Pro', monospace, monospace, monospace; + font-size: 0.9em; + padding: 0.5rem 1rem; + color: #e6e6e6; + background-color: #282e36; + border-radius: 0.2rem; + overflow-x: auto; + margin-top: 0; +} +pre.m-console { + background-color: #000000; +} +abbr { + cursor: help; + text-decoration: underline dotted; +} +sub, sup { + font-size: 0.75rem; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { top: -0.35rem; } +sub { bottom: -0.2rem; } +a { + color: #5b9dd9; +} +a.m-flat { + text-decoration: none; +} +a:hover, a:focus, a:active { + color: #a5c9ea; +} +a img { border: 0; } +svg a { cursor: pointer; } +mark { + padding: 0.0625rem; + background-color: #c7cf2f; + color: #2f83cc; +} +code { + font-family: 'Source Code Pro', monospace, monospace, monospace; + font-size: 0.9em; + padding: 0.125rem; + color: #e6e6e6; + background-color: #282e36; +} +code.m-console { + background-color: #000000; +} +*:focus { outline-color: #5b9dd9; } +div.m-scroll { + max-width: 100%; + overflow-x: auto; +} +.m-fullwidth { + width: 100%; +} +.m-spacing-150 { + line-height: 1.5rem; +} +.m-text-center, .m-text-center.m-noindent, table.m-table th.m-text-center, .m-text-center p { + text-align: center; +} +.m-text-left, .m-text-left.m-noindent, table.m-table th.m-text-left, .m-text-right p { + text-align: left; +} +.m-text-right, .m-text-right.m-noindent, table.m-table th.m-text-right, .m-text-right p { + text-align: right; +} +.m-text-top, table.m-table th.m-text-top, table.m-table td.m-text-top { + vertical-align: top; +} +.m-text-middle, table.m-table th.m-text-middle, table.m-table td.m-text-middle { + vertical-align: middle; +} +.m-text-bottom, table.m-table th.m-text-bottom, table.m-table td.m-text-bottom { + vertical-align: bottom; +} +.m-text.m-small { + font-size: 85.4%; +} +.m-text.m-big { + font-size: 117%; +} +.m-text.m-strong { + font-weight: bold; +} +.m-text.m-em { + font-style: italic; +} +h1 .m-thin, h2 .m-thin, h3 .m-thin, h4 .m-thin, h5 .m-thin, h6 .m-thin { + font-weight: normal; +} +ul.m-unstyled, ol.m-unstyled { + list-style-type: none; + padding-left: 0; +} +ul[class*='m-block-'], ol[class*='m-block-'] { + padding-left: 0; +} +ul[class*='m-block-'] li, ol[class*='m-block-'] li { + display: inline; +} +ul[class*='m-block-bar-'] li:not(:last-child)::after, ol[class*='m-block-bar-'] li:not(:last-child)::after { + content: " | "; +} +ul[class*='m-block-dot-'] li:not(:last-child)::after, ol[class*='m-block-dot-'] li:not(:last-child)::after { + content: " • "; +} +@media screen and (min-width: 576px) { + ul.m-block-bar-s, ol.m-block-bar-s, + ul.m-block-dot-s, ol.m-block-dot-s { padding-left: 2rem; } + ul.m-block-bar-s li, ol.m-block-bar-s li, + ul.m-block-dot-s li, ol.m-block-dot-s li { display: list-item; } + ul.m-block-bar-s li:not(:last-child)::after, ol.m-block-bar-s li:not(:last-child)::after, + ul.m-block-dot-s li:not(:last-child)::after, ol.m-block-dot-s li:not(:last-child)::after { content: ""; } +} +@media screen and (min-width: 768px) { + ul.m-block-bar-m, ol.m-block-bar-m, + ul.m-block-dot-m, ol.m-block-dot-m { padding-left: 2rem; } + ul.m-block-bar-m li, ol.m-block-bar-m li, + ul.m-block-dot-m li, ol.m-block-dot-m li { display: list-item; } + ul.m-block-bar-m li:not(:last-child)::after, ol.m-block-bar-m li:not(:last-child)::after, + ul.m-block-dot-m li:not(:last-child)::after, ol.m-block-dot-m li:not(:last-child)::after { content: ""; } +} +@media screen and (min-width: 992px) { + ul.m-block-bar-l, ol.m-block-bar-l, + ul.m-block-dot-l, ol.m-block-dot-l { padding-left: 2rem; } + ul.m-block-bar-l li, ol.m-block-bar-l li, + ul.m-block-dot-l li, ol.m-block-dot-l li { display: list-item; } + ul.m-block-bar-l li:not(:last-child)::after, ol.m-block-bar-l li:not(:last-child)::after, + ul.m-block-dot-l li:not(:last-child)::after, ol.m-block-dot-l li:not(:last-child)::after { content: ""; } +} +p.m-poem { + text-indent: 0; + text-align: left; + margin-left: 1.5rem; +} +p.m-transition { + color: #405363; + text-indent: 0; + text-align: center; + font-size: 2rem; +} +dl.m-diary { + margin-bottom: 1.25rem; +} +dl.m-diary:last-child { + margin-bottom: 0.25rem; +} +dl.m-diary dt { + font-weight: bold; + width: 3.5rem; + float: left; + clear: both; + padding-top: 0.25rem; +} +dl.m-diary dd { + padding-top: 0.25rem; + padding-left: 3.5rem; +} +.m-note { + border-radius: 0.2rem; + padding: 1rem; +} +.m-note pre, .m-note code { + background-color: rgba(34, 39, 46, 0.5); +} +.m-frame { + background-color: #2f363f; + border-style: solid; + border-width: 0.125rem; + border-radius: 0.2rem; + border-color: #405363; + padding: 0.875rem; +} +.m-block { + border-style: solid; + border-width: 0.0625rem; + border-left-width: 0.25rem; + border-radius: 0.2rem; + border-color: #405363; + padding: 0.9375rem 0.9375rem 0.9375rem 0.75rem; +} +.m-block.m-badge::after { + content: ' '; + display: block; + clear: both; +} +.m-block.m-badge h3 { + margin-left: 5rem; +} +.m-block.m-badge p { + margin-left: 5rem; + text-indent: 0; +} +.m-block.m-badge img { + width: 4rem; + height: 4rem; + border-radius: 2rem; + float: left; +} +div.m-button { + text-align: center; +} +div.m-button a { + display: inline-block; + border-radius: 0.2rem; + padding-top: 0.75rem; + padding-bottom: 0.75rem; + padding-left: 1.5rem; + padding-right: 1.5rem; + text-decoration: none; + font-size: 1.17rem; +} +div.m-button.m-fullwidth a { + display: block; + padding-left: 0.5rem; + padding-right: 0.5rem; +} +div.m-button a .m-big:first-child { + font-size: 1.37rem; + font-weight: bold; +} +div.m-button a .m-small:last-child { + font-size: 0.854rem; +} +.m-label { + border-radius: 0.2rem; + font-size: 75%; + font-weight: normal; + padding: 0.125rem 0.25rem; + vertical-align: 7.5%; +} +.m-label.m-flat { + border-width: 0.0625rem; + border-style: solid; + border-color: #747474; + padding: 0.0625rem 0.1875rem; +} +table.m-table { + border-collapse: collapse; + margin-left: auto; + margin-right: auto; +} +table.m-table.m-big { + margin-top: 1.75rem; +} +div.m-scroll > table.m-table:last-child { + margin-bottom: 0.0625rem; +} +table.m-table:not(.m-flat) tbody tr:hover { + background-color: #405363; +} +table.m-table th, table.m-table td { + vertical-align: top; + border-style: solid; + border-top-width: 0.0625rem; + border-left-width: 0; + border-right-width: 0; + border-bottom-width: 0; + border-color: #405363; +} +table.m-table caption { + padding-bottom: 0.5rem; +} +table.m-table thead tr:first-child th, table.m-table thead tr:first-child td { + border-top-width: 0.125rem; +} +table.m-table thead th, table.m-table thead td { + border-bottom-width: 0.125rem; + vertical-align: bottom; +} +table.m-table tfoot th, table.m-table tfoot td { + border-top-width: 0.125rem; +} +table.m-table th, table.m-table td { + padding: 0.5rem; +} +table.m-table.m-big th, table.m-table.m-big td { + padding: 0.75rem 1rem; +} +table.m-table th { + text-align: left; +} +table.m-table th.m-thin { + font-weight: normal; +} +table.m-table td.m-default, table.m-table th.m-default, +table.m-table td.m-primary, table.m-table th.m-primary, +table.m-table td.m-success, table.m-table th.m-success, +table.m-table td.m-warning, table.m-table th.m-warning, +table.m-table td.m-danger, table.m-table th.m-danger, +table.m-table td.m-info, table.m-table th.m-info, +table.m-table td.m-dim, table.m-table th.m-dim { + padding-left: 0.4375rem; + padding-right: 0.4375rem; + border-left-width: 0.0625rem; +} +table.m-table.m-big td.m-default, table.m-table.m-big th.m-default, +table.m-table.m-big td.m-primary, table.m-table.m-big th.m-primary, +table.m-table.m-big td.m-success, table.m-table.m-big th.m-success, +table.m-table.m-big td.m-warning, table.m-table.m-big th.m-warning, +table.m-table.m-big td.m-danger, table.m-table.m-big th.m-danger, +table.m-table.m-big td.m-info, table.m-table.m-big th.m-info, +table.m-table.m-big td.m-dim, table.m-table.m-big th.m-dim { + padding-left: 0.9375rem; + padding-right: 0.9375rem; + border-left-width: 0.0625rem; +} +table.m-table tr.m-default td, table.m-table td.m-default, +table.m-table tr.m-default th, table.m-table th.m-default, +table.m-table tr.m-primary td, table.m-table td.m-primary, +table.m-table tr.m-primary th, table.m-table th.m-primary, +table.m-table tr.m-success td, table.m-table td.m-success, +table.m-table tr.m-success th, table.m-table th.m-success, +table.m-table tr.m-warning td, table.m-table td.m-warning, +table.m-table tr.m-warning th, table.m-table th.m-warning, +table.m-table tr.m-danger td, table.m-table td.m-danger, +table.m-table tr.m-danger th, table.m-table th.m-danger, +table.m-table tr.m-info td, table.m-table td.m-info, +table.m-table tr.m-info th, table.m-table th.m-info, +table.m-table tr.m-dim td, table.m-table td.m-dim, +table.m-table tr.m-dim th, table.m-table th.m-dim { + border-color: #2f363f; +} +img.m-image, svg.m-image { + display: block; + margin-left: auto; + margin-right: auto; +} +div.m-image { + text-align: center; +} +img.m-image, svg.m-image, div.m-image img, div.m-image svg { + max-width: 100%; + border-radius: 0.2rem; +} +div.m-image.m-fullwidth img, div.m-image.m-fullwidth svg { + width: 100%; +} +figure.m-figure { + max-width: 100%; + margin-top: 0; + margin-left: auto; + margin-right: auto; + position: relative; + display: table; +} +figure.m-figure:before { + position: absolute; + content: ' '; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: -1; + border-style: solid; + border-width: 0.125rem; + border-radius: 0.2rem; + border-color: #405363; +} +figure.m-figure.m-flat:before { + border-color: transparent; +} +figure.m-figure > * { + margin-left: 1rem; + margin-right: 1rem; + display: table-caption; + caption-side: bottom; +} +figure.m-figure > *:first-child { + display: inline; +} +figure.m-figure > *:last-child { + margin-bottom: 1rem !important; +} +figure.m-figure img, figure.m-figure svg { + position: relative; + margin-left: 0; + margin-right: 0; + margin-bottom: 0; + border-top-left-radius: 0.2rem; + border-top-right-radius: 0.2rem; + max-width: 100%; +} +figure.m-figure.m-flat img, figure.m-figure.m-flat svg { + border-bottom-left-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; +} +figure.m-figure a img, figure.m-figure a svg { + margin-left: -1rem; + margin-right: -1rem; +} +figure.m-figure.m-fullwidth, figure.m-figure.m-fullwidth > * { + display: block; +} +figure.m-figure.m-fullwidth > *:first-child { + display: inline; +} +figure.m-figure.m-fullwidth img, figure.m-figure.m-fullwidth svg { + width: 100%; +} +figure.m-figure.m-fullwidth:after { + content: ' '; + display: block; + margin-top: 1rem; + height: 1px; +} +.m-code-figure, .m-console-figure { + margin-top: 0; + margin-left: 0; + margin-right: 0; + position: relative; + padding: 1rem; +} +.m-code-figure:before, .m-console-figure:before { + position: absolute; + content: ' '; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: -1; + border-style: solid; + border-width: 0.125rem; + border-radius: 0.2rem; +} +.m-code-figure:before { + border-color: #282e36; +} +.m-console-figure:before { + border-color: #000000; +} +.m-code-figure.m-flat:before, .m-console-figure.m-flat:before { + border-color: transparent; +} +.m-code-figure > pre:first-child, .m-console-figure > pre:first-child { + position: relative; + margin: -1rem -1rem 1rem -1rem; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +figure.m-figure figcaption, .m-code-figure figcaption, .m-console-figure figcaption { + margin-top: 0.5rem; + margin-bottom: 0.5rem; + font-weight: 600; + font-size: 1.17rem; +} +.m-imagegrid > div { + background-color: #2f363f; +} +.m-imagegrid > div > figure { + display: block; + float: left; + position: relative; + margin: 0; +} +.m-imagegrid > div > figure > div, +.m-imagegrid > div > figure > figcaption, +.m-imagegrid > div > figure > a > div, +.m-imagegrid > div > figure > a > figcaption { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-color: #2f363f; + border-style: solid; + border-width: 0.25rem; + padding: 0.5rem; +} +.m-imagegrid > div > figure:first-child > div, +.m-imagegrid > div > figure:first-child > figcaption, +.m-imagegrid > div > figure:first-child > a > div, +.m-imagegrid > div > figure:first-child > a > figcaption { + border-left-width: 0; +} +.m-imagegrid > div > figure:last-child > div, +.m-imagegrid > div > figure:last-child > figcaption, +.m-imagegrid > div > figure:last-child > a > div, +.m-imagegrid > div > figure:last-child > a > figcaption { + border-right-width: 0; +} +.m-imagegrid > div > figure > figcaption, +.m-imagegrid > div > figure > a > figcaption { + color: transparent; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 0.75rem; +} +.m-imagegrid > div > figure > div::before, +.m-imagegrid > div > figure > figcaption::before, +.m-imagegrid > div > figure > a > div::before, +.m-imagegrid > div > figure > a > figcaption::before { + content: ''; + display: inline-block; + height: 100%; + vertical-align: bottom; + width: 0; +} +.m-imagegrid > div > figure:hover > figcaption, +.m-imagegrid > div > figure:hover > a > figcaption { + background: linear-gradient(transparent 0%, transparent 75%, rgba(0, 0, 0, 0.85) 100%); + color: #ffffff; +} +.m-imagegrid > div > figure > img, +.m-imagegrid > div > figure > a > img { + width: 100%; + height: 100%; +} +.m-imagegrid > div::after { + display: block; + content: ' '; + clear: both; +} +@media screen and (max-width: 767px) { + .m-imagegrid > div > figure { + float: none; + width: 100% !important; + } + .m-imagegrid > div > figure > div, + .m-imagegrid > div > figure > figcaption, + .m-imagegrid > div > figure > a > div, + .m-imagegrid > div > figure > a > figcaption { + border-left-width: 0; + border-right-width: 0; + } +} +.m-container-inflatable > .m-row > [class*='m-col-'] > .m-note, +.m-container-inflatable > .m-row > [class*='m-col-'] > .m-frame, +.m-container-inflatable > .m-row > [class*='m-col-'] > .m-block, +.m-container-inflatable > .m-row > [class*='m-col-'] > .m-imagegrid, +.m-container-inflatable > .m-row > [class*='m-col-'] > pre, +.m-container-inflatable > .m-row > [class*='m-col-'] > .m-code-figure, +.m-container-inflatable > .m-row > [class*='m-col-'] > .m-console-figure, +.m-container-inflatable > .m-row > [class*='m-col-'] section > .m-note, +.m-container-inflatable > .m-row > [class*='m-col-'] section > .m-frame, +.m-container-inflatable > .m-row > [class*='m-col-'] section > .m-block, +.m-container-inflatable > .m-row > [class*='m-col-'] section > .m-imagegrid, +.m-container-inflatable > .m-row > [class*='m-col-'] section > pre, +.m-container-inflatable > .m-row > [class*='m-col-'] section > .m-code-figure, +.m-container-inflatable > .m-row > [class*='m-col-'] section > .m-console-figure, +.m-container-inflatable [class*='m-center-'] > .m-note, +.m-container-inflatable [class*='m-center-'] > .m-frame, +.m-container-inflatable [class*='m-center-'] > .m-block, +.m-container-inflatable [class*='m-center-'] > .m-imagegrid, +.m-container-inflatable [class*='m-center-'] > pre, +.m-container-inflatable [class*='m-center-'] > .m-code-figure, +.m-container-inflatable [class*='m-center-'] > .m-console-figure, +.m-container-inflatable [class*='m-left-'] > .m-note, +.m-container-inflatable [class*='m-left-'] > .m-frame, +.m-container-inflatable [class*='m-left-'] > .m-block, +.m-container-inflatable [class*='m-left-'] > .m-imagegrid, +.m-container-inflatable [class*='m-left-'] > pre, +.m-container-inflatable [class*='m-left-'] > .m-code-figure, +.m-container-inflatable [class*='m-left-'] > .m-console-figure, +.m-container-inflatable [class*='m-right-'] > .m-note, +.m-container-inflatable [class*='m-right-'] > .m-frame, +.m-container-inflatable [class*='m-right-'] > .m-block, +.m-container-inflatable [class*='m-right-'] > .m-imagegrid, +.m-container-inflatable [class*='m-right-'] > pre, +.m-container-inflatable [class*='m-right-'] > .m-code-figure, +.m-container-inflatable [class*='m-right-'] > .m-console-figure, +.m-container-inflatable .m-container-inflate > .m-note, +.m-container-inflatable .m-container-inflate > .m-frame, +.m-container-inflatable .m-container-inflate > .m-block, +.m-container-inflatable .m-container-inflate > .m-imagegrid, +.m-container-inflatable .m-container-inflate > pre, +.m-container-inflatable .m-container-inflate > .m-code-figure, +.m-container-inflatable .m-container-inflate > .m-console-figure +{ + margin-left: -1rem; + margin-right: -1rem; +} +@media screen and (min-width: 576px) { + .m-container-inflatable .m-center-s > .m-note, + .m-container-inflatable .m-center-s > .m-frame, + .m-container-inflatable .m-center-s > .m-block, + .m-container-inflatable .m-center-s > .m-imagegrid, + .m-container-inflatable .m-center-s > pre, + .m-container-inflatable .m-center-s > .m-code-figure, + .m-container-inflatable .m-center-s > .m-console-figure { + margin-left: -1rem; + margin-right: -1rem; + } + .m-container-inflatable .m-left-s > .m-note, + .m-container-inflatable .m-left-s > .m-frame, + .m-container-inflatable .m-left-s > .m-block, + .m-container-inflatable .m-left-s > .m-imagegrid, + .m-container-inflatable .m-left-s > pre, + .m-container-inflatable .m-left-s > .m-code-figure, + .m-container-inflatable .m-left-s > .m-console-figure { + margin-left: -1rem; + margin-right: 0; + } + .m-container-inflatable .m-right-s > .m-note, + .m-container-inflatable .m-right-s > .m-frame, + .m-container-inflatable .m-right-s > .m-block, + .m-container-inflatable .m-right-s > .m-imagegrid, + .m-container-inflatable .m-right-s > pre, + .m-container-inflatable .m-right-s > .m-code-figure, + .m-container-inflatable .m-right-s > .m-console-figure { + margin-left: 0; + margin-right: -1rem; + } + .m-container-inflatable > .m-row > .m-col-s-10 > .m-imagegrid.m-container-inflate, + .m-container-inflatable > .m-row > .m-col-s-10 section > .m-imagegrid.m-container-inflate { + margin-left: -10%; + margin-right: -10%; + } +} +@media screen and (min-width: 768px) { + .m-container-inflatable .m-center-m > .m-note, + .m-container-inflatable .m-center-m > .m-frame, + .m-container-inflatable .m-center-m > .m-block, + .m-container-inflatable .m-center-m > .m-imagegrid, + .m-container-inflatable .m-center-m > pre, + .m-container-inflatable .m-center-m > .m-code-figure, + .m-container-inflatable .m-center-m > .m-console-figure { + margin-left: -1rem; + margin-right: -1rem; + } + .m-container-inflatable .m-left-m > .m-note, + .m-container-inflatable .m-left-m > .m-frame, + .m-container-inflatable .m-left-m > .m-block, + .m-container-inflatable .m-left-m > .m-imagegrid, + .m-container-inflatable .m-left-m > pre, + .m-container-inflatable .m-left-m > .m-code-figure, + .m-container-inflatable .m-left-m > .m-console-figure { + margin-left: -1rem; + margin-right: 0; + } + .m-container-inflatable .m-right-m > .m-note, + .m-container-inflatable .m-right-m > .m-frame, + .m-container-inflatable .m-right-m > .m-block, + .m-container-inflatable .m-right-m > .m-imagegrid, + .m-container-inflatable .m-right-m > pre, + .m-container-inflatable .m-right-m > .m-code-figure, + .m-container-inflatable .m-right-m > .m-console-figure { + margin-left: 0; + margin-right: -1rem; + } + .m-container-inflatable > .m-row > .m-col-m-10 > .m-imagegrid.m-container-inflate, + .m-container-inflatable > .m-row > .m-col-m-10 section > .m-imagegrid.m-container-inflate { + margin-left: -10%; + margin-right: -10%; + } +} +@media screen and (min-width: 992px) { + .m-container-inflatable .m-center-l > .m-note, + .m-container-inflatable .m-center-l > .m-frame, + .m-container-inflatable .m-center-l > .m-block, + .m-container-inflatable .m-center-l > .m-imagegrid, + .m-container-inflatable .m-center-l > pre, + .m-container-inflatable .m-center-l > .m-code-figure, + .m-container-inflatable .m-center-l > .m-console-figure { + margin-left: -1rem; + margin-right: -1rem; + } + .m-container-inflatable .m-left-l > .m-note, + .m-container-inflatable .m-left-l > .m-frame, + .m-container-inflatable .m-left-l > .m-block, + .m-container-inflatable .m-left-l > .m-imagegrid, + .m-container-inflatable .m-left-l > pre, + .m-container-inflatable .m-left-l > .m-code-figure, + .m-container-inflatable .m-left-l > .m-console-figure { + margin-left: -1rem; + margin-right: 0; + } + .m-container-inflatable .m-right-l > .m-note, + .m-container-inflatable .m-right-l > .m-frame, + .m-container-inflatable .m-right-l > .m-block, + .m-container-inflatable .m-right-l > .m-imagegrid, + .m-container-inflatable .m-right-l > pre, + .m-container-inflatable .m-right-l > .m-code-figure, + .m-container-inflatable .m-right-l > .m-console-figure { + margin-left: 0; + margin-right: -1rem; + } + .m-container-inflatable > .m-row > .m-col-l-10 > .m-imagegrid.m-container-inflate, + .m-container-inflatable > .m-row > .m-col-l-10 section > .m-imagegrid.m-container-inflate { + margin-left: -10%; + margin-right: -10%; + } +} +pre.m-code span.hll { + margin-left: -1.0rem; + margin-right: -1.0rem; + padding-left: 1.0rem; +} +.m-code.m-inverted { + color: rgba(230, 230, 230, 0.33); +} +.m-code.m-inverted > span { + opacity: 0.3333; +} +.m-code.m-inverted > span.hll { + color: #dcdcdc; + opacity: 1; + background-color: transparent; + border-color: transparent; +} +.m-code-color { + display: inline-block; + width: 0.75rem; + height: 0.75rem; + vertical-align: -0.05rem; + margin-left: 0.2rem; + margin-right: 0.1rem; + border-radius: 0.1rem; +} +div.m-math { + overflow-x: auto; + overflow-y: hidden; +} +div.m-math svg { + margin-left: auto; + margin-right: auto; + display: block; +} +div.m-button a svg.m-math { fill: #22272e; } +div.m-button.m-flat a svg.m-math { fill: #dcdcdc; } +div.m-button.m-flat a:hover svg.m-math, div.m-button.m-default a:focus svg.m-math, +div.m-button.m-default a:active svg.m-math { + fill: #a5c9ea; +} +.m-graph { font-size: 16px; } +div.m-plot svg, div.m-graph svg { + max-width: 100%; + margin-left: auto; + margin-right: auto; + display: block; +} +div.m-plot .m-background { fill: #34424d; } +div.m-plot svg .m-label { font-size: 11px; } +div.m-plot svg .m-title { font-size: 13px; } +div.m-plot svg .m-label, div.m-plot svg .m-title { fill: #dcdcdc; } +div.m-plot svg .m-line { + stroke: #dcdcdc; + stroke-width: 0.8; +} +div.m-plot svg .m-error { + stroke: #ffffff; + stroke-width: 1.5; +} +div.m-plot svg .m-label.m-dim { fill: #747474; } +.m-graph g.m-edge path, .m-graph g.m-node.m-flat ellipse, +.m-graph g.m-node.m-flat polygon { + fill: none; +} +.m-graph g.m-node:not(.m-flat) text { + fill: #22272e; +} +figure.m-figure > svg.m-math:first-child, +figure.m-figure > svg.m-graph:first-child { + padding: 1rem; + box-sizing: content-box; +} +figure.m-figure:not(.m-flat) > svg.m-math:first-child, +figure.m-figure:not(.m-flat) > svg.m-graph:first-child { + background-color: #405363; +} +.m-block.m-default { border-left-color: #405363; } +.m-block.m-default h3, .m-block.m-default h4, .m-block.m-default h5, .m-block.m-default h6, +.m-text.m-default, .m-label.m-flat.m-default { + color: #dcdcdc; +} +.m-block.m-default h3 a, .m-block.m-default h4 a, .m-block.m-default h5 a, .m-block.m-default h6 a { + color: #5b9dd9; +} +.m-block.m-primary { border-left-color: #a5c9ea; } +.m-block.m-primary h3, .m-block.m-primary h4, .m-block.m-primary h5, .m-block.m-primary h6, +.m-block.m-primary h3 a, .m-block.m-primary h4 a, .m-block.m-primary h5 a, .m-block.m-primary h6 a, +.m-text.m-primary, .m-label.m-flat.m-primary { + color: #a5c9ea; +} +.m-block.m-success { border-left-color: #3bd267; } +.m-block.m-success h3, .m-block.m-success h4, .m-block.m-success h5, .m-block.m-success h6, +.m-block.m-success h3 a, .m-block.m-success h4 a, .m-block.m-success h5 a, .m-block.m-success h6 a, +.m-text.m-success, .m-label.m-flat.m-success { + color: #3bd267; +} +.m-block.m-warning { border-left-color: #c7cf2f; } +.m-block.m-warning h3, .m-block.m-warning h4, .m-block.m-warning h5, .m-block.m-warning h6, +.m-block.m-warning h3 a, .m-block.m-warning h4 a, .m-block.m-warning h5 a, .m-block.m-warning h6 a, +.m-text.m-warning, .m-label.m-flat.m-warning { + color: #c7cf2f; +} +.m-block.m-danger { border-left-color: #cd3431; } +.m-block.m-danger h3, .m-block.m-danger h4, .m-block.m-danger h5, .m-block.m-danger h6, +.m-block.m-danger h3 a, .m-block.m-danger h4 a, .m-block.m-danger h5 a, .m-block.m-danger h6 a, +.m-text.m-danger, .m-label.m-flat.m-danger { + color: #cd3431; +} +.m-block.m-info { border-left-color: #2f83cc; } +.m-block.m-info h3, .m-block.m-info h4, .m-block.m-info h5, .m-block.m-info h6, +.m-block.m-info h3 a, .m-block.m-info h4 a, .m-block.m-info h5 a, .m-block.m-info h6 a, +.m-text.m-info, .m-label.m-flat.m-info { + color: #2f83cc; +} +.m-block.m-dim { border-left-color: #747474; } +.m-block.m-dim, .m-text.m-dim, .m-label.m-flat.m-dim { + color: #747474; +} +.m-block.m-dim a, .m-text.m-dim a { color: #acacac; } +.m-block.m-dim a:hover, .m-block.m-dim a:focus, .m-block.m-dim a:active, +.m-text.m-dim a:hover, .m-text.m-dim a:focus, .m-text.m-dim a:active { + color: #747474; +} +.m-block.m-flat { border-color: transparent; } +.m-block.m-flat h3, .m-block.m-flat h4, .m-block.m-flat h5. .m-block.m-flat h6 { + color: #dcdcdc; +} +.m-block.m-default h3 a:hover, .m-block.m-default h3 a:focus, .m-block.m-default h3 a:active, +.m-block.m-default h4 a:hover, .m-block.m-default h4 a:focus, .m-block.m-default h4 a:active, +.m-block.m-default h5 a:hover, .m-block.m-default h5 a:focus, .m-block.m-default h5 a:active, +.m-block.m-default h6 a:hover, .m-block.m-default h6 a:focus, .m-block.m-default h6 a:active { + color: #a5c9ea; +} +.m-block.m-primary h3 a:hover, .m-block.m-primary h3 a:focus, .m-block.m-primary h3 a:active, +.m-block.m-primary h4 a:hover, .m-block.m-primary h4 a:focus, .m-block.m-primary h4 a:active, +.m-block.m-primary h5 a:hover, .m-block.m-primary h5 a:focus, .m-block.m-primary h5 a:active, +.m-block.m-primary h6 a:hover, .m-block.m-primary h6 a:focus, .m-block.m-primary h6 a:active { + color: #dcdcdc; +} +.m-block.m-success h3 a:hover, .m-block.m-success h3 a:focus, .m-block.m-success h3 a:active, +.m-block.m-success h4 a:hover, .m-block.m-success h4 a:focus, .m-block.m-success h4 a:active, +.m-block.m-success h5 a:hover, .m-block.m-success h5 a:focus, .m-block.m-success h5 a:active, +.m-block.m-success h6 a:hover, .m-block.m-success h6 a:focus, .m-block.m-success h6 a:active { + color: #acecbe; +} +.m-block.m-warning h3 a:hover, .m-block.m-warning h3 a:focus, .m-block.m-warning h3 a:active, +.m-block.m-warning h4 a:hover, .m-block.m-warning h4 a:focus, .m-block.m-warning h4 a:active, +.m-block.m-warning h5 a:hover, .m-block.m-warning h5 a:focus, .m-block.m-warning h5 a:active, +.m-block.m-warning h6 a:hover, .m-block.m-warning h6 a:focus, .m-block.m-warning h6 a:active { + color: #e9ecae; +} +.m-block.m-danger h3 a:hover, .m-block.m-danger h3 a:focus, .m-block.m-danger h3 a:active, +.m-block.m-danger h4 a:hover, .m-block.m-danger h4 a:focus, .m-block.m-danger h4 a:active, +.m-block.m-danger h5 a:hover, .m-block.m-danger h5 a:focus, .m-block.m-danger h5 a:active, +.m-block.m-danger h6 a:hover, .m-block.m-danger h6 a:focus, .m-block.m-danger h6 a:active { + color: #ff9391; +} +.m-block.m-info h3 a:hover, .m-block.m-info h3 a:focus, .m-block.m-info h3 a:active, +.m-block.m-info h4 a:hover, .m-block.m-info h4 a:focus, .m-block.m-info h4 a:active, +.m-block.m-info h5 a:hover, .m-block.m-info h5 a:focus, .m-block.m-info h5 a:active, +.m-block.m-info h6 a:hover, .m-block.m-info h6 a:focus, .m-block.m-info h6 a:active { + color: #5297d7; +} +div.m-button a, .m-label { color: #22272e; } +div.m-button.m-flat a { color: #dcdcdc; } +div.m-button.m-flat a:hover, div.m-button.m-default a:focus, div.m-button.m-default a:active { + color: #a5c9ea; +} +div.m-button.m-default a, .m-label:not(.m-flat).m-default { background-color: #dcdcdc; } +div.m-button.m-primary a, .m-label:not(.m-flat).m-primary { background-color: #a5c9ea; } +div.m-button.m-success a, .m-label:not(.m-flat).m-success { background-color: #3bd267; } +div.m-button.m-warning a, .m-label:not(.m-flat).m-warning { background-color: #c7cf2f; } +div.m-button.m-danger a, .m-label:not(.m-flat).m-danger { background-color: #cd3431; } +div.m-button.m-info a, .m-label:not(.m-flat).m-info { background-color: #2f83cc; } +div.m-button.m-dim a, .m-label:not(.m-flat).m-dim { background-color: #747474; } +div.m-button.m-default a:hover, div.m-button.m-default a:focus, div.m-button.m-default a:active { + background-color: #a5c9ea; +} +div.m-button.m-primary a:hover, div.m-button.m-primary a:focus, div.m-button.m-primary a:active { + background-color: #dcdcdc; +} +div.m-button.m-success a:hover, div.m-button.m-success a:focus, div.m-button.m-success a:active { + background-color: #acecbe; +} +div.m-button.m-warning a:hover, div.m-button.m-warning a:focus, div.m-button.m-warning a:active { + background-color: #e9ecae; +} +div.m-button.m-danger a:hover, div.m-button.m-danger a:focus, div.m-button.m-danger a:active { + background-color: #ff9391; +} +div.m-button.m-info a:hover, div.m-button.m-info a:focus, div.m-button.m-info a:active { + background-color: #5297d7; +} +div.m-button.m-dim a:hover, div.m-button.m-dim a:focus, div.m-button.m-dim a:active { + background-color: #acacac; +} +.m-note.m-default { background-color: #34424d; } +.m-note.m-default, +table.m-table tr.m-default td, table.m-table td.m-default, +table.m-table tr.m-default th, table.m-table th.m-default { + color: #dcdcdc; +} +.m-note.m-default a:hover, +table.m-table tr.m-default td a:hover, table.m-table td.m-default a:hover, +table.m-table tr.m-default th a:hover, table.m-table th.m-default a:hover, +.m-note.m-default a:focus, +table.m-table tr.m-default td a:focus, table.m-table td.m-default a:focus, +table.m-table tr.m-default th a:focus, table.m-table th.m-default a:focus, +.m-note.m-default a:active, +table.m-table tr.m-default td a:active, table.m-table td.m-default a:active, +table.m-table tr.m-default th a:active, table.m-table th.m-default a:active { + color: #a5c9ea; +} +.m-note.m-primary a, +table.m-table tr.m-primary td a, table.m-table td.m-primary a, +table.m-table tr.m-primary th a, table.m-table th.m-primary a { + color: #5b9dd9; +} +.m-note.m-primary, +table.m-table tr.m-primary td, table.m-table td.m-primary, +table.m-table tr.m-primary th, table.m-table th.m-primary { + background-color: #a5c2db; + color: #2f363f; +} +.m-note.m-primary a, +table.m-table tr.m-primary td a, table.m-table td.m-primary a, +table.m-table tr.m-primary th a, table.m-table th.m-primary a { + color: #2a75b6; +} +.m-note.m-primary a:hover, +table.m-table tr.m-primary td a:hover, table.m-table td.m-primary a:hover, +table.m-table tr.m-primary th a:hover, table.m-table th.m-primary a:hover, +.m-note.m-primary a:focus, +table.m-table tr.m-primary td a:focus, table.m-table td.m-primary a:focus, +table.m-table tr.m-primary th a:focus, table.m-table th.m-primary a:focus, +.m-note.m-primary a:active, +table.m-table tr.m-primary td a:active, table.m-table td.m-primary a:active, +table.m-table tr.m-primary th a:active, table.m-table th.m-primary a:active { + color: #2f363f; +} +.m-note.m-success, +table.m-table tr.m-success td, table.m-table td.m-success, +table.m-table tr.m-success th, table.m-table th.m-success { + background-color: #2a703f; + color: #acecbe; +} +.m-note.m-success a, +table.m-table tr.m-success td a, table.m-table td.m-success a, +table.m-table tr.m-success th a, table.m-table th.m-success a { + color: #3bd267; +} +.m-note.m-success a:hover, +table.m-table tr.m-success td a:hover, table.m-table td.m-success a:hover, +table.m-table tr.m-success th a:hover, table.m-table th.m-success a:hover, +.m-note.m-success a:focus, +table.m-table tr.m-success td a:focus, table.m-table td.m-success a:focus, +table.m-table tr.m-success th a:focus, table.m-table th.m-success a:focus, +.m-note.m-success a:active, +table.m-table tr.m-success td a:active, table.m-table td.m-success a:active, +table.m-table tr.m-success th a:active, table.m-table th.m-success a:active { + color: #acecbe; +} +.m-note.m-warning, table.m-table tr.m-warning td, table.m-table td.m-warning, + table.m-table tr.m-warning th, table.m-table th.m-warning { + background-color: #6d702a; + color: #e9ecae; +} +.m-note.m-warning a, table.m-table tr.m-warning td a, table.m-table td.m-warning a, + table.m-table tr.m-warning th a, table.m-table th.m-warning a { + color: #b8bf2b; +} +.m-note.m-warning a:hover, +table.m-table tr.m-warning td a:hover, table.m-table td.m-warning a:hover, +table.m-table tr.m-warning th a:hover, table.m-table th.m-warning a:hover, +.m-note.m-warning a:focus, +table.m-table tr.m-warning td a:focus, table.m-table td.m-warning a:focus, +table.m-table tr.m-warning th a:focus, table.m-table th.m-warning a:focus, +.m-note.m-warning a:active, +table.m-table tr.m-warning td a:active, table.m-table td.m-warning a:active, +table.m-table tr.m-warning th a:active, table.m-table th.m-warning a:active { + color: #e9ecae; +} +.m-note.m-danger, +table.m-table tr.m-danger td, table.m-table td.m-danger, +table.m-table tr.m-danger th, table.m-table th.m-danger { + background-color: #702b2a; + color: #ff9391; +} +.m-note.m-danger a, +table.m-table tr.m-danger td a, table.m-table td.m-danger a, +table.m-table tr.m-danger th a, table.m-table th.m-danger a { + color: #d85c59; +} +.m-note.m-danger a:hover, +table.m-table tr.m-danger td a:hover, table.m-table td.m-danger a:hover, +table.m-table tr.m-danger th a:hover, table.m-table th.m-danger a:hover, +.m-note.m-danger a:focus, +table.m-table tr.m-danger td a:focus, table.m-table td.m-danger a:focus, +table.m-table tr.m-danger th a:focus, table.m-table th.m-danger a:focus, +.m-note.m-danger a:active, +table.m-table tr.m-danger td a:active, table.m-table td.m-danger a:active, +table.m-table tr.m-danger th a:active, table.m-table th.m-danger a:active { + color: #ff9391; +} +.m-note.m-info, +table.m-table tr.m-info td, table.m-table td.m-info, +table.m-table tr.m-info th, table.m-table th.m-info { + background-color: #2a4f70; + color: #a5caeb; +} +.m-note.m-info a, +table.m-table tr.m-info td a, table.m-table td.m-info a, +table.m-table tr.m-info th a, table.m-table th.m-info a { + color: #5297d7; +} +.m-note.m-info a:hover, +table.m-table tr.m-info td a:hover, table.m-table td.m-info a:hover, +table.m-table tr.m-info th a:hover, table.m-table th.m-info a:hover, +.m-note.m-info a:focus, +table.m-table tr.m-info td a:focus, table.m-table td.m-info a:focus, +table.m-table tr.m-info th a:focus, table.m-table th.m-info a:focus, +.m-note.m-info a:active, +table.m-table tr.m-info td a:active, table.m-table td.m-info a:active, +table.m-table tr.m-info th a:active, table.m-table th.m-info a:active { + color: #a5caeb; +} +.m-note.m-dim, +table.m-table tr.m-dim td, table.m-table td.m-dim, +table.m-table tr.m-dim th, table.m-table th.m-dim { + background-color: #2d3236; + color: #747474; +} +.m-note.m-dim a, +table.m-table tr.m-dim td a, table.m-table td.m-dim a, +table.m-table tr.m-dim th a, table.m-table th.m-dim a { + color: #acacac; +} +.m-note.m-dim a:hover, +table.m-table tr.m-dim td a:hover, table.m-table td.m-dim a:hover, +table.m-table tr.m-dim th a:hover, table.m-table th.m-dim a:hover, +.m-note.m-dim a:focus, +table.m-table tr.m-dim td a:focus, table.m-table td.m-dim a:focus, +table.m-table tr.m-dim th a:focus, table.m-table th.m-dim a:focus, +.m-note.m-dim a:active, +table.m-table tr.m-dim td a:active, table.m-table td.m-dim a:active, +table.m-table tr.m-dim th a:active, table.m-table th.m-dim a:active { + color: #747474; +} +figure.m-figure.m-default:before { border-color: #34424d; } +figure.m-figure.m-default figcaption { color: #dcdcdc; } +figure.m-figure.m-primary:before { border-color: #a5c2db; } +figure.m-figure.m-primary figcaption { color: #a5c9ea; } +figure.m-figure.m-success:before { border-color: #2a703f; } +figure.m-figure.m-success figcaption { color: #3bd267; } +figure.m-figure.m-warning:before { border-color: #6d702a; } +figure.m-figure.m-warning figcaption { color: #c7cf2f; } +figure.m-figure.m-danger:before { border-color: #702b2a; } +figure.m-figure.m-danger figcaption { color: #cd3431; } +figure.m-figure.m-info:before { border-color: #2a4f70; } +figure.m-figure.m-info figcaption { color: #2f83cc; } +figure.m-figure.m-dim:before { border-color: #2d3236; } +figure.m-figure.m-dim { color: #747474; } +figure.m-figure.m-dim a { color: #acacac; } +figure.m-figure.m-dim a:hover, figure.m-figure.m-dim a:focus, figure.m-figure.m-dim a:active { + color: #747474; +} +.m-math { fill: #dcdcdc; } +.m-math.m-default, .m-math g.m-default, .m-math rect.m-default, +div.m-plot svg .m-bar.m-default, +.m-graph g.m-edge polygon, +.m-graph g.m-node:not(.m-flat) ellipse, +.m-graph g.m-node:not(.m-flat) polygon, +.m-graph g.m-edge text, +.m-graph g.m-node.m-flat text, +.m-graph.m-default g.m-edge polygon, +.m-graph.m-default g.m-node:not(.m-flat) ellipse, +.m-graph.m-default g.m-node:not(.m-flat) polygon, +.m-graph.m-default g.m-edge text, +.m-graph.m-default g.m-node.m-flat text { + fill: #dcdcdc; +} +.m-graph g.m-edge polygon, +.m-graph g.m-edge path, +.m-graph g.m-node ellipse, +.m-graph g.m-node polygon, +.m-graph g.m-node polyline, +.m-graph.m-default g.m-edge polygon, +.m-graph.m-default g.m-edge path, +.m-graph.m-default g.m-node ellipse, +.m-graph.m-default g.m-node polygon, +.m-graph.m-default g.m-node polyline { + stroke: #dcdcdc; +} +.m-math.m-primary, .m-math g.m-primary, .m-math rect.m-primary, +div.m-plot svg .m-bar.m-primary, +.m-graph.m-primary g.m-edge polygon, +.m-graph.m-primary g.m-node:not(.m-flat) ellipse, +.m-graph.m-primary g.m-node:not(.m-flat) polygon, +.m-graph.m-primary g.m-edge text, +.m-graph.m-primary g.m-node.m-flat text { + fill: #a5c9ea; +} +.m-graph.m-primary g.m-edge polygon, +.m-graph.m-primary g.m-edge path, +.m-graph.m-primary g.m-node ellipse, +.m-graph.m-primary g.m-node polygon, +.m-graph.m-primary g.m-node polyline { + stroke: #a5c9ea; +} +.m-math.m-success, .m-math g.m-success, .m-math rect.m-success, +div.m-plot svg .m-bar.m-success, +.m-graph.m-success g.m-edge polygon, +.m-graph.m-success g.m-node:not(.m-flat) ellipse, +.m-graph.m-success g.m-node:not(.m-flat) polygon, +.m-graph.m-success g.m-edge text, +.m-graph.m-success g.m-node.m-flat text { + fill: #3bd267; +} +.m-graph.m-success g.m-edge polygon, +.m-graph.m-success g.m-edge path, +.m-graph.m-success g.m-node ellipse, +.m-graph.m-success g.m-node polygon, +.m-graph.m-success g.m-node polyline { + stroke: #3bd267; +} +.m-math.m-warning, .m-math g.m-warning, .m-math rect.m-warning, +div.m-plot svg .m-bar.m-warning, +.m-graph.m-warning g.m-edge polygon, +.m-graph.m-warning g.m-node:not(.m-flat) ellipse, +.m-graph.m-warning g.m-node:not(.m-flat) polygon, +.m-graph.m-warning g.m-edge text, +.m-graph.m-warning g.m-node.m-flat text { + fill: #c7cf2f; +} +.m-graph.m-warning g.m-edge polygon, +.m-graph.m-warning g.m-edge path, +.m-graph.m-warning g.m-node ellipse, +.m-graph.m-warning g.m-node polygon, +.m-graph.m-warning g.m-node polyline { + stroke: #c7cf2f; +} +.m-math.m-danger, .m-math g.m-danger, .m-math rect.m-danger, +div.m-plot svg .m-bar.m-danger, +.m-graph.m-danger g.m-edge polygon, +.m-graph.m-danger g.m-node:not(.m-flat) ellipse, +.m-graph.m-danger g.m-node:not(.m-flat) polygon, +.m-graph.m-danger g.m-edge text, +.m-graph.m-danger g.m-node.m-flat text { + fill: #cd3431; +} +.m-graph.m-danger g.m-edge polygon, +.m-graph.m-danger g.m-edge path, +.m-graph.m-danger g.m-node ellipse, +.m-graph.m-danger g.m-node polygon, +.m-graph.m-danger g.m-node polyline { + stroke: #cd3431; +} +.m-math.m-info, .m-math g.m-info, .m-math rect.m-info, +div.m-plot svg .m-bar.m-info, +.m-graph.m-info g.m-edge polygon, +.m-graph.m-info g.m-node:not(.m-flat) ellipse, +.m-graph.m-info g.m-node:not(.m-flat) polygon, +.m-graph.m-info g.m-edge text, +.m-graph.m-info g.m-node.m-flat text { + fill: #2f83cc; +} +.m-graph.m-info g.m-edge polygon, +.m-graph.m-info g.m-edge path, +.m-graph.m-info g.m-node ellipse, +.m-graph.m-info g.m-node polygon, +.m-graph.m-info g.m-node polyline { + stroke: #2f83cc; +} +.m-math.m-dim, .m-math g.m-dim, .m-math rect.m-dim, +div.m-plot svg .m-bar.m-dim, +.m-graph.m-dim g.m-edge polygon, +.m-graph.m-dim g.m-node:not(.m-flat) ellipse, +.m-graph.m-dim g.m-node:not(.m-flat) polygon, +.m-graph.m-dim g.m-edge text, +.m-graph.m-dim g.m-node.m-flat text { + fill: #747474; +} +.m-graph.m-dim g.m-edge polygon, +.m-graph.m-dim g.m-edge path, +.m-graph.m-dim g.m-node ellipse, +.m-graph.m-dim g.m-node polygon, +.m-graph.m-dim g.m-node polyline { + stroke: #747474; +} +.m-graph g.m-edge.m-default polygon, +.m-graph g.m-node.m-default:not(.m-flat) ellipse, +.m-graph g.m-node.m-default:not(.m-flat) polygon, +.m-graph g.m-edge.m-default text, +.m-graph g.m-node.m-default.m-flat text { + fill: #dcdcdc; +} +.m-graph g.m-edge.m-default polygon, +.m-graph g.m-edge.m-default path, +.m-graph g.m-node.m-default ellipse, +.m-graph g.m-node.m-default polygon, +.m-graph g.m-node.m-default polyline { + stroke: #dcdcdc; +} +.m-graph g.m-edge.m-primary polygon, +.m-graph g.m-node.m-primary:not(.m-flat) ellipse, +.m-graph g.m-node.m-primary:not(.m-flat) polygon, +.m-graph g.m-edge.m-primary text, +.m-graph g.m-node.m-primary.m-flat text { + fill: #a5c9ea; +} +.m-graph g.m-edge.m-primary polygon, +.m-graph g.m-edge.m-primary path, +.m-graph g.m-node.m-primary ellipse, +.m-graph g.m-node.m-primary polygon, +.m-graph g.m-node.m-primary polyline { + stroke: #a5c9ea; +} +.m-graph g.m-edge.m-success polygon, +.m-graph g.m-node.m-success:not(.m-flat) ellipse, +.m-graph g.m-node.m-success:not(.m-flat) polygon, +.m-graph g.m-edge.m-success text, +.m-graph g.m-node.m-success.m-flat text { + fill: #3bd267; +} +.m-graph g.m-edge.m-success polygon, +.m-graph g.m-edge.m-success path, +.m-graph g.m-node.m-success ellipse, +.m-graph g.m-node.m-success polygon, +.m-graph g.m-node.m-success polyline { + stroke: #3bd267; +} +.m-graph g.m-edge.m-warning polygon, +.m-graph g.m-node.m-warning:not(.m-flat) ellipse, +.m-graph g.m-node.m-warning:not(.m-flat) polygon, +.m-graph g.m-edge.m-warning text, +.m-graph g.m-node.m-warning.m-flat text { + fill: #c7cf2f; +} +.m-graph g.m-edge.m-warning polygon, +.m-graph g.m-edge.m-warning path, +.m-graph g.m-node.m-warning ellipse, +.m-graph g.m-node.m-warning polygon, +.m-graph g.m-node.m-warning polyline { + stroke: #c7cf2f; +} +.m-graph g.m-edge.m-danger polygon, +.m-graph g.m-node.m-danger:not(.m-flat) ellipse, +.m-graph g.m-node.m-danger:not(.m-flat) polygon, +.m-graph g.m-edge.m-danger text, +.m-graph g.m-node.m-danger.m-flat text { + fill: #cd3431; +} +.m-graph g.m-edge.m-danger polygon, +.m-graph g.m-edge.m-danger path, +.m-graph g.m-node.m-danger ellipse, +.m-graph g.m-node.m-danger polygon, +.m-graph g.m-node.m-danger polyline { + stroke: #cd3431; +} +.m-graph g.m-edge.m-info polygon, +.m-graph g.m-node.m-info:not(.m-flat) ellipse, +.m-graph g.m-node.m-info:not(.m-flat) polygon, +.m-graph g.m-edge.m-info text, +.m-graph g.m-node.m-info.m-flat text { + fill: #2f83cc; +} +.m-graph g.m-edge.m-info polygon, +.m-graph g.m-edge.m-info path, +.m-graph g.m-node.m-info ellipse, +.m-graph g.m-node.m-info polygon, +.m-graph g.m-node.m-info polyline { + stroke: #2f83cc; +} +.m-graph g.m-edge.m-dim polygon, +.m-graph g.m-node.m-dim:not(.m-flat) ellipse, +.m-graph g.m-node.m-dim:not(.m-flat) polygon, +.m-graph g.m-edge.m-dim text, +.m-graph g.m-node.m-dim.m-flat text { + fill: #747474; +} +.m-graph g.m-edge.m-dim polygon, +.m-graph g.m-edge.m-dim path, +.m-graph g.m-node.m-dim ellipse, +.m-graph g.m-node.m-dim polygon, +.m-graph g.m-node.m-dim polyline { + stroke: #747474; +} +p, ul, ol, dl, blockquote, pre, .m-code-figure, .m-console-figure, hr, .m-note, +.m-frame, .m-block, div.m-button, div.m-scroll, table.m-table, div.m-image, +img.m-image, svg.m-image, figure.m-figure, .m-imagegrid, div.m-math, +div.m-graph, div.m-plot { + margin-bottom: 1rem; +} +p:last-child, p.m-nopadb, ul:last-child, ul.m-nopadb, +ol:last-child, ol.m-nopadb, dl:last-child, dl.m-nopadb, +blockquote:last-child, blockquote.m-nopadb, pre:last-child, pre.m-nopadb, +.m-code-figure:last-child, .m-code-figure.m-nopadb, +.m-console-figure:last-child, .m-console-figure.m-nopadb, +hr:last-child, hr.m-nopadb, .m-note:last-child, .m-note.m-nopadb, +.m-frame:last-child, .m-frame.m-nopadb, .m-block:last-child, .m-block.m-nopadb, +div.m-button:last-child, div.m-button.m-nopadb, +div.m-scroll:last-child, div.m-scroll.m-nopadb, +table.m-table:last-child, table.m-table.m-nopadb, +img.m-image:last-child, img.m-image.m-nopadb, +svg.m-image:last-child, svg.m-image.m-nopadb, +div.m-image:last-child, div.m-image.m-nopadb, +figure.m-figure:last-child, figure.m-figure.m-nopadb, +.m-imagegrid:last-child, .m-imagegrid.m-nopadb, +div.m-math:last-child, div.m-math.m-nopadb, +div.m-graph:last-child, div.m-graph.m-nopadb, +div.m-plot:last-child, div.m-plot.m-nopadb { + margin-bottom: 0; +} +li > p:last-child, li > blockquote:last-child, li > pre:last-child, +li > .m-code-figure:last-child, li > .m-console-figure:last-child, +li > .m-note:last-child, li > .m-frame:last-child, li > .m-block:last-child, +li > div.m-button:last-child, li > div.m-scroll:last-child, li > table.m-table:last-child, +li > img.m-image:last-child, li > svg.m-image:last-child, li > div.m-image:last-child, +li > figure.m-figure:last-child, li > div.m-math:last-child, +li > div.m-graph:last-child, li > div.m-plot:last-child { + margin-bottom: 1rem; +} +li:last-child > p:last-child, li:last-child > p.m-nopadb, +li:last-child > blockquote:last-child, li:last-child > blockquote.m-nopadb, +li:last-child > pre:last-child, li:last-child > pre.m-nopadb, +li:last-child > .m-code-figure:last-child, li:last-child > .m-code-figure.m-nopadb, +li:last-child > .m-console-figure:last-child, li:last-child > .m-console-figure.m-nopadb, +li:last-child > .m-note:last-child, li:last-child > .m-note.m-nopadb, +li:last-child > .m-frame:last-child, li:last-child > .m-frame.m-nopadb, +li:last-child > .m-block:last-child, li:last-child > .m-block.m-nopadb, +li:last-child > div.m-button:last-child, li:last-child > div.m-button.m-nopadb, +li:last-child > div.m-scroll:last-child, li:last-child > div.m-scroll.m-nopadb, +li:last-child > table.m-table:last-child, li:last-child > table.m-table.m-nopadb, +li:last-child > img.m-image:last-child, li:last-child > img.m-image.m-nopadb, +li:last-child > svg.m-image:last-child, li:last-child > svg.m-image.m-nopadb, +li:last-child > div.m-image:last-child, li:last-child > div.m-image.m-nopadb, +li:last-child > figure.m-figure:last-child, li:last-child > figure.m-figure.m-nopadb, +li:last-child > div.m-math:last-child, li:last-child > div.m-math.m-nopadb, +li:last-child > div.m-graph:last-child, li:last-child > div.m-graph.m-nopadb, +li:last-child > div.m-plot:last-child, li:last-child > div.m-plot.m-nopadb { + margin-bottom: 0; +} + +body > header > nav { + width: 100%; + background-color: #24525B; + min-height: 3rem; +} +body > header > nav.m-navbar-landing, +body > header > nav.m-navbar-cover { + background-color: transparent; + position: relative; +} +body > header > nav.m-navbar-landing { + opacity: 0.8; +} +body > header > nav.m-navbar-cover { + background-color: rgba(34, 39, 46, 0.25); + opacity: 1; +} +body > header > nav.m-navbar-landing:hover, +body > header > nav.m-navbar-cover:hover { + background-color: rgba(34, 39, 46, 0.75); + opacity: 1; +} +body> header > nav.m-navbar-landing:target, +body> header > nav.m-navbar-cover:target { + background-color: #24525B; + opacity: 1; +} +body > header > nav.m-navbar-landing #m-navbar-brand.m-navbar-brand-hidden { + visibility: hidden; +} +body > header > nav.m-navbar-landing:target #m-navbar-brand.m-navbar-brand-hidden { + visibility: visible; +} +body > header > nav { + margin-left: auto; + margin-right: auto; + color: #ffffff; +} +body > header > nav a { + text-decoration: none; + text-transform: none; + display: inline-block; + vertical-align: middle; + line-height: 2.75rem; + color: #ffffff; +} +body > header > nav #m-navbar-brand, body > header > nav a#m-navbar-show, body > header > nav a#m-navbar-hide { + font-weight: 600; + font-size: 1.125rem; + padding-left: 1rem; + padding-right: 1rem; +} +body > header > nav a#m-navbar-brand, body > header > nav #m-navbar-brand a { + text-transform: uppercase; +} +body > header > nav #m-navbar-brand a { + padding-left: 0; + padding-right: 0; +} +body > header > nav #m-navbar-brand .m-thin { + font-weight: normal; +} +body > header > nav #m-navbar-brand .m-breadcrumb { + color: #747474; +} +body > header > nav a#m-navbar-show:before, body > header > nav a#m-navbar-hide:before { + content:'\2630'; +} +body > header > nav #m-navbar-collapse { + padding-bottom: 1rem; +} +body > header > nav #m-navbar-collapse li { + border-style: solid; + border-color: transparent; + border-width: 0 0 0 0.25rem; + margin-left: -1rem; +} +body > header > nav #m-navbar-collapse li a { + border-style: solid; + border-color: transparent; + line-height: 1.5rem; + margin-left: -0.25rem; + padding-left: 0.75rem; + border-width: 0 0 0 0.25rem; + width: 100%; +} +body > header > nav #m-navbar-collapse li a#m-navbar-current { + color: #5b9dd9; + border-color: #5b9dd9; +} +body > header > nav ol { + list-style-type: none; + margin: 0; +} +body > header > nav ol ol { + padding-left: 1.5rem; +} +body > header > nav .m-row > [class*='m-col-'] { + padding-top: 0; + padding-bottom: 0; +} +body > header > nav a:hover, body > header > nav a:focus, body > header > nav a:active { + color: #a5c9ea; +} +body > header > nav #m-navbar-collapse li:hover { + border-color: #a5c9ea; +} +body > header > nav #m-navbar-collapse li a:hover, +body > header > nav #m-navbar-collapse li a:focus, +body > header > nav #m-navbar-collapse li a:active { + border-color: #a5c9ea; + background-color: #292f37; +} +body > header > nav.m-navbar-landing #m-navbar-collapse li a:hover, +body > header > nav.m-navbar-cover #m-navbar-collapse li a:hover, +body > header > nav.m-navbar-landing #m-navbar-collapse li a:focus, +body > header > nav.m-navbar-cover #m-navbar-collapse li a:focus, +body > header > nav.m-navbar-landing #m-navbar-collapse li a:active, +body > header > nav.m-navbar-cover #m-navbar-collapse li a:active { + background-color: rgba(41, 47, 55, 0.5); +} +body > header > nav #m-navbar-hide { + display: none; +} +body > header > nav:target #m-navbar-collapse { + display: block; +} +body > header > nav:target #m-navbar-show { + display: none; +} +body > header > nav:target #m-navbar-hide { + display: inline-block; +} +@media screen and (min-width: 768px) { + body > header > nav #m-navbar-show, body > header > nav #m-navbar-hide, + body > header > nav:target #m-navbar-show, body > header > nav:target #m-navbar-hide { + display: none; + } + body > header > nav #m-navbar-collapse li a { + line-height: 2.75rem; + } + body > header > nav a, body > header > nav #m-navbar-collapse li a { + margin-left: 0; + padding-left: 1rem; + padding-right: 1rem; + white-space: nowrap; + } + body > header > nav #m-navbar-collapse { + padding-bottom: 0; + } + body > header > nav #m-navbar-collapse li ol { + background-color: #24525B; + } + body > header > nav #m-navbar-collapse ol ol li { + margin-left: 0; + padding-left: 0; + border-left-width: 0; + } + body > header > nav #m-navbar-collapse ol ol li a { + padding-left: 0.75rem; + } + body > header > nav #m-navbar-collapse > .m-row > ol > li { + margin-left: 0; + border-left-width: 0; + } + body > header > nav #m-navbar-collapse > .m-row > ol > li > a { + border-width: 0 0 0.25rem 0; + } + body > header > nav #m-navbar-collapse ol { + padding-left: 0; + padding-right: 0; + } + body > header > nav #m-navbar-collapse > .m-row > ol, body > header > nav #m-navbar-collapse > .m-row > ol > li { + float: left; + } + body > header > nav #m-navbar-collapse ol ol { + z-index: 99999; + position: absolute; + visibility: hidden; + } + body > header > nav #m-navbar-collapse li:hover ol { + visibility: visible; + } +} +body > footer { + width: 100%; +} +body > footer > nav { + padding-top: 1rem; + padding-bottom: 1rem; + font-size: 0.85rem; + text-align: center; + color: #c5c5c5; + background-color: #24525B; +} +body > footer > nav h3, body > footer > nav h3 a { + text-transform: uppercase; + font-weight: normal; +} +body > footer > nav ul { + list-style-type: none; + padding: 0; + margin: 0; +} +body > footer > nav a { + text-decoration: none; + text-transform: none; + color: #ffffff; +} +body > footer > nav a:hover, body > footer > nav a:focus, body > footer > nav a:active { + color: #a5c9ea; +} +body > main { + padding-top: 1rem; + padding-bottom: 1rem; +} +article h1 { + font-size: 1.75rem; +} +article h1 .m-breadcrumb { + color: #747474; + font-weight: normal; +} +article h1 .m-breadcrumb a { + color: #a5c9ea; +} +article h1 .m-breadcrumb a:hover, article h1 a:focus, article h1 a:active { + color: #dcdcdc; +} +article > header h1 { + font-size: 2rem; + margin-bottom: 0.5rem; +} +article h1 a, article > header h1, article > header h1 a, +article section > h2, article section > h2 a, +article section > h3, article section > h3 a, +article section > h4, article section > h4 a, +article section > h5, article section > h5 a, +article section > h6, article section > h6 a { + color: #a5c9ea; +} +article h1 a:hover, article > header h1 a:hover, article > header h1 a:focus, article > header h1 a:active, +article section > h2 a:hover, article section > h2 a:focus, article section > h2 a:active, +article section > h3 a:hover, article section > h3 a:focus, article section > h3 a:active, +article section > h4 a:hover, article section > h4 a:focus, article section > h4 a:active, +article section > h5 a:hover, article section > h5 a:focus, article section > h5 a:active, +article section > h6 a:hover, article section > h6 a:focus, article section > h6 a:active { + color: #dcdcdc; +} +article > header .m-date { + display: block; + width: 2.5rem; + float: left; + text-align: center; + line-height: 95%; + font-size: 0.75rem; + font-weight: normal; + white-space: nowrap; + border-right-style: solid; + border-right-width: 0.125rem; + border-color: #a5c9ea; + padding-right: 0.75rem; + margin-top: -0.1rem; + margin-right: 0.75rem; + margin-bottom: 0.25rem; +} +article > header .m-date-day { + display: block; + font-weight: bold; + padding-top: 0.2rem; + padding-bottom: 0.15rem; + font-size: 1.25rem; +} +article > header p { + color: #f0f0f0; + font-size: 1.125rem; +} +article > header h1::after { + content: " "; + clear: both; + display: table; +} +article > footer { + color: #c5c5c5; +} +article > footer p { + font-style: italic; + font-size: 0.85rem; + text-indent: 0; +} +article section:target { + margin-left: -1.0rem; + border-left-style: solid; + border-left-width: 0.25rem; + padding-left: 0.75rem; + border-color: #a5c9ea; +} +article h1 a, article > header h1 a, article section > h2 a, article section > h3 a, +article section > h4 a, article section > h5 a, article section > h6 a { + text-decoration: none; +} +#m-landing-image, #m-cover-image, article#m-jumbo > header #m-jumbo-image { + background-size: cover; + background-color: #0f1217; + background-position: center center; + background-repeat: no-repeat; + margin-top: -4rem; + padding-top: 5rem; +} +#m-landing-image { + color: #ffffff; +} +#m-cover-image { + height: 30rem; + margin-bottom: -26rem; +} +#m-landing-cover h1 { + font-size: 2.8rem; + margin-top: -0.5rem; + padding-left: 1.5rem; + padding-bottom: 1rem; + text-transform: lowercase; +} +#m-landing-cover { + padding-bottom: 10rem; + margin-bottom: -6rem; +} +article#m-jumbo { + margin-top: -1rem; +} +#m-landing-cover, #m-cover-image > div, article#m-jumbo > header #m-jumbo-cover { + background: linear-gradient(transparent 0%, transparent 50%, #2f363f 100%); + width: 100%; + height: 100%; +} +article#m-jumbo > header h1, article#m-jumbo > header h2 { + text-align: center; + font-weight: bold; +} +article#m-jumbo > header a { + text-decoration: none; +} +article#m-jumbo > header #m-jumbo-cover { + padding-bottom: 5rem; +} +article#m-jumbo > header #m-jumbo-image { + font-size: 2.5vmin; + margin-bottom: -3rem; +} +article#m-jumbo > header h1 { + font-size: 10vmin; +} +article#m-jumbo > header h2 { + font-size: 3vmin; +} +@media screen and (max-height: 640px) , screen and (max-width: 640px) { + article#m-jumbo > header h1 { + font-size: 3rem; + } + article#m-jumbo > header #m-jumbo-image, article#m-jumbo > header h2 { + font-size: 1rem; + } +} +article#m-jumbo > header, article#m-jumbo > header h1, article#m-jumbo > header a { + color: #ffffff; +} +article#m-jumbo > header a:hover, article#m-jumbo > header a:focus, article#m-jumbo > header a:active { + color: #f0f0f0; +} +article#m-jumbo.m-inverted > header, article#m-jumbo.m-inverted > header h1, article#m-jumbo.m-inverted > header a { + color: #000000; +} +article#m-jumbo.m-inverted > header a:hover, article#m-jumbo.m-inverted > header a:focus, article#m-jumbo.m-inverted > header a:active { + color: #0f0f0f; +} +.m-landing-news h3 a { + color: #dcdcdc; + text-decoration: none; + text-transform: uppercase; +} +.m-landing-news h3 a:hover, .m-landing-news h3 a:hover, .m-landing-news h3 a:focus, .m-landing-news h3 a:active { + color: #a5c9ea; +} +.m-landing-news time { + display: inline-block; + margin-left: 1rem; + float: right; +} +.m-article-pagination { + text-align: center; + padding: 1rem; +} +nav.m-navpanel { + text-align: center; +} +nav.m-navpanel h3 { + text-transform: uppercase; + font-weight: normal; +} +nav.m-navpanel ol { + text-transform: lowercase; +} +nav.m-navpanel ol, nav.m-navpanel ul { + list-style-type: none; + padding: 0; +} +nav.m-navpanel a { + color: #ffffff; + text-decoration: none; +} +nav.m-navpanel a:hover, nav.m-navpanel a:focus, nav.m-navpanel a:active { + color: #a5c9ea; +} +ul.m-tagcloud li { display: inline; } +ul.m-tagcloud li.m-tag-1 { font-size: 0.75rem; } +ul.m-tagcloud li.m-tag-2 { font-size: 0.825rem; } +ul.m-tagcloud li.m-tag-3 { font-size: 1rem; } +ul.m-tagcloud li.m-tag-4 { font-size: 1.25rem; } +ul.m-tagcloud li.m-tag-5 { font-size: 1.5rem; } +article section:target figure.m-code-figure, article section:target figure.m-console-figure { + z-index: 1; +} +article, article > header, article section { margin-bottom: 1rem; } +article:last-child, article section:last-child { margin-bottom: 0; } +.m-container-inflatable section:target > .m-note, +.m-container-inflatable section:target > .m-frame, +.m-container-inflatable section:target > .m-block, +.m-container-inflatable section:target > pre, +.m-container-inflatable section:target > figure.m-code-figure > pre:first-child, +.m-container-inflatable section:target > figure.m-console-figure > pre:first-child, +.m-container-inflatable section:target section > .m-note, +.m-container-inflatable section:target section > .m-frame, +.m-container-inflatable section:target section > .m-block, +.m-container-inflatable section:target section > pre, +.m-container-inflatable section:target section > figure.m-code-figure > pre:first-child, +.m-container-inflatable section:target section > figure.m-console-figure > pre:first-child, +.m-container-inflatable section:target [class*='m-center-'] > .m-note, +.m-container-inflatable section:target [class*='m-center-'] > .m-frame, +.m-container-inflatable section:target [class*='m-center-'] > .m-block, +.m-container-inflatable section:target [class*='m-center-'] > pre, +.m-container-inflatable section:target [class*='m-center-'] > figure.m-code-figure > pre:first-child, +.m-container-inflatable section:target [class*='m-center-'] > figure.m-console-figure > pre:first-child, +.m-container-inflatable section:target [class*='m-left-'] > .m-note, +.m-container-inflatable section:target [class*='m-left-'] > .m-frame, +.m-container-inflatable section:target [class*='m-left-'] > .m-block, +.m-container-inflatable section:target [class*='m-left-'] > pre, +.m-container-inflatable section:target [class*='m-left-'] > figure.m-code-figure > pre:first-child, +.m-container-inflatable section:target [class*='m-left-'] > figure.m-console-figure > pre:first-child, +.m-container-inflatable section:target [class*='m-right-'] > .m-note, +.m-container-inflatable section:target [class*='m-right-'] > .m-frame, +.m-container-inflatable section:target [class*='m-right-'] > .m-block, +.m-container-inflatable section:target [class*='m-right-'] > pre, +.m-container-inflatable section:target [class*='m-right-'] > figure.m-code-figure > pre:first-child, +.m-container-inflatable section:target [class*='m-right-'] > figure.m-console-figure > pre:first-child, +.m-container-inflatable section:target .m-container-inflate > .m-note, +.m-container-inflatable section:target .m-container-inflate > .m-frame, +.m-container-inflatable section:target .m-container-inflate > .m-block, +.m-container-inflatable section:target .m-container-inflate > pre, +.m-container-inflatable section:target .m-container-inflate > figure.m-code-figure > pre:first-child, +.m-container-inflatable section:target .m-container-inflate > figure.m-console-figure > pre:first-child { + margin-left: -1.0rem; + border-left-style: solid; + border-left-width: 0.25rem; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + padding-left: 0.75rem; +} +.m-container-inflatable section:target > figure.m-code-figure::before, +.m-container-inflatable section:target > figure.m-console-figure::before, +.m-container-inflatable section:target section > figure.m-code-figure::before, +.m-container-inflatable section:target section > figure.m-console-figure::before, +.m-container-inflatable section:target [class*='m-center-'] > figure.m-code-figure::before, +.m-container-inflatable section:target [class*='m-center-'] > figure.m-console-figure::before, +.m-container-inflatable section:target [class*='m-left-'] > figure.m-code-figure::before, +.m-container-inflatable section:target [class*='m-left-'] > figure.m-console-figure::before, +.m-container-inflatable section:target [class*='m-right-'] > figure.m-code-figure::before, +.m-container-inflatable section:target [class*='m-right-'] > figure.m-console-figure::before, +.m-container-inflatable section:target .m-container-inflate > figure.m-code-figure::before, +.m-container-inflatable section:target .m-container-inflate > figure.m-console-figure::before { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left-width: 0.25rem; +} +@media screen and (min-width: 576px) { + .m-container-inflatable section:target .m-center-s > .m-note, + .m-container-inflatable section:target .m-center-s > pre, + .m-container-inflatable section:target .m-center-s > figure.m-code-figure > pre:first-child, + .m-container-inflatable section:target .m-center-s > figure.m-console-figure > pre:first-child, + .m-container-inflatable section:target .m-right-s > figure.m-code-figure > pre:first-child, + .m-container-inflatable section:target .m-right-s > figure.m-console-figure > pre:first-child { + border-left-width: 0; + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + padding-left: 1rem; + } + .m-container-inflatable section:target .m-center-s > .m-block, + .m-container-inflatable section:target .m-right-s > .m-block { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + } + .m-container-inflatable section:target .m-center-s > .m-frame, + .m-container-inflatable section:target .m-right-s > .m-frame { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + border-left-width: 0.125rem; + padding-left: 0.875rem; + } + .m-container-inflatable section:target .m-right-s > .m-block, + .m-container-inflatable section:target .m-right-s > .m-frame { + margin-left: 0; + } + .m-container-inflatable section:target .m-right-s > .m-note, + .m-container-inflatable section:target .m-right-s > pre { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + margin-left: 0; + border-left-width: 0; + padding-left: 1rem; + } + .m-container-inflatable section:target .m-center-s > figure.m-code-figure::before, + .m-container-inflatable section:target .m-center-s > figure.m-console-figure::before, + .m-container-inflatable section:target .m-right-s > figure.m-code-figure::before, + .m-container-inflatable section:target .m-right-s > figure.m-console-figure::before { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + border-left-width: 0.125rem; + } +} +@media screen and (min-width: 768px) { + .m-container-inflatable section:target .m-center-m > .m-note, + .m-container-inflatable section:target .m-center-m > pre, + .m-container-inflatable section:target .m-center-m > figure.m-code-figure > pre:first-child, + .m-container-inflatable section:target .m-center-m > figure.m-console-figure > pre:first-child, + .m-container-inflatable section:target .m-right-m > figure.m-code-figure > pre:first-child, + .m-container-inflatable section:target .m-right-m > figure.m-console-figure > pre:first-child { + border-left-width: 0; + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + padding-left: 1rem; + } + .m-container-inflatable section:target .m-center-m > .m-block, + .m-container-inflatable section:target .m-right-m > .m-block { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + } + .m-container-inflatable section:target .m-center-m > .m-frame, + .m-container-inflatable section:target .m-right-m > .m-frame { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + border-left-width: 0.125rem; + padding-left: 0.875rem; + } + .m-container-inflatable section:target .m-right-m > .m-block, + .m-container-inflatable section:target .m-right-m > .m-frame { + margin-left: 0; + } + .m-container-inflatable section:target .m-right-m > .m-note, + .m-container-inflatable section:target .m-right-m > pre { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + margin-left: 0; + border-left-width: 0; + padding-left: 1rem; + } + .m-container-inflatable section:target .m-center-m > figure.m-code-figure::before, + .m-container-inflatable section:target .m-center-m > figure.m-console-figure::before, + .m-container-inflatable section:target .m-right-m > figure.m-code-figure::before, + .m-container-inflatable section:target .m-right-m > figure.m-console-figure::before { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + border-left-width: 0.125rem; + } +} +@media screen and (min-width: 992px) { + .m-container-inflatable section:target .m-center-l > .m-note, + .m-container-inflatable section:target .m-center-l > pre, + .m-container-inflatable section:target .m-center-l > figure.m-code-figure > pre:first-child, + .m-container-inflatable section:target .m-center-l > figure.m-console-figure > pre:first-child, + .m-container-inflatable section:target .m-right-l > figure.m-code-figure > pre:first-child, + .m-container-inflatable section:target .m-right-l > figure.m-console-figure > pre:first-child { + border-left-width: 0; + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + padding-left: 1rem; + } + .m-container-inflatable section:target .m-center-l > .m-block, + .m-container-inflatable section:target .m-right-l > .m-block { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + } + .m-container-inflatable section:target .m-center-l > .m-frame, + .m-container-inflatable section:target .m-right-l > .m-frame { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + border-left-width: 0.125rem; + padding-left: 0.875rem; + } + .m-container-inflatable section:target .m-right-l > .m-block, + .m-container-inflatable section:target .m-right-l > .m-frame { + margin-left: 0; + } + .m-container-inflatable section:target .m-right-l > .m-note, + .m-container-inflatable section:target .m-right-l > pre { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + margin-left: 0; + border-left-width: 0; + padding-left: 1rem; + } + .m-container-inflatable section:target .m-center-l > figure.m-code-figure::before, + .m-container-inflatable section:target .m-center-l > figure.m-console-figure::before, + .m-container-inflatable section:target .m-right-l > figure.m-code-figure::before, + .m-container-inflatable section:target .m-right-l > figure.m-console-figure::before { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; + border-left-width: 0.125rem; + } +} +.m-container-inflatable section:target > figure.m-code-figure::before, +.m-container-inflatable section:target > figure.m-console-figure::before, +.m-container-inflatable section:target section > figure.m-code-figure::before, +.m-container-inflatable section:target section > figure.m-console-figure::before, +.m-container-inflatable section:target [class*='m-center-'] > figure.m-code-figure::before, +.m-container-inflatable section:target [class*='m-center-'] > figure.m-console-figure::before, +.m-container-inflatable section:target [class*='m-left-'] > figure.m-code-figure::before, +.m-container-inflatable section:target [class*='m-left-'] > figure.m-console-figure::before, +.m-container-inflatable section:target [class*='m-right-'] > figure.m-code-figure::before, +.m-container-inflatable section:target [class*='m-right-'] > figure.m-console-figure::before, +.m-container-inflatable section:target .m-container-inflatable > figure.m-code-figure::before, +.m-container-inflatable section:target .m-container-inflatable > figure.m-console-figure::before { + border-left-color: #405363; +} +@media screen and (min-width: 576px) { + .m-container-inflatable section:target .m-center-s > figure.m-code-figure::before, + .m-container-inflatable section:target .m-right-s > figure.m-code-figure::before { + border-color: #282e36; + } + .m-container-inflatable section:target .m-center-s > figure.m-console-figure::before, + .m-container-inflatable section:target .m-right-s > figure.m-console-figure::before { + border-color: #000000; + } +} +@media screen and (min-width: 768px) { + .m-container-inflatable section:target .m-center-m > figure.m-code-figure::before, + .m-container-inflatable section:target .m-right-m > figure.m-code-figure::before { + border-color: #282e36; + } + .m-container-inflatable section:target .m-center-m > figure.m-console-figure::before, + .m-container-inflatable section:target .m-right-m > figure.m-console-figure::before { + border-color: #000000; + } +} +@media screen and (min-width: 992px) { + .m-container-inflatable section:target .m-center-l > figure.m-code-figure::before, + .m-container-inflatable section:target .m-right-l > figure.m-code-figure::before { + border-color: #282e36; + } + .m-container-inflatable section:target .m-center-l > figure.m-console-figure::before, + .m-container-inflatable section:target .m-right-l > figure.m-console-figure::before { + border-color: #000000; + } +} +.m-container-inflatable section:target pre, +.m-container-inflatable section:target figure.m-code-figure > pre:first-child, +.m-container-inflatable section:target figure.m-console-figure > pre:first-child { + border-color: #405363; +} +.m-container-inflatable section:target .m-note.m-default { + border-color: #405363; +} +.m-container-inflatable section:target .m-note.m-primary { + border-color: #a5c9ea; +} +.m-container-inflatable section:target .m-note.m-success { + border-color: #3bd267; +} +.m-container-inflatable section:target .m-note.m-warning { + border-color: #c7cf2f; +} +.m-container-inflatable section:target .m-note.m-danger { + border-color: #cd3431; +} +.m-container-inflatable section:target .m-note.m-info { + border-color: #2f83cc; +} +.m-container-inflatable section:target .m-note.m-dim { + border-color: #747474; +} + +.m-code .hll { background-color: #34424d } +.m-code .c { color: #a5c9ea } +.m-code .k { color: #ffffff; font-weight: bold } +.m-code .n { color: #dcdcdc } +.m-code .o { color: #aaaaaa } +.m-code .p { color: #aaaaaa } +.m-code .ch { color: #a5c9ea } +.m-code .cm { color: #a5c9ea } +.m-code .cp { color: #3bd267 } +.m-code .cpf { color: #c7cf2f } +.m-code .c1 { color: #a5c9ea } +.m-code .cs { color: #a5c9ea } +.m-code .gd { color: #cd3431 } +.m-code .ge { color: #e6e6e6; font-style: italic } +.m-code .gh { color: #ffffff; font-weight: bold } +.m-code .gi { color: #3bd267 } +.m-code .gs { color: #e6e6e6; font-weight: bold } +.m-code .gu { color: #5b9dd9 } +.m-code .kc { color: #ffffff; font-weight: bold } +.m-code .kd { color: #ffffff; font-weight: bold } +.m-code .kn { color: #ffffff; font-weight: bold } +.m-code .kp { color: #ffffff; font-weight: bold } +.m-code .kr { color: #ffffff; font-weight: bold } +.m-code .kt { color: #ffffff; font-weight: bold } +.m-code .m { color: #c7cf2f } +.m-code .s { color: #e07f7c } +.m-code .na { color: #dcdcdc; font-weight: bold } +.m-code .nb { color: #ffffff; font-weight: bold } +.m-code .nc { color: #dcdcdc; font-weight: bold } +.m-code .no { color: #dcdcdc } +.m-code .nd { color: #dcdcdc } +.m-code .ni { color: #dcdcdc } +.m-code .ne { color: #dcdcdc } +.m-code .nf { color: #dcdcdc } +.m-code .nl { color: #dcdcdc } +.m-code .nn { color: #dcdcdc } +.m-code .nx { color: #dcdcdc } +.m-code .py { color: #dcdcdc } +.m-code .nt { color: #dcdcdc; font-weight: bold } +.m-code .nv { color: #c7cf2f } +.m-code .ow { color: #dcdcdc; font-weight: bold } +.m-code .mb { color: #c7cf2f } +.m-code .mf { color: #c7cf2f } +.m-code .mh { color: #c7cf2f } +.m-code .mi { color: #c7cf2f } +.m-code .mo { color: #c7cf2f } +.m-code .sa { color: #e07f7c } +.m-code .sb { color: #e07f7c } +.m-code .sc { color: #e07cdc } +.m-code .dl { color: #e07f7c } +.m-code .sd { color: #e07f7c } +.m-code .s2 { color: #e07f7c } +.m-code .se { color: #e07f7c } +.m-code .sh { color: #e07f7c } +.m-code .si { color: #e07f7c } +.m-code .sx { color: #e07f7c } +.m-code .sr { color: #e07f7c } +.m-code .s1 { color: #e07f7c } +.m-code .ss { color: #e07f7c } +.m-code .bp { color: #ffffff; font-weight: bold } +.m-code .fm { color: #dcdcdc } +.m-code .vc { color: #c7cf2f } +.m-code .vg { color: #c7cf2f } +.m-code .vi { color: #c7cf2f } +.m-code .vm { color: #c7cf2f } +.m-code .il { color: #c7cf2f } + +.m-console .hll { background-color: #ffffcc } +.m-console .g-AnsiBlack { color: #000000 } +.m-console .g-AnsiBlue { color: #3f3fd1 } +.m-console .g-AnsiBrightBlack { color: #686868; font-weight: bold } +.m-console .g-AnsiBrightBlue { color: #5454ff; font-weight: bold } +.m-console .g-AnsiBrightCyan { color: #54ffff; font-weight: bold } +.m-console .g-AnsiBrightDefault { color: #ffffff; font-weight: bold } +.m-console .g-AnsiBrightGreen { color: #54ff54; font-weight: bold } +.m-console .g-AnsiBrightMagenta { color: #ff54ff; font-weight: bold } +.m-console .g-AnsiBrightRed { color: #ff5454; font-weight: bold } +.m-console .g-AnsiBrightWhite { color: #ffffff; font-weight: bold } +.m-console .g-AnsiBrightYellow { color: #ffff54; font-weight: bold } +.m-console .g-AnsiCyan { color: #18b2b2 } +.m-console .g-AnsiDefault { color: #b2b2b2 } +.m-console .g-AnsiGreen { color: #18b218 } +.m-console .g-AnsiMagenta { color: #b218b2 } +.m-console .g-AnsiRed { color: #b21818 } +.m-console .g-AnsiWhite { color: #b2b2b2 } +.m-console .g-AnsiYellow { color: #b26818 } +.m-console .go { color: #b2b2b2 } +.m-console .gp { color: #54ffff; font-weight: bold } +.m-console .w { color: #b2b2b2 } + +a.m-dox, a.m-dox-self, a.m-dox-external, +ul.m-dox li.m-dox-expansible > a:first-child, ul.m-dox li.m-dox-collapsible > a:first-child, +.m-code.m-inverted.m-dox-include > a { + text-decoration: none; +} +a.m-dox, a.m-dox-self { + font-weight: bold; +} +.m-thin a.m-dox, .m-thin a.m-dox-self { + font-weight: normal; +} +ul.m-dox li.m-dox-expansible > a:first-child, +ul.m-dox li.m-dox-collapsible > a:first-child, +ul.m-dox li.m-dox-expansible > a:first-child:hover, +ul.m-dox li.m-dox-expansible > a:first-child:focus, +ul.m-dox li.m-dox-expansible > a:first-child:active, +ul.m-dox li.m-dox-collapsible > a:first-child:hover, +ul.m-dox li.m-dox-collapsible > a:first-child:focus, +ul.m-dox li.m-dox-collapsible > a:first-child:active { + color: #dcdcdc; +} +a.m-dox-self, +ul.m-dox li.m-dox-expansible > a:first-child:before, +ul.m-dox li.m-dox-collapsible > a:first-child:before { + color: #a5c9ea; +} +a.m-dox-self:hover, a.m-dox-self:focus, a.m-dox-self:active, +ul.m-dox li.m-dox-expansible > a:first-child:hover::before, +ul.m-dox li.m-dox-expansible > a:first-child:focus::before, +ul.m-dox li.m-dox-expansible > a:first-child:active::before, +ul.m-dox li.m-dox-collapsible > a:first-child:hover::before, +ul.m-dox li.m-dox-collapsible > a:first-child:focus::before, +ul.m-dox li.m-dox-collapsible > a:first-child:active::before { + color: #dcdcdc; +} +h3 a.m-dox-external { + font-weight: normal; +} +span.m-dox-wrap-bumper { + margin-right: -1rem; +} +span.m-dox-wrap { + padding-left: 1rem; + display: inline-block; + vertical-align: text-top; + white-space: pre-line; + max-width: 100%; +} +dl.m-dox dd { + margin-bottom: 0.5rem; +} +ul.m-dox { + list-style: none; + margin-left: 1.0375rem; + padding-left: 0.9rem; + border-left-color: #405363; + border-left-width: 0.0625rem; + border-left-style: solid; +} +ul.m-dox li { + text-indent: -1rem; + padding-left: 1rem; +} +ul.m-dox li.m-dox-expansible > ul { + display: none; +} +ul.m-dox li.m-dox-expansible, ul.m-dox li.m-dox-collapsible { + padding-left: 0.6rem; +} +ul.m-dox li.m-dox-expansible > ul.m-dox, ul.m-dox li.m-dox-collapsible > ul.m-dox { + margin-left: 0.5rem; +} +ul.m-dox li.m-dox-expansible > a:first-child:before, ul.m-dox li.m-dox-collapsible > a:first-child:before { + background-color: #2f363f; + display: inline-block; + width: 0.4rem; + font-weight: bold; +} +ul.m-dox li.m-dox-expansible > a:first-child:before { content: '⊕'; } +ul.m-dox li.m-dox-collapsible > a:first-child:before { content: '⊖'; } +h1 .m-dox-template, h1 .m-dox-include { + font-size: 1.3rem; + font-weight: normal; +} +h1 .m-dox-include:last-child { + margin-bottom: -0.5rem; +} +h3 .m-dox-template, h3 .m-dox-include { + font-size: 1rem; + font-weight: normal; +} +.m-dox-template, dl.m-dox dd, ul.m-dox li > span.m-dox { + color: #747474; +} +dl.m-dox dd svg.m-math, ul.m-dox li > span.m-dox svg.m-math { + fill: #747474; +} +.m-dox-template a, dl.m-dox dd a, ul.m-dox li > span.m-dox a { + color: #acacac; +} +.m-dox-template a:hover, .m-dox-template a:focus, .m-dox-template a:active, +dl.m-dox dd a:hover, dl.m-dox dd a:focus, dl.m-dox dd a:active, +ul.m-dox li > span.m-dox a:hover, ul.m-dox li > span.m-dox a:focus, ul.m-dox li > span.m-dox a:active { + color: #747474; +} +.m-code.m-inverted.m-dox-include > a:link, +.m-code.m-inverted.m-dox-include > a:visited { + opacity: 0.6666; +} +.m-code.m-inverted.m-dox-include > a:hover, +.m-code.m-inverted.m-dox-include > a:focus, +.m-code.m-inverted.m-dox-include > a:active { + opacity: 1; +} +article section.m-dox-details > div { + margin-top: 0; + margin-left: 0; + margin-right: 0; + position: relative; + padding: 1rem; +} +article section.m-dox-details > div::before { + position: absolute; + content: ' '; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: -1; + border-style: solid; + border-width: 0.125rem; + border-radius: 0.2rem; + border-color: #282e36; +} +article section.m-dox-details > div > h3:first-child { + position: relative; + margin: -1rem -1rem 1rem -1rem; + padding: 0.5rem 1rem; + background-color: #282e36; + border-top-left-radius: 0.2rem; + border-top-right-radius: 0.2rem; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +article section.m-dox-details:target { + border-color: transparent; +} +article section.m-dox-details:target > div { + z-index: 1; +} +.m-container-inflatable > .m-row > [class*='m-col-'] section.m-dox-details > div { + margin-left: -1rem; + margin-right: -1rem; +} +.m-container-inflatable section.m-dox-details:target > div > h3:first-child, +.m-container-inflatable section.m-dox-details:target section > div > h3:first-child { + margin-left: -1.0rem; + border-left-style: solid; + border-left-color: #dcdcdc; + border-left-width: 0.25rem; + padding-left: 0.75rem; +} +.m-container-inflatable section.m-dox-details:target > div::before, +.m-container-inflatable section-dox-details:target section > div.m::before { + border-left-width: 0.25rem; + border-left-color: #a5c9ea; +} +a.m-dox-search-icon { + padding-left: 1rem; + padding-right: 1rem; +} +a.m-dox-search-icon svg { + fill: #ffffff; +} +body > header > nav #m-navbar-collapse a.m-dox-search-icon svg { + vertical-align: -5%; +} +a.m-dox-search-icon:focus svg, a.m-dox-search-icon:hover svg, a.m-dox-search-icon:active svg { + fill: #a5c9ea; +} +.m-dox-search { + display: none; + z-index: 10; + position: fixed; + left: 0; + right: 0; + top: 0; + bottom: 0; + background-color: rgba(34, 39, 46, 0.75); +} +.m-dox-search:target { + display: block; +} +.m-dox-search > a { + display: block; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; +} +.m-dox-search-header { + margin-top: 2.5rem; + padding: 0.5rem 1rem; + height: 2rem; +} +.m-dox-search-header > div:first-child { + float: right; +} +.m-dox-search-content { + background-color: #24525B; + border-radius: 0.2rem; + padding: 1rem; +} +.m-dox-search input { + width: 100%; + height: 3rem; + font-size: 1.2rem; + border-width: 0; + color: #dcdcdc; + background-color: #34424d; + border-radius: 0.2rem; + margin-bottom: 1rem; + padding: 0 1rem; +} +.m-dox-search #search-notfound { + display: none; +} +.m-dox-search ul#search-results { + list-style-type: none; + padding-left: 0; + max-height: calc(100vh - 12.5rem); + overflow-y: auto; + display: none; +} +.m-dox-search ul#search-results li a { + display: block; + padding-left: 1rem; + padding-right: 1rem; + text-decoration: none; + width: 100%; + line-height: 1.5rem; + color: #dcdcdc; +} +.m-dox-search ul#search-results li a > div { + white-space: nowrap; + overflow: hidden; +} +.m-dox-search ul#search-results li a > div:not(.m-dox-search-alias) { + direction: rtl; +} +.m-dox-search ul#search-results li a .m-label { + float: right; + line-height: 1rem; + margin-top: 0.1rem; + margin-left: 0.25rem; +} +.m-dox-search ul#search-results li a .m-label.m-flat { + margin-right: -0.75rem; +} +.m-dox-search ul#search-results li#search-current a { + background-color: #34424d; +} +.m-dox-search ul#search-results li#search-current.m-dox-search-copied a { + background-color: #2a703f; +} +.m-dox-search-typed { + color: #5b9dd9; +} +.m-dox-search input[type="search"] { -webkit-appearance: textfield; } +.m-dox-search input[type="search"]::-webkit-search-decoration, +.m-dox-search input[type="search"]::-webkit-search-cancel-button, +.m-dox-search input[type="search"]::-webkit-search-results-button, +.m-dox-search input[type="search"]::-webkit-search-results-decoration { + display: none; +} diff --git a/modules.html b/modules.html new file mode 100644 index 0000000..50b6bf8 --- /dev/null +++ b/modules.html @@ -0,0 +1,197 @@ + + + + + + + Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

Modules

+
    +
  • module Base provides classes and functions to create continuable_base objects.
  • +
  • module Connections provides functions to connect continuable_bases through various strategies.
  • +
  • module Operations provides functions to work with asynchronous control flows.
  • +
  • module Primitives provides basic tag types for creating a customized callbacks and continuations.
  • +
  • module Promisify provides helper methods to convert various callback styles to continuable_bases.
  • +
  • module Result provides the result class and corresponding utility functions to work with the result of an asynchronous operation which can possibly yield:
  • +
  • module Transforms provides utilities to convert continuable_bases to other types such as (std::future).
  • +
  • module Traversal provides functions to traverse and remap nested packs.
  • +
  • module Types provides the continuable and promise facility for type erasure.
  • +
  • module Testing provides macro shortcuts for testing asynchronous continuations through GTest.
  • +
+ +
+
+
+
+ + + + + + diff --git a/namespacecti.html b/namespacecti.html new file mode 100644 index 0000000..721e053 --- /dev/null +++ b/namespacecti.html @@ -0,0 +1,585 @@ + + + + + + + cti namespace | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ cti namespace +

+

Declares the continuable library namespace.

+
+

Contents

+ +
+

The most important class is cti::continuable_base, that provides the whole functionality for continuation chaining.

The class cti::continuable_base is created through the cti::make_continuable() function which accepts a callback taking function.

Also there are following support functions available:

+
+

Namespaces

+
+
namespace transforms
+
The namespace transforms declares callable objects that transform any continuable_base to an object or to a continuable_base itself.
+
+
+
+

Classes

+
+
+ struct cancellation_result +
+
A class which is convertible to any result and that definitely holds a default constructed exception which signals the cancellation of the asynchronous control flow.
+
+
template<typename Data, typename Annotation>
+ class continuable_base +
+
The main class of the continuable library, it provides the functionality for chaining callbacks and continuations together to a unified hierarchy.
+
+ struct empty_result +
+
A class which is convertible to any result and that definitely holds no value so the real result gets invalidated when this object is passed to it.
+
+ struct exception_arg_t +
+
Represents the tag type that is used to disambiguate the callback operator() in order to take the exception asynchronous chain.
+
+ class exceptional_result +
+
A class which is convertible to any result and that holds an exception which is then passed to the converted result object.
+
+ struct is_ready_arg_t +
+
Represents the tag type that is used to query the continuation for whether it resolves the callback instantly with its arguments without having side effects.
+
+
template<typename Data, typename Hint>
+ class promise_base +
+
The promise_base makes it possible to resolve an asynchronous continuable through it's result or through an error type.
+
+
template<typename... Result>
+ class promisify +
+
Helper class for converting callback taking callable types into a a continuable. Various styles are supported.
+
+
template<typename... T>
+ class result +
+
The result class can carry the three kinds of results an asynchronous operation possibly can return, it's implemented in a variant like data structure which is also specialized to hold arbitrary arguments.
+
+ struct unpack_arg_t +
+
Represents the tag type that is used to unpack the result of a continuation.
+
+
template<typename Mapper = detail::asio::map_default>
+ struct use_continuable_t +
+
Type used as an ASIO completion token to specify an asynchronous operation that should return a continuable_base.
+
+
+
+

Typedefs

+
+
+
template<typename T>
+ using is_continuable = detail::base::is_continuable<T> +
+
Deduces to a true_type if the given type is a continuable_base.
+
+
template<typename... Args>
+ using signature_arg_t = detail::identity<Args...> +
+
Represents the tag type that is used to specify the signature hint of a continuable_base or promise_base.
+
+ using query_arg_t = unpack_arg_t deprecated +
+
Represents the tag type that is used to unpack the result of a continuation.
+
+ using dispatch_error_tag = exception_arg_t deprecated +
+
Represents the tag type that is used to disambiguate the callback operator() in order to take the exception asynchronous chain.
+
+ using exception_t = detail::types::exception_t +
+
Represents the type that is used as exception type.
+
+ using error_type = exception_t deprecated +
+
Represents the type that is used as exception type.
+
+
template<typename T>
+ using plain_t = detail::types::plain_tag<T> +
+
Represents the type that is used to disable the special meaning of types which are returned by a asynchronous result handler. See cti::plain for details.
+
+ using void_arg_t = detail::void_arg_t +
+
A tag which represents present void values in result.
+
+ using async_traverse_visit_tag = detail::traversal::async_traverse_visit_tag +
+
A tag which is passed to the operator() of the visitor if an element is visited synchronously through traverse_pack_async.
+
+ using async_traverse_detach_tag = detail::traversal::async_traverse_detach_tag +
+
A tag which is passed to the operator() of the visitor if an element is visited after the traversal was detached through traverse_pack_async.
+
+ using async_traverse_complete_tag = detail::traversal::async_traverse_complete_tag +
+
A tag which is passed to the operator() of the visitor if the asynchronous pack traversal was finished through traverse_pack_async.
+
+
template<typename T>
+ using async_traverse_in_place_tag = detail::traversal::async_traverse_in_place_tag<T> +
+
A tag to identify that a mapper shall be constructed in-place from the first argument passed to traverse_pack_async.
+
+
template<typename... Args>
+ using continuation_capacity = detail::erasure::continuation_capacity<Args...> +
+
Deduces to the preferred continuation capacity for a possible small functor optimization. The given capacity size is always enough to to avoid any allocation when storing a ready continuable_base.
+
+
template<typename... Args>
+ using continuable = continuable_base<detail::erasure::continuation<Args...>, signature_arg_t<Args...>> +
+
Defines a non-copyable continuation type which uses the function2 backend for type erasure.
+
+
template<typename... Args>
+ using promise = promise_base<detail::erasure::callback<Args...>, signature_arg_t<Args...>> +
+
Defines a non-copyable promise type which is using the function2 backend for type erasure.
+
+ using work = promise_base<detail::erasure::work, signature_arg_t<>> +
+
Defines a non-copyable type erasure which is capable of carrying callable objects passed to executors.
+
+ using asio_error_code_t = detail::asio::error_code_t +
+
The error code type used by your asio distribution.
+
+ using asio_basic_errors_t = detail::asio::basic_errors_t +
+
The basic error code enum used by your asio distribution.
+
+ using asio_system_error_t = detail::asio::system_error_t +
+
The system error type used by your asio distribution.
+
+ using use_continuable_raw_t = use_continuable_t<detail::asio::map_none> +
+
Type used as an ASIO completion token to specify an asynchronous operation that should return a continuable_base.
+
+
+
+

Functions

+
+
+
template<typename... Args, typename Continuation>
+ auto make_continuable(Continuation&& continuation) -> auto constexpr +
+
Creates a continuable_base from a promise/callback taking function.
+
+
template<typename... Args>
+ auto make_ready_continuable(Args && ... args) -> auto +
+
Returns a continuable_base with no result which instantly resolves the promise with no values.
+
+
template<typename... Args, typename Exception>
+ auto make_exceptional_continuable(Exception&& exception) -> auto constexpr +
+
Returns a continuable_base with the parameterized result which instantly resolves the promise with the given error type.
+
+
template<typename... Signature>
+ auto make_cancelling_continuable() -> auto +
+
Returns a continuable_base with the parameterized result which never resolves its promise and thus cancels the asynchronous continuation chain through throwing a default constructed exception_t.
+
+
template<typename T>
+ auto make_plain(T&& value) -> auto +
+
Can be used to disable the special meaning for a returned value in asynchronous handler functions.
+
+
template<typename... Args>
+ auto recover(Args && ... args) -> result<detail::traits::unrefcv_t<Args>...> +
+
Can be used to recover to from a failure handler, the result handler which comes after will be called with the corresponding result.
+
+ auto rethrow(exception_t exception) -> exceptional_result +
+
Can be used to rethrow an exception to the asynchronous continuation chain, the failure handler which comes after will be called with the corresponding exception.
+
+ auto cancel() -> cancellation_result +
+
Can be used to cancel an asynchronous continuation chain, the next failure handler which comes after cancel will be called with a default constructed exception_t object.
+
+ auto stop() -> empty_result +
+
Can be used to stop an asynchronous continuation chain, no handler which comes after stop was received won't be called.
+
+
template<typename... Args>
+ auto when_all(Args && ... args) -> auto +
+
Connects the given arguments with an all logic. All continuables contained inside the given nested pack are invoked at once. On completion the final handler is called with the aggregated result of all continuables.
+
+
template<typename Iterator, std::enable_if_t<detail::range::is_iterator<Iterator>::value>* = nullptr>
+ auto when_all(Iterator begin, + Iterator end) -> auto +
+
Connects the given arguments with an all logic. The content of the iterator is moved out and converted to a temporary std::vector which is then passed to when_all.
+
+
template<typename... Args>
+ auto when_seq(Args && ... args) -> auto +
+
Connects the given arguments with a sequential logic. All continuables contained inside the given nested pack are invoked one after one. On completion the final handler is called with the aggregated result of all continuables.
+
+
template<typename Iterator, std::enable_if_t<detail::range::is_iterator<Iterator>::value>* = nullptr>
+ auto when_seq(Iterator begin, + Iterator end) -> auto +
+
Connects the given arguments with a sequential logic. The content of the iterator is moved out and converted to a temporary std::vector which is then passed to when_seq.
+
+
template<typename... Args>
+ auto when_any(Args && ... args) -> auto +
+
Connects the given arguments with an any logic. All continuables contained inside the given nested pack are invoked at once. On completion of one continuable the final handler is called with the result of the resolved continuable.
+
+
template<typename Iterator, std::enable_if_t<detail::range::is_iterator<Iterator>::value>* = nullptr>
+ auto when_any(Iterator begin, + Iterator end) -> auto +
+
Connects the given arguments with an any logic. The content of the iterator is moved out and converted to a temporary std::vector which is then passed to when_all.
+
+
template<template<typename, typename> class C = std::vector, typename First, typename... Args>
+ auto populate(First&& first, + Args && ... args) -> C<std::decay_t<First>, std::allocator<std::decay_t<First>>> +
+
Populates a homogeneous container from the given arguments. All arguments need to be convertible to the first one, by default std::vector is used as container type.
+
+
template<std::size_t I, typename... T>
+ auto get(result<T...>& result) -> decltype(auto) +
+
Returns the value at position I of the given result.
+
+
template<std::size_t I, typename... T>
+ auto get(result<T...> const& result) -> decltype(auto) +
+
Returns the value at position I of the given result.
+
+
template<std::size_t I, typename... T>
+ auto get(result<T...>&& result) -> decltype(auto) +
+
Returns the value at position I of the given result.
+
+
template<typename... T, typename Result = result<detail::traits::unrefcv_t<T>...>>
+ auto make_result(T && ... values) -> Result +
+
Creates a present result from the given values.
+
+ auto make_result(exception_arg_t, + exception_t exception) -> exceptional_result +
+
Creates an exceptional_result from the given exception.
+
+
template<typename Visitor, typename... T>
+ auto traverse_pack_async(Visitor&& visitor, + T && ... pack) -> auto +
+
Traverses the pack with the given visitor in an asynchronous way.
+
+
template<typename Mapper, typename... T>
+ auto map_pack(Mapper&& mapper, + T && ... pack) -> decltype(auto) +
+
Maps the pack with the given mapper.
+
+
template<typename... T>
+ auto spread_this(T && ... args) -> detail::traversal::spreading::spread_box<std::decay_t<T>...> constexpr noexcept(…) +
+
Indicate that the result shall be spread across the parent container if possible. This can be used to create a mapper function used in map_pack that maps one element to an arbitrary count (1:n).
+
+
template<typename Mapper, typename... T>
+ void traverse_pack(Mapper&& mapper, + T && ... pack) +
+
Traverses the pack with the given visitor.
+
+
template<typename... Args>
+ auto use_continuable_ignoring(Args && ... args) -> auto noexcept +
+
Represents a special asio completion token which treats the given asio basic error codes as success instead of failure.
+
+
+
+

Variables

+
+
+ use_continuable_t use_continuable constexpr +
+
Special value for instance of use_continuable_t which performs remapping of asio error codes to align the cancellation behaviour with the library.
+
+ use_continuable_raw_t use_continuable_raw constexpr +
+
Special value for instance of use_continuable_raw_t which doesn't perform remapping of asio error codes and rethrows the raw error code.
+
+
+
+

Typedef documentation

+
+

+ using cti::asio_error_code_t = detail::asio::error_code_t +

+

The error code type used by your asio distribution.

+ +
+
+

+ using cti::asio_basic_errors_t = detail::asio::basic_errors_t +

+

The basic error code enum used by your asio distribution.

+ +
+
+

+ using cti::asio_system_error_t = detail::asio::system_error_t +

+

The system error type used by your asio distribution.

+ +
+
+

+ using cti::use_continuable_raw_t = use_continuable_t<detail::asio::map_none> +

+

Type used as an ASIO completion token to specify an asynchronous operation that should return a continuable_base.

+
  • Boost 1.70 or asio 1.13.0 is required for the async initiation
  • Until boost 1.72 or asio 1.16.0 overhead through an additional type erasure is added. It is recommended to update to those versions.

The special static variable use_continuable can be appended to any (boost) asio function that accepts a callback to make it return a continuable_base.

#include <continuable/continuable.hpp>
+#include <continuable/external/asio.hpp>
+#include <asio.hpp>
+
+// ...
+
+asio::tcp::resolver resolver(...);
+resolver.async_resolve("127.0.0.1", "daytime", cti::use_continuable)
+  .then([](asio::udp::resolver::iterator iterator) {
+    // ...
+  });

The raw async completion handler token does not remap the asio error asio::error::basic_errors::operation_aborted to a default constructed exception type.

+
+
+
+

Function documentation

+
+

+
+ template<typename... Args> +
+ auto cti::use_continuable_ignoring(Args && ... args) noexcept +

+

Represents a special asio completion token which treats the given asio basic error codes as success instead of failure.

+

asio::error::basic_errors::operation_aborted is mapped as cancellation token.

+
+
+
+

Variable documentation

+
+

+ use_continuable_t cti::use_continuable constexpr +

+

Special value for instance of use_continuable_t which performs remapping of asio error codes to align the cancellation behaviour with the library.

+
  • Boost 1.70 or asio 1.13.0 is required for the async initiation
  • Until boost 1.72 or asio 1.16.0 overhead through an additional type erasure is added. It is recommended to update to those versions.

The special static variable use_continuable can be appended to any (boost) asio function that accepts a callback to make it return a continuable_base.

#include <continuable/continuable.hpp>
+#include <continuable/external/asio.hpp>
+#include <asio.hpp>
+
+// ...
+
+asio::tcp::resolver resolver(...);
+resolver.async_resolve("127.0.0.1", "daytime", cti::use_continuable)
+  .then([](asio::udp::resolver::iterator iterator) {
+    // ...
+  });
+
+
+

+ use_continuable_raw_t cti::use_continuable_raw constexpr +

+

Special value for instance of use_continuable_raw_t which doesn't perform remapping of asio error codes and rethrows the raw error code.

+
  • Boost 1.70 or asio 1.13.0 is required for the async initiation
  • Until boost 1.72 or asio 1.16.0 overhead through an additional type erasure is added. It is recommended to update to those versions.

The special static variable use_continuable can be appended to any (boost) asio function that accepts a callback to make it return a continuable_base.

#include <continuable/continuable.hpp>
+#include <continuable/external/asio.hpp>
+#include <asio.hpp>
+
+// ...
+
+asio::tcp::resolver resolver(...);
+resolver.async_resolve("127.0.0.1", "daytime", cti::use_continuable)
+  .then([](asio::udp::resolver::iterator iterator) {
+    // ...
+  });

The raw async completion handler token does not remap the asio error asio::error::basic_errors::operation_aborted to a default constructed exception type.

+
+
+
+
+
+
+ + + + + + diff --git a/namespacecti_1_1transforms.html b/namespacecti_1_1transforms.html new file mode 100644 index 0000000..a6f0519 --- /dev/null +++ b/namespacecti_1_1transforms.html @@ -0,0 +1,286 @@ + + + + + + + cti::transforms namespace | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ cti::transforms namespace +

+

The namespace transforms declares callable objects that transform any continuable_base to an object or to a continuable_base itself.

+
+

Contents

+ +
+

Transforms can be applied to continuables through using the cti::continuable_base::apply method accordingly.

+
+

Functions

+
+
+ auto to_future() -> auto +
+
Returns a transform that if applied to a continuable, it will start the continuation chain and returns the asynchronous result as std::future<...>.
+
+ auto wait() -> auto +
+
Returns a transform that if applied to a continuable, it will start the continuation chain and returns the result synchronously. The current thread is blocked until the continuation chain is finished.
+
+
template<typename Rep, typename Period>
+ auto wait_for(std::chrono::duration<Rep, Period> duration) -> auto +
+
Returns a transform that if applied to a continuable, it will start the continuation chain and returns the result synchronously. The current thread is blocked until the continuation chain is finished.
+
+
template<typename Clock, typename Duration>
+ auto wait_until(std::chrono::time_point<Clock, Duration> time_point) -> auto +
+
Returns a transform that if applied to a continuable, it will start the continuation chain and returns the result synchronously. The current thread is blocked until the continuation chain is finished.
+
+
+
+

Function documentation

+
+

+ auto cti::transforms::to_future() +

+

Returns a transform that if applied to a continuable, it will start the continuation chain and returns the asynchronous result as std::future<...>.

+ + + + + + + +
Returns

Returns a std::future<...> which becomes ready as soon as the the continuation chain has finished. The signature of the future depends on the result type:

Continuation typeReturn type
continuable_base with <>std::future<void>
continuable_base with <Arg>std::future<Arg>
continuable_base with <Args...>std::future<std::tuple<Args...>>
+ +
+
+

+ auto cti::transforms::wait() +

+

Returns a transform that if applied to a continuable, it will start the continuation chain and returns the result synchronously. The current thread is blocked until the continuation chain is finished.

+ + + + + + + + + + + + + + + + +
Returns

Returns a value that is available immediately. The signature of the future depends on the result type:

Continuation typeReturn type
continuable_base with <>void
continuable_base with <Arg>Arg
continuable_base with <Args...>std::tuple<Args...>
Exceptions
wait_transform_canceled_exceptionif the awaited continuable_base is cancelled, and thus was resolved with a default constructed exception type.
+ +
+
+

+
+ template<typename Rep, typename Period> +
+ auto cti::transforms::wait_for(std::chrono::duration<Rep, Period> duration) +

+

Returns a transform that if applied to a continuable, it will start the continuation chain and returns the result synchronously. The current thread is blocked until the continuation chain is finished.

+ + + + + + + +
Returns

Returns a result that is available immediately. The signature of the future depends on the result type:

Continuation typeReturn type
continuable_base with <>result<>
continuable_base with <Arg>result<Arg>
continuable_base with <Args...>result<Args...>
+ +
+
+

+
+ template<typename Clock, typename Duration> +
+ auto cti::transforms::wait_until(std::chrono::time_point<Clock, Duration> time_point) +

+

Returns a transform that if applied to a continuable, it will start the continuation chain and returns the result synchronously. The current thread is blocked until the continuation chain is finished.

+ + + + + + + +
Returns

Returns a result that is available immediately. The signature of the future depends on the result type:

Continuation typeReturn type
continuable_base with <>result<>
continuable_base with <Arg>result<Arg>
continuable_base with <Args...>result<Args...>
+ +
+
+
+
+
+
+ + + + + + diff --git a/namespaces.html b/namespaces.html new file mode 100644 index 0000000..b6fab3e --- /dev/null +++ b/namespaces.html @@ -0,0 +1,194 @@ + + + + + + + Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

Namespaces

+ + +
+
+
+
+ + + + + + diff --git a/pages.html b/pages.html new file mode 100644 index 0000000..dc7eb05 --- /dev/null +++ b/pages.html @@ -0,0 +1,203 @@ + + + + + + + Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

Pages

+ + +
+
+
+
+ + + + + + diff --git a/search.js b/search.js new file mode 100644 index 0000000..13fc322 --- /dev/null +++ b/search.js @@ -0,0 +1,786 @@ +/* + This file is part of m.css. + + Copyright © 2017, 2018, 2019 Vladimír VondruÅ¡ + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +"use strict"; /* it summons the Cthulhu in a proper way, they say */ + +var Search = { + trie: null, + map: null, + dataSize: 0, + symbolCount: 0, + maxResults: 0, + + /* Always contains at least the root node offset and then one node offset + per entered character */ + searchString: '', + searchStack: [], + + /* So items don't get selected right away when a cursor is over results but + only after mouse moves */ + mouseMovedSinceLastRender: false, + + /* Whether we can go back in history in order to hide the search box or + not. We can't do that if we arrived directly on #search from outside. */ + canGoBackToHideSearch: false, + + /* Autocompletion in the input field is whitelisted only for character + input (so not deletion, cut, or anything else). This is flipped in the + onkeypress event and reset after each oninput event. */ + autocompleteNextInputEvent: false, + + init: function(buffer, maxResults) { + let view = new DataView(buffer); + + /* The file is too short to contain at least the headers */ + if(view.byteLength < 20) { + console.error("Search data too short"); + return false; + } + + if(view.getUint8(0) != 'M'.charCodeAt(0) || + view.getUint8(1) != 'C'.charCodeAt(0) || + view.getUint8(2) != 'S'.charCodeAt(0)) { + console.error("Invalid search data signature"); + return false; + } + + if(view.getUint8(3) != 0) { + console.error("Invalid search data version"); + return false; + } + + /* Separate the data into the trie and the result map */ + let mapOffset = view.getUint32(6, true); + this.trie = new DataView(buffer, 10, mapOffset - 10); + this.map = new DataView(buffer, mapOffset); + + /* Set initial properties */ + this.dataSize = buffer.byteLength; + this.symbolCount = view.getUint16(4, true); + this.maxResults = maxResults ? maxResults : 100; + this.searchString = ''; + this.searchStack = [this.trie.getUint32(0, true)]; + + /* istanbul ignore if */ + if(typeof document !== 'undefined') { + document.getElementById('search-symbolcount').innerHTML = + this.symbolCount + " symbols (" + Math.round(this.dataSize/102.4)/10 + " kB)"; + document.getElementById('search-input').disabled = false; + document.getElementById('search-input').placeholder = "Type something here …"; + document.getElementById('search-input').focus(); + + /* Search for the input value (there might be something already, + for example when going back in the browser) */ + let value = document.getElementById('search-input').value; + + /* Otherwise check the GET parameters for `q` and fill the input + with that */ + if(!value.length) { + var args = decodeURIComponent(window.location.search.substr(1)).trim().split('&'); + for(var i = 0; i != args.length; ++i) { + if(args[i].substring(0, 2) != 'q=') continue; + + value = document.getElementById('search-input').value = args[i].substring(2); + break; + } + } + + if(value.length) Search.searchAndRender(value); + } + + return true; + }, + + download: /* istanbul ignore next */ function(url) { + var req = window.XDomainRequest ? new XDomainRequest() : new XMLHttpRequest(); + if(!req) return; + + req.open("GET", url, true); + req.responseType = 'arraybuffer'; + req.onreadystatechange = function() { + if(req.readyState != 4) return; + + Search.init(req.response); + } + req.send(); + }, + + base85decode: function(base85string) { + function charValue(char) { + if(char >= 48 && char < 58) /* 0-9 -> 0-9 */ + return char - 48 + 0; + if(char >= 65 && char < 91) /* A-Z -> 10-35 */ + return char - 65 + 10; + if(char >= 97 && char < 123) /* a-z -> 36-61 */ + return char - 97 + 36; + if(char == 33) /* ! -> 62 */ + return 62; + /* skipping 34 (') */ + if(char >= 35 && char < 39) /* #-& -> 63-66 */ + return char - 35 + 63; + /* skipping 39 (") */ + if(char >= 40 && char < 44) /* (-+ -> 67-70 */ + return char - 40 + 67; + /* skipping 44 (,) */ + if(char == 45) /* - -> 71 */ + return 71; + if(char >= 59 && char < 65) /* ;-@ -> 72-77 */ + return char - 59 + 72; + if(char >= 94 && char < 97) /* ^-` -> 78-80 */ + return char - 94 + 78; + if(char >= 123 && char < 127) /* {-~ -> 81-84 */ + return char - 123 + 81; + + return 0; /* Interpret padding values as zeros */ + } + + /* Pad the string for easier decode later. We don't read past the file + end, so it doesn't matter what garbage is there. */ + if(base85string.length % 5) { + console.log("Expected properly padded base85 data"); + return; + } + + let buffer = new ArrayBuffer(base85string.length*4/5); + let data8 = new DataView(buffer); + for(let i = 0; i < base85string.length; i += 5) { + let char1 = charValue(base85string.charCodeAt(i + 0)); + let char2 = charValue(base85string.charCodeAt(i + 1)); + let char3 = charValue(base85string.charCodeAt(i + 2)); + let char4 = charValue(base85string.charCodeAt(i + 3)); + let char5 = charValue(base85string.charCodeAt(i + 4)); + + data8.setUint32(i*4/5, char5 + + char4*85 + + char3*85*85 + + char2*85*85*85 + + char1*85*85*85*85, false); /* BE, yes */ + } + + return buffer; + }, + + load: function(base85string) { + return this.init(this.base85decode(base85string)); + }, + + /* http://ecmanaut.blogspot.com/2006/07/encoding-decoding-utf8-in-javascript.html */ + toUtf8: function(string) { return unescape(encodeURIComponent(string)); }, + fromUtf8: function(string) { return decodeURIComponent(escape(string)); }, + + autocompletedCharsToString: function(chars) { + /* Strip incomplete UTF-8 chars from the autocompletion end */ + for(let i = chars.length - 1; i >= 0; --i) { + let c = chars[i]; + + /* We're safe, finish */ + if( + /* ASCII value at the end */ + (c < 128 && i + 1 == chars.length) || + + /* Full two-byte character at the end */ + ((c & 0xe0) == 0xc0 && i + 2 == chars.length) || + + /* Full three-byte character at the end */ + ((c & 0xf0) == 0xe0 && i + 3 == chars.length) || + + /* Full four-byte character at the end */ + ((c & 0xf8) == 0xf0 && i + 4 == chars.length) + ) break; + + /* Continuing UTF-8 character, go further back */ + if((c & 0xc0) == 0x80) continue; + + /* Otherwise the character is not complete, drop it from the end */ + chars.length = i; + break; + } + + /* Convert the autocompleted UTF-8 sequence to a string */ + let suggestedTabAutocompletionString = ''; + for(let i = 0; i != chars.length; ++i) + suggestedTabAutocompletionString += String.fromCharCode(chars[i]); + return this.fromUtf8(suggestedTabAutocompletionString); + }, + + /* Returns the values in UTF-8, but input is in whatever shitty 16bit + encoding JS has */ + search: function(searchString) { + /* Normalize the search string first, convert to UTF-8 */ + searchString = this.toUtf8(searchString.toLowerCase().trim()); + + /* TODO: maybe i could make use of InputEvent.data and others here */ + + /* Find longest common prefix of previous and current value so we don't + need to needlessly search again */ + let max = Math.min(searchString.length, this.searchString.length); + let commonPrefix = 0; + for(; commonPrefix != max; ++commonPrefix) + if(searchString[commonPrefix] != this.searchString[commonPrefix]) break; + + /* Drop items off the stack if it has has more than is needed for the + common prefix (it needs to have at least one item, though) */ + if(commonPrefix + 1 < this.searchStack.length) + this.searchStack.splice(commonPrefix + 1, this.searchStack.length - commonPrefix - 1); + + /* Add new characters from the search string */ + let foundPrefix = commonPrefix; + for(; foundPrefix != searchString.length; ++foundPrefix) { + /* Calculate offset and count of children */ + let offset = this.searchStack[this.searchStack.length - 1]; + let relChildOffset = 2 + this.trie.getUint8(offset)*2; + let childCount = this.trie.getUint8(offset + 1); + + /* Go through all children and find the next offset */ + let childOffset = offset + relChildOffset; + let found = false; + for(let j = 0; j != childCount; ++j) { + if(String.fromCharCode(this.trie.getUint8(childOffset + j*4 + 3)) != searchString[foundPrefix]) + continue; + + this.searchStack.push(this.trie.getUint32(childOffset + j*4, true) & 0x007fffff); + found = true; + break; + } + + /* Character not found, exit */ + if(!found) break; + } + + /* Save the whole found prefix for next time */ + this.searchString = searchString.substr(0, foundPrefix); + + /* If the whole thing was not found, return an empty result and offer + external search */ + if(foundPrefix != searchString.length) { + /* istanbul ignore if */ + if(typeof document !== 'undefined') { + let link = document.getElementById('search-external'); + if(link) + link.href = link.dataset.searchEngine.replace('{query}', encodeURIComponent(searchString)); + } + return [[], '']; + } + + /* Otherwise gather the results */ + let suggestedTabAutocompletionChars = []; + let results = []; + let leaves = [[this.searchStack[this.searchStack.length - 1], 0]]; + while(leaves.length) { + /* Pop offset from the queue */ + let current = leaves.shift(); + let offset = current[0]; + let suffixLength = current[1]; + + /* Populate the results with all values associated with this node */ + let resultCount = this.trie.getUint8(offset); + for(let i = 0; i != resultCount; ++i) { + let index = this.trie.getUint16(offset + (i + 1)*2, true); + results.push(this.gatherResult(index, suffixLength, 0xffffff)); /* should be enough haha */ + + /* 'nuff said. */ + if(results.length >= this.maxResults) + return [results, this.autocompletedCharsToString(suggestedTabAutocompletionChars)]; + } + + /* Dig deeper */ + /* TODO: hmmm. this is helluvalot duplicated code. hmm. */ + let relChildOffset = 2 + this.trie.getUint8(offset)*2; + let childCount = this.trie.getUint8(offset + 1); + let childOffset = offset + relChildOffset; + for(let j = 0; j != childCount; ++j) { + let offsetBarrier = this.trie.getUint32(childOffset + j*4, true); + + /* Lookahead barrier, don't dig deeper */ + if(offsetBarrier & 0x00800000) continue; + + /* Append to the queue */ + leaves.push([offsetBarrier & 0x007fffff, suffixLength + 1]); + + /* We don't have anything yet and this is the only path + forward, add the char to suggested Tab autocompletion. Can't + extract it from the leftmost 8 bits of offsetBarrier because + that would make it negative, have to load as Uint8 instead. + Also can't use String.fromCharCode(), because later doing + str.charCodeAt() would give me back UTF-16 values, which is + absolutely unwanted when all I want is check for truncated + UTF-8. */ + if(!results.length && leaves.length == 1 && childCount == 1) + suggestedTabAutocompletionChars.push(this.trie.getUint8(childOffset + j*4 + 3)); + } + } + + return [results, this.autocompletedCharsToString(suggestedTabAutocompletionChars)]; + }, + + gatherResult: function(index, suffixLength, maxUrlPrefix) { + let flags = this.map.getUint8(index*4 + 3); + let resultOffset = this.map.getUint32(index*4, true) & 0x00ffffff; + + /* The result is an alias, parse the aliased prefix */ + let aliasedIndex = null; + if((flags & 0xf0) == 0x00) { + aliasedIndex = this.map.getUint16(resultOffset, true); + resultOffset += 2; + } + + /* The result has a prefix, parse that first, recursively */ + let name = ''; + let url = ''; + if(flags & (1 << 3)) { + let prefixIndex = this.map.getUint16(resultOffset, true); + let prefixUrlPrefixLength = Math.min(this.map.getUint8(resultOffset + 2), maxUrlPrefix); + + let prefix = this.gatherResult(prefixIndex, 0 /*ignored*/, prefixUrlPrefixLength); + name = prefix.name; + url = prefix.url; + + resultOffset += 3; + } + + /* The result has a suffix, extract its length */ + let resultSuffixLength = 0; + if(flags & (1 << 0)) { + resultSuffixLength = this.map.getUint8(resultOffset); + ++resultOffset; + } + + let nextResultOffset = this.map.getUint32((index + 1)*4, true) & 0x00ffffff; + + /* Extract name */ + let j = resultOffset; + for(; j != nextResultOffset; ++j) { + let c = this.map.getUint8(j); + + /* End of null-delimited name */ + if(!c) { + ++j; + break; /* null-delimited */ + } + + name += String.fromCharCode(c); /* eheh. IS THIS FAST?! */ + } + + /* The result is an alias and we're not deep inside resolving a prefix, + extract the aliased name and URL */ + /* TODO: this abuses 0xffffff to guess how the call stack is deep and + that's just wrong, fix! */ + if(aliasedIndex != null && maxUrlPrefix == 0xffffff) { + let alias = this.gatherResult(aliasedIndex, 0 /* ignored */, 0xffffff); /* should be enough haha */ + url = alias.url; + flags = alias.flags; + + /* Keeping in UTF-8, as we need that for proper slicing (and concatenating) */ + return {name: name, + alias: alias.name, + url: alias.url, + flags: alias.flags, + suffixLength: suffixLength + resultSuffixLength}; + } + + /* Otherwise extract URL from here */ + let max = Math.min(j + maxUrlPrefix - url.length, nextResultOffset); + for(; j != max; ++j) { + url += String.fromCharCode(this.map.getUint8(j)); + } + + /* Keeping in UTF-8, as we need that for proper slicing (and concatenating) */ + return {name: name, + url: url, + flags: flags, + suffixLength: suffixLength + resultSuffixLength}; + }, + + escape: function(name) { + return name.replace(/[\"&<>]/g, function (a) { + return { '"': '"', '&': '&', '<': '<', '>': '>' }[a]; + }); + }, + escapeForRtl: function(name) { + /* Besides the obvious escaping of HTML entities we also need + to escape punctuation, because due to the RTL hack to cut + text off on left side the punctuation characters get + reordered (of course). Prepending ‎ works for most + characters, parentheses we need to *soak* in it. But only + the right ones. And that for some reason needs to be also for &. + Huh. https://en.wikipedia.org/wiki/Right-to-left_mark */ + return this.escape(name).replace(/[:=]/g, '‎$&').replace(/(\)|>|&|\/)/g, '‎$&‎'); + }, + + renderResults: /* istanbul ignore next */ function(value, resultsSuggestedTabAutocompletion) { + /* Normalize the value and encode as UTF-8 so the slicing works + properly */ + value = this.toUtf8(value.trim()); + + if(!value.length) { + document.getElementById('search-help').style.display = 'block'; + document.getElementById('search-results').style.display = 'none'; + document.getElementById('search-notfound').style.display = 'none'; + return; + } + + document.getElementById('search-help').style.display = 'none'; + + /* Results found */ + if(resultsSuggestedTabAutocompletion[0].length) { + let results = resultsSuggestedTabAutocompletion[0]; + + document.getElementById('search-results').style.display = 'block'; + document.getElementById('search-notfound').style.display = 'none'; + + let list = ''; + for(let i = 0; i != results.length; ++i) { + let type = ''; + let color = ''; + switch(results[i].flags >> 4) { + /* Keep in sync with dox2html5.py */ + case 1: + type = 'page'; + color = 'm-success'; + break; + case 2: + type = 'namespace'; + color = 'm-primary'; + break; + case 3: + type = 'group'; + color = 'm-success'; + break; + case 4: + type = 'class'; + color = 'm-primary'; + break; + case 5: + type = 'struct'; + color = 'm-primary'; + break; + case 6: + type = 'union'; + color = 'm-primary'; + break; + case 7: + type = 'typedef'; + color = 'm-primary'; + break; + case 8: + type = 'dir'; + color = 'm-warning'; + break; + case 9: + type = 'file'; + color = 'm-warning'; + break; + case 10: + type = 'func'; + color = 'm-info'; + break; + case 11: + type = 'define'; + color = 'm-info'; + break; + case 12: + type = 'enum'; + color = 'm-primary'; + break; + case 13: + type = 'enum val'; + color = 'm-default'; + break; + case 14: + type = 'var'; + color = 'm-default'; + break; + } + + /* Labels + */ + list += '
' + type + '
' + (results[i].flags & 2 ? '
deprecated
' : '') + (results[i].flags & 4 ? '
deleted
' : ''); + + /* Render the alias (cut off from the right) */ + if(results[i].alias) { + list += '
' + this.escape(results[i].name.substr(0, results[i].name.length - value.length - results[i].suffixLength)) + '' + this.escape(results[i].name.substr(results[i].name.length - value.length - results[i].suffixLength, value.length)) + '' + this.escapeForRtl(results[i].name.substr(results[i].name.length - results[i].suffixLength)) + ': ' + this.escape(results[i].alias) + ''; + + /* Render the normal thing (cut off from the left, have to + escape for RTL) */ + } else { + list += '
' + this.escapeForRtl(results[i].name.substr(0, results[i].name.length - value.length - results[i].suffixLength)) + '' + this.escapeForRtl(results[i].name.substr(results[i].name.length - value.length - results[i].suffixLength, value.length)) + '' + this.escapeForRtl(results[i].name.substr(results[i].name.length - results[i].suffixLength)); + } + + /* The closing */ + list += '
'; + } + document.getElementById('search-results').innerHTML = this.fromUtf8(list); + document.getElementById('search-current').scrollIntoView(true); + + /* Append the suggested tab autocompletion, if any, and if the user + didn't just delete it */ + let searchInput = document.getElementById('search-input'); + if(this.autocompleteNextInputEvent && resultsSuggestedTabAutocompletion[1].length && searchInput.selectionEnd == searchInput.value.length) { + let suggestedTabAutocompletion = this.fromUtf8(resultsSuggestedTabAutocompletion[1]); + + let lengthBefore = searchInput.value.length; + searchInput.value += suggestedTabAutocompletion; + searchInput.setSelectionRange(lengthBefore, searchInput.value.length); + } + + /* Nothing found */ + } else { + document.getElementById('search-results').innerHTML = ''; + document.getElementById('search-results').style.display = 'none'; + document.getElementById('search-notfound').style.display = 'block'; + } + + /* Don't allow things to be selected just by motionless mouse cursor + suddenly appearing over a search result */ + this.mouseMovedSinceLastRender = false; + + /* Reset autocompletion, if it was allowed. It'll get whitelisted next + time a character gets inserted. */ + this.autocompleteNextInputEvent = false; + }, + + searchAndRender: /* istanbul ignore next */ function(value) { + let prev = performance.now(); + let results = this.search(value); + let after = performance.now(); + this.renderResults(value, results); + if(value.trim().length) { + document.getElementById('search-symbolcount').innerHTML = + results[0].length + (results.length >= this.maxResults ? '+' : '') + " results (" + Math.round((after - prev)*10)/10 + " ms)"; + } else + document.getElementById('search-symbolcount').innerHTML = + this.symbolCount + " symbols (" + Math.round(this.dataSize/102.4)/10 + " kB)"; + }, +}; + +/* istanbul ignore next */ +function selectResult(event) { + if(!Search.mouseMovedSinceLastRender) return; + + if(event.currentTarget.parentNode.id == 'search-current') return; + + let current = document.getElementById('search-current'); + current.removeAttribute('id'); + event.currentTarget.parentNode.id = 'search-current'; +} + +/* This is separated from showSearch() because we need non-destructive behavior + when appearing directly on a URL with #search */ /* istanbul ignore next */ +function updateForSearchVisible() { + /* Prevent accidental scrolling of the body, prevent page layout jumps */ + let scrolledBodyWidth = document.body.offsetWidth; + document.body.style.overflow = 'hidden'; + document.body.style.paddingRight = (document.body.offsetWidth - scrolledBodyWidth) + 'px'; + + document.getElementById('search-input').value = ''; + document.getElementById('search-input').focus(); + document.getElementById('search-results').style.display = 'none'; + document.getElementById('search-notfound').style.display = 'none'; + document.getElementById('search-help').style.display = 'block'; +} + +/* istanbul ignore next */ +function showSearch() { + window.location.hash = '#search'; + Search.canGoBackToHideSearch = true; + + updateForSearchVisible(); + return false; +} + +/* istanbul ignore next */ +function hideSearch() { + /* If the search box was opened using showSearch(), we can go back in the + history. Otherwise (for example when we landed to #search from a + bookmark or another server), going back would not do the right thing and + in that case we simply replace the current history state. */ + if(Search.canGoBackToHideSearch) { + Search.canGoBackToHideSearch = false; + window.history.back(); + } else { + window.location.hash = '#!'; + window.history.replaceState('', '', window.location.pathname); + } + + /* Restore scrollbar, prevent page layout jumps */ + document.body.style.overflow = 'auto'; + document.body.style.paddingRight = '0'; + + return false; +} + +/* istanbul ignore next */ +function copyToKeyboard(text) { + /* Append to the popup, appending to document.body would cause it to + scroll when focused */ + let searchPopup = document.getElementsByClassName('m-dox-search')[0]; + let textarea = document.createElement("textarea"); + textarea.value = text; + searchPopup.appendChild(textarea); + textarea.focus(); + textarea.select(); + + document.execCommand('copy'); + + searchPopup.removeChild(textarea); + document.getElementById('search-input').focus(); +} + +/* Only in case we're running in a browser. Why a simple if(document) doesn't + work is beyond me. */ /* istanbul ignore if */ +if(typeof document !== 'undefined') { + document.getElementById('search-input').oninput = function(event) { + Search.searchAndRender(document.getElementById('search-input').value); + }; + + document.onkeydown = function(event) { + /* Search shown */ + if(window.location.hash == '#search') { + /* Close the search */ + if(event.key == 'Escape') { + hideSearch(); + + /* Focus the search input, if not already, using T or Tab */ + } else if((!document.activeElement || document.activeElement.id != 'search-input') && (event.key.toLowerCase() == 't' || event.key == 'Tab') && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey) { + document.getElementById('search-input').focus(); + return false; /* so T doesn't get entered into the box */ + + /* Fill in the autocompleted selection */ + } else if(event.key == 'Tab' && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey) { + /* But only if the input has selection at the end */ + let input = document.getElementById('search-input'); + if(input.selectionEnd == input.value.length && input.selectionStart != input.selectionEnd) + input.setSelectionRange(input.value.length, input.value.length); + + /* Select next item */ + } else if(event.key == 'ArrowDown') { + let current = document.getElementById('search-current'); + if(current) { + let next = current.nextSibling; + if(next) { + current.id = ''; + next.id = 'search-current'; + next.scrollIntoView(false); + } + } + return false; /* so the keypress doesn't affect input cursor */ + + /* Select prev item */ + } else if(event.key == 'ArrowUp') { + let current = document.getElementById('search-current'); + if(current) { + let prev = current.previousSibling; + if(prev) { + current.id = ''; + prev.id = 'search-current'; + prev.scrollIntoView(false); + } + } + return false; /* so the keypress doesn't affect input cursor */ + + /* Go to result (if any) */ + } else if(event.key == 'Enter') { + let result = document.getElementById('search-current'); + if(result) { + result.firstElementChild.click(); + + /* We might be staying on the same page, so restore scrollbar, + and prevent page layout jumps */ + document.body.style.overflow = 'auto'; + document.body.style.paddingRight = '0'; + } + + return false; /* so the form doesn't get sent */ + + /* Copy (Markdown) link to keyboard */ + } else if((event.key.toLowerCase() == 'l' || event.key.toLowerCase() == 'm') && event.metaKey) { + let result = document.getElementById('search-current'); + if(result) { + let plain = event.key.toLowerCase() == 'l'; + let link = plain ? result.firstElementChild.href : + '[' + result.firstElementChild.dataset.mdLinkTitle + '](' + result.firstElementChild.href + ')'; + + copyToKeyboard(link); + + /* Add CSS class to the element for visual feedback (this + will get removed on keyup), but only if it's not already + there (in case of key repeat, e.g.) */ + if(result.className.indexOf('m-dox-search-copied') == -1) + result.className += ' m-dox-search-copied'; + console.log("Copied " + (plain ? "link" : "Markdown link") + " to " + result.firstElementChild.dataset.mdLinkTitle); + } + + return false; /* so L doesn't get entered into the box */ + + /* Looks like the user is inserting some text (and not cutting, + copying or whatever), allow autocompletion for the new + character. The oninput event resets this back to false, so this + basically whitelists only keyboard input, including Shift-key + and special chars using right Alt (or equivalent on Mac), but + excluding Ctrl-key, which is usually not for text input. In the + worst case the autocompletion won't be allowed ever, which is + much more acceptable behavior than having no ability to disable + it and annoying the users. See also this WONTFIX Android bug: + https://bugs.chromium.org/p/chromium/issues/detail?id=118639 */ + } else if(event.key != 'Backspace' && event.key != 'Delete' && !event.metaKey && (!event.ctrlKey || event.altKey)) { + Search.autocompleteNextInputEvent = true; + /* Otherwise reset the flag, because when the user would press e.g. + the 'a' key and then e.g. ArrowRight (which doesn't trigger + oninput), a Backspace after would still result in + autocompleteNextInputEvent, because nothing reset it back. */ + } else { + Search.autocompleteNextInputEvent = false; + } + + /* Search hidden */ + } else { + /* Open the search on the T or Tab key */ + if((event.key.toLowerCase() == 't' || event.key == 'Tab') && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey) { + showSearch(); + return false; /* so T doesn't get entered into the box */ + } + } + }; + + document.onkeyup = function(event) { + /* Remove highlight after key is released after a link copy */ + if((event.key.toLowerCase() == 'l' || event.key.toLowerCase() == 'm') && event.metaKey) { + let result = document.getElementById('search-current'); + if(result) result.className = result.className.replace(' m-dox-search-copied', ''); + } + }; + + /* Allow selecting items by mouse hover only after it moves once the + results are populated. This prevents a random item getting selected if + the cursor is left motionless over the result area. */ + document.getElementById('search-results').onmousemove = function() { + Search.mouseMovedSinceLastRender = true; + }; + + /* If #search is already present in the URL, hide the scrollbar etc. for a + consistent experience */ + if(window.location.hash == '#search') updateForSearchVisible(); +} + +/* For Node.js testing */ /* istanbul ignore else */ +if(typeof module !== 'undefined') { module.exports = { Search: Search }; } diff --git a/searchdata.js b/searchdata.js new file mode 100644 index 0000000..0010056 --- /dev/null +++ b/searchdata.js @@ -0,0 +1,2 @@ +/* Generated by https://mcss.mosra.cz/doxygen/. Do not edit. */ +Search.load('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'); diff --git a/structcti_1_1cancellation__result.html b/structcti_1_1cancellation__result.html new file mode 100644 index 0000000..e38b041 --- /dev/null +++ b/structcti_1_1cancellation__result.html @@ -0,0 +1,174 @@ + + + + + + + cti::cancellation_result struct | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ cti::cancellation_result struct +

+

A class which is convertible to any result and that definitely holds a default constructed exception which signals the cancellation of the asynchronous control flow.

+ +
+
+
+
+ + + + + + diff --git a/structcti_1_1empty__result.html b/structcti_1_1empty__result.html new file mode 100644 index 0000000..a46ed64 --- /dev/null +++ b/structcti_1_1empty__result.html @@ -0,0 +1,174 @@ + + + + + + + cti::empty_result struct | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ cti::empty_result struct +

+

A class which is convertible to any result and that definitely holds no value so the real result gets invalidated when this object is passed to it.

+ +
+
+
+
+ + + + + + diff --git a/structcti_1_1exception__arg__t.html b/structcti_1_1exception__arg__t.html new file mode 100644 index 0000000..952e977 --- /dev/null +++ b/structcti_1_1exception__arg__t.html @@ -0,0 +1,174 @@ + + + + + + + cti::exception_arg_t struct | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ cti::exception_arg_t struct +

+

Represents the tag type that is used to disambiguate the callback operator() in order to take the exception asynchronous chain.

+ +
+
+
+
+ + + + + + diff --git a/structcti_1_1is__ready__arg__t.html b/structcti_1_1is__ready__arg__t.html new file mode 100644 index 0000000..148322c --- /dev/null +++ b/structcti_1_1is__ready__arg__t.html @@ -0,0 +1,174 @@ + + + + + + + cti::is_ready_arg_t struct | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ cti::is_ready_arg_t struct +

+

Represents the tag type that is used to query the continuation for whether it resolves the callback instantly with its arguments without having side effects.

+ +
+
+
+
+ + + + + + diff --git a/structcti_1_1unpack__arg__t.html b/structcti_1_1unpack__arg__t.html new file mode 100644 index 0000000..de8107f --- /dev/null +++ b/structcti_1_1unpack__arg__t.html @@ -0,0 +1,174 @@ + + + + + + + cti::unpack_arg_t struct | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ cti::unpack_arg_t struct +

+

Represents the tag type that is used to unpack the result of a continuation.

+ +
+
+
+
+ + + + + + diff --git a/structcti_1_1use__continuable__t.html b/structcti_1_1use__continuable__t.html new file mode 100644 index 0000000..9052427 --- /dev/null +++ b/structcti_1_1use__continuable__t.html @@ -0,0 +1,207 @@ + + + + + + + cti::use_continuable_t struct | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+
template<typename Mapper = detail::asio::map_default>
+ cti::use_continuable_t struct +

+

Type used as an ASIO completion token to specify an asynchronous operation that should return a continuable_base.

+ + + + + + + + + + +
Template parameters
Mapper

The token can be instantiated with a custom mapper for asio error codes which makes it possible to ignore errors or treat them as cancellation types. The mapper has the following form:

struct my_mapper {
+  constexpr my_mapper() noexcept {}
+
+  /// Returns true when the error_code_t is a type which represents
+  /// cancellation and
+  bool is_cancellation(error_code_t const& /*ec*/) const noexcept {
+    return false;
+  }
+  bool is_ignored(error_code_t const& /*ec*/) const noexcept {
+    return false;
+  }
+};
+
  • Boost 1.70 or asio 1.13.0 is required for the async initiation
  • Until boost 1.72 or asio 1.16.0 overhead through an additional type erasure is added. It is recommended to update to those versions.

The special static variable use_continuable can be appended to any (boost) asio function that accepts a callback to make it return a continuable_base.

#include <continuable/continuable.hpp>
+#include <continuable/external/asio.hpp>
+#include <asio.hpp>
+
+// ...
+
+asio::tcp::resolver resolver(...);
+resolver.async_resolve("127.0.0.1", "daytime", cti::use_continuable)
+  .then([](asio::udp::resolver::iterator iterator) {
+    // ...
+  });
+
+
+
+
+ + + + + + diff --git a/terminal.css b/terminal.css new file mode 100644 index 0000000..a11b645 --- /dev/null +++ b/terminal.css @@ -0,0 +1,85 @@ +.terminal { + box-shadow: rgba(0, 0, 0, 0.8) 0px 20px 70px; + box-sizing: border-box; + max-width: 550px; + height: 210px; + margin: 0 auto; + background-color: #272a3aa6; +} + +.terminal > .fakeMenu { + box-sizing: border-box; + height: 25px; + background-color: #1b1e2d; + margin: 0 auto; + border-top-right-radius: 5px; + border-top-left-radius: 5px; + font-family: initial; +} + +.terminal > .fakeMenu > .fakeButtons { + height: 10px; + width: 10px; + border-radius: 50%; + border: 1px solid #000; + position: relative; + top: 6px; + left: 6px; + background-color: #ff3b47; + border-color: #9d252b; + display: inline-block; +} + +.terminal > .fakeMenu > .fakeMinimize { + left: 11px; + background-color: #ffc100; + border-color: #9d802c; +} + +.terminal > .fakeMenu > .fakeZoom { + left: 16px; + background-color: #00d742; + border-color: #049931; +} + +.terminal > .fakeScreen { + box-sizing: border-box; + margin: 0 auto; + padding: 10px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; +} + +.terminal > .fakeScreen > pre { + background-color: initial; + margin: initial; + padding: initial; + overflow-x: initial; +} + +.terminal > .fakeScreen > pre > code { + background: initial; + background-color: initial; + overflow: hidden; + margin: initial; + padding: initial; +} + +.terminal > .fakeScreen > p { + color: #9CD9F0; + position: relative; + left: 50%; + margin-left: -8.5em; + text-align: left; + font-size: 1.25em; + font-family: monospace; + white-space: normal; + overflow: hidden; +} + +.starbar { + max-width: 550px; + margin: 0 auto; + padding-top: 10px; + text-align: center; +} diff --git a/terminal.js b/terminal.js new file mode 100644 index 0000000..1833585 --- /dev/null +++ b/terminal.js @@ -0,0 +1,44 @@ +(function() { + var backend = '// Continuable for backend developers:\n(http_request("github.com/Naios") && http_request("atom.io"))\n .then([] (std::string github, std::string atom) {\n // ...\n return mysql_query("SELECT * FROM `users`");\n })\n .then([] (ResultSet result) {\n // ...\n }, executor->post());'; + var game = '// Continuable for game developers:\nme->WaitForPlayer()\n .then([&] (Player* player) {\n return me->MoveTo(player->GetPosition());\n })\n .then(me->Say("Hello friend!"))\n .then(me->Wait(3s)))\n .then(me->MoveTo(me->GetHomePosition()));'; + var adventurous = '// Continuable for the adventurous:\ntry {\n auto response = co_await http_request("github.com/Naios");\n} catch (std::exception const& e) {\n // ...\n}\nauto c = cti::make_ready_continuable(0, 1);\nauto [ first, second ] = co_await std::move(c);\nco_return first + second;'; + var coroutines = '// Continuable for mastering coroutines:\ncti::when_all(\n []() -> cti::continuable {\n co_return std::make_tuple(0, 1); // ...\n }(), []() -> cti::continuable {\n co_return std::make_tuple(2, 3); // ...\n }()).then([](int, int, int, int) {\n // ...\n });'; + + // Teach hljs some new keywords... + var cpp = hljs.getLanguage('cpp').exports.k; + cpp.built_in += + " http_request mysql_query then exception post make_continuable cti make_ready_continuable ResultSet move WaitForPlayer MoveTo Player GetPosition GetHomePosition Wait Say when_all continuable make_tuple"; + cpp.keyword += + " co_await co_return"; + cpp.literal += + " 3s"; + + hljs.configure({ + tabReplace: ' ', + // classPrefix: '', + languages: ['cpp'], + }); + + function highlight(code) { + return hljs.highlight('cpp', code, "", null).value; + }; + + var typed = new Typed('#typedterminal', { + strings: [ + highlight(backend), + highlight(game), + highlight(adventurous), + highlight(coroutines), + ], + typeSpeed: 6, + backSpeed: 4, + startDelay: 1100, + loop: true, + shuffle: true, + backDelay: 5500, + // smartBackspace: true, + // fadeOut: true, + // fadeOutClass: 'typed-fade-out', + // fadeOutDelay: 5500, + }); +})(); diff --git a/tutorial-awaiting-continuables.html b/tutorial-awaiting-continuables.html new file mode 100644 index 0000000..032a5d5 --- /dev/null +++ b/tutorial-awaiting-continuables.html @@ -0,0 +1,219 @@ + + + + + + + Tutorial » Awaiting continuables | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Tutorial » + + Awaiting continuables +

+ +

Explains how to use the continuable_base together with co_await.

+ +

Using co_await on continuables

Coroutines (co_await) are supported by continuables when the underlying toolchain supports the TS. Currently this works in MSVC 2017 and Clang 5.0.

It is possible to await for any continuable_base as shown below:

int i = co_await cti::make_continuable<int>([](auto&& promise) {
+  promise.set_value(0);
+});

As described in continuable_base::operator co_await() a continuable with multiple arguments as result will wrap its result into a std::tuple:

std::tuple<int, int> i = co_await cti::make_ready_continuable(0, 1);

Using co_await with exceptions

When a continuable_base was resolved through an exception the exception is rethrown from the co_await expression:

try {
+  auto response = co_await http_request("github.com");
+} catch(std::exception const& e) {
+  // Handle the exception
+}

Using co_await with disabled exceptions

In case the library is configured to use error codes or a custom error type the return type of the co_await expression is changed.

The result is returned through an internal proxy object which may be queried for the error object:

Continuation typeco_await returns
continuable_base with <>unspecified<void>
continuable_base with <Arg>unspecified<Arg>
continuable_base with <Args...>unspecified<std::tuple<Args...>>

The interface of the proxy object is similar to the one proposed in the std::expected proposal:

if (auto&& result = co_await http_request("github.com")) {
+  auto value = *result;
+} else {
+  cti::error_type error = result.get_exception();
+}
+
+auto result = co_await http_request("github.com");
+
+bool(result);
+result.is_value();
+result.is_exception();
+*result; // Same as result.get_value()
+result.get_value();
+result.get_exception();

Using continuables as return type from coroutines

It is possible to use a continuable_base as return type from coroutines.

cti::continuable<> resolve_async_void() {
+  co_await http_request("github.com");
+  // ...
+  co_return;
+}
+
+cti::continuable<int> resolve_async() {
+  co_await http_request("github.com");
+  // ...
+  co_return 0;
+}

Additionally it's possible to return multiple return values from coroutines by wrapping those in a tuple like type:

cti::continuable<int, int, int> resolve_async_multiple() {
+  co_await http_request("github.com");
+  // ...
+  co_return std::make_tuple(0, 1, 2);
+}
+
+
+
+
+ + + + + + diff --git a/tutorial-chaining-continuables.html b/tutorial-chaining-continuables.html new file mode 100644 index 0000000..c696ec9 --- /dev/null +++ b/tutorial-chaining-continuables.html @@ -0,0 +1,276 @@ + + + + + + + Tutorial » Chaining continuables | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Tutorial » + + Chaining continuables +

+ +

Explains how to chain multiple continuable_base objects together.

+ +

Using then and results

A continuable_base provides various methods to continue the asynchronous call hierarchy. The most important method therefor is continuable_base::then which changes the object through attaching a result handler:

http_request("github.com")
+  .then([] (std::string result) {
+    // Do something...
+  });

A new continuable_base is created which result depends on the return type of the handler. For instance it is possible to return plain values or the next continuable_base to continue the call hierarchy. See continuable_base::then for details.

mysql_query("SELECT `id`, `name` FROM `users`")
+  .then([](ResultSet users) {
+    // Return the next continuable to process ...
+    return mysql_query("SELECT `id` name FROM `sessions`");
+  })
+  .then([](ResultSet sessions) {
+    // ... or pass multiple values to the next callback using tuples or pairs ...
+    return std::make_tuple(std::move(sessions), true);
+  })
+  .then([](ResultSet sessions, bool is_ok) {
+    // ... or pass a single value to the next callback ...
+    return 10;
+  })
+  .then([](auto value) {
+    //     ^^^^ Templated callbacks are possible too
+  })
+  // ... you may even pass continuables to the `then` method directly:
+  .then(mysql_query("SELECT * FROM `statistics`"))
+  .then([](ResultSet result) {
+    // ...
+  });

Making use of partial argument application

Callbacks passed to then are only called with the amount of arguments that are accepted.

(http_request("github.com") && read_file("entries.csv"))
+  .then([] {
+    // ^^^^^^ The original signature was <std::string, Buffer>,
+    // however, the callback is only invoked with the amount of
+    // arguments it's accepting.
+  });

This makes it possible to attach a callback accepting nothing to every continuable_base.

Assigning a specific executor to then

Dispatching a callback through a specific executor is a common usage scenario and supported through the second argument of then:

auto executor = [](auto&& work) {
+  // Dispatch the work here, store it for later
+  // invocation or move it to another thread.
+  std::forward<decltype(work)>(work)();
+};
+
+read_file("entries.csv")
+  .then([](Buffer buffer) {
+    // ...
+  }, executor);
+//   ^^^^^^^^

The supplied work callable may be stored and moved for later usage on a possible different thread or execution context.

Using fail and exceptions

Asynchronous exceptions are supported too. Exceptions that were set through promise_base::set_exception are forwarded to the first available registered handler that was attached through continuable_base::fail :

http_request("github.com")
+  .then([] (std::string result) {
+    // Is never called if an error occurs
+  })
+  .fail([] (std::exception_ptr ptr) {
+    try {
+      std::rethrow_exception(ptr);
+    } catch(std::exception const& e) {
+      // Handle the exception or error code here
+    }
+  });

Multiple handlers are allowed to be registered, however the asynchronous call hierarchy is aborted after the first called fail handler and only the closest handler below is called.

Continuable also supports error codes automatically if exceptions are disabled. Additionally it is possible to specify a custom error type through defining.

http_request("github.com")
+  .then([] (std::string result) {
+    // Is never called if an error occurs
+  })
+  .fail([] (std::error_condition error) {
+    error.value();
+    error.category();
+  });

The error_type will be std::exception_ptr except if any of the following definitions is defined:

  • CONTINUABLE_WITH_NO_EXCEPTIONS: Define this to use std::error_condition as error_type and to disable exception support. When exceptions are disabled this definition is set automatically.
  • CONTINUABLE_WITH_CUSTOM_ERROR_TYPE: Define this to use a user defined error type.

Using next to handle all paths

Sometimes it's required to provide a continuation and error handler from the same object. In order to avoid overloading conflicts there is the special method continuable_base::next provided. The exception path overload is marked through the dispatch_error_tag :

struct handle_all_paths {
+  void operator() (std::string result) {
+    // ...
+  }
+  void operator() (cti::dispatch_error_tag, cti::error_type) {
+    // ...
+  }
+};
+
+// ...
+
+http_request("github.com")
+  .next(handle_all_paths{});
+
+
+
+
+ + + + + + diff --git a/tutorial-connecting-continuables.html b/tutorial-connecting-continuables.html new file mode 100644 index 0000000..e6ddf91 --- /dev/null +++ b/tutorial-connecting-continuables.html @@ -0,0 +1,256 @@ + + + + + + + Tutorial » Connecting continuables | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Tutorial » + + Connecting continuables +

+ +

Explains how to connect various continuable_base objects together.

+ +

Connections and strategies

Connections make it possible to describe the dependencies between an arbitrary count of continuable_base objects in order resolve a returned continuable_base as soon as the dependencies are fulfilled.

For each connection strategy continuable_base provides an operator for for instance continuable_base::operator && and a free function, when_all for example. Both work similar however the free functions are capable of working with nested sequences as described in Nested continuables and plain types.

Using aggregated strategies

Aggregated strategies will call the result handler with the compound result of all connected continuable_base objects.

The compound result is deduced as following. Every continuable_base maps its result to the result itself as shown below. When multiple continuable_base objects are connected on the same depth, the result is joined. See Nested continuables and plain types for details.

Continuation typeIn tuple likeIn container (std::vector)
continuable_base with <><none><none>
continuable_base with <Arg>ArgArg
continuable_base with <Args...>Args...std::tuple<Args...>

Using the all connection

The all strategy invokes all connected continuable at once, it tries to resolve the connected continuable_base objects as fast as possible. It is possible to connect multiple continuable_base objects together through the all strategy by using continuable_base::operator && or when_all. In contrast to the operator the free functions are capable of workin with plain types and deeply nested continuable_base objects as described in Nested continuables and plain types .

(http_request("github.com") && http_request("travis-ci.org") &&
+ http_request("atom.io"))
+  .then([](std::string github, std::string travis,
+           std::string atom) {
+    // The callback is called with the
+    // response of github, travis and atom.
+  });

Using the sequential connection

The sequential strategy invokes all connected continuable one after each other, it tries to resolve the next connected continuable_base objects as soon as the previous one was resolved. It is possible to connect multiple continuable_base objects together through the sequential strategy by using continuable_base::operator>> or when_seq.

(http_request("github.com") >> http_request("travis-ci.org") >>
+ http_request("atom.io"))
+  .then([](std::string github, std::string travis,
+           std::string atom) {
+    // The requests are invoked sequentially instead
+    // of requesting all at once.
+  });

Using the any connection

The any connection strategy is completely different from the two introduces before: It calls the result handler with the first result or exception available. All continuable_base objects are required to have the same types of arguments.

(http_request("github.com") || http_request("travis-ci.org") ||
+ http_request("atom.io"))
+  .then([](std::string github_or_travis_or_atom) {
+    // The callback is called with the first response
+    // of either github, travis or atom.
+  });

Mixing different strategies

Mixing different strategies through operators and free functions is natively supported as shown below:

(http_request("github.com") &&
+ (http_request("travis-ci.org") || http_request("atom.io")))
+    .then([](std::string github, std::string travis_or_atom) {
+      // The callback is called with the response of
+      // github for sure and the second parameter represents
+      // the response of travis or atom.
+    });

Nested continuables and plain types

For every operator that was shown above, there exists a free function that provides at least the same functionality:

cti::when_all(http_request("github.com"), http_request("travis-ci.org"));
+cti::when_any(http_request("github.com"), http_request("travis-ci.org"));
+cti::when_seq(http_request("github.com"), http_request("travis-ci.org"));

Additionally the free functions are capable of working with continuables deeply nested inside tuple like objects (std::tuple, std::pair and std::array) as well as homogeneous containers (std::vector, std::list etc.).

std::tuple<std::vector<cti::continuable<int>>> outstanding;
+// ...
+
+cti::when_all(std::make_tuple(std::move(outstanding),
+                              http_request("github.com")))
+      .then([](std::tuple<std::tuple<std::vector<int>>,
+                          std::string> result) {
+        // ...
+      });

Values which are given to such a free function are preserved and later passed to the result handler:

cti::when_seq(0, 1,
+              cti::make_ready_continuable(2, 3),
+              4, 5)
+      .then([](int r0, int r1, int r2,
+               int r3, int r4) {
+        // ...
+      });

When combining both capabilities it's even possible do something like this:

cti::when_all(
+    cti::make_ready_continuable(0, 1),
+    2, //< See this plain value
+    cti::populate(cti::make_ready_continuable(3),  // Creates a runtime
+                  cti::make_ready_continuable(4)), // sized container.
+    std::make_tuple(std::make_tuple(cti::make_ready_continuable(5))))
+      .then([](int r0, int r1, int r2, std::vector<int> r34,
+               std::tuple<std::tuple<int>> r5) {
+        // ...
+      });

Populating a container from arbitrary continuables

populate mainly helps to create a homogeneous container from a runtime known count of continuables which type isn't exactly known. All continuables which are passed to this function should be originating from the same source or a method called with the same types of arguments:

// cti::populate just creates a std::vector from the two continuables.
+auto v = cti::populate(cti::make_ready_continuable(0),
+                       cti::make_ready_continuable(1));
+
+for (int i = 2; i < 5; ++i) {
+  // It is possible to  add more continuables
+  // to the container afterwards
+  container.emplace_back(cti::make_ready_continuable(i));
+}
+
+cti::when_all(std::move(v))
+  .then([](std::vector<int> resolved) {
+    // ...
+  });
+
+
+
+
+ + + + + + diff --git a/tutorial-creating-continuables.html b/tutorial-creating-continuables.html new file mode 100644 index 0000000..5e7f555 --- /dev/null +++ b/tutorial-creating-continuables.html @@ -0,0 +1,206 @@ + + + + + + + Tutorial » Creating continuables | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Tutorial » + + Creating continuables +

+ +

Explains how to create a continuable_base.

+ +

A continuable is an arbitrary instantiation of a continuable_base, it represents the main class of the library and makes it possible to build up an asynchronous call hierarchy. When dealing with continuables we usually don't know its exact type for avoiding expensive type erasure.

The continuable_base is convertible to a continuable which represents a specified type of the continuable_base on the cost of a type erasure.

From a value or exception

The library provides make_ready_continuable which may be used to create a continuable_base from an arbitrary amount of values:

auto one = cti::make_ready_continuable(0);
+
+cti::continuable<int, float, char> three =
+  cti::make_ready_continuable(0, 1.f, '2');

Additionally a continuable_base which resolves with an exception may be created through make_exceptional_continuable.

cti::continuable<int> c = cti::make_exceptional_continuable(std::exception{});

From a promise taking callable

The main function for creating a continuable_base is make_continuable which must be invoked with the types of arguments it resolves to. It accepts a callable object which accepts an arbitrary object (the promise_base). The promise_base is created by the library and then passed to the given callback. This is in contrast to the usage of the standard std::promise which is created by the user.

The promise_base exposes methods to resolve it through result values or through an exception. Below we implement pseudo http_request function which resolves the request asynchronously trough a std::string.

auto http_request(std::string url) {
+  return cti::make_continuable<std::string>(
+    [url = std::move(url)](auto&& promise) {
+      // Resolve the promise upon completion of the task.
+      promise.set_value("<html> ... </html>");
+
+      // Or promise.set_exception(...);
+    });
+}

An alternative would be a continuable_base with a result of zero arguments:

auto wait_for(std::chrono::milliseconds duration) {
+  return cti::make_continuable<void>([](auto&& promise) {
+  //                           ^^^^
+
+  // Resolve the promise later when the duration is over
+  promise.set_value();
+});

A continuable_base may resolve with an arbitrary count of result values:

auto resolve_sth() {
+  return cti::make_continuable<int, int, float, char>(
+    [](auto&& promise) {
+      promise.set_value(0, 1, 2.f, '3');
+    });

A promise_base always exposes a call operator for resolving it as like when using promise_base::set_value or promise_base::set_exception. See promise_base for details.

The continuable invocation model

An asynchronous call hierarchy that is stored inside the continuable_base is executed when its result is requested (lazy evaluation) in contrast to other commonly used implementations such as std::future which execute the asynchronous call hierarchy instantly on creation (eager evaluation).

The lazy evaluation strategy used by continuables has many benefits over eager evaluation that is used by other common implementations:

  • prevention of side effects
  • evasion of race conditions
  • ensured deterministic behaviour.

The asynchronous call hierarchy is started when the continuable_base is destructed or the continuable_base::done method is called. It is possible to disable the automatic start through calling continuable_base::freeze on the corresponding continuable_base.

+
+
+
+
+ + + + + + diff --git a/tutorial-promisify-continuables.html b/tutorial-promisify-continuables.html new file mode 100644 index 0000000..e28a864 --- /dev/null +++ b/tutorial-promisify-continuables.html @@ -0,0 +1,204 @@ + + + + + + + Tutorial » Promisify functions | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Tutorial » + + Promisify functions +

+ +

Explains how to promisify callback taking functions into a continuable_base.

+ +

Promisification and continuables

The promisification has a longer history in the JavaScript world where the legacy way of asynchronous programming was the usage of callbacks of the form function(error, result...). The ideal way of dealing with such an asynchronous result is to return a promise and soon utility helpers were provided to do so.

The usage of callbacks to represent an asynchronous result is still a popular way nowadays. Thus the library provides the promisify helper class which makes it possible to convert callback taking functions of various styles into one that returns a continuable_base instead.

Promisify boost::asio

The default callback style is something like function(error, result...) as described above. Continuable offers the promisify::from method for such callback styles.

See an example of how to promisify boost asio's async_resolve below:

auto async_resolve(std::string host, std::string service) {
+  return cti::promisify<asio::ip::udp::resolver::iterator>::from(
+      [&](auto&&... args) {
+        resolver_.async_resolve(std::forward<decltype(args)>(args)...);
+      },
+      std::move(host), std::move(service));
+}

Then it should be possible to use asio::async_resolve like this:

async_resolve("127.0.0.1", "daytime")
+  .then([](udp::resolver::iterator iterator) {
+    // ...
+  });

asio and boost::asio async completion tokens

Since version 4.0.0 continuable also supports asio async initiation tokens.

  • Boost 1.70 or asio 1.13.0 is required for the async initiation
  • Until boost 1.72 or asio 1.16.0 overhead through an additional type erasure is added. It is recommended to update to those versions.

The special static variable cti::use_continuable can be appended to any (boost) asio function that accepts a callback to make it return a continuable_base.

#include <continuable/continuable.hpp>
+#include <continuable/external/asio.hpp>
+#include <asio.hpp>
+
+// ...
+
+asio::tcp::resolver resolver(...);
+resolver.async_resolve("127.0.0.1", "daytime", cti::use_continuable)
+  .then([](asio::udp::resolver::iterator iterator) {
+    // ...
+  });
+
+
+
+
+ + + + + + diff --git a/tutorial-transforming-continuables.html b/tutorial-transforming-continuables.html new file mode 100644 index 0000000..fc4c289 --- /dev/null +++ b/tutorial-transforming-continuables.html @@ -0,0 +1,200 @@ + + + + + + + Tutorial » Transforming continuables | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Tutorial » + + Transforming continuables +

+ +

Explains the conversion into other types such as std::future.

+ +

Transforms in general

Sometimes it's required to change a continuable_base object by its whole. Thus the library offers the ability to apply a transformation to any continuable_base through using apply.

A transformation is a callable object that accepts a continuable_base and returns an arbitrary object

The library provides several transforms already as part of the cti::transforms namespace.

Synchronous wait

The library is capable of converting every asynchronous control flow into a synchronous one through transforms::wait, transforms::wait_for and transforms::wait_until.

std::string response = http_request("github.com")
+  .apply(cti::transforms::wait());
+
+std::string response = http_request("github.com")
+  .apply(cti::transforms::wait_for(std::chrono::seconds(5)));
+
+std::string response = http_request("github.com")
+  .apply(cti::transforms::wait_until(...));

The current thread will be blocked until the result has arrived

Conversion into std::future

The library is capable of converting (futurizing) every continuable into a fitting std::future through the transforms::to_future transform:

std::future<std::string> future = http_request("github.com")
+  .then([](std::string response) {
+    // Do sth...
+    return http_request("travis-ci.org") || http_request("atom.io");
+  })
+  .apply(cti::transforms::to_future());
+// ^^^^^^^^

Multiple arguments which can't be handled by std::future itself are converted into std::tuple, see transforms::to_future for details.

std::future<std::tuple<std::string, std::string>> future =
+  (http_request("travis-ci.org") && http_request("atom.io"))
+    .apply(cti::transforms::to_future());
+
+
+
+
+ + + + + + diff --git a/tutorial.html b/tutorial.html new file mode 100644 index 0000000..01df29e --- /dev/null +++ b/tutorial.html @@ -0,0 +1,175 @@ + + + + + + + Tutorial | Continuable + + + + + + + + + + + + + + +
+
+
+
+
+

+ Tutorial +

+ +

An introduction for using the continuable library.

+

This tutorial will give a short overview about using the library. We assume that the library is available in your current environment, if not, follow the Installation section in order to get it to work.

This tutorial is split across multiple chapters which should be read in order:

+
+
+
+
+ + + + + + diff --git a/typed.js b/typed.js new file mode 100644 index 0000000..5d45ac7 --- /dev/null +++ b/typed.js @@ -0,0 +1,1040 @@ +/*! + * + * typed.js - A JavaScript Typing Animation Library + * Author: Matt Boldt + * Version: v2.0.6 + * Url: https://github.com/mattboldt/typed.js + * License(s): MIT + * + */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["Typed"] = factory(); + else + root["Typed"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, '__esModule', { + value: true + }); + + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + + var _initializerJs = __webpack_require__(1); + + var _htmlParserJs = __webpack_require__(3); + + /** + * Welcome to Typed.js! + * @param {string} elementId HTML element ID _OR_ HTML element + * @param {object} options options object + * @returns {object} a new Typed object + */ + + var Typed = (function () { + function Typed(elementId, options) { + _classCallCheck(this, Typed); + + // Initialize it up + _initializerJs.initializer.load(this, options, elementId); + // All systems go! + this.begin(); + } + + /** + * Toggle start() and stop() of the Typed instance + * @public + */ + + _createClass(Typed, [{ + key: 'toggle', + value: function toggle() { + this.pause.status ? this.start() : this.stop(); + } + + /** + * Stop typing / backspacing and enable cursor blinking + * @public + */ + }, { + key: 'stop', + value: function stop() { + if (this.typingComplete) return; + if (this.pause.status) return; + this.toggleBlinking(true); + this.pause.status = true; + this.options.onStop(this.arrayPos, this); + } + + /** + * Start typing / backspacing after being stopped + * @public + */ + }, { + key: 'start', + value: function start() { + if (this.typingComplete) return; + if (!this.pause.status) return; + this.pause.status = false; + if (this.pause.typewrite) { + this.typewrite(this.pause.curString, this.pause.curStrPos); + } else { + this.backspace(this.pause.curString, this.pause.curStrPos); + } + this.options.onStart(this.arrayPos, this); + } + + /** + * Destroy this instance of Typed + * @public + */ + }, { + key: 'destroy', + value: function destroy() { + this.reset(false); + this.options.onDestroy(this); + } + + /** + * Reset Typed and optionally restarts + * @param {boolean} restart + * @public + */ + }, { + key: 'reset', + value: function reset() { + var restart = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; + + clearInterval(this.timeout); + this.replaceText(''); + if (this.cursor && this.cursor.parentNode) { + this.cursor.parentNode.removeChild(this.cursor); + this.cursor = null; + } + this.strPos = 0; + this.arrayPos = 0; + this.curLoop = 0; + if (restart) { + this.insertCursor(); + this.options.onReset(this); + this.begin(); + } + } + + /** + * Begins the typing animation + * @private + */ + }, { + key: 'begin', + value: function begin() { + var _this = this; + + this.typingComplete = false; + this.shuffleStringsIfNeeded(this); + this.insertCursor(); + if (this.bindInputFocusEvents) this.bindFocusEvents(); + this.timeout = setTimeout(function () { + // Check if there is some text in the element, if yes start by backspacing the default message + if (!_this.currentElContent || _this.currentElContent.length === 0) { + _this.typewrite(_this.strings[_this.sequence[_this.arrayPos]], _this.strPos); + } else { + // Start typing + _this.backspace(_this.currentElContent, _this.currentElContent.length); + } + }, this.startDelay); + } + + /** + * Called for each character typed + * @param {string} curString the current string in the strings array + * @param {number} curStrPos the current position in the curString + * @private + */ + }, { + key: 'typewrite', + value: function typewrite(curString, curStrPos) { + var _this2 = this; + + if (this.fadeOut && this.el.classList.contains(this.fadeOutClass)) { + this.el.classList.remove(this.fadeOutClass); + if (this.cursor) this.cursor.classList.remove(this.fadeOutClass); + } + + var humanize = this.humanizer(this.typeSpeed); + var numChars = 1; + + if (this.pause.status === true) { + this.setPauseStatus(curString, curStrPos, true); + return; + } + + // contain typing function in a timeout humanize'd delay + this.timeout = setTimeout(function () { + // skip over any HTML chars + curStrPos = _htmlParserJs.htmlParser.typeHtmlChars(curString, curStrPos, _this2); + + var pauseTime = 0; + var substr = curString.substr(curStrPos); + // check for an escape character before a pause value + // format: \^\d+ .. eg: ^1000 .. should be able to print the ^ too using ^^ + // single ^ are removed from string + if (substr.charAt(0) === '^') { + if (/^\^\d+/.test(substr)) { + var skip = 1; // skip at least 1 + substr = /\d+/.exec(substr)[0]; + skip += substr.length; + pauseTime = parseInt(substr); + _this2.temporaryPause = true; + _this2.options.onTypingPaused(_this2.arrayPos, _this2); + // strip out the escape character and pause value so they're not printed + curString = curString.substring(0, curStrPos) + curString.substring(curStrPos + skip); + _this2.toggleBlinking(true); + } + } + + // check for skip characters formatted as + // "this is a `string to print NOW` ..." + if (substr.charAt(0) === '`') { + while (curString.substr(curStrPos + numChars).charAt(0) !== '`') { + numChars++; + if (curStrPos + numChars > curString.length) break; + } + // strip out the escape characters and append all the string in between + var stringBeforeSkip = curString.substring(0, curStrPos); + var stringSkipped = curString.substring(stringBeforeSkip.length + 1, curStrPos + numChars); + var stringAfterSkip = curString.substring(curStrPos + numChars + 1); + curString = stringBeforeSkip + stringSkipped + stringAfterSkip; + numChars--; + } + + // timeout for any pause after a character + _this2.timeout = setTimeout(function () { + // Accounts for blinking while paused + _this2.toggleBlinking(false); + + if (curStrPos > curString.length) { + curStrPos = curString.length; + } + + // We're done with this sentence! + if (curStrPos === curString.length) { + _this2.doneTyping(curString, curStrPos); + } else { + _this2.keepTyping(curString, curStrPos, numChars); + } + // end of character pause + if (_this2.temporaryPause) { + _this2.temporaryPause = false; + _this2.options.onTypingResumed(_this2.arrayPos, _this2); + } + }, pauseTime); + + // humanized value for typing + }, humanize); + } + + /** + * Continue to the next string & begin typing + * @param {string} curString the current string in the strings array + * @param {number} curStrPos the current position in the curString + * @private + */ + }, { + key: 'keepTyping', + value: function keepTyping(curString, curStrPos, numChars) { + // call before functions if applicable + if (curStrPos === 0) { + this.toggleBlinking(false); + this.options.preStringTyped(this.arrayPos, this); + } + // start typing each new char into existing string + // curString: arg, this.el.html: original text inside element + curStrPos += numChars; + var nextString = curString.substr(0, curStrPos); + this.replaceText(nextString); + // loop the function + this.typewrite(curString, curStrPos); + } + + /** + * We're done typing all strings + * @param {string} curString the current string in the strings array + * @param {number} curStrPos the current position in the curString + * @private + */ + }, { + key: 'doneTyping', + value: function doneTyping(curString, curStrPos) { + var _this3 = this; + + // fires callback function + this.options.onStringTyped(this.arrayPos, this); + this.toggleBlinking(true); + // is this the final string + if (this.arrayPos === this.strings.length - 1) { + // callback that occurs on the last typed string + this.complete(); + // quit if we wont loop back + if (this.loop === false || this.curLoop === this.loopCount) { + return; + } + } + this.timeout = setTimeout(function () { + _this3.backspace(curString, curStrPos); + }, this.backDelay); + } + + /** + * Backspaces 1 character at a time + * @param {string} curString the current string in the strings array + * @param {number} curStrPos the current position in the curString + * @private + */ + }, { + key: 'backspace', + value: function backspace(curString, curStrPos) { + var _this4 = this; + + if (this.pause.status === true) { + this.setPauseStatus(curString, curStrPos, true); + return; + } + if (this.fadeOut) return this.initFadeOut(); + + this.toggleBlinking(false); + var humanize = this.humanizer(this.backSpeed); + + this.timeout = setTimeout(function () { + curStrPos = _htmlParserJs.htmlParser.backSpaceHtmlChars(curString, curStrPos, _this4); + // replace text with base text + typed characters + var curStringAtPosition = curString.substr(0, curStrPos); + _this4.replaceText(curStringAtPosition); + + // if smartBack is enabled + if (_this4.smartBackspace) { + // the remaining part of the current string is equal of the same part of the new string + var nextString = _this4.strings[_this4.arrayPos + 1]; + if (nextString && curStringAtPosition === nextString.substr(0, curStrPos)) { + _this4.stopNum = curStrPos; + } else { + _this4.stopNum = 0; + } + } + + // if the number (id of character in current string) is + // less than the stop number, keep going + if (curStrPos > _this4.stopNum) { + // subtract characters one by one + curStrPos--; + // loop the function + _this4.backspace(curString, curStrPos); + } else if (curStrPos <= _this4.stopNum) { + // if the stop number has been reached, increase + // array position to next string + _this4.arrayPos++; + // When looping, begin at the beginning after backspace complete + if (_this4.arrayPos === _this4.strings.length) { + _this4.arrayPos = 0; + _this4.options.onLastStringBackspaced(); + _this4.shuffleStringsIfNeeded(); + _this4.begin(); + } else { + _this4.typewrite(_this4.strings[_this4.sequence[_this4.arrayPos]], curStrPos); + } + } + // humanized value for typing + }, humanize); + } + + /** + * Full animation is complete + * @private + */ + }, { + key: 'complete', + value: function complete() { + this.options.onComplete(this); + if (this.loop) { + this.curLoop++; + } else { + this.typingComplete = true; + } + } + + /** + * Has the typing been stopped + * @param {string} curString the current string in the strings array + * @param {number} curStrPos the current position in the curString + * @param {boolean} isTyping + * @private + */ + }, { + key: 'setPauseStatus', + value: function setPauseStatus(curString, curStrPos, isTyping) { + this.pause.typewrite = isTyping; + this.pause.curString = curString; + this.pause.curStrPos = curStrPos; + } + + /** + * Toggle the blinking cursor + * @param {boolean} isBlinking + * @private + */ + }, { + key: 'toggleBlinking', + value: function toggleBlinking(isBlinking) { + if (!this.cursor) return; + // if in paused state, don't toggle blinking a 2nd time + if (this.pause.status) return; + if (this.cursorBlinking === isBlinking) return; + this.cursorBlinking = isBlinking; + var status = isBlinking ? 'infinite' : 0; + this.cursor.style.animationIterationCount = status; + } + + /** + * Speed in MS to type + * @param {number} speed + * @private + */ + }, { + key: 'humanizer', + value: function humanizer(speed) { + return Math.round(Math.random() * speed / 2) + speed; + } + + /** + * Shuffle the sequence of the strings array + * @private + */ + }, { + key: 'shuffleStringsIfNeeded', + value: function shuffleStringsIfNeeded() { + if (!this.shuffle) return; + this.sequence = this.sequence.sort(function () { + return Math.random() - 0.5; + }); + } + + /** + * Adds a CSS class to fade out current string + * @private + */ + }, { + key: 'initFadeOut', + value: function initFadeOut() { + var _this5 = this; + + this.el.className += ' ' + this.fadeOutClass; + if (this.cursor) this.cursor.className += ' ' + this.fadeOutClass; + return setTimeout(function () { + _this5.arrayPos++; + _this5.replaceText(''); + + // Resets current string if end of loop reached + if (_this5.strings.length > _this5.arrayPos) { + _this5.typewrite(_this5.strings[_this5.sequence[_this5.arrayPos]], 0); + } else { + _this5.typewrite(_this5.strings[0], 0); + _this5.arrayPos = 0; + } + }, this.fadeOutDelay); + } + + /** + * Replaces current text in the HTML element + * depending on element type + * @param {string} str + * @private + */ + }, { + key: 'replaceText', + value: function replaceText(str) { + if (this.attr) { + this.el.setAttribute(this.attr, str); + } else { + if (this.isInput) { + this.el.value = str; + } else if (this.contentType === 'html') { + this.el.innerHTML = str; + } else { + this.el.textContent = str; + } + } + } + + /** + * If using input elements, bind focus in order to + * start and stop the animation + * @private + */ + }, { + key: 'bindFocusEvents', + value: function bindFocusEvents() { + var _this6 = this; + + if (!this.isInput) return; + this.el.addEventListener('focus', function (e) { + _this6.stop(); + }); + this.el.addEventListener('blur', function (e) { + if (_this6.el.value && _this6.el.value.length !== 0) { + return; + } + _this6.start(); + }); + } + + /** + * On init, insert the cursor element + * @private + */ + }, { + key: 'insertCursor', + value: function insertCursor() { + if (!this.showCursor) return; + if (this.cursor) return; + this.cursor = document.createElement('span'); + this.cursor.className = 'typed-cursor'; + this.cursor.innerHTML = this.cursorChar; + this.el.parentNode && this.el.parentNode.insertBefore(this.cursor, this.el.nextSibling); + } + }]); + + return Typed; + })(); + + exports['default'] = Typed; + module.exports = exports['default']; + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + + 'use strict'; + + Object.defineProperty(exports, '__esModule', { + value: true + }); + + var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + + var _defaultsJs = __webpack_require__(2); + + var _defaultsJs2 = _interopRequireDefault(_defaultsJs); + + /** + * Initialize the Typed object + */ + + var Initializer = (function () { + function Initializer() { + _classCallCheck(this, Initializer); + } + + _createClass(Initializer, [{ + key: 'load', + + /** + * Load up defaults & options on the Typed instance + * @param {Typed} self instance of Typed + * @param {object} options options object + * @param {string} elementId HTML element ID _OR_ instance of HTML element + * @private + */ + + value: function load(self, options, elementId) { + // chosen element to manipulate text + if (typeof elementId === 'string') { + self.el = document.querySelector(elementId); + } else { + self.el = elementId; + } + + self.options = _extends({}, _defaultsJs2['default'], options); + + // attribute to type into + self.isInput = self.el.tagName.toLowerCase() === 'input'; + self.attr = self.options.attr; + self.bindInputFocusEvents = self.options.bindInputFocusEvents; + + // show cursor + self.showCursor = self.isInput ? false : self.options.showCursor; + + // custom cursor + self.cursorChar = self.options.cursorChar; + + // Is the cursor blinking + self.cursorBlinking = true; + + // text content of element + self.elContent = self.attr ? self.el.getAttribute(self.attr) : self.el.textContent; + + // html or plain text + self.contentType = self.options.contentType; + + // typing speed + self.typeSpeed = self.options.typeSpeed; + + // add a delay before typing starts + self.startDelay = self.options.startDelay; + + // backspacing speed + self.backSpeed = self.options.backSpeed; + + // only backspace what doesn't match the previous string + self.smartBackspace = self.options.smartBackspace; + + // amount of time to wait before backspacing + self.backDelay = self.options.backDelay; + + // Fade out instead of backspace + self.fadeOut = self.options.fadeOut; + self.fadeOutClass = self.options.fadeOutClass; + self.fadeOutDelay = self.options.fadeOutDelay; + + // variable to check whether typing is currently paused + self.isPaused = false; + + // input strings of text + self.strings = self.options.strings.map(function (s) { + return s.trim(); + }); + + // div containing strings + if (typeof self.options.stringsElement === 'string') { + self.stringsElement = document.querySelector(self.options.stringsElement); + } else { + self.stringsElement = self.options.stringsElement; + } + + if (self.stringsElement) { + self.strings = []; + self.stringsElement.style.display = 'none'; + var strings = Array.prototype.slice.apply(self.stringsElement.children); + var stringsLength = strings.length; + + if (stringsLength) { + for (var i = 0; i < stringsLength; i += 1) { + var stringEl = strings[i]; + self.strings.push(stringEl.innerHTML.trim()); + } + } + } + + // character number position of current string + self.strPos = 0; + + // current array position + self.arrayPos = 0; + + // index of string to stop backspacing on + self.stopNum = 0; + + // Looping logic + self.loop = self.options.loop; + self.loopCount = self.options.loopCount; + self.curLoop = 0; + + // shuffle the strings + self.shuffle = self.options.shuffle; + // the order of strings + self.sequence = []; + + self.pause = { + status: false, + typewrite: true, + curString: '', + curStrPos: 0 + }; + + // When the typing is complete (when not looped) + self.typingComplete = false; + + // Set the order in which the strings are typed + for (var i in self.strings) { + self.sequence[i] = i; + } + + // If there is some text in the element + self.currentElContent = this.getCurrentElContent(self); + + self.autoInsertCss = self.options.autoInsertCss; + + this.appendAnimationCss(self); + } + }, { + key: 'getCurrentElContent', + value: function getCurrentElContent(self) { + var elContent = ''; + if (self.attr) { + elContent = self.el.getAttribute(self.attr); + } else if (self.isInput) { + elContent = self.el.value; + } else if (self.contentType === 'html') { + elContent = self.el.innerHTML; + } else { + elContent = self.el.textContent; + } + return elContent; + } + }, { + key: 'appendAnimationCss', + value: function appendAnimationCss(self) { + if (!self.autoInsertCss) { + return; + } + if (!self.showCursor || !self.fadeOut) { + return; + } + + var css = document.createElement('style'); + css.type = 'text/css'; + var innerCss = ''; + if (self.showCursor) { + innerCss += '\n .typed-cursor{\n opacity: 1;\n animation: typedjsBlink 0.7s infinite;\n -webkit-animation: typedjsBlink 0.7s infinite;\n animation: typedjsBlink 0.7s infinite;\n }\n @keyframes typedjsBlink{\n 50% { opacity: 0.0; }\n }\n @-webkit-keyframes typedjsBlink{\n 0% { opacity: 1; }\n 50% { opacity: 0.0; }\n 100% { opacity: 1; }\n }\n '; + } + if (self.fadeOut) { + innerCss += '\n .typed-fade-out{\n opacity: 0;\n transition: opacity .25s;\n -webkit-animation: 0;\n animation: 0;\n }\n '; + } + if (css.length === 0) { + return; + } + css.innerHTML = innerCss; + document.body.appendChild(css); + } + }]); + + return Initializer; + })(); + + exports['default'] = Initializer; + var initializer = new Initializer(); + exports.initializer = initializer; + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + + /** + * Defaults & options + * @returns {object} Typed defaults & options + * @public + */ + + 'use strict'; + + Object.defineProperty(exports, '__esModule', { + value: true + }); + var defaults = { + /** + * @property {array} strings strings to be typed + * @property {string} stringsElement ID of element containing string children + */ + strings: ['These are the default values...', 'You know what you should do?', 'Use your own!', 'Have a great day!'], + stringsElement: null, + + /** + * @property {number} typeSpeed type speed in milliseconds + */ + typeSpeed: 0, + + /** + * @property {number} startDelay time before typing starts in milliseconds + */ + startDelay: 0, + + /** + * @property {number} backSpeed backspacing speed in milliseconds + */ + backSpeed: 0, + + /** + * @property {boolean} smartBackspace only backspace what doesn't match the previous string + */ + smartBackspace: true, + + /** + * @property {boolean} shuffle shuffle the strings + */ + shuffle: false, + + /** + * @property {number} backDelay time before backspacing in milliseconds + */ + backDelay: 700, + + /** + * @property {boolean} fadeOut Fade out instead of backspace + * @property {string} fadeOutClass css class for fade animation + * @property {boolean} fadeOutDelay Fade out delay in milliseconds + */ + fadeOut: false, + fadeOutClass: 'typed-fade-out', + fadeOutDelay: 500, + + /** + * @property {boolean} loop loop strings + * @property {number} loopCount amount of loops + */ + loop: false, + loopCount: Infinity, + + /** + * @property {boolean} showCursor show cursor + * @property {string} cursorChar character for cursor + * @property {boolean} autoInsertCss insert CSS for cursor and fadeOut into HTML + */ + showCursor: true, + cursorChar: '|', + autoInsertCss: true, + + /** + * @property {string} attr attribute for typing + * Ex: input placeholder, value, or just HTML text + */ + attr: null, + + /** + * @property {boolean} bindInputFocusEvents bind to focus and blur if el is text input + */ + bindInputFocusEvents: false, + + /** + * @property {string} contentType 'html' or 'null' for plaintext + */ + contentType: 'html', + + /** + * All typing is complete + * @param {Typed} self + */ + onComplete: function onComplete(self) {}, + + /** + * Before each string is typed + * @param {number} arrayPos + * @param {Typed} self + */ + preStringTyped: function preStringTyped(arrayPos, self) {}, + + /** + * After each string is typed + * @param {number} arrayPos + * @param {Typed} self + */ + onStringTyped: function onStringTyped(arrayPos, self) {}, + + /** + * During looping, after last string is typed + * @param {Typed} self + */ + onLastStringBackspaced: function onLastStringBackspaced(self) {}, + + /** + * Typing has been stopped + * @param {number} arrayPos + * @param {Typed} self + */ + onTypingPaused: function onTypingPaused(arrayPos, self) {}, + + /** + * Typing has been started after being stopped + * @param {number} arrayPos + * @param {Typed} self + */ + onTypingResumed: function onTypingResumed(arrayPos, self) {}, + + /** + * After reset + * @param {Typed} self + */ + onReset: function onReset(self) {}, + + /** + * After stop + * @param {number} arrayPos + * @param {Typed} self + */ + onStop: function onStop(arrayPos, self) {}, + + /** + * After start + * @param {number} arrayPos + * @param {Typed} self + */ + onStart: function onStart(arrayPos, self) {}, + + /** + * After destroy + * @param {Typed} self + */ + onDestroy: function onDestroy(self) {} + }; + + exports['default'] = defaults; + module.exports = exports['default']; + +/***/ }), +/* 3 */ +/***/ (function(module, exports) { + + + /** + * TODO: These methods can probably be combined somehow + * Parse HTML tags & HTML Characters + */ + + 'use strict'; + + Object.defineProperty(exports, '__esModule', { + value: true + }); + + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + + var HTMLParser = (function () { + function HTMLParser() { + _classCallCheck(this, HTMLParser); + } + + _createClass(HTMLParser, [{ + key: 'typeHtmlChars', + + /** + * Type HTML tags & HTML Characters + * @param {string} curString Current string + * @param {number} curStrPos Position in current string + * @param {Typed} self instance of Typed + * @returns {number} a new string position + * @private + */ + + value: function typeHtmlChars(curString, curStrPos, self) { + if (self.contentType !== 'html') return curStrPos; + var curChar = curString.substr(curStrPos).charAt(0); + if (curChar === '<' || curChar === '&') { + var endTag = ''; + if (curChar === '<') { + endTag = '>'; + } else { + endTag = ';'; + } + while (curString.substr(curStrPos + 1).charAt(0) !== endTag) { + curStrPos++; + if (curStrPos + 1 > curString.length) { + break; + } + } + curStrPos++; + } + return curStrPos; + } + + /** + * Backspace HTML tags and HTML Characters + * @param {string} curString Current string + * @param {number} curStrPos Position in current string + * @param {Typed} self instance of Typed + * @returns {number} a new string position + * @private + */ + }, { + key: 'backSpaceHtmlChars', + value: function backSpaceHtmlChars(curString, curStrPos, self) { + if (self.contentType !== 'html') return curStrPos; + var curChar = curString.substr(curStrPos).charAt(0); + if (curChar === '>' || curChar === ';') { + var endTag = ''; + if (curChar === '>') { + endTag = '<'; + } else { + endTag = '&'; + } + while (curString.substr(curStrPos - 1).charAt(0) !== endTag) { + curStrPos--; + if (curStrPos < 0) { + break; + } + } + curStrPos--; + } + return curStrPos; + } + }]); + + return HTMLParser; + })(); + + exports['default'] = HTMLParser; + var htmlParser = new HTMLParser(); + exports.htmlParser = htmlParser; + +/***/ }) +/******/ ]) +}); +; \ No newline at end of file